LCOV - code coverage report
Current view: top level - EnergyPlus - Furnaces.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 62.6 % 5306 3319
Test Date: 2025-06-02 07:23:51 Functions: 97.1 % 34 33

            Line data    Source code
       1              : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
       2              : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
       3              : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
       4              : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
       5              : // contributors. All rights reserved.
       6              : //
       7              : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
       8              : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
       9              : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
      10              : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
      11              : // derivative works, and perform publicly and display publicly, and to permit others to do so.
      12              : //
      13              : // Redistribution and use in source and binary forms, with or without modification, are permitted
      14              : // provided that the following conditions are met:
      15              : //
      16              : // (1) Redistributions of source code must retain the above copyright notice, this list of
      17              : //     conditions and the following disclaimer.
      18              : //
      19              : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
      20              : //     conditions and the following disclaimer in the documentation and/or other materials
      21              : //     provided with the distribution.
      22              : //
      23              : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
      24              : //     the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
      25              : //     used to endorse or promote products derived from this software without specific prior
      26              : //     written permission.
      27              : //
      28              : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
      29              : //     without changes from the version obtained under this License, or (ii) Licensee makes a
      30              : //     reference solely to the software portion of its product, Licensee must refer to the
      31              : //     software as "EnergyPlus version X" software, where "X" is the version number Licensee
      32              : //     obtained under this License and may not use a different name for the software. Except as
      33              : //     specifically required in this Section (4), Licensee shall not use in a company name, a
      34              : //     product name, in advertising, publicity, or other promotional activities any name, trade
      35              : //     name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
      36              : //     similar designation, without the U.S. Department of Energy's prior written consent.
      37              : //
      38              : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
      39              : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
      40              : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
      41              : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      42              : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      43              : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      44              : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      45              : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      46              : // POSSIBILITY OF SUCH DAMAGE.
      47              : 
      48              : // C++ Headers
      49              : #include <cassert>
      50              : #include <cmath>
      51              : 
      52              : // ObjexxFCL Headers
      53              : #include <ObjexxFCL/Array.functions.hh>
      54              : 
      55              : // EnergyPlus Headers
      56              : #include <AirflowNetwork/Solver.hpp>
      57              : #include <EnergyPlus/Autosizing/Base.hh>
      58              : #include <EnergyPlus/BranchInputManager.hh>
      59              : #include <EnergyPlus/BranchNodeConnections.hh>
      60              : #include <EnergyPlus/Coils/CoilCoolingDX.hh>
      61              : #include <EnergyPlus/DXCoils.hh>
      62              : #include <EnergyPlus/Data/EnergyPlusData.hh>
      63              : #include <EnergyPlus/DataAirSystems.hh>
      64              : #include <EnergyPlus/DataHVACGlobals.hh>
      65              : #include <EnergyPlus/DataHeatBalFanSys.hh>
      66              : #include <EnergyPlus/DataHeatBalance.hh>
      67              : #include <EnergyPlus/DataIPShortCuts.hh>
      68              : #include <EnergyPlus/DataSizing.hh>
      69              : #include <EnergyPlus/DataZoneControls.hh>
      70              : #include <EnergyPlus/DataZoneEnergyDemands.hh>
      71              : #include <EnergyPlus/DataZoneEquipment.hh>
      72              : #include <EnergyPlus/EMSManager.hh>
      73              : #include <EnergyPlus/Fans.hh>
      74              : #include <EnergyPlus/FluidProperties.hh>
      75              : #include <EnergyPlus/Furnaces.hh>
      76              : #include <EnergyPlus/General.hh>
      77              : #include <EnergyPlus/GeneralRoutines.hh>
      78              : #include <EnergyPlus/GlobalNames.hh>
      79              : #include <EnergyPlus/HVACControllers.hh>
      80              : #include <EnergyPlus/HVACHXAssistedCoolingCoil.hh>
      81              : #include <EnergyPlus/HeatingCoils.hh>
      82              : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      83              : #include <EnergyPlus/IntegratedHeatPump.hh>
      84              : #include <EnergyPlus/NodeInputManager.hh>
      85              : #include <EnergyPlus/OutAirNodeManager.hh>
      86              : #include <EnergyPlus/OutputProcessor.hh>
      87              : #include <EnergyPlus/OutputReportPredefined.hh>
      88              : #include <EnergyPlus/PlantUtilities.hh>
      89              : #include <EnergyPlus/Psychrometrics.hh>
      90              : #include <EnergyPlus/ScheduleManager.hh>
      91              : #include <EnergyPlus/SteamCoils.hh>
      92              : #include <EnergyPlus/WaterCoils.hh>
      93              : #include <EnergyPlus/WaterToAirHeatPump.hh>
      94              : #include <EnergyPlus/WaterToAirHeatPumpSimple.hh>
      95              : #include <EnergyPlus/ZoneTempPredictorCorrector.hh>
      96              : 
      97              : namespace EnergyPlus {
      98              : 
      99              : namespace Furnaces {
     100              :     // Module containing the Furnace and Unitary System simulation routines
     101              : 
     102              :     // MODULE INFORMATION:
     103              :     //       AUTHOR         Dan Fisher
     104              :     //       DATE WRITTEN   Jan 2001
     105              :     //       MODIFIED       Richard Liesen, Feb 2001; Don Shirey, Mar/Oct 2001, Oct 2003
     106              :     //                      Richard Raustad, Nov 2006 - allow draw through fan and alternate air flow in cooling,
     107              :     //                      heating, and when no cooling or heating is required.
     108              :     //                      Bereket Nigusse, FSEC, June 2010 - deprecated supply air flow fraction through controlled
     109              :     //                      zone from the furnace object input field. Now, the flow fraction is calculated internally
     110              :     //                      B. Nigusse, FSEC, Jan 2012 - added steam and hot water heating coils as an option
     111              :     //                      Bo Shen, ORNL, March 2012 - added variable-speed water source heat pump cooling and heating coils, using curve-fits
     112              :     //                      Bo Shen, ORNL, July 2012 - added variable-speed air source heat pump cooling and heating coils, using curve-fits
     113              : 
     114              :     // PURPOSE OF THIS MODULE:
     115              :     // To encapsulate the data and algorithms required to
     116              :     // manage the Furnace/Unitary System Compound Component
     117              : 
     118              :     // METHODOLOGY EMPLOYED:
     119              :     // Calculates the part-load ratio of the HVAC system to meet the zone sensible load. For non-heat pump HVAC systems,
     120              :     // if humidity control is specified and the latent capacity at the sensible PLR is insufficient to meet the latent load,
     121              :     // calculate a latent part-load ratio to meet the zone sensible load (MultiMode dehumidification control) or the zone
     122              :     // latent load (CoolReheat dehumidification control). Use the greater of the sensible PLR and latent PLR to control
     123              :     // the HVAC system.
     124              :     // Subroutines:
     125              :     // SimFurnace - Top level simulate routine CALLed by other modules. Each child object is simulated a final time after
     126              :     //              the part-load ratio for child components has been determined.
     127              :     //  Note: A supplemental heater augments the heating capacity for both air-to-air and water-to-air heat pump systems.
     128              :     //        A reheat coil is used for the HeatCool furnace/unitarysystem to offset the sensible cooling when the
     129              :     //        dehumidification control type is COOLREHEAT. Both the supplemental and reheat heating coil load is calculated
     130              :     //        in the Calc routines. The actual simulation of these coils is performed in the SimFurnace routine (i.e. the
     131              :     //        supplemental and reheat coil loads are passed as 0 to CalcFurnaceOutput).
     132              :     // CalcNewZoneHeatOnlyFlowRates - HeatOnly furnace/unitarysystem routine.
     133              :     //                                Calculates a part-load ratio to meet the sensible load.
     134              :     // CalcNewZoneHeatCoolFlowRates - HeatCool furnace/unitarysystem and air-to-air HeatPump routine.
     135              :     //                                Calculates a part-load ratio for the system (sensible and/or latent).
     136              :     //                                For dehumidification control type COOLREHEAT, both a sensible and latent PLR
     137              :     //                                may exist for a single time step (heating and dehumidification can occur). For all
     138              :     //                                other system types, only a single PLR is allowed for any given time step.
     139              :     //                                Order of simulation depends on dehumidification control option as described below.
     140              :     // Dehumidification control options (non-heat pump versions):
     141              :     // Dehumidification Control NONE:   Cooling performance is simulated first and then heating performance. If a HX
     142              :     //                                  assisted cooling coil is selected, the HX is always active (cooling).
     143              :     // Dehumidification Control COOLREHEAT: For cooling operation, the sensible capacity is calculated to
     144              :     //                                      meet the thermostat setpoint. If a HX assisted cooling coil is selected,
     145              :     //                                      the HX is always active. If the latent load is not met by operating the
     146              :     //                                      system at the sensible PLR, a new PLR is calculated to meet the humidistat
     147              :     //                                      setpoint. The reheat coil load is then calculated to meet the HEATING
     148              :     //                                      setpoint temperature.
     149              :     // Dehumidification Control MULTIMODE: For cooling operation, the sensible capacity is calculated to
     150              :     //                                     meet the thermostat setpoint. If a HX assisted cooling coil is selected,
     151              :     //                                     the HX is off for this calculation. If the latent load is not met by operating
     152              :     //                                     the system at the sensible PLR, a new PLR is calculated with the HX operating
     153              :     //                                     and the target is the zone SENSIBLE load (thermostat setpoint). Humidity is not
     154              :     //                                     controlled in this mode. No reheat coil is used in this configuration.
     155              :     // CalcWaterToAirHeatPump - Water-to-air HeatPump routine.
     156              :     //                          Calculates a part-load ratio to meet the sensible load.
     157              :     // CalcFurnaceOutput - Simulates each child component in order.
     158              :     //                     For cooling operation, the heating coil is off.
     159              :     //                     For heating operation, the cooling coil is off.
     160              :     //                     Reheat or supplemental heating coil is simulated here just to pass the inlet node conditions
     161              :     //                     to the output node (actual simulation of these coils is done on the final simulation of the
     162              :     //                     child components in SimFurnace).
     163              :     //                     Fan is simulated based on placement (drawthru or blowthru).
     164              : 
     165              :     // MODULE PARAMETER DEFINITIONS
     166              :     static constexpr std::string_view BlankString;
     167              : 
     168              :     // Functions
     169              : 
     170      6219025 :     void SimFurnace(EnergyPlusData &state,
     171              :                     std::string_view FurnaceName,
     172              :                     bool const FirstHVACIteration,
     173              :                     int const AirLoopNum, // Primary air loop number
     174              :                     int &CompIndex        // Pointer to which furnace
     175              :     )
     176              :     {
     177              : 
     178              :         // SUBROUTINE INFORMATION:
     179              :         //       AUTHOR         Dan Fisher
     180              :         //       DATE WRITTEN   Jan 2001
     181              :         //       MODIFIED       Richard Liesen, Oct 2001 - Richard Raustad; Bo Shen, March 2012, for VS WSHP
     182              :         //       RE-ENGINEERED  Feb 2001
     183              : 
     184              :         // PURPOSE OF THIS SUBROUTINE:
     185              :         // This subroutine manages Furnace component simulation.
     186              : 
     187              :         // METHODOLOGY EMPLOYED:
     188              :         // Call the calc routine to determine an operating PLR. Resimulate child components at this PLR.
     189              :         // A supplemental heater augments the heating capacity for both air-to-air and water-to-air heat pump systems.
     190              :         // A reheat coil is used for the HeatCool furnace/unitarysystem to offset the sensible cooling when the
     191              :         // dehumidification control type is COOLREHEAT. Both the supplemental and reheat heating coil load is calculated
     192              :         // in the Calc routines and returned here through subroutine arguments. The actual simulation of these coils is
     193              :         // performed here (i.e. the supplemental and reheat coil loads are passed as 0 to CalcFurnaceOutput).
     194              : 
     195              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     196              :         int FurnaceNum;           // Furnace number
     197      6219025 :         Real64 HeatCoilLoad(0.0); // Zone heating coil load
     198              :         Real64 ReheatCoilLoad;    // Load to be met by the reheat coil (if high humidity control)
     199              :         Real64 MoistureLoad;      // Control zone latent load
     200      6219025 :         Real64 Dummy(0.0);
     201      6219025 :         HVAC::FanOp fanOp = HVAC::FanOp::Invalid; // Fan operating mode (1=FanOp::Cycling, 2=FanOp::Continuous)
     202              : 
     203              :         Real64 QActual;           // actual heating coil output (W)
     204              :         bool SuppHeatingCoilFlag; // true if supplemental heating coil
     205              : 
     206              :         // Obtains and Allocates Furnace related parameters from input file
     207      6219025 :         if (state.dataFurnaces->GetFurnaceInputFlag) { // First time subroutine has been entered
     208              :             // Get the furnace input
     209           97 :             GetFurnaceInput(state);
     210           97 :             state.dataFurnaces->GetFurnaceInputFlag = false;
     211              :         }
     212              : 
     213              :         // Find the correct Furnace
     214      6219025 :         if (CompIndex == 0) {
     215          359 :             FurnaceNum = Util::FindItemInList(FurnaceName, state.dataFurnaces->Furnace);
     216          359 :             if (FurnaceNum == 0) {
     217            0 :                 ShowFatalError(state, format("SimFurnace: Unit not found={}", FurnaceName));
     218              :             }
     219          359 :             CompIndex = FurnaceNum;
     220              :         } else {
     221      6218666 :             FurnaceNum = CompIndex;
     222      6218666 :             if (FurnaceNum > state.dataFurnaces->NumFurnaces || FurnaceNum < 1) {
     223            0 :                 ShowFatalError(state,
     224            0 :                                format("SimFurnace:  Invalid CompIndex passed={}, Number of Units={}, Entered Unit name={}",
     225              :                                       FurnaceNum,
     226            0 :                                       state.dataFurnaces->NumFurnaces,
     227              :                                       FurnaceName));
     228              :             }
     229      6218666 :             if (state.dataFurnaces->CheckEquipName(FurnaceNum)) {
     230          359 :                 if (FurnaceName != state.dataFurnaces->Furnace(FurnaceNum).Name) {
     231            0 :                     ShowFatalError(state,
     232            0 :                                    format("SimFurnace: Invalid CompIndex passed={}, Unit name={}, stored Unit Name for that index={}",
     233              :                                           FurnaceNum,
     234              :                                           FurnaceName,
     235            0 :                                           state.dataFurnaces->Furnace(FurnaceNum).Name));
     236              :                 }
     237          359 :                 state.dataFurnaces->CheckEquipName(FurnaceNum) = false;
     238              :             }
     239              :         }
     240              : 
     241      6219025 :         bool HXUnitOn = false;          // flag to control HX assisted cooling coil
     242      6219025 :         Real64 OnOffAirFlowRatio = 0.0; // Ratio of compressor ON air flow to AVERAGE air flow over time step
     243              :         // here we need to deal with sequenced zone equip sensible load in control zone
     244      6219025 :         Real64 ZoneLoad = 0.0;
     245              : 
     246      6219025 :         auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
     247      6219025 :         auto &zoneSysEnergyDemand = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(thisFurnace.ControlZoneNum);
     248      6219025 :         if (thisFurnace.ZoneSequenceCoolingNum > 0 && thisFurnace.ZoneSequenceHeatingNum > 0) {
     249      6218666 :             Real64 ZoneLoadToCoolSPSequenced = zoneSysEnergyDemand.SequencedOutputRequiredToCoolingSP(thisFurnace.ZoneSequenceCoolingNum);
     250      6218666 :             Real64 ZoneLoadToHeatSPSequenced = zoneSysEnergyDemand.SequencedOutputRequiredToHeatingSP(thisFurnace.ZoneSequenceHeatingNum);
     251      6218666 :             auto const &tempControlType = state.dataHeatBalFanSys->TempControlType(thisFurnace.ControlZoneNum);
     252      6218666 :             if (ZoneLoadToHeatSPSequenced > 0.0 && ZoneLoadToCoolSPSequenced > 0.0 && tempControlType != HVAC::SetptType::SingleCool) {
     253      2027000 :                 ZoneLoad = ZoneLoadToHeatSPSequenced;
     254      4191666 :             } else if (ZoneLoadToHeatSPSequenced > 0.0 && ZoneLoadToCoolSPSequenced > 0.0 && tempControlType == HVAC::SetptType::SingleCool) {
     255        66828 :                 ZoneLoad = 0.0;
     256      4124838 :             } else if (ZoneLoadToHeatSPSequenced < 0.0 && ZoneLoadToCoolSPSequenced < 0.0 && tempControlType != HVAC::SetptType::SingleHeat) {
     257      3036608 :                 ZoneLoad = ZoneLoadToCoolSPSequenced;
     258      1088230 :             } else if (ZoneLoadToHeatSPSequenced < 0.0 && ZoneLoadToCoolSPSequenced < 0.0 && tempControlType == HVAC::SetptType::SingleHeat) {
     259        25175 :                 ZoneLoad = 0.0;
     260      1063055 :             } else if (ZoneLoadToHeatSPSequenced <= 0.0 && ZoneLoadToCoolSPSequenced >= 0.0) {
     261      1063055 :                 ZoneLoad = 0.0;
     262              :             }
     263      6218666 :             MoistureLoad = state.dataZoneEnergyDemand->ZoneSysMoistureDemand(thisFurnace.ControlZoneNum)
     264      6218666 :                                .SequencedOutputRequiredToDehumidSP(thisFurnace.ZoneSequenceCoolingNum);
     265      6218666 :         } else {
     266          359 :             ZoneLoad = zoneSysEnergyDemand.RemainingOutputRequired;
     267          359 :             MoistureLoad = state.dataZoneEnergyDemand->ZoneSysMoistureDemand(thisFurnace.ControlZoneNum).OutputRequiredToDehumidifyingSP;
     268              :         }
     269              : 
     270              :         // H2OHtOfVap
     271      6219025 :         MoistureLoad *= Psychrometrics::PsyHfgAirFnWTdb(state.dataLoopNodes->Node(thisFurnace.NodeNumOfControlledZone).HumRat,
     272      6219025 :                                                         state.dataLoopNodes->Node(thisFurnace.NodeNumOfControlledZone).Temp);
     273              : 
     274              :         // Initialize Furnace Flows
     275      6219025 :         InitFurnace(state, FurnaceNum, AirLoopNum, OnOffAirFlowRatio, fanOp, ZoneLoad, MoistureLoad, FirstHVACIteration);
     276              : 
     277      6219025 :         int FurnaceInletNode = thisFurnace.FurnaceInletNodeNum;
     278              : 
     279              :         // MassFlowRateMaxAvail issues are impeding non-VAV air loop equipment by limiting air flow
     280              :         // temporarily open up flow limits while simulating, and then set this same value at the INLET after this parent has simulated
     281      6219025 :         Real64 TempMassFlowRateMaxAvail = state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRateMaxAvail;
     282      6219025 :         state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRateMaxAvail = thisFurnace.DesignMassFlowRate;
     283              : 
     284      6219025 :         Real64 FurnaceSavMdot = state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate;
     285      6219025 :         HVAC::CompressorOp compressorOp = HVAC::CompressorOp::On;
     286      6219025 :         state.dataFurnaces->CoolHeatPLRRat = 1.0;
     287              : 
     288              :         // Simulate correct system type (1 of 4 choices)
     289      6219025 :         switch (thisFurnace.type) {
     290              :             // Simulate HeatOnly systems:
     291        24444 :         case HVAC::UnitarySysType::Furnace_HeatOnly:
     292              :         case HVAC::UnitarySysType::Unitary_HeatOnly: {
     293              :             // Update the furnace flow rates
     294        24444 :             CalcNewZoneHeatOnlyFlowRates(state, FurnaceNum, FirstHVACIteration, ZoneLoad, HeatCoilLoad, OnOffAirFlowRatio);
     295              : 
     296        24444 :             if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
     297              :                 // simulate fan
     298        24444 :                 state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
     299              :             }
     300              : 
     301              :             // simulate furnace heating coil
     302        24444 :             SuppHeatingCoilFlag = false; // if true simulates supplemental heating coil
     303        24444 :             CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, fanOp, QActual);
     304              : 
     305        24444 :             if (thisFurnace.fanPlace == HVAC::FanPlace::DrawThru) {
     306              :                 // simulate fan
     307            0 :                 state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
     308              :             }
     309        24444 :         } break;
     310              :             // Simulate HeatCool systems:
     311      3738201 :         case HVAC::UnitarySysType::Furnace_HeatCool:
     312              :         case HVAC::UnitarySysType::Unitary_HeatCool: {
     313      3738201 :             if (thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingAirToAirVariableSpeed) {
     314              :                 // variable speed cooling coil
     315      1247320 :                 HeatCoilLoad = 0.0;
     316      1247320 :                 if (thisFurnace.bIsIHP) {
     317            0 :                     state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).ControlledZoneTemp =
     318            0 :                         state.dataLoopNodes->Node(thisFurnace.NodeNumOfControlledZone).Temp;
     319              :                 }
     320      1247320 :                 SimVariableSpeedHP(state, FurnaceNum, FirstHVACIteration, AirLoopNum, ZoneLoad, MoistureLoad, OnOffAirFlowRatio);
     321              :             } else {
     322              :                 // calculate the system flow rate
     323      2743943 :                 if (!FirstHVACIteration && thisFurnace.fanOp == HVAC::FanOp::Cycling && state.dataFurnaces->CoolingLoad &&
     324       253062 :                     state.dataAirLoop->AirLoopControlInfo(AirLoopNum).EconoActive) {
     325              :                     // for cycling fan, cooling load, check whether furnace can meet load with compressor off
     326         5692 :                     compressorOp = HVAC::CompressorOp::Off;
     327         5692 :                     CalcNewZoneHeatCoolFlowRates(state,
     328              :                                                  FurnaceNum,
     329              :                                                  FirstHVACIteration,
     330              :                                                  compressorOp,
     331              :                                                  ZoneLoad,
     332              :                                                  MoistureLoad,
     333              :                                                  HeatCoilLoad,
     334              :                                                  ReheatCoilLoad,
     335              :                                                  OnOffAirFlowRatio,
     336              :                                                  HXUnitOn);
     337         5692 :                     if (thisFurnace.CoolPartLoadRatio >= 1.0 || thisFurnace.HeatPartLoadRatio >= 1.0 ||
     338         2160 :                         (thisFurnace.CoolPartLoadRatio <= 0.0 && thisFurnace.HeatPartLoadRatio <= 0.0)) {
     339              :                         // compressor on (reset inlet air mass flow rate to starting value)
     340         5672 :                         state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = FurnaceSavMdot;
     341         5672 :                         compressorOp = HVAC::CompressorOp::On;
     342         5672 :                         CalcNewZoneHeatCoolFlowRates(state,
     343              :                                                      FurnaceNum,
     344              :                                                      FirstHVACIteration,
     345              :                                                      compressorOp,
     346              :                                                      ZoneLoad,
     347              :                                                      MoistureLoad,
     348              :                                                      HeatCoilLoad,
     349              :                                                      ReheatCoilLoad,
     350              :                                                      OnOffAirFlowRatio,
     351              :                                                      HXUnitOn);
     352              :                     }
     353              :                 } else {
     354              :                     // compressor on
     355      2485189 :                     CalcNewZoneHeatCoolFlowRates(state,
     356              :                                                  FurnaceNum,
     357              :                                                  FirstHVACIteration,
     358              :                                                  compressorOp,
     359              :                                                  ZoneLoad,
     360              :                                                  MoistureLoad,
     361              :                                                  HeatCoilLoad,
     362              :                                                  ReheatCoilLoad,
     363              :                                                  OnOffAirFlowRatio,
     364              :                                                  HXUnitOn);
     365              :                 }
     366              : 
     367      2490881 :                 if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
     368              :                     // simulate fan
     369      2451427 :                     state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
     370              :                 }
     371              : 
     372      2490881 :                 if (!thisFurnace.CoolingCoilUpstream) {
     373              :                     // simulate furnace heating coil
     374      1128522 :                     SuppHeatingCoilFlag = false; // if true simulates supplemental heating coil
     375      1128522 :                     CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, fanOp, QActual);
     376              :                 }
     377              : 
     378              :                 // simulate furnace DX cooling coil
     379      2490881 :                 if (thisFurnace.CoolingCoilType_Num == HVAC::CoilDX_CoolingHXAssisted) {
     380       151317 :                     HVACHXAssistedCoolingCoil::SimHXAssistedCoolingCoil(state,
     381              :                                                                         BlankString,
     382              :                                                                         FirstHVACIteration,
     383              :                                                                         compressorOp,
     384              :                                                                         thisFurnace.CoolPartLoadRatio,
     385        50439 :                                                                         thisFurnace.CoolingCoilIndex,
     386              :                                                                         fanOp,
     387              :                                                                         HXUnitOn,
     388              :                                                                         OnOffAirFlowRatio,
     389        50439 :                                                                         state.dataFurnaces->EconomizerFlag);
     390              :                 } else {
     391      7321326 :                     DXCoils::SimDXCoil(state,
     392              :                                        BlankString,
     393              :                                        compressorOp,
     394              :                                        FirstHVACIteration,
     395      2440442 :                                        thisFurnace.CoolingCoilIndex,
     396              :                                        fanOp,
     397      2440442 :                                        thisFurnace.CoolPartLoadRatio,
     398              :                                        OnOffAirFlowRatio,
     399      2440442 :                                        state.dataFurnaces->CoolHeatPLRRat);
     400              :                 }
     401              : 
     402      2490881 :                 if (thisFurnace.CoolingCoilUpstream) {
     403              :                     // simulate furnace heating coil
     404      1362359 :                     SuppHeatingCoilFlag = false; // if true simulates supplemental heating coil
     405      1362359 :                     CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, fanOp, QActual);
     406              :                 }
     407              : 
     408      2490881 :                 if (thisFurnace.fanPlace == HVAC::FanPlace::DrawThru) {
     409              :                     // simulate fan
     410        39454 :                     state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
     411              :                 }
     412              : 
     413              :                 // Simulate furnace reheat coil if a humidistat is used or if the reheat coil is present
     414      2490881 :                 if (thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat || thisFurnace.SuppHeatCoilIndex > 0) {
     415       837862 :                     SuppHeatingCoilFlag = true; // if true simulates supplemental heating coil
     416       837862 :                     CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, ReheatCoilLoad, fanOp, QActual);
     417              :                 }
     418              :             }
     419      3738201 :         } break;
     420              :             // Simulate air-to-air heat pumps:
     421       421792 :         case HVAC::UnitarySysType::Unitary_HeatPump_AirToAir: {
     422       421792 :             if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingAirToAirVariableSpeed) {
     423              :                 // variable speed heat pump
     424        30262 :                 HeatCoilLoad = 0.0;
     425        30262 :                 if (thisFurnace.bIsIHP) {
     426        10106 :                     auto &integratedHP = state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex);
     427        10106 :                     integratedHP.ControlledZoneTemp = state.dataLoopNodes->Node(thisFurnace.NodeNumOfControlledZone).Temp;
     428        10106 :                     integratedHP.IDFanID = thisFurnace.FanIndex; // why do this every time?
     429        10106 :                     integratedHP.IDFanName = BlankString;
     430        10106 :                     integratedHP.fanPlace = thisFurnace.fanPlace;
     431              :                 }
     432              : 
     433        30262 :                 SimVariableSpeedHP(state, FurnaceNum, FirstHVACIteration, AirLoopNum, ZoneLoad, MoistureLoad, OnOffAirFlowRatio);
     434              :             } else {
     435              :                 // Update the furnace flow rates
     436       496877 :                 if (!FirstHVACIteration && thisFurnace.fanOp == HVAC::FanOp::Cycling && state.dataFurnaces->CoolingLoad &&
     437       105347 :                     state.dataAirLoop->AirLoopControlInfo(AirLoopNum).EconoActive) {
     438              :                     // for cycling fan, cooling load, check whether furnace can meet load with compressor off
     439          538 :                     compressorOp = HVAC::CompressorOp::Off;
     440          538 :                     CalcNewZoneHeatCoolFlowRates(state,
     441              :                                                  FurnaceNum,
     442              :                                                  FirstHVACIteration,
     443              :                                                  compressorOp,
     444              :                                                  ZoneLoad,
     445              :                                                  MoistureLoad,
     446              :                                                  HeatCoilLoad,
     447              :                                                  ReheatCoilLoad,
     448              :                                                  OnOffAirFlowRatio,
     449              :                                                  HXUnitOn);
     450          538 :                     if (thisFurnace.CoolPartLoadRatio >= 1.0 || thisFurnace.HeatPartLoadRatio >= 1.0 ||
     451          406 :                         (thisFurnace.CoolPartLoadRatio <= 0.0 && thisFurnace.HeatPartLoadRatio <= 0.0)) {
     452              :                         // compressor on (reset inlet air mass flow rate to starting value)
     453          132 :                         compressorOp = HVAC::CompressorOp::On;
     454          132 :                         state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = FurnaceSavMdot;
     455          132 :                         CalcNewZoneHeatCoolFlowRates(state,
     456              :                                                      FurnaceNum,
     457              :                                                      FirstHVACIteration,
     458              :                                                      compressorOp,
     459              :                                                      ZoneLoad,
     460              :                                                      MoistureLoad,
     461              :                                                      HeatCoilLoad,
     462              :                                                      ReheatCoilLoad,
     463              :                                                      OnOffAirFlowRatio,
     464              :                                                      HXUnitOn);
     465              :                     }
     466              :                 } else {
     467              :                     // compressor on
     468       390992 :                     CalcNewZoneHeatCoolFlowRates(state,
     469              :                                                  FurnaceNum,
     470              :                                                  FirstHVACIteration,
     471              :                                                  compressorOp,
     472              :                                                  ZoneLoad,
     473              :                                                  MoistureLoad,
     474              :                                                  HeatCoilLoad,
     475              :                                                  ReheatCoilLoad,
     476              :                                                  OnOffAirFlowRatio,
     477              :                                                  HXUnitOn);
     478              :                 }
     479              : 
     480       391530 :                 if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
     481       391530 :                     state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
     482              :                 }
     483              : 
     484       391530 :                 if (thisFurnace.CoolingCoilType_Num == HVAC::CoilDX_CoolingHXAssisted) {
     485            0 :                     HVACHXAssistedCoolingCoil::SimHXAssistedCoolingCoil(state,
     486              :                                                                         BlankString,
     487              :                                                                         FirstHVACIteration,
     488              :                                                                         compressorOp,
     489              :                                                                         thisFurnace.CoolPartLoadRatio,
     490            0 :                                                                         thisFurnace.CoolingCoilIndex,
     491              :                                                                         fanOp,
     492              :                                                                         HXUnitOn,
     493              :                                                                         OnOffAirFlowRatio,
     494            0 :                                                                         state.dataFurnaces->EconomizerFlag);
     495              :                 } else {
     496       783060 :                     DXCoils::SimDXCoil(state,
     497              :                                        BlankString,
     498              :                                        compressorOp,
     499              :                                        FirstHVACIteration,
     500       391530 :                                        thisFurnace.CoolingCoilIndex,
     501              :                                        fanOp,
     502       391530 :                                        thisFurnace.CoolPartLoadRatio,
     503              :                                        OnOffAirFlowRatio);
     504              :                 }
     505       783060 :                 DXCoils::SimDXCoil(state,
     506              :                                    BlankString,
     507              :                                    compressorOp,
     508              :                                    FirstHVACIteration,
     509       391530 :                                    thisFurnace.HeatingCoilIndex,
     510              :                                    fanOp,
     511       391530 :                                    thisFurnace.HeatPartLoadRatio,
     512              :                                    OnOffAirFlowRatio);
     513       391530 :                 if (thisFurnace.fanPlace == HVAC::FanPlace::DrawThru) {
     514            0 :                     state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
     515              :                 }
     516              : 
     517              :                 // Simulate furnace reheat coil if a humidistat is present, the dehumidification type of coolreheat and
     518              :                 // reheat coil load exists
     519       391530 :                 if (thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat && ReheatCoilLoad > 0.0) {
     520         6194 :                     SuppHeatingCoilFlag = true; // if true simulates supplemental heating coil
     521         6194 :                     CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, ReheatCoilLoad, fanOp, QActual);
     522              :                 } else {
     523       385336 :                     SuppHeatingCoilFlag = true; // if true simulates supplemental heating coil
     524       385336 :                     CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, fanOp, QActual);
     525              :                 }
     526              :             }
     527       421792 :         } break;
     528              :         // Simulate water-to-air systems:
     529      2034588 :         case HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir: {
     530      2034588 :             if (thisFurnace.WatertoAirHPType == WAHPCoilType::Simple) {
     531              :                 // Update the furnace flow rates
     532              :                 //   When CompressorOp logic is added to the child cooling coil (COIL:WaterToAirHP:EquationFit:Cooling), then this logic
     533              :                 //   needs to be reinstated... to align with Unitary/Furnace HeatCool and Unitary Air-to-Air Heat Pump (see above).
     534      2114306 :                 if (!FirstHVACIteration && thisFurnace.fanOp == HVAC::FanOp::Cycling && state.dataFurnaces->CoolingLoad &&
     535       429030 :                     state.dataAirLoop->AirLoopControlInfo(AirLoopNum).EconoActive) {
     536              :                     // for cycling fan, cooling load, check whether furnace can meet load with compressor off
     537            0 :                     compressorOp = HVAC::CompressorOp::Off;
     538            0 :                     CalcNewZoneHeatCoolFlowRates(state,
     539              :                                                  FurnaceNum,
     540              :                                                  FirstHVACIteration,
     541              :                                                  compressorOp,
     542              :                                                  ZoneLoad,
     543              :                                                  MoistureLoad,
     544              :                                                  HeatCoilLoad,
     545              :                                                  ReheatCoilLoad,
     546              :                                                  OnOffAirFlowRatio,
     547              :                                                  HXUnitOn);
     548            0 :                     if (thisFurnace.CoolPartLoadRatio >= 1.0 || thisFurnace.HeatPartLoadRatio >= 1.0 ||
     549            0 :                         (thisFurnace.CoolPartLoadRatio <= 0.0 && thisFurnace.HeatPartLoadRatio <= 0.0)) {
     550              :                         // compressor on (reset inlet air mass flow rate to starting value)
     551            0 :                         compressorOp = HVAC::CompressorOp::On;
     552            0 :                         state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = FurnaceSavMdot;
     553            0 :                         CalcNewZoneHeatCoolFlowRates(state,
     554              :                                                      FurnaceNum,
     555              :                                                      FirstHVACIteration,
     556              :                                                      compressorOp,
     557              :                                                      ZoneLoad,
     558              :                                                      MoistureLoad,
     559              :                                                      HeatCoilLoad,
     560              :                                                      ReheatCoilLoad,
     561              :                                                      OnOffAirFlowRatio,
     562              :                                                      HXUnitOn);
     563              :                     }
     564              :                 } else {
     565              :                     // compressor on
     566      1685276 :                     CalcNewZoneHeatCoolFlowRates(state,
     567              :                                                  FurnaceNum,
     568              :                                                  FirstHVACIteration,
     569              :                                                  compressorOp,
     570              :                                                  ZoneLoad,
     571              :                                                  MoistureLoad,
     572              :                                                  HeatCoilLoad,
     573              :                                                  ReheatCoilLoad,
     574              :                                                  OnOffAirFlowRatio,
     575              :                                                  HXUnitOn);
     576              :                 }
     577      1685276 :                 if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
     578      1685276 :                     state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
     579              :                 }
     580              : 
     581      1685276 :                 WaterToAirHeatPumpSimple::SimWatertoAirHPSimple(state,
     582              :                                                                 BlankString,
     583      1685276 :                                                                 thisFurnace.CoolingCoilIndex,
     584              :                                                                 thisFurnace.CoolingCoilSensDemand,
     585              :                                                                 thisFurnace.CoolingCoilLatentDemand,
     586              :                                                                 thisFurnace.fanOp,
     587              :                                                                 compressorOp,
     588              :                                                                 thisFurnace.CoolPartLoadRatio,
     589              :                                                                 FirstHVACIteration);
     590      1685276 :                 WaterToAirHeatPumpSimple::SimWatertoAirHPSimple(state,
     591              :                                                                 BlankString,
     592      1685276 :                                                                 thisFurnace.HeatingCoilIndex,
     593              :                                                                 thisFurnace.HeatingCoilSensDemand,
     594              :                                                                 Dummy,
     595              :                                                                 thisFurnace.fanOp,
     596              :                                                                 compressorOp,
     597              :                                                                 thisFurnace.HeatPartLoadRatio,
     598              :                                                                 FirstHVACIteration);
     599              : 
     600      1685276 :                 if (thisFurnace.fanPlace == HVAC::FanPlace::DrawThru) {
     601            0 :                     state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
     602              :                 }
     603      1685276 :                 if (thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat && ReheatCoilLoad > 0.0) {
     604        15850 :                     SuppHeatingCoilFlag = true; // if true simulates supplemental heating coil
     605        15850 :                     CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, ReheatCoilLoad, fanOp, QActual);
     606              :                 } else {
     607      1669426 :                     SuppHeatingCoilFlag = true; // if true simulates supplemental heating coil
     608      1669426 :                     CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, fanOp, QActual);
     609              :                 }
     610       349312 :             } else if (thisFurnace.WatertoAirHPType == WAHPCoilType::ParEst) {
     611              : 
     612              :                 // simulate the heat pump
     613       119270 :                 HeatCoilLoad = 0.0;
     614       119270 :                 CalcWaterToAirHeatPump(state, FurnaceNum, FirstHVACIteration, compressorOp, ZoneLoad, MoistureLoad);
     615       230042 :             } else if (thisFurnace.WatertoAirHPType == WAHPCoilType::VarSpeedEquationFit) {
     616              :                 // simulate the heat pump
     617       230042 :                 HeatCoilLoad = 0.0;
     618       230042 :                 if (thisFurnace.bIsIHP) {
     619            0 :                     state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).ControlledZoneTemp =
     620            0 :                         state.dataLoopNodes->Node(thisFurnace.NodeNumOfControlledZone).Temp;
     621              :                 }
     622       230042 :                 SimVariableSpeedHP(state, FurnaceNum, FirstHVACIteration, AirLoopNum, ZoneLoad, MoistureLoad, OnOffAirFlowRatio);
     623              : 
     624            0 :             } else if (thisFurnace.WatertoAirHPType == WAHPCoilType::VarSpeedLookupTable) {
     625            0 :                 HeatCoilLoad = 0.0; // Added: Used below
     626              :             } else {
     627            0 :                 assert(false); //? If all possible states covered by if conditions change to HeatCoilLoad = 0.0;
     628              :             }
     629      2034588 :         } break;
     630            0 :         default: {
     631              :             // will never get here, all system types are simulated above
     632            0 :             assert(false);
     633              :         } break;
     634              :         }
     635              : 
     636              :         // set the econo lockout flags
     637      6219025 :         auto &airLoopControlInfo = state.dataAirLoop->AirLoopControlInfo(AirLoopNum);
     638      6219025 :         if (thisFurnace.CompPartLoadRatio > 0.0 && airLoopControlInfo.CanLockoutEconoWithCompressor) {
     639       278181 :             airLoopControlInfo.ReqstEconoLockoutWithCompressor = true;
     640              :         } else {
     641      5940844 :             airLoopControlInfo.ReqstEconoLockoutWithCompressor = false;
     642              :         }
     643              : 
     644      6219025 :         if ((HeatCoilLoad > 0.0 || thisFurnace.HeatPartLoadRatio > 0.0) &&
     645      1744246 :             (airLoopControlInfo.CanLockoutEconoWithCompressor || airLoopControlInfo.CanLockoutEconoWithHeating)) {
     646       905744 :             airLoopControlInfo.ReqstEconoLockoutWithHeating = true;
     647              :         } else {
     648      5313281 :             airLoopControlInfo.ReqstEconoLockoutWithHeating = false;
     649              :         }
     650              : 
     651      6219025 :         if (thisFurnace.fanOp == HVAC::FanOp::Cycling) {
     652      2858974 :             state.dataAirLoop->AirLoopFlow(AirLoopNum).FanPLR = thisFurnace.FanPartLoadRatio;
     653              :         } else {
     654      3360051 :             state.dataAirLoop->AirLoopFlow(AirLoopNum).FanPLR = 1.0; // 1 means constant fan does not cycle.
     655              :         }
     656              : 
     657              :         // Report the current Furnace output
     658      6219025 :         ReportFurnace(state, FurnaceNum, AirLoopNum);
     659              : 
     660              :         // Reset OnOffFanPartLoadFraction to 1 in case another on/off fan is called without a part-load curve
     661      6219025 :         state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
     662              : 
     663      6219025 :         state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRateMaxAvail = TempMassFlowRateMaxAvail;
     664      6219025 :     }
     665              : 
     666              :     // Get Input Section of the Module
     667              :     //******************************************************************************
     668              : 
     669           97 :     void GetFurnaceInput(EnergyPlusData &state)
     670              :     {
     671              : 
     672              :         // SUBROUTINE INFORMATION:
     673              :         //       AUTHOR         Richard Liesen
     674              :         //       DATE WRITTEN   Feb 2001
     675              :         //       MODIFIED       Don Shirey and Rich Raustad, Mar/Oct 2001, Mar 2003
     676              :         //                      Bereket Nigusse, April 2010 - deprecated supply air flow fraction through
     677              :         //                      controlled zone from the input field.
     678              :         //                      Bo Shen, March 2012, add inputs for VS WSHP,
     679              :         //                      Bo Shen, ORNL, July 2012 - added variable-speed air source heat pump cooling and heating coils, using curve-fits
     680              : 
     681              :         // PURPOSE OF THIS SUBROUTINE:
     682              :         // Obtains input data for fans and coils and stores it in the Furnace data structures
     683              : 
     684              :         // METHODOLOGY EMPLOYED:
     685              :         // Uses "Get" routines to read in data.
     686              : 
     687              :         // SUBROUTINE PARAMETER DEFINITIONS:
     688           97 :         std::string_view constexpr getUnitaryHeatOnly("GetUnitaryHeatOnly");
     689           97 :         std::string_view constexpr getAirLoopHVACHeatCoolInput("GetAirLoopHVACHeatCoolInput");
     690           97 :         std::string_view constexpr routineName = "GetFurnaceInput";
     691              : 
     692              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     693              :         int FurnaceNum;                // The Furnace that you are currently loading input into
     694              :         int GetObjectNum;              // The index to each specific object name
     695              :         int NumFields;                 // Total number of fields in object
     696              :         int NumAlphas;                 // Total number of alpha fields in object
     697              :         int NumNumbers;                // Total number of numeric fields in object
     698              :         int IOStatus;                  // Function call status
     699           97 :         Array1D<Real64> Numbers;       // Numeric data
     700           97 :         Array1D_string Alphas;         // Alpha data
     701           97 :         Array1D_string cAlphaFields;   // Alpha field names
     702           97 :         Array1D_string cNumericFields; // Numeric field names
     703           97 :         Array1D_bool lAlphaBlanks;     // Logical array, alpha field input BLANK = .TRUE.
     704           97 :         Array1D_bool lNumericBlanks;   // Logical array, numeric field input BLANK = .TRUE.
     705           97 :         std::string CompSetFanInlet;
     706           97 :         std::string CompSetFanOutlet;
     707           97 :         std::string CompSetCoolInlet;
     708           97 :         std::string CompSetHeatInlet;
     709           97 :         std::string CompSetHeatOutlet;
     710           97 :         bool ErrorsFound(false);       // If errors detected in input
     711              :         bool IsNotOK;                  // Flag to verify name
     712              :         bool AirNodeFound;             // Used to determine if control zone is valid
     713              :         bool AirLoopFound;             // Used to determine if control zone is served by furnace air loop
     714              :         int TstatZoneNum;              // Used to determine if control zone has a thermostat object
     715              :         int HStatZoneNum;              // Used to determine if control zone has a humidistat object
     716              :         bool errFlag;                  // Mining function error flag
     717              :         int FanInletNode;              // Used for node checking warning messages
     718              :         int FanOutletNode;             // Used for node checking warning messages
     719              :         int CoolingCoilInletNode;      // Used for node checking warning messages
     720              :         int CoolingCoilOutletNode;     // Used for node checking warning messages
     721              :         int HeatingCoilInletNode;      // Used for node checking warning messages
     722              :         int HeatingCoilOutletNode;     // Used for node checking warning messages
     723              :         int SupHeatCoilInletNode;      // Used for node checking warning messages
     724              :         int SupHeatCoilOutletNode;     // Used for node checking warning messages
     725           97 :         std::string CoolingCoilType;   // Used in mining function CALLS
     726           97 :         std::string CoolingCoilName;   // Used in mining function CALLS
     727           97 :         std::string HeatingCoilType;   // Used in mining function CALLS
     728           97 :         std::string HeatingCoilName;   // Used in mining function CALLS
     729           97 :         std::string ReheatingCoilType; // Used in mining function CALLS
     730           97 :         std::string ReheatingCoilName; // Used in mining function CALLS
     731           97 :         std::string SuppHeatCoilType;  // Used in mining function CALLS
     732           97 :         std::string SuppHeatCoilName;  // Used in mining function CALLS
     733           97 :         std::string FanName;           // Used in mining function CALLS
     734              :         bool PrintMessage;             // Used in mining function CALLS
     735              :         int HeatingCoilPLFCurveIndex;  // index of heating coil PLF curve
     736              :         Real64 SteamDensity;           // density of steam at 100C
     737              :         int DXCoilIndex;               // Index to DX coil in HXAssited object
     738           97 :         std::string IHPCoilName;       // IHP cooling coil name
     739           97 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
     740              :         DataLoopNode::ConnectionObjectType currentModuleObjectType;
     741              : 
     742           97 :         state.dataFurnaces->GetFurnaceInputFlag = false;
     743           97 :         int MaxNumbers = 0;
     744           97 :         int MaxAlphas = 0;
     745              : 
     746           97 :         std::string_view CurrentModuleObject = "AirLoopHVAC:Unitary:Furnace:HeatOnly";
     747           97 :         int NumHeatOnly = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
     748           97 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NumFields, NumAlphas, NumNumbers);
     749           97 :         MaxNumbers = max(MaxNumbers, NumNumbers);
     750           97 :         MaxAlphas = max(MaxAlphas, NumAlphas);
     751              : 
     752           97 :         CurrentModuleObject = "AirLoopHVAC:Unitary:Furnace:HeatCool";
     753           97 :         int NumHeatCool = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
     754           97 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NumFields, NumAlphas, NumNumbers);
     755           97 :         MaxNumbers = max(MaxNumbers, NumNumbers);
     756           97 :         MaxAlphas = max(MaxAlphas, NumAlphas);
     757              : 
     758           97 :         CurrentModuleObject = "AirLoopHVAC:UnitaryHeatOnly";
     759           97 :         int NumUnitaryHeatOnly = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
     760           97 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NumFields, NumAlphas, NumNumbers);
     761           97 :         MaxNumbers = max(MaxNumbers, NumNumbers);
     762           97 :         MaxAlphas = max(MaxAlphas, NumAlphas);
     763              : 
     764           97 :         CurrentModuleObject = "AirLoopHVAC:UnitaryHeatCool";
     765           97 :         int NumUnitaryHeatCool = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
     766           97 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NumFields, NumAlphas, NumNumbers);
     767           97 :         MaxNumbers = max(MaxNumbers, NumNumbers);
     768           97 :         MaxAlphas = max(MaxAlphas, NumAlphas);
     769              : 
     770           97 :         CurrentModuleObject = "AirLoopHVAC:UnitaryHeatPump:AirToAir";
     771           97 :         int NumHeatPump = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
     772           97 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NumFields, NumAlphas, NumNumbers);
     773           97 :         MaxNumbers = max(MaxNumbers, NumNumbers);
     774           97 :         MaxAlphas = max(MaxAlphas, NumAlphas);
     775              : 
     776           97 :         CurrentModuleObject = "AirLoopHVAC:UnitaryHeatPump:WaterToAir";
     777           97 :         int NumWaterToAirHeatPump = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
     778           97 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NumFields, NumAlphas, NumNumbers);
     779           97 :         MaxNumbers = max(MaxNumbers, NumNumbers);
     780           97 :         MaxAlphas = max(MaxAlphas, NumAlphas);
     781              : 
     782           97 :         Alphas.allocate(MaxAlphas);
     783           97 :         Numbers.dimension(MaxNumbers, 0.0);
     784           97 :         cAlphaFields.allocate(MaxAlphas);
     785           97 :         cNumericFields.allocate(MaxNumbers);
     786           97 :         lAlphaBlanks.dimension(MaxAlphas, true);
     787           97 :         lNumericBlanks.dimension(MaxNumbers, true);
     788              : 
     789           97 :         state.dataFurnaces->NumFurnaces = NumHeatOnly + NumHeatCool + NumUnitaryHeatOnly + NumUnitaryHeatCool + NumHeatPump + NumWaterToAirHeatPump;
     790              : 
     791           97 :         if (state.dataFurnaces->NumFurnaces > 0) {
     792           97 :             state.dataFurnaces->Furnace.allocate(state.dataFurnaces->NumFurnaces);
     793           97 :             state.dataFurnaces->UniqueFurnaceNames.reserve(state.dataFurnaces->NumFurnaces);
     794              :         }
     795           97 :         state.dataFurnaces->CheckEquipName.dimension(state.dataFurnaces->NumFurnaces, true);
     796              : 
     797           97 :         int IHPCoilIndex = 0;
     798              : 
     799              :         // Get the data for the HeatOnly Furnace
     800          101 :         for (int HeatOnlyNum = 1; HeatOnlyNum <= NumHeatOnly + NumUnitaryHeatOnly; ++HeatOnlyNum) {
     801              : 
     802            4 :             FanInletNode = 0;
     803            4 :             FanOutletNode = 0;
     804            4 :             HeatingCoilInletNode = 0;
     805            4 :             HeatingCoilOutletNode = 0;
     806            4 :             CoolingCoilType = ' ';
     807            4 :             CoolingCoilName = ' ';
     808            4 :             HeatingCoilType = ' ';
     809            4 :             HeatingCoilName = ' ';
     810              : 
     811            4 :             FurnaceNum = HeatOnlyNum;
     812            4 :             auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
     813              : 
     814              :             //       Furnace and UnitarySystem objects are both read in here.
     815              :             //       Will still have 2 differently named objects for the user, but read in with 1 DO loop.
     816            4 :             if (HeatOnlyNum <= NumHeatOnly) {
     817            3 :                 CurrentModuleObject = "AirLoopHVAC:Unitary:Furnace:HeatOnly";
     818            3 :                 currentModuleObjectType = DataLoopNode::ConnectionObjectType::AirLoopHVACUnitaryFurnaceHeatOnly;
     819            3 :                 thisFurnace.type = HVAC::UnitarySysType::Furnace_HeatOnly;
     820            3 :                 GetObjectNum = HeatOnlyNum;
     821              :             } else {
     822            1 :                 CurrentModuleObject = "AirLoopHVAC:UnitaryHeatOnly";
     823            1 :                 currentModuleObjectType = DataLoopNode::ConnectionObjectType::AirLoopHVACUnitaryHeatOnly;
     824            1 :                 thisFurnace.type = HVAC::UnitarySysType::Unitary_HeatOnly;
     825            1 :                 GetObjectNum = HeatOnlyNum - NumHeatOnly;
     826              :             }
     827              : 
     828            4 :             thisFurnace.iterationMode.allocate(3);
     829              : 
     830            4 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     831              :                                                                      CurrentModuleObject,
     832              :                                                                      GetObjectNum,
     833              :                                                                      Alphas,
     834              :                                                                      NumAlphas,
     835              :                                                                      Numbers,
     836              :                                                                      NumNumbers,
     837              :                                                                      IOStatus,
     838              :                                                                      lNumericBlanks,
     839              :                                                                      lAlphaBlanks,
     840              :                                                                      cAlphaFields,
     841              :                                                                      cNumericFields);
     842              : 
     843            8 :             GlobalNames::VerifyUniqueInterObjectName(
     844            4 :                 state, state.dataFurnaces->UniqueFurnaceNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
     845              : 
     846            4 :             thisFurnace.Name = Alphas(1);
     847            4 :             ErrorObjectHeader eoh{routineName, cAlphaFields(1), thisFurnace.Name};
     848              : 
     849            4 :             if (lAlphaBlanks(2)) {
     850            0 :                 thisFurnace.availSched = Sched::GetScheduleAlwaysOn(state);
     851            4 :             } else if ((thisFurnace.availSched = Sched::GetSchedule(state, Alphas(2))) == nullptr) {
     852            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(2), Alphas(2));
     853            0 :                 ErrorsFound = true;
     854              :             }
     855              : 
     856            4 :             thisFurnace.FurnaceInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
     857            4 :                                                                                   Alphas(3),
     858              :                                                                                   ErrorsFound,
     859              :                                                                                   currentModuleObjectType,
     860            4 :                                                                                   Alphas(1),
     861              :                                                                                   DataLoopNode::NodeFluidType::Air,
     862              :                                                                                   DataLoopNode::ConnectionType::Inlet,
     863              :                                                                                   NodeInputManager::CompFluidStream::Primary,
     864              :                                                                                   DataLoopNode::ObjectIsParent);
     865            8 :             thisFurnace.FurnaceOutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
     866            4 :                                                                                    Alphas(4),
     867              :                                                                                    ErrorsFound,
     868              :                                                                                    currentModuleObjectType,
     869            4 :                                                                                    Alphas(1),
     870              :                                                                                    DataLoopNode::NodeFluidType::Air,
     871              :                                                                                    DataLoopNode::ConnectionType::Outlet,
     872              :                                                                                    NodeInputManager::CompFluidStream::Primary,
     873              :                                                                                    DataLoopNode::ObjectIsParent);
     874              : 
     875            4 :             BranchNodeConnections::TestCompSet(state, CurrentModuleObject, Alphas(1), Alphas(3), Alphas(4), "Air Nodes");
     876              : 
     877            4 :             if (lAlphaBlanks(5)) {
     878            0 :                 thisFurnace.fanOp = HVAC::FanOp::Cycling;
     879            4 :             } else if ((thisFurnace.fanOpModeSched = Sched::GetSchedule(state, Alphas(5))) == nullptr) {
     880            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(5), Alphas(5));
     881            0 :                 ErrorsFound = true;
     882              :             }
     883              : 
     884              :             // Get the Controlling Zone or Location of the Furnace Thermostat
     885              : 
     886            4 :             thisFurnace.ControlZoneNum = Util::FindItemInList(Alphas(6), state.dataHeatBal->Zone);
     887            4 :             if (thisFurnace.ControlZoneNum == 0) {
     888            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
     889            0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(6), Alphas(6)));
     890            0 :                 ErrorsFound = true;
     891              :             }
     892              : 
     893              :             // Get the node number for the zone with the thermostat
     894            4 :             if (thisFurnace.ControlZoneNum > 0) {
     895            4 :                 AirNodeFound = false;
     896            4 :                 AirLoopFound = false;
     897            4 :                 int ControlledZoneNum = thisFurnace.ControlZoneNum;
     898              :                 //             Find the controlled zone number for the specified thermostat location
     899            4 :                 thisFurnace.NodeNumOfControlledZone = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).ZoneNode;
     900              :                 //             Determine if furnace is on air loop served by the thermostat location specified
     901            4 :                 for (int zoneInNode = 1; zoneInNode <= state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).NumInletNodes; ++zoneInNode) {
     902            4 :                     int AirLoopNumber = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).InletNodeAirLoopNum(zoneInNode);
     903            4 :                     if (AirLoopNumber > 0) {
     904            4 :                         for (int BranchNum = 1; BranchNum <= state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).NumBranches; ++BranchNum) {
     905            4 :                             for (int CompNum = 1;
     906            4 :                                  CompNum <= state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).Branch(BranchNum).TotalComponents;
     907              :                                  ++CompNum) {
     908            4 :                                 if (!Util::SameString(state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).Branch(BranchNum).Comp(CompNum).Name,
     909            8 :                                                       thisFurnace.Name) ||
     910            4 :                                     !Util::SameString(
     911            4 :                                         state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).Branch(BranchNum).Comp(CompNum).TypeOf,
     912              :                                         CurrentModuleObject)) {
     913            0 :                                     continue;
     914              :                                 }
     915            4 :                                 AirLoopFound = true;
     916            4 :                                 thisFurnace.ZoneInletNode = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).InletNode(zoneInNode);
     917            4 :                                 break;
     918              :                             }
     919            4 :                             if (AirLoopFound) {
     920            4 :                                 break;
     921              :                             }
     922              :                         }
     923           10 :                         for (TstatZoneNum = 1; TstatZoneNum <= state.dataZoneCtrls->NumTempControlledZones; ++TstatZoneNum) {
     924            6 :                             if (state.dataZoneCtrls->TempControlledZone(TstatZoneNum).ActualZoneNum != thisFurnace.ControlZoneNum) {
     925            2 :                                 continue;
     926              :                             }
     927            4 :                             AirNodeFound = true;
     928              :                         }
     929            4 :                         for (TstatZoneNum = 1; TstatZoneNum <= state.dataZoneCtrls->NumComfortControlledZones; ++TstatZoneNum) {
     930            0 :                             if (state.dataZoneCtrls->ComfortControlledZone(TstatZoneNum).ActualZoneNum != thisFurnace.ControlZoneNum) {
     931            0 :                                 continue;
     932              :                             }
     933            0 :                             AirNodeFound = true;
     934              :                         }
     935              :                     }
     936            4 :                     if (AirLoopFound) {
     937            4 :                         break;
     938              :                     }
     939              :                 }
     940            4 :                 if (!AirNodeFound) {
     941            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
     942            0 :                     ShowContinueError(state, "Did not find Air Node (Zone with Thermostat).");
     943            0 :                     ShowContinueError(state, format("Specified {} = {}", cAlphaFields(6), Alphas(6)));
     944            0 :                     ShowContinueError(
     945              :                         state, "Both a ZoneHVAC:EquipmentConnections object and a ZoneControl:Thermostat object must be specified for this zone.");
     946            0 :                     ErrorsFound = true;
     947              :                 }
     948            4 :                 if (!AirLoopFound) {
     949            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
     950            0 :                     ShowContinueError(state, "Did not find correct Primary Air Loop.");
     951            0 :                     ShowContinueError(state, format("Specified {} = {} is not served by this AirLoopHVAC equipment.", cAlphaFields(6), Alphas(6)));
     952            0 :                     ErrorsFound = true;
     953              :                 }
     954              :             }
     955              : 
     956              :             // Get fan data
     957            4 :             FanName = Alphas(8);
     958            4 :             errFlag = false;
     959              : 
     960            4 :             thisFurnace.fanType = static_cast<HVAC::FanType>(getEnumValue(HVAC::fanTypeNamesUC, Alphas(7)));
     961            4 :             if (thisFurnace.fanType != HVAC::FanType::OnOff && thisFurnace.fanType != HVAC::FanType::Constant) {
     962            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
     963            0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(7), Alphas(7)));
     964            0 :                 ErrorsFound = true;
     965              : 
     966            4 :             } else if ((thisFurnace.FanIndex = Fans::GetFanIndex(state, FanName)) == 0) {
     967            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(8), FanName);
     968            0 :                 ErrorsFound = true;
     969              : 
     970              :             } else {
     971            4 :                 auto *fan = state.dataFans->fans(thisFurnace.FanIndex);
     972            4 :                 thisFurnace.ActualFanVolFlowRate = fan->maxAirFlowRate;
     973            4 :                 FanInletNode = fan->inletNodeNum;
     974            4 :                 FanOutletNode = fan->outletNodeNum;
     975            4 :                 thisFurnace.fanAvailSched = fan->availSched;
     976              : 
     977              :                 // Check fan's schedule for cycling fan operation if constant volume fan is used
     978            4 :                 if (thisFurnace.fanOpModeSched != nullptr && thisFurnace.fanType == HVAC::FanType::Constant) {
     979            0 :                     if (!thisFurnace.fanOpModeSched->checkMinMaxVals(state, Clusive::Ex, 0.0, Clusive::In, 1.0)) {
     980            0 :                         Sched::ShowSevereBadMinMax(
     981              :                             state,
     982              :                             eoh,
     983            0 :                             cAlphaFields(5),
     984            0 :                             Alphas(5),
     985              :                             Clusive::Ex,
     986              :                             0.0,
     987              :                             Clusive::In,
     988              :                             1.0,
     989            0 :                             format("For {} = {}, Fan operating mode must be continuous (schedule values > 0)", cAlphaFields(7), Alphas(7)));
     990            0 :                         ErrorsFound = true;
     991              :                     }
     992            4 :                 } else if (lAlphaBlanks(5) && thisFurnace.fanType != HVAC::FanType::OnOff) {
     993            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, thisFurnace.Name));
     994            0 :                     ShowContinueError(state, format("{} = {}", cAlphaFields(7), Alphas(7)));
     995            0 :                     ShowContinueError(state, format("Fan type must be Fan:OnOff when {} = Blank.", cAlphaFields(5)));
     996            0 :                     ErrorsFound = true;
     997              :                 }
     998              :             }
     999              : 
    1000            4 :             thisFurnace.fanPlace = static_cast<HVAC::FanPlace>(getEnumValue(HVAC::fanPlaceNamesUC, Alphas(9)));
    1001            4 :             assert(thisFurnace.fanPlace != HVAC::FanPlace::Invalid);
    1002              : 
    1003              :             // Get coil data
    1004            4 :             HeatingCoilType = Alphas(10);
    1005            4 :             HeatingCoilName = Alphas(11);
    1006            4 :             thisFurnace.HeatingCoilType = HeatingCoilType;
    1007            4 :             thisFurnace.HeatingCoilName = HeatingCoilName;
    1008            4 :             if (Util::SameString(HeatingCoilType, "Coil:Heating:Fuel") || Util::SameString(HeatingCoilType, "Coil:Heating:Electric")) {
    1009            4 :                 errFlag = false;
    1010            4 :                 thisFurnace.HeatingCoilType_Num = HeatingCoils::GetHeatingCoilTypeNum(state, HeatingCoilType, HeatingCoilName, errFlag);
    1011            4 :                 if (errFlag) {
    1012            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1013            0 :                     ErrorsFound = true;
    1014              :                 } else {
    1015            4 :                     ValidateComponent(state, HeatingCoilType, HeatingCoilName, IsNotOK, CurrentModuleObject);
    1016            4 :                     if (IsNotOK) {
    1017            0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1018            0 :                         ErrorsFound = true;
    1019              : 
    1020              :                     } else { // mine data from heating coil object
    1021              : 
    1022              :                         // Get index to Heating Coil
    1023            4 :                         errFlag = false;
    1024            4 :                         HeatingCoils::GetCoilIndex(state, HeatingCoilName, thisFurnace.HeatingCoilIndex, errFlag);
    1025            4 :                         if (errFlag) {
    1026            0 :                             ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1027            0 :                             ErrorsFound = true;
    1028              :                         }
    1029              : 
    1030              :                         // Get the furnace design capacity
    1031            4 :                         errFlag = false;
    1032            4 :                         thisFurnace.DesignHeatingCapacity = HeatingCoils::GetCoilCapacity(state, HeatingCoilType, HeatingCoilName, errFlag);
    1033            4 :                         if (errFlag) {
    1034            0 :                             ShowContinueError(state, format("...occurs in {} ={}", CurrentModuleObject, Alphas(1)));
    1035            0 :                             ErrorsFound = true;
    1036              :                         }
    1037              : 
    1038              :                         // Get the Heating Coil Inlet Node
    1039            4 :                         errFlag = false;
    1040            4 :                         HeatingCoilInletNode = HeatingCoils::GetCoilInletNode(state, HeatingCoilType, HeatingCoilName, errFlag);
    1041            4 :                         thisFurnace.HWCoilAirInletNode = HeatingCoilInletNode;
    1042            4 :                         if (errFlag) {
    1043            0 :                             ShowContinueError(state, format("...occurs in {} ={}", CurrentModuleObject, Alphas(1)));
    1044            0 :                             ErrorsFound = true;
    1045              :                         }
    1046              : 
    1047              :                         // Get the Heating Coil Outlet Node
    1048            4 :                         errFlag = false;
    1049            4 :                         HeatingCoilOutletNode = HeatingCoils::GetCoilOutletNode(state, HeatingCoilType, HeatingCoilName, errFlag);
    1050            4 :                         if (errFlag) {
    1051            0 :                             ShowContinueError(state, format("...occurs in {} ={}", CurrentModuleObject, Alphas(1)));
    1052            0 :                             ErrorsFound = true;
    1053              :                         }
    1054              : 
    1055              :                     } // IF (IsNotOK) THEN
    1056              :                 }
    1057              : 
    1058            0 :             } else if (Util::SameString(HeatingCoilType, "Coil:Heating:Water")) {
    1059            0 :                 thisFurnace.HeatingCoilType_Num = HVAC::Coil_HeatingWater;
    1060            0 :                 ValidateComponent(state, HeatingCoilType, HeatingCoilName, IsNotOK, CurrentModuleObject);
    1061            0 :                 if (IsNotOK) {
    1062            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1063            0 :                     ErrorsFound = true;
    1064              :                 } else { // mine data from heating coil object
    1065              : 
    1066              :                     // Get the Heating Coil water Inlet or control Node number
    1067            0 :                     errFlag = false;
    1068            0 :                     thisFurnace.CoilControlNode = WaterCoils::GetCoilWaterInletNode(state, "Coil:Heating:Water", HeatingCoilName, errFlag);
    1069            0 :                     if (errFlag) {
    1070            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1071            0 :                         ErrorsFound = true;
    1072              :                     }
    1073              : 
    1074              :                     // Get the Heating Coil hot water max volume flow rate
    1075            0 :                     errFlag = false;
    1076            0 :                     thisFurnace.MaxHeatCoilFluidFlow = WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", HeatingCoilName, errFlag);
    1077            0 :                     if (errFlag) {
    1078            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1079            0 :                         ErrorsFound = true;
    1080              :                     }
    1081              : 
    1082              :                     // Get the Heating Coil Inlet Node
    1083            0 :                     errFlag = false;
    1084            0 :                     HeatingCoilInletNode = WaterCoils::GetCoilInletNode(state, "Coil:Heating:Water", HeatingCoilName, errFlag);
    1085            0 :                     thisFurnace.HWCoilAirInletNode = HeatingCoilInletNode;
    1086            0 :                     if (errFlag) {
    1087            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1088            0 :                         ErrorsFound = true;
    1089              :                     }
    1090              : 
    1091              :                     // Get the Heating Coil Outlet Node
    1092            0 :                     errFlag = false;
    1093            0 :                     HeatingCoilOutletNode = WaterCoils::GetCoilOutletNode(state, "Coil:Heating:Water", HeatingCoilName, errFlag);
    1094            0 :                     thisFurnace.HWCoilAirOutletNode = HeatingCoilOutletNode;
    1095            0 :                     if (errFlag) {
    1096            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1097            0 :                         ErrorsFound = true;
    1098              :                     }
    1099              : 
    1100              :                     // check if user has also used a water coil controller, which they should not do
    1101            0 :                     errFlag = false;
    1102            0 :                     HVACControllers::CheckCoilWaterInletNode(state, thisFurnace.CoilControlNode, errFlag);
    1103            0 :                     if (!errFlag) { // then did find a controller so that is bad
    1104            0 :                         ShowSevereError(state,
    1105            0 :                                         format("{} = {} has a conflicting Controller:WaterCoil object", CurrentModuleObject, thisFurnace.Name));
    1106            0 :                         ShowContinueError(state, "Hot water coils are controlled directly by unitary and furnace systems.");
    1107            0 :                         ShowContinueError(state, "No water coil controller should be input for the coil.");
    1108            0 :                         ErrorsFound = true;
    1109              :                     }
    1110              :                 }
    1111              : 
    1112            0 :             } else if (Util::SameString(HeatingCoilType, "Coil:Heating:Steam")) {
    1113            0 :                 thisFurnace.HeatingCoilType_Num = HVAC::Coil_HeatingSteam;
    1114            0 :                 ValidateComponent(state, HeatingCoilType, HeatingCoilName, IsNotOK, CurrentModuleObject);
    1115            0 :                 if (IsNotOK) {
    1116            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1117            0 :                     ErrorsFound = true;
    1118              :                 } else { // mine data from heating coil object
    1119              : 
    1120            0 :                     errFlag = false;
    1121            0 :                     thisFurnace.HeatingCoilIndex = SteamCoils::GetSteamCoilIndex(state, "COIL:HEATING:STEAM", HeatingCoilName, errFlag);
    1122            0 :                     if (thisFurnace.HeatingCoilIndex == 0) {
    1123            0 :                         ShowSevereError(state, format("{} illegal {} = {}", CurrentModuleObject, cAlphaFields(11), HeatingCoilName));
    1124            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1125            0 :                         ErrorsFound = true;
    1126              :                     }
    1127              : 
    1128              :                     // Get the Heating Coil steam inlet node number
    1129            0 :                     errFlag = false;
    1130            0 :                     thisFurnace.CoilControlNode = SteamCoils::GetCoilSteamInletNode(state, "COIL:HEATING:STEAM", HeatingCoilName, errFlag);
    1131            0 :                     if (errFlag) {
    1132            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1133            0 :                         ErrorsFound = true;
    1134              :                     }
    1135              : 
    1136              :                     // Get the Heating Coil steam max volume flow rate
    1137            0 :                     thisFurnace.MaxHeatCoilFluidFlow = SteamCoils::GetCoilMaxSteamFlowRate(state, thisFurnace.HeatingCoilIndex, errFlag);
    1138            0 :                     if (thisFurnace.MaxHeatCoilFluidFlow > 0.0) {
    1139            0 :                         SteamDensity = Fluid::GetSteam(state)->getSatDensity(state, state.dataFurnaces->TempSteamIn, 1.0, getUnitaryHeatOnly);
    1140            0 :                         thisFurnace.MaxHeatCoilFluidFlow *= SteamDensity;
    1141              :                     }
    1142              : 
    1143              :                     // Get the Heating Coil Inlet Node
    1144            0 :                     errFlag = false;
    1145            0 :                     HeatingCoilInletNode = SteamCoils::GetCoilAirInletNode(state, thisFurnace.HeatingCoilIndex, HeatingCoilName, errFlag);
    1146            0 :                     thisFurnace.HWCoilAirInletNode = HeatingCoilInletNode;
    1147            0 :                     if (errFlag) {
    1148            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1149            0 :                         ErrorsFound = true;
    1150              :                     }
    1151              : 
    1152              :                     // Get the Heating Coil Outlet Node
    1153            0 :                     errFlag = false;
    1154            0 :                     HeatingCoilOutletNode = SteamCoils::GetCoilAirOutletNode(state, thisFurnace.HeatingCoilIndex, HeatingCoilName, errFlag);
    1155            0 :                     thisFurnace.HWCoilAirOutletNode = HeatingCoilOutletNode;
    1156            0 :                     if (errFlag) {
    1157            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1158            0 :                         ErrorsFound = true;
    1159              :                     }
    1160              :                 }
    1161              : 
    1162              :             } else {
    1163            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1164            0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(11), Alphas(11)));
    1165            0 :                 ErrorsFound = true;
    1166              :             } // IF (Furnace(FurnaceNum)%HeatingCoilType_Num == Coil_HeatingGasOrOtherFuel .OR. &, etc.
    1167              : 
    1168              :             // Add component sets array
    1169            4 :             if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
    1170            4 :                 CompSetFanInlet = Alphas(3);
    1171            4 :                 CompSetFanOutlet = state.dataLoopNodes->NodeID(FanOutletNode);
    1172            4 :                 CompSetHeatInlet = state.dataLoopNodes->NodeID(FanOutletNode);
    1173            4 :                 CompSetHeatOutlet = Alphas(4);
    1174              :                 // Fan inlet node name must not be the same as the furnace inlet node name
    1175            4 :                 if (FanInletNode != thisFurnace.FurnaceInletNodeNum) {
    1176            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1177            0 :                     if (thisFurnace.type == HVAC::UnitarySysType::Furnace_HeatOnly) {
    1178            0 :                         ShowContinueError(
    1179              :                             state, "When a blow through fan is specified, the fan inlet node name must be the same as the furnace inlet node name.");
    1180            0 :                         ShowContinueError(state, format("...Fan inlet node name     = {}", state.dataLoopNodes->NodeID(FanInletNode)));
    1181            0 :                         ShowContinueError(state,
    1182            0 :                                           format("...Furnace inlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceInletNodeNum)));
    1183              :                     } else {
    1184            0 :                         ShowContinueError(
    1185              :                             state,
    1186              :                             "When a blow through fan is specified, the fan inlet node name must be the same as the unitary system inlet node name.");
    1187            0 :                         ShowContinueError(state, format("...Fan inlet node name            = {}", state.dataLoopNodes->NodeID(FanInletNode)));
    1188            0 :                         ShowContinueError(
    1189            0 :                             state, format("...Unitary System inlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceInletNodeNum)));
    1190              :                     }
    1191            0 :                     ErrorsFound = true;
    1192              :                 }
    1193              :                 // Fan outlet node name must be the same as the heating coil inlet node name
    1194            4 :                 if (FanOutletNode != HeatingCoilInletNode) {
    1195            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1196            0 :                     ShowContinueError(
    1197              :                         state,
    1198              :                         "When a blow through fan is specified, the fan outlet node name must be the same as the heating coil inlet node name.");
    1199            0 :                     ShowContinueError(state, format("...Fan outlet node name         = {}", state.dataLoopNodes->NodeID(FanOutletNode)));
    1200            0 :                     ShowContinueError(state, format("...Heating coil inlet node name = {}", state.dataLoopNodes->NodeID(HeatingCoilInletNode)));
    1201            0 :                     ErrorsFound = true;
    1202              :                 }
    1203              :                 // Heating coil outlet node name must be the same as the furnace outlet node name
    1204            4 :                 if (HeatingCoilOutletNode != thisFurnace.FurnaceOutletNodeNum) {
    1205            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1206            0 :                     if (thisFurnace.type == HVAC::UnitarySysType::Furnace_HeatOnly) {
    1207            0 :                         ShowContinueError(state,
    1208              :                                           "When a blow through fan is specified, the heating coil outlet node name must be the same as the furnace "
    1209              :                                           "outlet node name.");
    1210            0 :                         ShowContinueError(state, format("...Heating coil outlet node name = {}", state.dataLoopNodes->NodeID(HeatingCoilOutletNode)));
    1211            0 :                         ShowContinueError(
    1212            0 :                             state, format("...Furnace outlet node name      = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    1213              :                     } else {
    1214            0 :                         ShowContinueError(state,
    1215              :                                           "When a blow through fan is specified, the heating coil outlet node name must be the same as the unitary "
    1216              :                                           "system outlet node name.");
    1217            0 :                         ShowContinueError(state,
    1218            0 :                                           format("...Heating coil outlet node name  = {}", state.dataLoopNodes->NodeID(HeatingCoilOutletNode)));
    1219            0 :                         ShowContinueError(
    1220            0 :                             state, format("...UnitarySystem outlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    1221              :                     }
    1222            0 :                     ErrorsFound = true;
    1223              :                 }
    1224              :             } else { // draw through fan
    1225            0 :                 CompSetHeatInlet = Alphas(3);
    1226            0 :                 CompSetHeatOutlet = state.dataLoopNodes->NodeID(FanInletNode);
    1227            0 :                 CompSetFanInlet = state.dataLoopNodes->NodeID(FanInletNode);
    1228            0 :                 CompSetFanOutlet = Alphas(4);
    1229              :                 // Heating coil inlet node name must not be the same as the furnace inlet node name
    1230            0 :                 if (HeatingCoilInletNode != thisFurnace.FurnaceInletNodeNum) {
    1231            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1232            0 :                     if (thisFurnace.type == HVAC::UnitarySysType::Furnace_HeatOnly) {
    1233            0 :                         ShowContinueError(state,
    1234              :                                           "When a draw through fan is specified, the heating coil inlet node name must be the same as the furnace "
    1235              :                                           "inlet node name.");
    1236            0 :                         ShowContinueError(state, format("...Heating coil inlet node name = {}", state.dataLoopNodes->NodeID(HeatingCoilInletNode)));
    1237            0 :                         ShowContinueError(
    1238            0 :                             state, format("...Furnace inlet node name      = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceInletNodeNum)));
    1239              :                     } else {
    1240            0 :                         ShowContinueError(state,
    1241              :                                           "When a draw through fan is specified, the heating coil inlet node name must be the same as the unitary "
    1242              :                                           "system inlet node name.");
    1243            0 :                         ShowContinueError(state, format("...Heating coil inlet node name  = {}", state.dataLoopNodes->NodeID(HeatingCoilInletNode)));
    1244            0 :                         ShowContinueError(
    1245            0 :                             state, format("...UnitarySystem inlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceInletNodeNum)));
    1246              :                     }
    1247            0 :                     ErrorsFound = true;
    1248              :                 }
    1249              :                 // Heating coil outlet node name must be the same as the fan inlet node name
    1250            0 :                 if (HeatingCoilOutletNode != FanInletNode) {
    1251            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1252            0 :                     ShowContinueError(
    1253              :                         state,
    1254              :                         "When a draw through fan is specified, the heating coil outlet node name must be the same as the fan inlet node name.");
    1255            0 :                     ShowContinueError(state, format("...Heating coil outlet node name = {}", state.dataLoopNodes->NodeID(HeatingCoilOutletNode)));
    1256            0 :                     ShowContinueError(state, format("...Fan inlet node name           = {}", state.dataLoopNodes->NodeID(FanInletNode)));
    1257            0 :                     ErrorsFound = true;
    1258              :                 }
    1259              :                 // Fan coil outlet node name must be the same as the furnace outlet node name
    1260            0 :                 if (FanOutletNode != thisFurnace.FurnaceOutletNodeNum) {
    1261            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1262            0 :                     if (thisFurnace.type == HVAC::UnitarySysType::Furnace_HeatOnly) {
    1263            0 :                         ShowContinueError(
    1264              :                             state,
    1265              :                             "When a draw through fan is specified, the fan outlet node name must be the same as the furnace outlet node name.");
    1266            0 :                         ShowContinueError(state, format("...Fan outlet node name     = {}", state.dataLoopNodes->NodeID(FanOutletNode)));
    1267            0 :                         ShowContinueError(state,
    1268            0 :                                           format("...Furnace outlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    1269              :                     } else {
    1270            0 :                         ShowContinueError(state,
    1271              :                                           "When a draw through fan is specified, the fan outlet node name must be the same as the unitary system "
    1272              :                                           "outlet node name.");
    1273            0 :                         ShowContinueError(state, format("...Fan outlet node name           = {}", state.dataLoopNodes->NodeID(FanOutletNode)));
    1274            0 :                         ShowContinueError(
    1275            0 :                             state, format("...UnitarySystem outlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    1276              :                     }
    1277            0 :                     ErrorsFound = true;
    1278              :                 }
    1279              :             }
    1280              : 
    1281              :             // Add fan to component sets array
    1282            8 :             BranchNodeConnections::SetUpCompSets(
    1283            4 :                 state, CurrentModuleObject, thisFurnace.Name, Alphas(7), Alphas(8), CompSetFanInlet, CompSetFanOutlet);
    1284              :             // Add heating coil to component sets array
    1285            8 :             BranchNodeConnections::SetUpCompSets(
    1286            4 :                 state, CurrentModuleObject, thisFurnace.Name, Alphas(10), Alphas(11), CompSetHeatInlet, CompSetHeatOutlet);
    1287              : 
    1288              :             // Set the furnace max outlet temperature
    1289            4 :             thisFurnace.DesignMaxOutletTemp = Numbers(1);
    1290              : 
    1291              :             // Set the furnace design fan volumetric flow rate
    1292            4 :             thisFurnace.DesignFanVolFlowRate = Numbers(2);
    1293              : 
    1294              :             // Compare the flow rates.
    1295            4 :             if (thisFurnace.ActualFanVolFlowRate != DataSizing::AutoSize && thisFurnace.DesignFanVolFlowRate != DataSizing::AutoSize) {
    1296            4 :                 if (thisFurnace.DesignFanVolFlowRate > thisFurnace.ActualFanVolFlowRate) {
    1297            0 :                     ShowWarningError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1298            0 :                     ShowContinueError(
    1299            0 :                         state, format("... The {} > Max Volume Flow Rate defined in the associated fan object, should be <=.", cNumericFields(2)));
    1300            0 :                     ShowContinueError(state,
    1301            0 :                                       format("... Entered value = {:.4R}... Fan [{} = {}] Max Value = {:.4R}",
    1302            0 :                                              thisFurnace.DesignFanVolFlowRate,
    1303            0 :                                              HVAC::fanTypeNames[(int)thisFurnace.fanType],
    1304              :                                              FanName,
    1305            0 :                                              thisFurnace.ActualFanVolFlowRate));
    1306            0 :                     ShowContinueError(state, " The HVAC system  flow rate is reset to the fan flow rate and the simulation continues.");
    1307            0 :                     thisFurnace.DesignFanVolFlowRate = thisFurnace.ActualFanVolFlowRate;
    1308              :                 }
    1309              :             }
    1310            4 :             if (thisFurnace.DesignFanVolFlowRate != DataSizing::AutoSize) {
    1311            4 :                 if (thisFurnace.DesignFanVolFlowRate <= 0.0) {
    1312            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1313            0 :                     ShowContinueError(state, format("... The {} <= 0.0, it must be > 0.0.", cNumericFields(2)));
    1314            0 :                     ShowContinueError(state, format("... Entered value = {:.2R}", thisFurnace.DesignFanVolFlowRate));
    1315            0 :                     ErrorsFound = true;
    1316              :                 }
    1317              :             }
    1318              : 
    1319              :             //       HeatOnly furnace has only 1 flow rate, initialize other variables used in this module
    1320            4 :             thisFurnace.MaxHeatAirVolFlow = thisFurnace.DesignFanVolFlowRate;
    1321            4 :             thisFurnace.MaxCoolAirVolFlow = thisFurnace.DesignFanVolFlowRate;
    1322            4 :             thisFurnace.MaxNoCoolHeatAirVolFlow = thisFurnace.DesignFanVolFlowRate;
    1323            4 :             thisFurnace.AirFlowControl = AirFlowControlConstFan::UseCompressorOnFlow;
    1324              : 
    1325              :             // Set heating convergence tolerance
    1326            4 :             thisFurnace.HeatingConvergenceTolerance = 0.001;
    1327              : 
    1328              :             // set minimum outdoor temperature for compressor operation
    1329            4 :             SetMinOATCompressor(state, FurnaceNum, cCurrentModuleObject, ErrorsFound);
    1330              : 
    1331              :         } // End of the HeatOnly Furnace Loop
    1332              : 
    1333              :         // Get the data for the HeatCool Furnace or UnitarySystem
    1334          278 :         for (int HeatCoolNum = 1; HeatCoolNum <= NumHeatCool + NumUnitaryHeatCool; ++HeatCoolNum) {
    1335              : 
    1336          181 :             FanInletNode = 0;
    1337          181 :             FanOutletNode = 0;
    1338          181 :             CoolingCoilInletNode = 0;
    1339          181 :             CoolingCoilOutletNode = 0;
    1340          181 :             HeatingCoilInletNode = 0;
    1341          181 :             HeatingCoilOutletNode = 0;
    1342          181 :             int ReheatCoilInletNode = 0;
    1343          181 :             int ReheatCoilOutletNode = 0;
    1344          181 :             CoolingCoilType = ' ';
    1345          181 :             CoolingCoilName = ' ';
    1346          181 :             HeatingCoilType = ' ';
    1347          181 :             HeatingCoilName = ' ';
    1348              : 
    1349          181 :             FurnaceNum = HeatCoolNum + NumHeatOnly + NumUnitaryHeatOnly;
    1350          181 :             auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    1351              : 
    1352              :             //      Furnace and UnitarySystem objects are both read in here.
    1353              :             //      Will still have 2 differently named objects for the user, but read in with 1 DO loop.
    1354          181 :             if (HeatCoolNum <= NumHeatCool) {
    1355          108 :                 CurrentModuleObject = "AirLoopHVAC:Unitary:Furnace:HeatCool";
    1356          108 :                 currentModuleObjectType = DataLoopNode::ConnectionObjectType::AirLoopHVACUnitaryFurnaceHeatCool;
    1357          108 :                 thisFurnace.type = HVAC::UnitarySysType::Furnace_HeatCool;
    1358          108 :                 GetObjectNum = HeatCoolNum;
    1359              :             } else {
    1360           73 :                 CurrentModuleObject = "AirLoopHVAC:UnitaryHeatCool";
    1361           73 :                 currentModuleObjectType = DataLoopNode::ConnectionObjectType::AirLoopHVACUnitaryHeatCool;
    1362           73 :                 thisFurnace.type = HVAC::UnitarySysType::Unitary_HeatCool;
    1363           73 :                 GetObjectNum = HeatCoolNum - NumHeatCool;
    1364              :             }
    1365              : 
    1366          181 :             thisFurnace.iterationMode.allocate(3);
    1367              : 
    1368          181 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1369              :                                                                      CurrentModuleObject,
    1370              :                                                                      GetObjectNum,
    1371              :                                                                      Alphas,
    1372              :                                                                      NumAlphas,
    1373              :                                                                      Numbers,
    1374              :                                                                      NumNumbers,
    1375              :                                                                      IOStatus,
    1376              :                                                                      lNumericBlanks,
    1377              :                                                                      lAlphaBlanks,
    1378              :                                                                      cAlphaFields,
    1379              :                                                                      cNumericFields);
    1380              : 
    1381          362 :             GlobalNames::VerifyUniqueInterObjectName(
    1382          181 :                 state, state.dataFurnaces->UniqueFurnaceNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
    1383              : 
    1384          181 :             thisFurnace.Name = Alphas(1);
    1385              : 
    1386          181 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, thisFurnace.Name};
    1387              : 
    1388          181 :             if (lAlphaBlanks(2)) {
    1389           58 :                 thisFurnace.availSched = Sched::GetScheduleAlwaysOn(state);
    1390          123 :             } else if ((thisFurnace.availSched = Sched::GetSchedule(state, Alphas(2))) == nullptr) {
    1391            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(2), Alphas(2));
    1392            0 :                 ErrorsFound = true;
    1393              :             }
    1394              : 
    1395          181 :             thisFurnace.FurnaceInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
    1396          181 :                                                                                   Alphas(3),
    1397              :                                                                                   ErrorsFound,
    1398              :                                                                                   currentModuleObjectType,
    1399          181 :                                                                                   Alphas(1),
    1400              :                                                                                   DataLoopNode::NodeFluidType::Air,
    1401              :                                                                                   DataLoopNode::ConnectionType::Inlet,
    1402              :                                                                                   NodeInputManager::CompFluidStream::Primary,
    1403              :                                                                                   DataLoopNode::ObjectIsParent);
    1404          362 :             thisFurnace.FurnaceOutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
    1405          181 :                                                                                    Alphas(4),
    1406              :                                                                                    ErrorsFound,
    1407              :                                                                                    currentModuleObjectType,
    1408          181 :                                                                                    Alphas(1),
    1409              :                                                                                    DataLoopNode::NodeFluidType::Air,
    1410              :                                                                                    DataLoopNode::ConnectionType::Outlet,
    1411              :                                                                                    NodeInputManager::CompFluidStream::Primary,
    1412              :                                                                                    DataLoopNode::ObjectIsParent);
    1413              : 
    1414          181 :             BranchNodeConnections::TestCompSet(state, CurrentModuleObject, Alphas(1), Alphas(3), Alphas(4), "Air Nodes");
    1415              : 
    1416          181 :             if (lAlphaBlanks(5)) {
    1417           20 :                 thisFurnace.fanOp = HVAC::FanOp::Cycling;
    1418          161 :             } else if ((thisFurnace.fanOpModeSched = Sched::GetSchedule(state, Alphas(5))) == nullptr) {
    1419            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(5), Alphas(5));
    1420            0 :                 ErrorsFound = true;
    1421              :             }
    1422              : 
    1423              :             // Get the Controlling Zone or Location of the Furnace Thermostat
    1424          181 :             thisFurnace.ControlZoneNum = Util::FindItemInList(Alphas(6), state.dataHeatBal->Zone);
    1425          181 :             if (thisFurnace.ControlZoneNum == 0) {
    1426            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1427            0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(6), Alphas(6)));
    1428            0 :                 ErrorsFound = true;
    1429              :             }
    1430              : 
    1431              :             // Get the node number for the zone with the thermostat
    1432          181 :             if (thisFurnace.ControlZoneNum > 0) {
    1433          181 :                 AirNodeFound = false;
    1434          181 :                 AirLoopFound = false;
    1435          181 :                 int ControlledZoneNum = thisFurnace.ControlZoneNum;
    1436              :                 //             Find the controlled zone number for the specified thermostat location
    1437          181 :                 thisFurnace.NodeNumOfControlledZone = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).ZoneNode;
    1438              :                 //             Determine if system is on air loop served by the thermostat location specified
    1439          186 :                 for (int zoneInNode = 1; zoneInNode <= state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).NumInletNodes; ++zoneInNode) {
    1440          186 :                     int AirLoopNumber = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).InletNodeAirLoopNum(zoneInNode);
    1441          186 :                     if (AirLoopNumber > 0) {
    1442          191 :                         for (int BranchNum = 1; BranchNum <= state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).NumBranches; ++BranchNum) {
    1443          354 :                             for (int CompNum = 1;
    1444          354 :                                  CompNum <= state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).Branch(BranchNum).TotalComponents;
    1445              :                                  ++CompNum) {
    1446          349 :                                 if (!Util::SameString(state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).Branch(BranchNum).Comp(CompNum).Name,
    1447          879 :                                                       Alphas(1)) ||
    1448          181 :                                     !Util::SameString(
    1449          181 :                                         state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).Branch(BranchNum).Comp(CompNum).TypeOf,
    1450              :                                         CurrentModuleObject)) {
    1451          168 :                                     continue;
    1452              :                                 }
    1453          181 :                                 AirLoopFound = true;
    1454          181 :                                 thisFurnace.ZoneInletNode = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).InletNode(zoneInNode);
    1455          181 :                                 break;
    1456              :                             }
    1457          186 :                             if (AirLoopFound) {
    1458          181 :                                 break;
    1459              :                             }
    1460              :                         }
    1461         2184 :                         for (TstatZoneNum = 1; TstatZoneNum <= state.dataZoneCtrls->NumTempControlledZones; ++TstatZoneNum) {
    1462         1998 :                             if (state.dataZoneCtrls->TempControlledZone(TstatZoneNum).ActualZoneNum != thisFurnace.ControlZoneNum) {
    1463         1812 :                                 continue;
    1464              :                             }
    1465          186 :                             AirNodeFound = true;
    1466              :                         }
    1467          187 :                         for (TstatZoneNum = 1; TstatZoneNum <= state.dataZoneCtrls->NumComfortControlledZones; ++TstatZoneNum) {
    1468            1 :                             if (state.dataZoneCtrls->ComfortControlledZone(TstatZoneNum).ActualZoneNum != thisFurnace.ControlZoneNum) {
    1469            0 :                                 continue;
    1470              :                             }
    1471            1 :                             AirNodeFound = true;
    1472              :                         }
    1473              :                     }
    1474          186 :                     if (AirLoopFound) {
    1475          181 :                         break;
    1476              :                     }
    1477              :                 }
    1478          181 :                 if (!AirNodeFound) {
    1479            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1480            0 :                     ShowContinueError(state, "Did not find air node (zone with thermostat).");
    1481            0 :                     ShowContinueError(state, format("Specified {} = {}", cAlphaFields(6), Alphas(6)));
    1482            0 :                     ShowContinueError(
    1483              :                         state, "Both a ZoneHVAC:EquipmentConnections object and a ZoneControl:Thermostat object must be specified for this zone.");
    1484            0 :                     ErrorsFound = true;
    1485              :                 }
    1486          181 :                 if (!AirLoopFound) {
    1487            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1488            0 :                     ShowContinueError(state, "Did not find correct AirLoopHVAC.");
    1489            0 :                     ShowContinueError(state, format("Specified {} = {}", cAlphaFields(6), Alphas(6)));
    1490            0 :                     ErrorsFound = true;
    1491              :                 }
    1492              :             }
    1493              : 
    1494              :             // Get fan data
    1495          181 :             FanName = Alphas(8);
    1496              : 
    1497          181 :             thisFurnace.fanType = static_cast<HVAC::FanType>(getEnumValue(HVAC::fanTypeNamesUC, Alphas(7)));
    1498              : 
    1499          181 :             if (thisFurnace.fanType != HVAC::FanType::OnOff && thisFurnace.fanType != HVAC::FanType::Constant) {
    1500            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1501            0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(7), Alphas(7)));
    1502            0 :                 ErrorsFound = true;
    1503              : 
    1504          181 :             } else if ((thisFurnace.FanIndex = Fans::GetFanIndex(state, FanName)) == 0) {
    1505            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(8), FanName);
    1506            0 :                 ErrorsFound = true;
    1507              : 
    1508              :             } else {
    1509          181 :                 auto *fan = state.dataFans->fans(thisFurnace.FanIndex);
    1510          181 :                 thisFurnace.ActualFanVolFlowRate = fan->maxAirFlowRate;
    1511          181 :                 FanInletNode = fan->inletNodeNum;
    1512          181 :                 FanOutletNode = fan->outletNodeNum;
    1513          181 :                 thisFurnace.fanAvailSched = fan->availSched;
    1514              : 
    1515              :                 // Check fan's schedule for cycling fan operation if constant volume fan is used
    1516          181 :                 if (thisFurnace.fanOpModeSched != nullptr && thisFurnace.fanType == HVAC::FanType::Constant) {
    1517            5 :                     if (!thisFurnace.fanOpModeSched->checkMinMaxVals(state, Clusive::Ex, 0.0, Clusive::In, 1.0)) {
    1518            0 :                         Sched::ShowSevereBadMinMax(
    1519              :                             state,
    1520              :                             eoh,
    1521            0 :                             cAlphaFields(5),
    1522            0 :                             Alphas(5),
    1523              :                             Clusive::In,
    1524              :                             0.0,
    1525              :                             Clusive::In,
    1526              :                             1.0,
    1527            0 :                             format("For {} = {}, fan operating mode must be continuous (schedule values > 0)", cAlphaFields(7), Alphas(7)));
    1528            0 :                         ErrorsFound = true;
    1529              :                     }
    1530          176 :                 } else if (lAlphaBlanks(5) && thisFurnace.fanType != HVAC::FanType::OnOff) {
    1531            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, thisFurnace.Name));
    1532            0 :                     ShowContinueError(state, format("{} = {}", cAlphaFields(7), Alphas(7)));
    1533            0 :                     ShowContinueError(state, format("Fan type must be Fan:OnOff when {} = Blank.", cAlphaFields(5)));
    1534            0 :                     ErrorsFound = true;
    1535              :                 }
    1536              :             }
    1537              : 
    1538          181 :             thisFurnace.fanPlace = static_cast<HVAC::FanPlace>(getEnumValue(HVAC::fanPlaceNamesUC, Alphas(9)));
    1539          181 :             assert(thisFurnace.fanPlace != HVAC::FanPlace::Invalid);
    1540              : 
    1541              :             // Get coil data
    1542          181 :             HeatingCoilType = Alphas(10);
    1543          181 :             HeatingCoilName = Alphas(11);
    1544          181 :             HeatingCoilPLFCurveIndex = 0;
    1545          181 :             thisFurnace.HeatingCoilType = HeatingCoilType;
    1546          181 :             thisFurnace.HeatingCoilName = HeatingCoilName;
    1547          181 :             if (Util::SameString(HeatingCoilType, "Coil:Heating:Fuel") || Util::SameString(HeatingCoilType, "Coil:Heating:Electric")) {
    1548          181 :                 errFlag = false;
    1549          181 :                 thisFurnace.HeatingCoilType_Num = HeatingCoils::GetHeatingCoilTypeNum(state, HeatingCoilType, HeatingCoilName, errFlag);
    1550          181 :                 if (errFlag) {
    1551            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1552            0 :                     ErrorsFound = true;
    1553              :                 } else {
    1554              : 
    1555          181 :                     ValidateComponent(state, HeatingCoilType, HeatingCoilName, IsNotOK, CurrentModuleObject);
    1556          181 :                     if (IsNotOK) {
    1557            0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1558            0 :                         ErrorsFound = true;
    1559              : 
    1560              :                     } else { // mine data from heating coil
    1561              : 
    1562              :                         // Get heating coil index
    1563          181 :                         errFlag = false;
    1564          181 :                         HeatingCoils::GetCoilIndex(state, HeatingCoilName, thisFurnace.HeatingCoilIndex, errFlag);
    1565          181 :                         if (errFlag) {
    1566            0 :                             ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1567            0 :                             ErrorsFound = true;
    1568              :                         }
    1569              : 
    1570              :                         // Get the design heating capacity
    1571          181 :                         errFlag = false;
    1572          181 :                         thisFurnace.DesignHeatingCapacity = HeatingCoils::GetCoilCapacity(state, HeatingCoilType, HeatingCoilName, errFlag);
    1573          181 :                         if (errFlag) {
    1574            0 :                             ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1575            0 :                             ErrorsFound = true;
    1576              :                         }
    1577              : 
    1578              :                         // Get the Heating Coil Inlet Node
    1579          181 :                         errFlag = false;
    1580          181 :                         HeatingCoilInletNode = HeatingCoils::GetCoilInletNode(state, HeatingCoilType, HeatingCoilName, errFlag);
    1581          181 :                         if (errFlag) {
    1582            0 :                             ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1583            0 :                             ErrorsFound = true;
    1584              :                         }
    1585              : 
    1586              :                         // Get the Heating Coil Outlet Node
    1587          181 :                         errFlag = false;
    1588          181 :                         HeatingCoilOutletNode = HeatingCoils::GetCoilOutletNode(state, HeatingCoilType, HeatingCoilName, errFlag);
    1589          181 :                         if (errFlag) {
    1590            0 :                             ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1591            0 :                             ErrorsFound = true;
    1592              :                         }
    1593              : 
    1594              :                         // Get the Heating Coil PLF Curve Index
    1595          181 :                         errFlag = false;
    1596          181 :                         HeatingCoilPLFCurveIndex = HeatingCoils::GetHeatingCoilPLFCurveIndex(state, HeatingCoilType, HeatingCoilName, errFlag);
    1597          181 :                         if (errFlag) {
    1598            0 :                             ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1599            0 :                             ErrorsFound = true;
    1600              :                         }
    1601              : 
    1602              :                     } // IF (IsNotOK) THEN
    1603              :                 }
    1604              : 
    1605            0 :             } else if (Util::SameString(HeatingCoilType, "Coil:Heating:Water")) {
    1606            0 :                 thisFurnace.HeatingCoilType_Num = HVAC::Coil_HeatingWater;
    1607            0 :                 ValidateComponent(state, HeatingCoilType, HeatingCoilName, IsNotOK, CurrentModuleObject);
    1608            0 :                 if (IsNotOK) {
    1609            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1610            0 :                     ErrorsFound = true;
    1611              :                 } else { // mine data from heating coil object
    1612              : 
    1613              :                     // Get the Heating Coil water Inlet or control Node number
    1614            0 :                     errFlag = false;
    1615            0 :                     thisFurnace.CoilControlNode = WaterCoils::GetCoilWaterInletNode(state, "Coil:Heating:Water", HeatingCoilName, errFlag);
    1616            0 :                     if (errFlag) {
    1617            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1618            0 :                         ErrorsFound = true;
    1619              :                     }
    1620              : 
    1621              :                     // Get the Heating Coil hot water max volume flow rate
    1622            0 :                     errFlag = false;
    1623            0 :                     thisFurnace.MaxHeatCoilFluidFlow = WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", HeatingCoilName, errFlag);
    1624            0 :                     if (errFlag) {
    1625            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1626            0 :                         ErrorsFound = true;
    1627              :                     }
    1628              : 
    1629              :                     // Get the Heating Coil Inlet Node
    1630            0 :                     errFlag = false;
    1631            0 :                     HeatingCoilInletNode = WaterCoils::GetCoilInletNode(state, "Coil:Heating:Water", HeatingCoilName, errFlag);
    1632            0 :                     thisFurnace.HWCoilAirInletNode = HeatingCoilInletNode;
    1633            0 :                     if (errFlag) {
    1634            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1635            0 :                         ErrorsFound = true;
    1636              :                     }
    1637              : 
    1638              :                     // Get the Heating Coil Outlet Node
    1639            0 :                     errFlag = false;
    1640            0 :                     HeatingCoilOutletNode = WaterCoils::GetCoilOutletNode(state, "Coil:Heating:Water", HeatingCoilName, errFlag);
    1641            0 :                     thisFurnace.HWCoilAirOutletNode = HeatingCoilOutletNode;
    1642            0 :                     if (errFlag) {
    1643            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1644            0 :                         ErrorsFound = true;
    1645              :                     }
    1646              : 
    1647              :                     // check if user has also used a water coil controller, which they should not do
    1648            0 :                     errFlag = false;
    1649            0 :                     HVACControllers::CheckCoilWaterInletNode(state, thisFurnace.CoilControlNode, errFlag);
    1650            0 :                     if (!errFlag) { // then did find a controller so that is bad
    1651            0 :                         ShowSevereError(state,
    1652            0 :                                         format("{} = {} has a conflicting Controller:WaterCoil object", CurrentModuleObject, thisFurnace.Name));
    1653            0 :                         ShowContinueError(state, "Hot water coils are controlled directly by unitary and furnace systems.");
    1654            0 :                         ShowContinueError(state, "No water coil controller should be input for the coil.");
    1655            0 :                         ErrorsFound = true;
    1656              :                     }
    1657              :                 }
    1658              : 
    1659            0 :             } else if (Util::SameString(HeatingCoilType, "Coil:Heating:Steam")) {
    1660            0 :                 thisFurnace.HeatingCoilType_Num = HVAC::Coil_HeatingSteam;
    1661            0 :                 ValidateComponent(state, HeatingCoilType, HeatingCoilName, IsNotOK, CurrentModuleObject);
    1662            0 :                 if (IsNotOK) {
    1663            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1664            0 :                     ErrorsFound = true;
    1665              :                 } else { // mine data from heating coil object
    1666              : 
    1667            0 :                     errFlag = false;
    1668            0 :                     thisFurnace.HeatingCoilIndex = SteamCoils::GetSteamCoilIndex(state, "COIL:HEATING:STEAM", HeatingCoilName, errFlag);
    1669            0 :                     if (thisFurnace.HeatingCoilIndex == 0) {
    1670            0 :                         ShowSevereError(state, format("{} illegal {} = {}", CurrentModuleObject, cAlphaFields(11), HeatingCoilName));
    1671            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1672            0 :                         ErrorsFound = true;
    1673              :                     }
    1674              : 
    1675              :                     // Get the Heating Coil steam inlet node number
    1676            0 :                     errFlag = false;
    1677            0 :                     thisFurnace.CoilControlNode = SteamCoils::GetCoilSteamInletNode(state, "Coil:Heating:Steam", HeatingCoilName, errFlag);
    1678            0 :                     if (errFlag) {
    1679            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1680            0 :                         ErrorsFound = true;
    1681              :                     }
    1682              : 
    1683              :                     // Get the Heating Coil steam max volume flow rate
    1684            0 :                     thisFurnace.MaxHeatCoilFluidFlow = SteamCoils::GetCoilMaxSteamFlowRate(state, thisFurnace.HeatingCoilIndex, errFlag);
    1685            0 :                     if (thisFurnace.MaxHeatCoilFluidFlow > 0.0) {
    1686              :                         SteamDensity =
    1687            0 :                             Fluid::GetSteam(state)->getSatDensity(state, state.dataFurnaces->TempSteamIn, 1.0, getAirLoopHVACHeatCoolInput);
    1688            0 :                         thisFurnace.MaxHeatCoilFluidFlow *= SteamDensity;
    1689              :                     }
    1690              : 
    1691              :                     // Get the Heating Coil Inlet Node
    1692            0 :                     errFlag = false;
    1693            0 :                     HeatingCoilInletNode = SteamCoils::GetCoilAirInletNode(state, thisFurnace.HeatingCoilIndex, HeatingCoilName, errFlag);
    1694            0 :                     thisFurnace.HWCoilAirInletNode = HeatingCoilInletNode;
    1695            0 :                     if (errFlag) {
    1696            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1697            0 :                         ErrorsFound = true;
    1698              :                     }
    1699              : 
    1700              :                     // Get the Heating Coil Outlet Node
    1701            0 :                     errFlag = false;
    1702            0 :                     HeatingCoilOutletNode = SteamCoils::GetCoilAirOutletNode(state, thisFurnace.HeatingCoilIndex, HeatingCoilName, errFlag);
    1703            0 :                     thisFurnace.HWCoilAirOutletNode = HeatingCoilOutletNode;
    1704            0 :                     if (errFlag) {
    1705            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1706            0 :                         ErrorsFound = true;
    1707              :                     }
    1708              :                 }
    1709              : 
    1710              :             } else {
    1711            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1712            0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(11), Alphas(11)));
    1713            0 :                 ErrorsFound = true;
    1714              :             } // IF (Furnace(FurnaceNum)%HeatingCoilType_Num == Coil_HeatingGasOrOtherFuel .OR. &, etc.
    1715              : 
    1716              :             // Get Cooling Coil Information if available
    1717          181 :             CoolingCoilType = Alphas(12);
    1718          181 :             CoolingCoilName = Alphas(13);
    1719              :             //       Find the type of coil. Do not print message since this may not be the correct coil type.
    1720          181 :             errFlag = false;
    1721          181 :             PrintMessage = false;
    1722              : 
    1723          358 :             if (Util::SameString(CoolingCoilType, "COIL:COOLING:DX:VARIABLESPEED") ||
    1724          358 :                 Util::SameString(CoolingCoilType, "COILSYSTEM:INTEGRATEDHEATPUMP:AIRSOURCE")) {
    1725            4 :                 thisFurnace.CoolingCoilType_Num = HVAC::Coil_CoolingAirToAirVariableSpeed;
    1726            4 :                 if (Util::SameString(CoolingCoilType, "COILSYSTEM:INTEGRATEDHEATPUMP:AIRSOURCE")) {
    1727            0 :                     thisFurnace.bIsIHP = true;
    1728              :                 }
    1729              :             } else {
    1730          177 :                 thisFurnace.CoolingCoilType_Num = DXCoils::GetCoilTypeNum(state, CoolingCoilType, CoolingCoilName, errFlag, PrintMessage);
    1731              :             }
    1732              : 
    1733              :             // If coil type not found, check to see if a HX assisted cooling coil is used.
    1734          181 :             if (thisFurnace.CoolingCoilType_Num == 0) {
    1735            3 :                 errFlag = false;
    1736            3 :                 thisFurnace.CoolingCoilType_Num =
    1737            3 :                     HVACHXAssistedCoolingCoil::GetCoilGroupTypeNum(state, CoolingCoilType, CoolingCoilName, errFlag, PrintMessage);
    1738              :             }
    1739              : 
    1740          181 :             if (thisFurnace.CoolingCoilType_Num == HVAC::CoilDX_CoolingSingleSpeed) {
    1741          174 :                 ValidateComponent(state, CoolingCoilType, CoolingCoilName, IsNotOK, CurrentModuleObject);
    1742          174 :                 if (IsNotOK) {
    1743            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1744            0 :                     ErrorsFound = true;
    1745              : 
    1746              :                 } else { // mine data from DX cooling coil
    1747              : 
    1748              :                     // Get DX cooling coil index
    1749          174 :                     DXCoils::GetDXCoilIndex(state, CoolingCoilName, thisFurnace.CoolingCoilIndex, IsNotOK);
    1750          174 :                     if (IsNotOK) {
    1751            0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1752            0 :                         ErrorsFound = true;
    1753              :                     }
    1754              : 
    1755              :                     // Get DX cooling coil capacity
    1756          174 :                     errFlag = false;
    1757          174 :                     thisFurnace.DesignCoolingCapacity = DXCoils::GetCoilCapacity(state, CoolingCoilType, CoolingCoilName, errFlag);
    1758          174 :                     if (errFlag) {
    1759            0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1760            0 :                         ErrorsFound = true;
    1761              :                     }
    1762              : 
    1763              :                     // Get the Cooling Coil Nodes
    1764          174 :                     errFlag = false;
    1765          174 :                     CoolingCoilInletNode = DXCoils::GetCoilInletNode(state, CoolingCoilType, CoolingCoilName, errFlag);
    1766          174 :                     CoolingCoilOutletNode = DXCoils::GetCoilOutletNode(state, CoolingCoilType, CoolingCoilName, errFlag);
    1767          174 :                     if (errFlag) {
    1768            0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1769            0 :                         ErrorsFound = true;
    1770              :                     }
    1771              : 
    1772              :                     // Get outdoor condenser node from DX coil object
    1773          174 :                     errFlag = false;
    1774          174 :                     if (thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingAirToAirVariableSpeed) {
    1775            0 :                         if (thisFurnace.bIsIHP) {
    1776            0 :                             IHPCoilIndex = IntegratedHeatPump::GetCoilIndexIHP(state, CoolingCoilType, CoolingCoilName, errFlag);
    1777            0 :                             IHPCoilName = state.dataIntegratedHP->IntegratedHeatPumps(IHPCoilIndex).SCCoilName;
    1778            0 :                             thisFurnace.CondenserNodeNum = VariableSpeedCoils::GetVSCoilCondenserInletNode(state, IHPCoilName, errFlag);
    1779              :                         } else {
    1780            0 :                             thisFurnace.CondenserNodeNum = VariableSpeedCoils::GetVSCoilCondenserInletNode(state, CoolingCoilName, errFlag);
    1781              :                         }
    1782              :                     } else {
    1783          174 :                         thisFurnace.CondenserNodeNum = DXCoils::GetCoilCondenserInletNode(state, CoolingCoilType, CoolingCoilName, errFlag);
    1784              :                     }
    1785          174 :                     if (errFlag) {
    1786            0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1787            0 :                         ErrorsFound = true;
    1788              :                     }
    1789              : 
    1790              :                 } // IF (IsNotOK) THEN
    1791              : 
    1792              :                 // Push heating coil PLF curve index to DX coil
    1793          174 :                 if (HeatingCoilPLFCurveIndex > 0) {
    1794           48 :                     DXCoils::SetDXCoolingCoilData(state, thisFurnace.CoolingCoilIndex, ErrorsFound, HeatingCoilPLFCurveIndex);
    1795              :                 }
    1796              : 
    1797            7 :             } else if (thisFurnace.CoolingCoilType_Num == HVAC::CoilDX_CoolingHXAssisted) {
    1798            3 :                 ValidateComponent(state, CoolingCoilType, CoolingCoilName, IsNotOK, CurrentModuleObject);
    1799            3 :                 if (IsNotOK) {
    1800            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1801            0 :                     ErrorsFound = true;
    1802              : 
    1803              :                 } else { // mine data from heat exchanger assisted cooling coil
    1804              : 
    1805              :                     // Get DX heat exchanger assisted cooling coil index
    1806            3 :                     HVACHXAssistedCoolingCoil::GetHXDXCoilIndex(state, CoolingCoilName, thisFurnace.CoolingCoilIndex, IsNotOK);
    1807            3 :                     if (IsNotOK) {
    1808            0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1809            0 :                         ErrorsFound = true;
    1810              :                     }
    1811              : 
    1812              :                     // Get DX cooling coil capacity
    1813            3 :                     errFlag = false;
    1814            3 :                     thisFurnace.DesignCoolingCapacity = HVACHXAssistedCoolingCoil::GetCoilCapacity(state, CoolingCoilType, CoolingCoilName, errFlag);
    1815            3 :                     if (errFlag) {
    1816            0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1817            0 :                         ErrorsFound = true;
    1818              :                     }
    1819              : 
    1820              :                     // Get the Cooling Coil Nodes
    1821            3 :                     errFlag = false;
    1822            3 :                     CoolingCoilInletNode = HVACHXAssistedCoolingCoil::GetCoilInletNode(state, CoolingCoilType, CoolingCoilName, errFlag);
    1823            3 :                     CoolingCoilOutletNode = HVACHXAssistedCoolingCoil::GetCoilOutletNode(state, CoolingCoilType, CoolingCoilName, errFlag);
    1824            3 :                     if (errFlag) {
    1825            0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1826            0 :                         ErrorsFound = true;
    1827              :                     }
    1828              : 
    1829              :                     // Get outdoor condenser node from heat exchanger assisted DX coil object
    1830            3 :                     errFlag = false;
    1831            3 :                     std::string ChildCoolingCoilName = HVACHXAssistedCoolingCoil::GetHXDXCoilName(state, CoolingCoilType, CoolingCoilName, IsNotOK);
    1832            3 :                     std::string ChildCoolingCoilType = HVACHXAssistedCoolingCoil::GetHXDXCoilType(state, CoolingCoilType, CoolingCoilName, IsNotOK);
    1833            3 :                     if (IsNotOK) {
    1834            0 :                         ShowContinueError(state, format("Occurs in {} = {}", cCurrentModuleObject, Alphas(1)));
    1835            0 :                         ErrorsFound = true;
    1836              :                     }
    1837              : 
    1838              :                     // if (thisFurnace.CoolingCoilType_Num == CoilDX_CoolingHXAssisted) {
    1839            3 :                     if (Util::SameString(ChildCoolingCoilType, "COIL:COOLING:DX")) {
    1840              : 
    1841            1 :                         int childCCIndex = CoilCoolingDX::factory(state, ChildCoolingCoilName);
    1842            1 :                         if (childCCIndex < 0) {
    1843            0 :                             ShowContinueError(state, format("Occurs in {} = {}", cCurrentModuleObject, Alphas(1)));
    1844            0 :                             errFlag = true;
    1845            0 :                             ErrorsFound = true;
    1846              :                         }
    1847            1 :                         auto const &newCoil = state.dataCoilCoolingDX->coilCoolingDXs[childCCIndex];
    1848              : 
    1849            1 :                         thisFurnace.CondenserNodeNum = newCoil.condInletNodeIndex;
    1850              : 
    1851              :                     }
    1852              :                     // else if (thisFurnace.CoolingCoilType_Num == Coil_CoolingAirToAirVariableSpeed) {
    1853            2 :                     else if (Util::SameString(ChildCoolingCoilType, "Coil:Cooling:DX:VariableSpeed")) {
    1854            0 :                         if (thisFurnace.bIsIHP) {
    1855            0 :                             IHPCoilIndex = IntegratedHeatPump::GetCoilIndexIHP(state, CoolingCoilType, CoolingCoilName, errFlag);
    1856            0 :                             IHPCoilName = state.dataIntegratedHP->IntegratedHeatPumps(IHPCoilIndex).SCCoilName;
    1857            0 :                             thisFurnace.CondenserNodeNum = VariableSpeedCoils::GetVSCoilCondenserInletNode(state, IHPCoilName, errFlag);
    1858              :                         } else {
    1859            0 :                             thisFurnace.CondenserNodeNum = VariableSpeedCoils::GetVSCoilCondenserInletNode(state, CoolingCoilName, errFlag);
    1860              :                         }
    1861              :                     } else {
    1862            2 :                         thisFurnace.CondenserNodeNum = DXCoils::GetCoilCondenserInletNode(
    1863              :                             state,
    1864              :                             "COIL:COOLING:DX:SINGLESPEED",
    1865            4 :                             HVACHXAssistedCoolingCoil::GetHXDXCoilName(state, CoolingCoilType, CoolingCoilName, errFlag),
    1866              :                             errFlag);
    1867              :                     }
    1868              : 
    1869            3 :                     if (errFlag) {
    1870            0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1871            0 :                         ErrorsFound = true;
    1872              :                     }
    1873              : 
    1874              :                     // Push heating coil PLF curve index to DX coil
    1875            3 :                     if (HeatingCoilPLFCurveIndex > 0) {
    1876              :                         // get the actual index to the DX cooling coil object
    1877            0 :                         DXCoilIndex = HVACHXAssistedCoolingCoil::GetActualDXCoilIndex(state, CoolingCoilType, CoolingCoilName, ErrorsFound);
    1878            0 :                         thisFurnace.ActualDXCoilIndexForHXAssisted = DXCoilIndex;
    1879              :                         int ActualCoolCoilType =
    1880            0 :                             HVACHXAssistedCoolingCoil::GetCoilObjectTypeNum(state, CoolingCoilType, CoolingCoilName, errFlag, true);
    1881            0 :                         if (ActualCoolCoilType == HVAC::CoilDX_CoolingSingleSpeed) {
    1882            0 :                             DXCoils::SetDXCoolingCoilData(state, DXCoilIndex, ErrorsFound, HeatingCoilPLFCurveIndex);
    1883              :                         }
    1884              :                         // what could we do for VS coil here? odd thing here
    1885              :                     }
    1886              : 
    1887            3 :                 } // IF (IsNotOK) THEN
    1888            4 :             } else if (thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingAirToAirVariableSpeed) {
    1889              :                 // BOS ADDED, AUG/2012, VARIIABLE SPEED DX COOLING COIL
    1890              :                 //  Furnace(FurnaceNum)%DXCoolCoilType = 'COIL:COOLING:DX:VARIABLESPEED'
    1891              :                 //  Furnace(FurnaceNum)%DXCoolCoilName = CoolingCoilName
    1892            4 :                 if (Util::SameString(CoolingCoilType, "COILSYSTEM:INTEGRATEDHEATPUMP:AIRSOURCE")) {
    1893            0 :                     thisFurnace.bIsIHP = true;
    1894              :                 }
    1895            4 :                 ValidateComponent(state, CoolingCoilType, CoolingCoilName, IsNotOK, CurrentModuleObject);
    1896              : 
    1897            4 :                 if (IsNotOK) {
    1898            0 :                     ShowContinueError(state, format("...specified in {}=\"{}\".", CurrentModuleObject, Alphas(1)));
    1899            0 :                     ErrorsFound = true;
    1900              :                 } else {
    1901            4 :                     errFlag = false;
    1902            4 :                     if (thisFurnace.bIsIHP) {
    1903            0 :                         thisFurnace.CoolingCoilIndex = IntegratedHeatPump::GetCoilIndexIHP(state, CoolingCoilType, CoolingCoilName, errFlag);
    1904            0 :                         IHPCoilName = state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).SCCoilName;
    1905              :                     } else {
    1906            4 :                         thisFurnace.CoolingCoilIndex =
    1907            4 :                             VariableSpeedCoils::GetCoilIndexVariableSpeed(state, CoolingCoilType, CoolingCoilName, errFlag);
    1908            4 :                         IHPCoilName = CoolingCoilName;
    1909              :                     }
    1910              : 
    1911            4 :                     if (errFlag) {
    1912            0 :                         ShowContinueError(state, format("...specified in {}=\"{}\".", CurrentModuleObject, Alphas(1)));
    1913            0 :                         ErrorsFound = true;
    1914              :                     }
    1915              : 
    1916            4 :                     if (thisFurnace.bIsIHP) {
    1917              :                         CoolingCoilInletNode =
    1918            0 :                             VariableSpeedCoils::GetCoilInletNodeVariableSpeed(state, "COIL:COOLING:DX:VARIABLESPEED", IHPCoilName, errFlag);
    1919              :                         CoolingCoilOutletNode =
    1920            0 :                             VariableSpeedCoils::GetCoilOutletNodeVariableSpeed(state, "COIL:COOLING:DX:VARIABLESPEED", IHPCoilName, errFlag);
    1921            0 :                         thisFurnace.CondenserNodeNum = VariableSpeedCoils::GetVSCoilCondenserInletNode(state, IHPCoilName, errFlag);
    1922              :                     } else {
    1923            4 :                         CoolingCoilInletNode = VariableSpeedCoils::GetCoilInletNodeVariableSpeed(state, CoolingCoilType, CoolingCoilName, errFlag);
    1924            4 :                         CoolingCoilOutletNode = VariableSpeedCoils::GetCoilOutletNodeVariableSpeed(state, CoolingCoilType, CoolingCoilName, errFlag);
    1925            4 :                         thisFurnace.CondenserNodeNum = VariableSpeedCoils::GetVSCoilCondenserInletNode(state, CoolingCoilName, errFlag);
    1926              :                     }
    1927              : 
    1928            4 :                     if (errFlag) {
    1929            0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1930            0 :                         ErrorsFound = true;
    1931              :                     }
    1932              :                 }
    1933              :             } else {
    1934            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1935            0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(12), Alphas(12)));
    1936            0 :                 ErrorsFound = true;
    1937              :             }
    1938              : 
    1939          181 :             if (Util::SameString(Alphas(14), "None") || Util::SameString(Alphas(14), "Multimode") || Util::SameString(Alphas(14), "CoolReheat")) {
    1940          181 :                 AirNodeFound = false;
    1941          181 :                 if (Util::SameString(Alphas(14), "Multimode")) {
    1942            3 :                     thisFurnace.DehumidControlType_Num = DehumidificationControlMode::Multimode;
    1943            3 :                     thisFurnace.Humidistat = true;
    1944            3 :                     if (thisFurnace.CoolingCoilType_Num != HVAC::CoilDX_CoolingHXAssisted) {
    1945            0 :                         ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1946            0 :                         ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(14), Alphas(14)));
    1947            0 :                         ShowContinueError(state, "Multimode control must be used with a Heat Exchanger Assisted Cooling Coil.");
    1948            0 :                         if (lAlphaBlanks(15)) {
    1949            0 :                             ShowContinueError(state,
    1950              :                                               "Dehumidification control type is assumed to be None since a reheat coil has not been specified and "
    1951              :                                               "the simulation continues.");
    1952            0 :                             thisFurnace.Humidistat = false;
    1953            0 :                             thisFurnace.DehumidControlType_Num = DehumidificationControlMode::None;
    1954              :                         } else {
    1955            0 :                             ShowContinueError(state, "Dehumidification control type is assumed to be CoolReheat and the simulation continues.");
    1956            0 :                             thisFurnace.DehumidControlType_Num = DehumidificationControlMode::CoolReheat;
    1957              :                         }
    1958              :                     }
    1959              :                 }
    1960          181 :                 if (Util::SameString(Alphas(14), "CoolReheat")) {
    1961           22 :                     thisFurnace.DehumidControlType_Num = DehumidificationControlMode::CoolReheat;
    1962           22 :                     thisFurnace.Humidistat = true;
    1963           22 :                     if (lAlphaBlanks(15)) {
    1964            0 :                         ShowWarningError(state, format("{} \"{}\"", CurrentModuleObject, Alphas(1)));
    1965            0 :                         ShowContinueError(state,
    1966              :                                           "Dehumidification control type is assumed to be None since a reheat coil has not been specified and the "
    1967              :                                           "simulation continues.");
    1968            0 :                         thisFurnace.Humidistat = false;
    1969            0 :                         thisFurnace.DehumidControlType_Num = DehumidificationControlMode::None;
    1970              :                     }
    1971              :                 }
    1972          181 :                 if (Util::SameString(Alphas(14), "None")) {
    1973          156 :                     thisFurnace.DehumidControlType_Num = DehumidificationControlMode::None;
    1974          156 :                     thisFurnace.Humidistat = false;
    1975              :                 }
    1976          181 :                 if (thisFurnace.Humidistat) {
    1977           62 :                     for (HStatZoneNum = 1; HStatZoneNum <= state.dataZoneCtrls->NumHumidityControlZones; ++HStatZoneNum) {
    1978           37 :                         if (state.dataZoneCtrls->HumidityControlZone(HStatZoneNum).ActualZoneNum != thisFurnace.ControlZoneNum) {
    1979           12 :                             continue;
    1980              :                         }
    1981           25 :                         AirNodeFound = true;
    1982              :                     }
    1983           25 :                     if (!AirNodeFound) {
    1984            0 :                         ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1985            0 :                         ShowContinueError(state, "Did not find Air Node (Zone with Humidistat).");
    1986            0 :                         ShowContinueError(state, format("Specified {} = {}", cAlphaFields(6), Alphas(6)));
    1987            0 :                         ErrorsFound = true;
    1988              :                     }
    1989              :                 }
    1990              :             } else { // invalid input
    1991            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1992            0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(14), Alphas(14)));
    1993            0 :                 thisFurnace.Humidistat = false;
    1994            0 :                 ErrorsFound = true;
    1995              :             }
    1996              : 
    1997              :             //       Check placement of cooling coil with respect to fan placement and dehumidification control type
    1998          181 :             if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
    1999          178 :                 if (FanOutletNode == HeatingCoilInletNode && thisFurnace.DehumidControlType_Num != DehumidificationControlMode::CoolReheat) {
    2000          102 :                     thisFurnace.CoolingCoilUpstream = false;
    2001              :                 }
    2002              :             } else {
    2003            3 :                 if (HeatingCoilOutletNode == CoolingCoilInletNode && thisFurnace.DehumidControlType_Num != DehumidificationControlMode::CoolReheat) {
    2004            2 :                     thisFurnace.CoolingCoilUpstream = false;
    2005              :                 }
    2006              :             }
    2007              : 
    2008              :             // Get reheat coil data if humidistat is used
    2009          181 :             ReheatingCoilType = Alphas(15);
    2010          181 :             ReheatingCoilName = Alphas(16);
    2011          181 :             thisFurnace.SuppHeatCoilType = ReheatingCoilType;
    2012          181 :             thisFurnace.SuppHeatCoilName = ReheatingCoilName;
    2013          181 :             errFlag = false;
    2014          181 :             if (!lAlphaBlanks(15)) {
    2015           25 :                 if (Util::SameString(ReheatingCoilType, "Coil:Heating:Fuel") || Util::SameString(ReheatingCoilType, "Coil:Heating:Electric") ||
    2016           25 :                     Util::SameString(ReheatingCoilType, "Coil:Heating:Desuperheater")) {
    2017              : 
    2018           23 :                     thisFurnace.SuppHeatCoilType_Num = HeatingCoils::GetHeatingCoilTypeNum(state, ReheatingCoilType, ReheatingCoilName, errFlag);
    2019           23 :                     if (errFlag) {
    2020            0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2021            0 :                         ErrorsFound = true;
    2022              :                     } else {
    2023              : 
    2024           23 :                         ValidateComponent(state, ReheatingCoilType, ReheatingCoilName, IsNotOK, CurrentModuleObject);
    2025           23 :                         if (IsNotOK) {
    2026            0 :                             ShowContinueError(state, format("In {} \"{}\"", CurrentModuleObject, Alphas(1)));
    2027            0 :                             ErrorsFound = true;
    2028              : 
    2029              :                         } else { // mine data from reheat coil
    2030              : 
    2031              :                             // Get the heating coil index
    2032           23 :                             HeatingCoils::GetCoilIndex(state, ReheatingCoilName, thisFurnace.SuppHeatCoilIndex, IsNotOK);
    2033           23 :                             if (IsNotOK) {
    2034            0 :                                 ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2035            0 :                                 ErrorsFound = true;
    2036              :                             }
    2037              : 
    2038              :                             // Get the design supplemental heating capacity
    2039           23 :                             errFlag = false;
    2040           23 :                             thisFurnace.DesignSuppHeatingCapacity =
    2041           23 :                                 HeatingCoils::GetCoilCapacity(state, ReheatingCoilType, ReheatingCoilName, errFlag);
    2042           23 :                             if (errFlag) {
    2043            0 :                                 ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2044            0 :                                 ErrorsFound = true;
    2045              :                             }
    2046              : 
    2047              :                             // Get the Reheat Coil Inlet Node
    2048           23 :                             errFlag = false;
    2049           23 :                             ReheatCoilInletNode = HeatingCoils::GetCoilInletNode(state, ReheatingCoilType, ReheatingCoilName, errFlag);
    2050           23 :                             if (errFlag) {
    2051            0 :                                 ShowContinueError(state, format("...occurs in {} \"{}\"", CurrentModuleObject, Alphas(1)));
    2052            0 :                                 ErrorsFound = true;
    2053              :                             }
    2054              : 
    2055              :                             // Get the Reheat Coil Outlet Node
    2056           23 :                             errFlag = false;
    2057           23 :                             ReheatCoilOutletNode = HeatingCoils::GetCoilOutletNode(state, ReheatingCoilType, ReheatingCoilName, errFlag);
    2058           23 :                             if (errFlag) {
    2059            0 :                                 ShowContinueError(state, format("...occurs in {} \"{}\"", CurrentModuleObject, Alphas(1)));
    2060            0 :                                 ErrorsFound = true;
    2061              :                             }
    2062              : 
    2063              :                         } // IF (IsNotOK) THEN
    2064              :                     }
    2065              : 
    2066            0 :                 } else if (Util::SameString(ReheatingCoilType, "Coil:Heating:Water")) {
    2067            0 :                     thisFurnace.SuppHeatCoilType_Num = HVAC::Coil_HeatingWater;
    2068            0 :                     ValidateComponent(state, ReheatingCoilType, ReheatingCoilName, IsNotOK, CurrentModuleObject);
    2069            0 :                     if (IsNotOK) {
    2070            0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2071            0 :                         ErrorsFound = true;
    2072              :                     } else { // mine data from heating coil object
    2073              : 
    2074              :                         // Get the Heating Coil water Inlet or control Node number
    2075            0 :                         errFlag = false;
    2076            0 :                         thisFurnace.SuppCoilControlNode = WaterCoils::GetCoilWaterInletNode(state, "Coil:Heating:Water", ReheatingCoilName, errFlag);
    2077            0 :                         if (errFlag) {
    2078            0 :                             ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    2079            0 :                             ErrorsFound = true;
    2080              :                         }
    2081              : 
    2082              :                         // Get the ReHeat Coil hot water max volume flow rate
    2083            0 :                         errFlag = false;
    2084            0 :                         thisFurnace.MaxSuppCoilFluidFlow =
    2085            0 :                             WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", ReheatingCoilName, errFlag);
    2086            0 :                         if (errFlag) {
    2087            0 :                             ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    2088            0 :                             ErrorsFound = true;
    2089              :                         }
    2090              : 
    2091              :                         // Get the ReHeat Coil Inlet Node
    2092            0 :                         errFlag = false;
    2093            0 :                         ReheatCoilInletNode = WaterCoils::GetCoilInletNode(state, "Coil:Heating:Water", ReheatingCoilName, errFlag);
    2094            0 :                         thisFurnace.SuppCoilAirInletNode = ReheatCoilInletNode;
    2095            0 :                         if (errFlag) {
    2096            0 :                             ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    2097            0 :                             ErrorsFound = true;
    2098              :                         }
    2099              : 
    2100              :                         // Get the ReHeat Coil Outlet Node
    2101            0 :                         errFlag = false;
    2102            0 :                         ReheatCoilOutletNode = WaterCoils::GetCoilOutletNode(state, "Coil:Heating:Water", ReheatingCoilName, errFlag);
    2103            0 :                         thisFurnace.SuppCoilAirOutletNode = ReheatCoilOutletNode;
    2104            0 :                         if (errFlag) {
    2105            0 :                             ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    2106            0 :                             ErrorsFound = true;
    2107              :                         }
    2108              : 
    2109              :                         // check if user has also used a water coil controller, which they should not do
    2110            0 :                         errFlag = false;
    2111            0 :                         HVACControllers::CheckCoilWaterInletNode(state, thisFurnace.CoilControlNode, errFlag);
    2112            0 :                         if (!errFlag) { // then did find a controller so that is bad
    2113            0 :                             ShowSevereError(state,
    2114            0 :                                             format("{} = {} has a conflicting Controller:WaterCoil object", CurrentModuleObject, thisFurnace.Name));
    2115            0 :                             ShowContinueError(state, "Hot water coils are controlled directly by unitary and furnace systems.");
    2116            0 :                             ShowContinueError(state, "No water coil controller should be input for the coil.");
    2117            0 :                             ErrorsFound = true;
    2118              :                         }
    2119              :                     }
    2120              : 
    2121            0 :                 } else if (Util::SameString(ReheatingCoilType, "Coil:Heating:Steam")) {
    2122            0 :                     thisFurnace.SuppHeatCoilType_Num = HVAC::Coil_HeatingSteam;
    2123            0 :                     ValidateComponent(state, ReheatingCoilType, ReheatingCoilName, IsNotOK, CurrentModuleObject);
    2124            0 :                     if (IsNotOK) {
    2125            0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2126            0 :                         ErrorsFound = true;
    2127              :                     } else { // mine data from heating coil object
    2128              : 
    2129            0 :                         errFlag = false;
    2130            0 :                         thisFurnace.SuppHeatCoilIndex = SteamCoils::GetSteamCoilIndex(state, "COIL:HEATING:STEAM", ReheatingCoilName, errFlag);
    2131            0 :                         if (thisFurnace.SuppHeatCoilIndex == 0) {
    2132            0 :                             ShowSevereError(state, format("{} illegal {} = {}", CurrentModuleObject, cAlphaFields(11), ReheatingCoilName));
    2133            0 :                             ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    2134            0 :                             ErrorsFound = true;
    2135              :                         }
    2136              : 
    2137              :                         // Get the Heating Coil steam inlet node number
    2138            0 :                         errFlag = false;
    2139            0 :                         thisFurnace.SuppCoilControlNode = SteamCoils::GetCoilSteamInletNode(state, "Coil:Heating:Steam", ReheatingCoilName, errFlag);
    2140            0 :                         if (errFlag) {
    2141            0 :                             ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    2142            0 :                             ErrorsFound = true;
    2143              :                         }
    2144              : 
    2145              :                         // Get the Heating Coil steam max volume flow rate
    2146            0 :                         thisFurnace.MaxSuppCoilFluidFlow = SteamCoils::GetCoilMaxSteamFlowRate(state, thisFurnace.SuppHeatCoilIndex, errFlag);
    2147            0 :                         if (thisFurnace.MaxSuppCoilFluidFlow > 0.0) {
    2148              :                             SteamDensity =
    2149            0 :                                 Fluid::GetSteam(state)->getSatDensity(state, state.dataFurnaces->TempSteamIn, 1.0, getAirLoopHVACHeatCoolInput);
    2150            0 :                             thisFurnace.MaxSuppCoilFluidFlow =
    2151            0 :                                 SteamCoils::GetCoilMaxSteamFlowRate(state, thisFurnace.SuppHeatCoilIndex, errFlag) * SteamDensity;
    2152              :                         }
    2153              : 
    2154              :                         // Get the Heating Coil Inlet Node
    2155            0 :                         errFlag = false;
    2156            0 :                         ReheatCoilInletNode = SteamCoils::GetCoilAirInletNode(state, thisFurnace.SuppHeatCoilIndex, ReheatingCoilName, errFlag);
    2157            0 :                         thisFurnace.SuppCoilAirInletNode = ReheatCoilInletNode;
    2158            0 :                         if (errFlag) {
    2159            0 :                             ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    2160            0 :                             ErrorsFound = true;
    2161              :                         }
    2162              : 
    2163              :                         // Get the Heating Coil Outlet Node
    2164            0 :                         errFlag = false;
    2165            0 :                         ReheatCoilOutletNode = SteamCoils::GetCoilAirOutletNode(state, thisFurnace.SuppHeatCoilIndex, ReheatingCoilName, errFlag);
    2166            0 :                         thisFurnace.SuppCoilAirOutletNode = ReheatCoilOutletNode;
    2167            0 :                         if (errFlag) {
    2168            0 :                             ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    2169            0 :                             ErrorsFound = true;
    2170              :                         }
    2171              :                     }
    2172              : 
    2173              :                 } else { // Illegal heating coil
    2174            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    2175            0 :                     ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(15), Alphas(15)));
    2176            0 :                     ErrorsFound = true;
    2177              :                 } // IF (Furnace(FurnaceNum)%SuppHeatCoilType_Num == Coil_HeatingGasOrOtherFuel .OR. &, etc.
    2178              : 
    2179              :             } // IF(.NOT. lAlphaBlanks(15))THEN
    2180              : 
    2181          181 :             if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
    2182              : 
    2183          178 :                 if (FanInletNode != thisFurnace.FurnaceInletNodeNum) {
    2184            0 :                     ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2185            0 :                     if (thisFurnace.type == HVAC::UnitarySysType::Furnace_HeatCool) {
    2186            0 :                         ShowContinueError(
    2187              :                             state, "When a blow through fan is specified, the fan inlet node name must be the same as the furnace inlet node name.");
    2188            0 :                         ShowContinueError(state, format("...Fan inlet node name     = {}", state.dataLoopNodes->NodeID(FanInletNode)));
    2189            0 :                         ShowContinueError(state,
    2190            0 :                                           format("...Furnace inlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceInletNodeNum)));
    2191              :                     } else {
    2192            0 :                         ShowContinueError(
    2193              :                             state,
    2194              :                             "When a blow through fan is specified, the fan inlet node name must be the same as the unitary system inlet node name.");
    2195            0 :                         ShowContinueError(state, format("...Fan inlet node name           = {}", state.dataLoopNodes->NodeID(FanInletNode)));
    2196            0 :                         ShowContinueError(
    2197            0 :                             state, format("...UnitarySystem inlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceInletNodeNum)));
    2198              :                     }
    2199            0 :                     ErrorsFound = true;
    2200              :                 }
    2201          178 :                 if (thisFurnace.CoolingCoilUpstream) {
    2202           76 :                     if (FanOutletNode != CoolingCoilInletNode) {
    2203            0 :                         ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2204            0 :                         ShowContinueError(
    2205              :                             state,
    2206              :                             "When a blow through fan is specified, the fan outlet node name must be the same as the cooling coil inlet node name.");
    2207            0 :                         ShowContinueError(state, format("...Fan outlet node name         = {}", state.dataLoopNodes->NodeID(FanOutletNode)));
    2208            0 :                         ShowContinueError(state, format("...Cooling coil inlet node name = {}", state.dataLoopNodes->NodeID(CoolingCoilInletNode)));
    2209            0 :                         ErrorsFound = true;
    2210              :                     }
    2211           76 :                     if (CoolingCoilOutletNode != HeatingCoilInletNode) {
    2212            0 :                         ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2213            0 :                         ShowContinueError(state, "The cooling coil outlet node name must be the same as the heating coil inlet node name.");
    2214            0 :                         ShowContinueError(state, format("...Cooling coil outlet node name = {}", state.dataLoopNodes->NodeID(CoolingCoilOutletNode)));
    2215            0 :                         ShowContinueError(state, format("...Heating coil inlet node name  = {}", state.dataLoopNodes->NodeID(HeatingCoilInletNode)));
    2216            0 :                         ErrorsFound = true;
    2217              :                     }
    2218           76 :                     if ((thisFurnace.Humidistat && thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat) ||
    2219              :                         ReheatCoilInletNode > 0) {
    2220           22 :                         if (HeatingCoilOutletNode != ReheatCoilInletNode) {
    2221            0 :                             ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2222            0 :                             ShowContinueError(state,
    2223              :                                               "When a blow through fan is specified, the heating coil outlet node name must be the same as the "
    2224              :                                               "reheat coil inlet node name.");
    2225            0 :                             ShowContinueError(state,
    2226            0 :                                               format("...Heating coil outlet node name = {}", state.dataLoopNodes->NodeID(HeatingCoilOutletNode)));
    2227            0 :                             ShowContinueError(state,
    2228            0 :                                               format("...Reheat coil inlet node name   = {}", state.dataLoopNodes->NodeID(ReheatCoilInletNode)));
    2229            0 :                             ErrorsFound = true;
    2230              :                         }
    2231           22 :                         if (ReheatCoilOutletNode != thisFurnace.FurnaceOutletNodeNum) {
    2232            0 :                             ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2233            0 :                             if (thisFurnace.type == HVAC::UnitarySysType::Furnace_HeatCool) {
    2234            0 :                                 ShowContinueError(state, "The reheat coil outlet node name must be the same as the furnace outlet node name.");
    2235            0 :                                 ShowContinueError(state,
    2236            0 :                                                   format("...Reheat coil outlet node name = {}", state.dataLoopNodes->NodeID(ReheatCoilOutletNode)));
    2237            0 :                                 ShowContinueError(
    2238              :                                     state,
    2239            0 :                                     format("...Furnace outlet node name     = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    2240              :                             } else {
    2241            0 :                                 ShowContinueError(state, "The reheat coil outlet node name must be the same as the unitary system outlet node name.");
    2242            0 :                                 ShowContinueError(
    2243            0 :                                     state, format("...Reheat coil outlet node name   = {}", state.dataLoopNodes->NodeID(ReheatCoilOutletNode)));
    2244            0 :                                 ShowContinueError(
    2245              :                                     state,
    2246            0 :                                     format("...UnitarySystem outlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    2247              :                             }
    2248            0 :                             ErrorsFound = true;
    2249              :                         }
    2250              :                     } else { // IF((Furnace(FurnaceNum)%Humidistat ...
    2251              :                         // Heating coil outlet node name must be the same as the furnace outlet node name
    2252           54 :                         if (HeatingCoilOutletNode != thisFurnace.FurnaceOutletNodeNum) {
    2253            0 :                             ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    2254            0 :                             if (thisFurnace.type == HVAC::UnitarySysType::Furnace_HeatOnly) {
    2255            0 :                                 ShowContinueError(state,
    2256              :                                                   "When a blow through fan is specified, the heating coil outlet node name must be the same as the "
    2257              :                                                   "furnace outlet node name.");
    2258            0 :                                 ShowContinueError(
    2259            0 :                                     state, format("...Heating coil outlet node name = {}", state.dataLoopNodes->NodeID(HeatingCoilOutletNode)));
    2260            0 :                                 ShowContinueError(
    2261              :                                     state,
    2262            0 :                                     format("...Furnace outlet node name      = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    2263              :                             } else {
    2264            0 :                                 ShowContinueError(state,
    2265              :                                                   "When a blow through fan is specified, the heating coil outlet node name must be the same as the "
    2266              :                                                   "unitary system outlet node name.");
    2267            0 :                                 ShowContinueError(
    2268            0 :                                     state, format("...Heating coil outlet node name  = {}", state.dataLoopNodes->NodeID(HeatingCoilOutletNode)));
    2269            0 :                                 ShowContinueError(
    2270              :                                     state,
    2271            0 :                                     format("...UnitarySystem outlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    2272              :                             }
    2273            0 :                             ErrorsFound = true;
    2274              :                         }
    2275              :                     }
    2276              :                 } else { // IF(Furnace(FurnaceNum)%CoolingCoilUpstream)THEN
    2277          102 :                     if (FanOutletNode != HeatingCoilInletNode) {
    2278            0 :                         ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2279            0 :                         ShowContinueError(
    2280              :                             state,
    2281              :                             "When a blow through fan is specified, the fan outlet node name must be the same as the heating coil inlet node name.");
    2282            0 :                         ShowContinueError(state, format("...Fan outlet node name         = {}", state.dataLoopNodes->NodeID(FanOutletNode)));
    2283            0 :                         ShowContinueError(state, format("...Heating coil inlet node name = {}", state.dataLoopNodes->NodeID(HeatingCoilInletNode)));
    2284            0 :                         ErrorsFound = true;
    2285              :                     }
    2286          102 :                     if (HeatingCoilOutletNode != CoolingCoilInletNode) {
    2287            0 :                         ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2288            0 :                         ShowContinueError(state, "The heating coil outlet node name must be the same as the cooling coil inlet node name.");
    2289            0 :                         ShowContinueError(state, format("...Heating coil outlet node name = {}", state.dataLoopNodes->NodeID(HeatingCoilOutletNode)));
    2290            0 :                         ShowContinueError(state, format("...Cooling coil inlet node name  = {}", state.dataLoopNodes->NodeID(CoolingCoilInletNode)));
    2291            0 :                         ErrorsFound = true;
    2292              :                     }
    2293          102 :                     if (CoolingCoilOutletNode != thisFurnace.FurnaceOutletNodeNum) {
    2294            0 :                         ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2295            0 :                         if (thisFurnace.type == HVAC::UnitarySysType::Furnace_HeatCool) {
    2296            0 :                             ShowContinueError(state,
    2297              :                                               "When a blow through fan is specified, the cooling coil outlet node name must be the same as the "
    2298              :                                               "furnace outlet node name.");
    2299            0 :                             ShowContinueError(state,
    2300            0 :                                               format("...Cooling coil outlet node name = {}", state.dataLoopNodes->NodeID(CoolingCoilOutletNode)));
    2301            0 :                             ShowContinueError(
    2302              :                                 state,
    2303            0 :                                 format("...Furnace outlet node name      = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    2304              :                         } else {
    2305            0 :                             ShowContinueError(state,
    2306              :                                               "When a blow through fan is specified, the cooling coil outlet node name must be the same as the "
    2307              :                                               "unitary system outlet node name.");
    2308            0 :                             ShowContinueError(state,
    2309            0 :                                               format("...Cooling coil outlet node name   = {}", state.dataLoopNodes->NodeID(CoolingCoilOutletNode)));
    2310            0 :                             ShowContinueError(
    2311              :                                 state,
    2312            0 :                                 format("...UnitarySystem outlet node name  = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    2313              :                         }
    2314            0 :                         ErrorsFound = true;
    2315              :                     }
    2316              :                 }
    2317              : 
    2318              :             } else { // ELSE from IF(Furnace(FurnaceNum)%FanPlace .EQ. BlowThru)THEN
    2319              : 
    2320            3 :                 if (thisFurnace.CoolingCoilUpstream) {
    2321            1 :                     if (CoolingCoilInletNode != thisFurnace.FurnaceInletNodeNum) {
    2322            0 :                         ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2323            0 :                         if (thisFurnace.type == HVAC::UnitarySysType::Furnace_HeatCool) {
    2324            0 :                             ShowContinueError(state,
    2325              :                                               "When a draw through fan is specified, the cooling coil inlet node name must be the same as the "
    2326              :                                               "furnace inlet node name.");
    2327            0 :                             ShowContinueError(state,
    2328            0 :                                               format("...Cooling coil inlet node name = {}", state.dataLoopNodes->NodeID(CoolingCoilInletNode)));
    2329            0 :                             ShowContinueError(
    2330            0 :                                 state, format("...Furnace inlet node name      = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceInletNodeNum)));
    2331              :                         } else {
    2332            0 :                             ShowContinueError(state,
    2333              :                                               "When a draw through fan is specified, the cooling coil inlet node name must be the same as the "
    2334              :                                               "unitary system inlet node name.");
    2335            0 :                             ShowContinueError(state,
    2336            0 :                                               format("...Cooling coil inlet node name  = {}", state.dataLoopNodes->NodeID(CoolingCoilInletNode)));
    2337            0 :                             ShowContinueError(
    2338            0 :                                 state, format("...UnitarySystem inlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceInletNodeNum)));
    2339              :                         }
    2340            0 :                         ErrorsFound = true;
    2341              :                     }
    2342            1 :                     if (CoolingCoilOutletNode != HeatingCoilInletNode) {
    2343            0 :                         ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2344            0 :                         ShowContinueError(state, "The cooling coil outlet node name must be the same as the heating coil inlet node name.");
    2345            0 :                         ShowContinueError(state, format("...Cooling coil outlet node name = {}", state.dataLoopNodes->NodeID(CoolingCoilOutletNode)));
    2346            0 :                         ShowContinueError(state, format("...Heating coil inlet node name  = {}", state.dataLoopNodes->NodeID(HeatingCoilInletNode)));
    2347            0 :                         ErrorsFound = true;
    2348              :                     }
    2349            1 :                     if (HeatingCoilOutletNode != FanInletNode) {
    2350            0 :                         ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2351            0 :                         ShowContinueError(
    2352              :                             state,
    2353              :                             "When a draw through fan is specified, the heating coil outlet node name must be the same as the fan inlet node name.");
    2354            0 :                         ShowContinueError(state, format("...Heating coil outlet node name = {}", state.dataLoopNodes->NodeID(HeatingCoilOutletNode)));
    2355            0 :                         ShowContinueError(state, format("...Fan inlet node name           = {}", state.dataLoopNodes->NodeID(FanInletNode)));
    2356            0 :                         ErrorsFound = true;
    2357              :                     }
    2358            1 :                     if ((thisFurnace.Humidistat && thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat) ||
    2359              :                         ReheatCoilInletNode > 0) {
    2360            1 :                         if (FanOutletNode != ReheatCoilInletNode) {
    2361            0 :                             ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2362            0 :                             ShowContinueError(state,
    2363              :                                               "When a draw through fan is specified, the fan outlet node name must be the same as the reheat coil "
    2364              :                                               "inlet node name.");
    2365            0 :                             ShowContinueError(state, format("...Fan outlet node name        = {}", state.dataLoopNodes->NodeID(FanOutletNode)));
    2366            0 :                             ShowContinueError(state, format("...Reheat coil inlet node name = {}", state.dataLoopNodes->NodeID(ReheatCoilInletNode)));
    2367            0 :                             ErrorsFound = true;
    2368              :                         }
    2369            1 :                         if (ReheatCoilOutletNode != thisFurnace.FurnaceOutletNodeNum) {
    2370            0 :                             ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2371            0 :                             if (thisFurnace.type == HVAC::UnitarySysType::Furnace_HeatCool) {
    2372            0 :                                 ShowContinueError(state, "The reheat coil outlet node name must be the same as the furnace outlet node name.");
    2373            0 :                                 ShowContinueError(state,
    2374            0 :                                                   format("...Reheat coil outlet node name = {}", state.dataLoopNodes->NodeID(ReheatCoilOutletNode)));
    2375            0 :                                 ShowContinueError(
    2376              :                                     state,
    2377            0 :                                     format("...Furnace outlet node name     = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    2378              :                             } else {
    2379            0 :                                 ShowContinueError(state, "The reheat coil outlet node name must be the same as the unitary system outlet node name.");
    2380            0 :                                 ShowContinueError(
    2381            0 :                                     state, format("...Reheat coil outlet node name   = {}", state.dataLoopNodes->NodeID(ReheatCoilOutletNode)));
    2382            0 :                                 ShowContinueError(
    2383              :                                     state,
    2384            0 :                                     format("...UnitarySystem outlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    2385              :                             }
    2386            0 :                             ErrorsFound = true;
    2387              :                         }
    2388              :                     } else {
    2389            0 :                         if (FanOutletNode != thisFurnace.FurnaceOutletNodeNum) {
    2390            0 :                             ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2391            0 :                             ShowContinueError(state,
    2392              :                                               "When a draw through fan is specified, the fan outlet node name must be the same as the unitary system "
    2393              :                                               "outlet node name.");
    2394            0 :                             ShowContinueError(state, format("...Fan outlet node name        = {}", state.dataLoopNodes->NodeID(FanOutletNode)));
    2395            0 :                             ShowContinueError(
    2396              :                                 state,
    2397            0 :                                 format("...Unitary system outlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    2398            0 :                             ErrorsFound = true;
    2399              :                         }
    2400              :                     }
    2401              :                 } else { // IF(Furnace(FurnaceNum)%CoolingCoilUpstream)THEN
    2402            2 :                     if (HeatingCoilInletNode != thisFurnace.FurnaceInletNodeNum) {
    2403            0 :                         ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2404            0 :                         if (thisFurnace.type == HVAC::UnitarySysType::Furnace_HeatCool) {
    2405            0 :                             ShowContinueError(state,
    2406              :                                               "When a draw through fan is specified, the heating coil inlet node name must be the same as the "
    2407              :                                               "furnace inlet node name.");
    2408            0 :                             ShowContinueError(state,
    2409            0 :                                               format("...Heating coil inlet node name = {}", state.dataLoopNodes->NodeID(HeatingCoilInletNode)));
    2410            0 :                             ShowContinueError(
    2411            0 :                                 state, format("...Furnace inlet node name      = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceInletNodeNum)));
    2412              :                         } else {
    2413            0 :                             ShowContinueError(state,
    2414              :                                               "When a draw through fan is specified, the heating coil inlet node name must be the same as the "
    2415              :                                               "unitary system inlet node name.");
    2416            0 :                             ShowContinueError(state,
    2417            0 :                                               format("...Heating coil inlet node name  = {}", state.dataLoopNodes->NodeID(HeatingCoilInletNode)));
    2418            0 :                             ShowContinueError(
    2419            0 :                                 state, format("...UnitarySystem inlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceInletNodeNum)));
    2420              :                         }
    2421            0 :                         ErrorsFound = true;
    2422              :                     }
    2423            2 :                     if (HeatingCoilOutletNode != CoolingCoilInletNode) {
    2424            0 :                         ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2425            0 :                         ShowContinueError(state, "The heating coil outlet node name must be the same as the cooling coil inlet node name.");
    2426            0 :                         ShowContinueError(state, format("...Heating coil outlet node name = {}", state.dataLoopNodes->NodeID(HeatingCoilOutletNode)));
    2427            0 :                         ShowContinueError(state, format("...Cooling coil inlet node name  = {}", state.dataLoopNodes->NodeID(CoolingCoilInletNode)));
    2428            0 :                         ErrorsFound = true;
    2429              :                     }
    2430            2 :                     if (CoolingCoilOutletNode != FanInletNode) {
    2431            0 :                         ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2432            0 :                         ShowContinueError(
    2433              :                             state,
    2434              :                             "When a draw through fan is specified, the cooling coil outlet node name must be the same as the fan inlet node name.");
    2435            0 :                         ShowContinueError(state, format("...Cooling coil outlet node name = {}", state.dataLoopNodes->NodeID(CoolingCoilOutletNode)));
    2436            0 :                         ShowContinueError(state, format("...Fan inlet node name           = {}", state.dataLoopNodes->NodeID(FanInletNode)));
    2437            0 :                         ErrorsFound = true;
    2438              :                     }
    2439            2 :                     if (FanOutletNode != thisFurnace.FurnaceOutletNodeNum) {
    2440            0 :                         ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2441            0 :                         if (thisFurnace.type == HVAC::UnitarySysType::Furnace_HeatCool) {
    2442            0 :                             ShowContinueError(
    2443              :                                 state,
    2444              :                                 "When a draw through fan is specified, the fan outlet node name must be the same as the furnace outlet node name.");
    2445            0 :                             ShowContinueError(state, format("...Fan outlet node name     = {}", state.dataLoopNodes->NodeID(FanOutletNode)));
    2446            0 :                             ShowContinueError(
    2447            0 :                                 state, format("...Furnace outlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    2448              :                         } else {
    2449            0 :                             ShowContinueError(state,
    2450              :                                               "When a draw through fan is specified, the fan outlet node name must be the same as the unitary system "
    2451              :                                               "outlet node name.");
    2452            0 :                             ShowContinueError(state, format("...Fan outlet node name           = {}", state.dataLoopNodes->NodeID(FanOutletNode)));
    2453            0 :                             ShowContinueError(
    2454              :                                 state,
    2455            0 :                                 format("...UnitarySystem outlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    2456              :                         }
    2457            0 :                         ErrorsFound = true;
    2458              :                     }
    2459              :                 }
    2460              :             } // ELSE from IF(Furnace(FurnaceNum)%FanPlace .EQ. BlowThru)THEN
    2461              : 
    2462              :             // Add fan to component sets array
    2463          362 :             BranchNodeConnections::SetUpCompSets(state,
    2464              :                                                  CurrentModuleObject,
    2465          181 :                                                  Alphas(1),
    2466          181 :                                                  Alphas(7),
    2467          181 :                                                  Alphas(8),
    2468          181 :                                                  state.dataLoopNodes->NodeID(FanInletNode),
    2469          181 :                                                  state.dataLoopNodes->NodeID(FanOutletNode));
    2470              : 
    2471              :             // Add DX cooling coil to component sets array
    2472          181 :             if (thisFurnace.bIsIHP) {
    2473            0 :                 BranchNodeConnections::SetUpCompSets(state,
    2474              :                                                      CurrentModuleObject,
    2475            0 :                                                      Alphas(1),
    2476            0 :                                                      Alphas(12),
    2477            0 :                                                      Alphas(13) + " Cooling Coil",
    2478            0 :                                                      state.dataLoopNodes->NodeID(CoolingCoilInletNode),
    2479            0 :                                                      state.dataLoopNodes->NodeID(CoolingCoilOutletNode));
    2480              :             } else {
    2481          362 :                 BranchNodeConnections::SetUpCompSets(state,
    2482              :                                                      CurrentModuleObject,
    2483          181 :                                                      Alphas(1),
    2484          181 :                                                      Alphas(12),
    2485          181 :                                                      Alphas(13),
    2486          181 :                                                      state.dataLoopNodes->NodeID(CoolingCoilInletNode),
    2487          181 :                                                      state.dataLoopNodes->NodeID(CoolingCoilOutletNode));
    2488              :             }
    2489              : 
    2490              :             // Add heating coil to component sets array
    2491          181 :             if (thisFurnace.bIsIHP) {
    2492            0 :                 BranchNodeConnections::SetUpCompSets(state,
    2493              :                                                      CurrentModuleObject,
    2494            0 :                                                      Alphas(1),
    2495            0 :                                                      Alphas(10),
    2496            0 :                                                      Alphas(11) + " Heating Coil",
    2497            0 :                                                      state.dataLoopNodes->NodeID(HeatingCoilInletNode),
    2498            0 :                                                      state.dataLoopNodes->NodeID(HeatingCoilOutletNode));
    2499              :             } else {
    2500          362 :                 BranchNodeConnections::SetUpCompSets(state,
    2501              :                                                      CurrentModuleObject,
    2502          181 :                                                      Alphas(1),
    2503          181 :                                                      Alphas(10),
    2504          181 :                                                      Alphas(11),
    2505          181 :                                                      state.dataLoopNodes->NodeID(HeatingCoilInletNode),
    2506          181 :                                                      state.dataLoopNodes->NodeID(HeatingCoilOutletNode));
    2507              :             }
    2508              : 
    2509          181 :             if (ReheatCoilInletNode > 0) {
    2510              : 
    2511              :                 // Add reheating coil to component sets array
    2512           46 :                 BranchNodeConnections::SetUpCompSets(state,
    2513              :                                                      CurrentModuleObject,
    2514           23 :                                                      Alphas(1),
    2515           23 :                                                      Alphas(15),
    2516           23 :                                                      Alphas(16),
    2517           23 :                                                      state.dataLoopNodes->NodeID(ReheatCoilInletNode),
    2518           23 :                                                      state.dataLoopNodes->NodeID(ReheatCoilOutletNode));
    2519              :             }
    2520              : 
    2521              :             // Set the furnace max outlet temperature
    2522          181 :             thisFurnace.DesignMaxOutletTemp = Numbers(1);
    2523              : 
    2524          181 :             thisFurnace.MaxCoolAirVolFlow = Numbers(2);
    2525          181 :             if (thisFurnace.MaxCoolAirVolFlow <= 0 && thisFurnace.MaxCoolAirVolFlow != DataSizing::AutoSize) {
    2526            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    2527            0 :                 ShowContinueError(state, format("Illegal {} = {:.7T}", cNumericFields(2), Numbers(2)));
    2528            0 :                 ErrorsFound = true;
    2529              :             }
    2530              : 
    2531          181 :             thisFurnace.MaxHeatAirVolFlow = Numbers(3);
    2532          181 :             if (thisFurnace.MaxHeatAirVolFlow <= 0 && thisFurnace.MaxHeatAirVolFlow != DataSizing::AutoSize) {
    2533            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    2534            0 :                 ShowContinueError(state, format("Illegal {} = {:.7T}", cNumericFields(3), Numbers(3)));
    2535            0 :                 ErrorsFound = true;
    2536              :             }
    2537              : 
    2538          181 :             thisFurnace.MaxNoCoolHeatAirVolFlow = Numbers(4);
    2539          181 :             if (thisFurnace.MaxNoCoolHeatAirVolFlow < 0 && thisFurnace.MaxNoCoolHeatAirVolFlow != DataSizing::AutoSize) {
    2540            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    2541            0 :                 ShowContinueError(state, format("Illegal {} = {:.7T}", cNumericFields(4), Numbers(4)));
    2542            0 :                 ErrorsFound = true;
    2543              :             }
    2544              : 
    2545          181 :             if (Numbers(2) != DataSizing::AutoSize && Numbers(3) != DataSizing::AutoSize && Numbers(4) != DataSizing::AutoSize) {
    2546           25 :                 thisFurnace.DesignFanVolFlowRate = max(Numbers(2), Numbers(3), Numbers(4));
    2547              :             } else {
    2548          156 :                 thisFurnace.DesignFanVolFlowRate = DataSizing::AutoSize;
    2549              :             }
    2550              : 
    2551          181 :             if (thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingAirToAirVariableSpeed) {
    2552            4 :                 errFlag = false;
    2553            4 :                 if (thisFurnace.bIsIHP) {
    2554            0 :                     thisFurnace.CoolingCoilIndex = IntegratedHeatPump::GetCoilIndexIHP(state, CoolingCoilType, CoolingCoilName, errFlag);
    2555            0 :                     IHPCoilName = state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).SCCoilName;
    2556            0 :                     thisFurnace.MaxCoolAirVolFlow =
    2557            0 :                         VariableSpeedCoils::GetCoilAirFlowRateVariableSpeed(state, "COIL:COOLING:DX:VARIABLESPEED", IHPCoilName, errFlag);
    2558              :                 } else {
    2559            4 :                     thisFurnace.MaxCoolAirVolFlow =
    2560            4 :                         VariableSpeedCoils::GetCoilAirFlowRateVariableSpeed(state, CoolingCoilType, CoolingCoilName, errFlag);
    2561              :                 }
    2562              : 
    2563            4 :                 if (errFlag) {
    2564            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2565            0 :                     ErrorsFound = true;
    2566              :                 }
    2567              : 
    2568            4 :                 thisFurnace.MaxNoCoolHeatAirVolFlow = min(thisFurnace.MaxHeatAirVolFlow, thisFurnace.MaxCoolAirVolFlow);
    2569            4 :                 if (thisFurnace.MaxHeatAirVolFlow != DataSizing::AutoSize && thisFurnace.MaxCoolAirVolFlow != DataSizing::AutoSize) {
    2570            0 :                     thisFurnace.DesignFanVolFlowRate = max(thisFurnace.MaxHeatAirVolFlow, thisFurnace.MaxCoolAirVolFlow);
    2571              :                 } else {
    2572            4 :                     thisFurnace.DesignFanVolFlowRate = DataSizing::AutoSize;
    2573              :                 }
    2574              :             }
    2575              : 
    2576          181 :             if (thisFurnace.ActualFanVolFlowRate != DataSizing::AutoSize) {
    2577           25 :                 if (thisFurnace.ActualFanVolFlowRate < thisFurnace.MaxCoolAirVolFlow && thisFurnace.MaxCoolAirVolFlow != DataSizing::AutoSize) {
    2578            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    2579            0 :                     ShowContinueError(
    2580              :                         state,
    2581            0 :                         format("... air flow rate = {:.7T} in fan object {} is less than the maximum HVAC system air flow rate in cooling mode.",
    2582            0 :                                thisFurnace.ActualFanVolFlowRate,
    2583              :                                FanName));
    2584            0 :                     ShowContinueError(state, format(" The {} is reset to the fan flow rate and the simulation continues.", cNumericFields(2)));
    2585            0 :                     thisFurnace.MaxCoolAirVolFlow = thisFurnace.ActualFanVolFlowRate;
    2586            0 :                     thisFurnace.DesignFanVolFlowRate = thisFurnace.ActualFanVolFlowRate;
    2587              :                 }
    2588           25 :                 if (thisFurnace.ActualFanVolFlowRate < thisFurnace.MaxHeatAirVolFlow && thisFurnace.MaxHeatAirVolFlow != DataSizing::AutoSize) {
    2589            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    2590            0 :                     ShowContinueError(
    2591              :                         state,
    2592            0 :                         format("... air flow rate = {:.7T} in fan object {} is less than the maximum HVAC system air flow rate in heating mode.",
    2593            0 :                                thisFurnace.ActualFanVolFlowRate,
    2594              :                                FanName));
    2595            0 :                     ShowContinueError(state, format(" The {} is reset to the fan flow rate and the simulation continues.", cNumericFields(3)));
    2596            0 :                     thisFurnace.MaxHeatAirVolFlow = thisFurnace.ActualFanVolFlowRate;
    2597            0 :                     thisFurnace.DesignFanVolFlowRate = thisFurnace.ActualFanVolFlowRate;
    2598              :                 }
    2599              :             }
    2600              : 
    2601          181 :             if (thisFurnace.fanOpModeSched != nullptr) {
    2602              :                 // Is this correct? 0.0 for max also?
    2603          161 :                 if (!thisFurnace.fanOpModeSched->checkMinMaxVals(state, Clusive::In, 0.0, Clusive::In, 0.0)) {
    2604              :                     //           set air flow control mode:
    2605              :                     //             UseCompressorOnFlow = operate at last cooling or heating air flow requested when compressor is off
    2606              :                     //             UseCompressorOffFlow = operate at value specified by user
    2607              :                     //           AirFlowControl only valid if fan opmode = ContFanCycComp
    2608           96 :                     if (thisFurnace.MaxNoCoolHeatAirVolFlow == 0.0) {
    2609            1 :                         thisFurnace.AirFlowControl = AirFlowControlConstFan::UseCompressorOnFlow;
    2610              :                     } else {
    2611           95 :                         thisFurnace.AirFlowControl = AirFlowControlConstFan::UseCompressorOffFlow;
    2612              :                     }
    2613              :                 }
    2614              :             }
    2615              : 
    2616          181 :             if (thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingAirToAirVariableSpeed) {
    2617            4 :                 errFlag = false;
    2618            4 :                 if (thisFurnace.bIsIHP) {
    2619            0 :                     thisFurnace.CoolingCoilIndex = IntegratedHeatPump::GetCoilIndexIHP(state, CoolingCoilType, CoolingCoilName, errFlag);
    2620            0 :                     IHPCoilName = state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).SCCoilName;
    2621            0 :                     thisFurnace.DesignCoolingCapacity =
    2622            0 :                         VariableSpeedCoils::GetCoilCapacityVariableSpeed(state, "COIL:COOLING:DX:VARIABLESPEED", IHPCoilName, errFlag);
    2623              :                 } else {
    2624            4 :                     thisFurnace.DesignCoolingCapacity =
    2625            4 :                         VariableSpeedCoils::GetCoilCapacityVariableSpeed(state, CoolingCoilType, CoolingCoilName, errFlag);
    2626              :                 }
    2627              : 
    2628            4 :                 if (errFlag) {
    2629            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2630            0 :                     ErrorsFound = true;
    2631              :                 }
    2632              :             }
    2633              : 
    2634              :             // Set heating convergence tolerance
    2635          181 :             thisFurnace.HeatingConvergenceTolerance = 0.001;
    2636              : 
    2637              :             // Set cooling convergence tolerance
    2638          181 :             thisFurnace.CoolingConvergenceTolerance = 0.001;
    2639              : 
    2640              :             // set minimum outdoor temperature for compressor operation
    2641          181 :             SetMinOATCompressor(state, FurnaceNum, cCurrentModuleObject, ErrorsFound);
    2642              : 
    2643              :         } // End of the HeatCool Furnace Loop
    2644              : 
    2645              :         // Get the data for the Unitary System HeatPump AirToAir (UnitarySystem:HeatPump:AirToAir)
    2646          132 :         for (int HeatPumpNum = 1; HeatPumpNum <= NumHeatPump; ++HeatPumpNum) {
    2647              : 
    2648           35 :             CurrentModuleObject = "AirLoopHVAC:UnitaryHeatPump:AirToAir";
    2649           35 :             FanInletNode = 0;
    2650           35 :             FanOutletNode = 0;
    2651           35 :             CoolingCoilInletNode = 0;
    2652           35 :             CoolingCoilOutletNode = 0;
    2653           35 :             HeatingCoilInletNode = 0;
    2654           35 :             HeatingCoilOutletNode = 0;
    2655           35 :             SupHeatCoilInletNode = 0;
    2656           35 :             SupHeatCoilOutletNode = 0;
    2657           35 :             CoolingCoilType = ' ';
    2658           35 :             CoolingCoilName = ' ';
    2659           35 :             HeatingCoilType = ' ';
    2660           35 :             HeatingCoilName = ' ';
    2661              : 
    2662           35 :             FurnaceNum = NumHeatOnly + NumHeatCool + NumUnitaryHeatOnly + NumUnitaryHeatCool + HeatPumpNum;
    2663           35 :             auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    2664           35 :             thisFurnace.iterationMode.allocate(3);
    2665              : 
    2666           35 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    2667              :                                                                      CurrentModuleObject,
    2668              :                                                                      HeatPumpNum,
    2669              :                                                                      Alphas,
    2670              :                                                                      NumAlphas,
    2671              :                                                                      Numbers,
    2672              :                                                                      NumNumbers,
    2673              :                                                                      IOStatus,
    2674              :                                                                      lNumericBlanks,
    2675              :                                                                      lAlphaBlanks,
    2676              :                                                                      cAlphaFields,
    2677              :                                                                      cNumericFields);
    2678              : 
    2679           70 :             GlobalNames::VerifyUniqueInterObjectName(
    2680           35 :                 state, state.dataFurnaces->UniqueFurnaceNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
    2681              : 
    2682           35 :             thisFurnace.type = HVAC::UnitarySysType::Unitary_HeatPump_AirToAir;
    2683           35 :             thisFurnace.Name = Alphas(1);
    2684              : 
    2685           35 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, thisFurnace.Name};
    2686              : 
    2687           35 :             if (lAlphaBlanks(2)) {
    2688            6 :                 thisFurnace.availSched = Sched::GetScheduleAlwaysOn(state);
    2689           29 :             } else if ((thisFurnace.availSched = Sched::GetSchedule(state, Alphas(2))) == nullptr) {
    2690            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(2), Alphas(2));
    2691            0 :                 ErrorsFound = true;
    2692              :             }
    2693              : 
    2694           35 :             thisFurnace.FurnaceInletNodeNum =
    2695           35 :                 NodeInputManager::GetOnlySingleNode(state,
    2696           35 :                                                     Alphas(3),
    2697              :                                                     ErrorsFound,
    2698              :                                                     DataLoopNode::ConnectionObjectType::AirLoopHVACUnitaryHeatPumpAirToAir,
    2699           35 :                                                     Alphas(1),
    2700              :                                                     DataLoopNode::NodeFluidType::Air,
    2701              :                                                     DataLoopNode::ConnectionType::Inlet,
    2702              :                                                     NodeInputManager::CompFluidStream::Primary,
    2703              :                                                     DataLoopNode::ObjectIsParent);
    2704              : 
    2705           35 :             thisFurnace.FurnaceOutletNodeNum =
    2706           70 :                 NodeInputManager::GetOnlySingleNode(state,
    2707           35 :                                                     Alphas(4),
    2708              :                                                     ErrorsFound,
    2709              :                                                     DataLoopNode::ConnectionObjectType::AirLoopHVACUnitaryHeatPumpAirToAir,
    2710           35 :                                                     Alphas(1),
    2711              :                                                     DataLoopNode::NodeFluidType::Air,
    2712              :                                                     DataLoopNode::ConnectionType::Outlet,
    2713              :                                                     NodeInputManager::CompFluidStream::Primary,
    2714              :                                                     DataLoopNode::ObjectIsParent);
    2715              : 
    2716           35 :             BranchNodeConnections::TestCompSet(state, CurrentModuleObject, Alphas(1), Alphas(3), Alphas(4), "Air Nodes");
    2717              : 
    2718              :             // Get the Controlling Zone or Location of the Furnace Thermostat
    2719           35 :             thisFurnace.ControlZoneNum = Util::FindItemInList(Alphas(5), state.dataHeatBal->Zone);
    2720           35 :             if (thisFurnace.ControlZoneNum == 0) {
    2721            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    2722            0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(5), Alphas(5)));
    2723            0 :                 ErrorsFound = true;
    2724              :             }
    2725              : 
    2726              :             // Get the node number for the zone with the thermostat
    2727           35 :             if (thisFurnace.ControlZoneNum > 0) {
    2728           35 :                 AirNodeFound = false;
    2729           35 :                 AirLoopFound = false;
    2730           35 :                 int ControlledZoneNum = thisFurnace.ControlZoneNum;
    2731              :                 //             Find the controlled zone number for the specified thermostat location
    2732           35 :                 thisFurnace.NodeNumOfControlledZone = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).ZoneNode;
    2733              :                 //             Determine if furnace is on air loop served by the thermostat location specified
    2734           35 :                 for (int zoneInNode = 1; zoneInNode <= state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).NumInletNodes; ++zoneInNode) {
    2735           35 :                     int AirLoopNumber = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).InletNodeAirLoopNum(zoneInNode);
    2736           35 :                     if (AirLoopNumber > 0) {
    2737           35 :                         for (int BranchNum = 1; BranchNum <= state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).NumBranches; ++BranchNum) {
    2738           65 :                             for (int CompNum = 1;
    2739           65 :                                  CompNum <= state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).Branch(BranchNum).TotalComponents;
    2740              :                                  ++CompNum) {
    2741           65 :                                 if (!Util::SameString(state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).Branch(BranchNum).Comp(CompNum).Name,
    2742          165 :                                                       Alphas(1)) ||
    2743           35 :                                     !Util::SameString(
    2744           35 :                                         state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).Branch(BranchNum).Comp(CompNum).TypeOf,
    2745              :                                         CurrentModuleObject)) {
    2746           30 :                                     continue;
    2747              :                                 }
    2748           35 :                                 AirLoopFound = true;
    2749           35 :                                 thisFurnace.ZoneInletNode = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).InletNode(zoneInNode);
    2750           35 :                                 break;
    2751              :                             }
    2752           35 :                             if (AirLoopFound) {
    2753           35 :                                 break;
    2754              :                             }
    2755              :                         }
    2756          115 :                         for (TstatZoneNum = 1; TstatZoneNum <= state.dataZoneCtrls->NumTempControlledZones; ++TstatZoneNum) {
    2757           80 :                             if (state.dataZoneCtrls->TempControlledZone(TstatZoneNum).ActualZoneNum != thisFurnace.ControlZoneNum) {
    2758           45 :                                 continue;
    2759              :                             }
    2760           35 :                             AirNodeFound = true;
    2761              :                         }
    2762           35 :                         for (TstatZoneNum = 1; TstatZoneNum <= state.dataZoneCtrls->NumComfortControlledZones; ++TstatZoneNum) {
    2763            0 :                             if (state.dataZoneCtrls->ComfortControlledZone(TstatZoneNum).ActualZoneNum != thisFurnace.ControlZoneNum) {
    2764            0 :                                 continue;
    2765              :                             }
    2766            0 :                             AirNodeFound = true;
    2767              :                         }
    2768              :                     }
    2769           35 :                     if (AirLoopFound) {
    2770           35 :                         break;
    2771              :                     }
    2772              :                 }
    2773           35 :                 if (!AirNodeFound) {
    2774            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    2775            0 :                     ShowContinueError(state, "Did not find air node (zone with thermostat).");
    2776            0 :                     ShowContinueError(state, format("Specified {} = {}", cAlphaFields(5), Alphas(5)));
    2777            0 :                     ShowContinueError(
    2778              :                         state, "Both a ZoneHVAC:EquipmentConnections object and a ZoneControl:Thermostat object must be specified for this zone.");
    2779            0 :                     ErrorsFound = true;
    2780              :                 }
    2781           35 :                 if (!AirLoopFound) {
    2782            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    2783            0 :                     ShowContinueError(state, "Did not find correct AirLoopHVAC.");
    2784            0 :                     ShowContinueError(state, format("Specified {} = {}", cAlphaFields(5), Alphas(5)));
    2785            0 :                     ErrorsFound = true;
    2786              :                 }
    2787              :             }
    2788              : 
    2789              :             // Get fan data
    2790           35 :             FanName = Alphas(7);
    2791              : 
    2792           35 :             thisFurnace.fanType = static_cast<HVAC::FanType>(getEnumValue(HVAC::fanTypeNamesUC, Alphas(6)));
    2793              : 
    2794           35 :             if (thisFurnace.fanType == HVAC::FanType::OnOff || thisFurnace.fanType == HVAC::FanType::Constant) {
    2795              : 
    2796           35 :                 if ((thisFurnace.FanIndex = Fans::GetFanIndex(state, FanName)) == 0) {
    2797            0 :                     ShowSevereItemNotFound(state, eoh, cAlphaFields(7), FanName);
    2798            0 :                     ErrorsFound = true;
    2799              :                 } else {
    2800           35 :                     auto *fan = state.dataFans->fans(thisFurnace.FanIndex);
    2801           35 :                     FanInletNode = fan->inletNodeNum;
    2802           35 :                     FanOutletNode = fan->outletNodeNum;
    2803           35 :                     thisFurnace.fanAvailSched = fan->availSched;
    2804           35 :                     thisFurnace.ActualFanVolFlowRate = fan->maxAirFlowRate;
    2805              :                 }
    2806              :             }
    2807              : 
    2808              :             // Get heating coil type and name data
    2809           35 :             HeatingCoilType = Alphas(8);
    2810           35 :             HeatingCoilName = Alphas(9);
    2811              : 
    2812           35 :             errFlag = false;
    2813              : 
    2814           68 :             if (Util::SameString(HeatingCoilType, "COIL:HEATING:DX:VARIABLESPEED") ||
    2815           68 :                 Util::SameString(HeatingCoilType, "COILSYSTEM:INTEGRATEDHEATPUMP:AIRSOURCE")) {
    2816            3 :                 thisFurnace.HeatingCoilType_Num = HVAC::Coil_HeatingAirToAirVariableSpeed;
    2817            3 :                 if (Util::SameString(HeatingCoilType, "COILSYSTEM:INTEGRATEDHEATPUMP:AIRSOURCE")) {
    2818            1 :                     thisFurnace.bIsIHP = true;
    2819              :                 }
    2820              :             } else {
    2821           32 :                 thisFurnace.HeatingCoilType_Num = DXCoils::GetCoilTypeNum(state, HeatingCoilType, HeatingCoilName, errFlag);
    2822              :             }
    2823              : 
    2824           35 :             if (errFlag) {
    2825            0 :                 ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2826            0 :                 ErrorsFound = true;
    2827              :             }
    2828              : 
    2829           35 :             if (thisFurnace.HeatingCoilType_Num == HVAC::CoilDX_HeatingEmpirical) {
    2830           32 :                 ValidateComponent(state, HeatingCoilType, HeatingCoilName, IsNotOK, CurrentModuleObject);
    2831           32 :                 if (IsNotOK) {
    2832            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2833            0 :                     ErrorsFound = true;
    2834              : 
    2835              :                 } else { // mine data from DX heating coil
    2836              : 
    2837           32 :                     DXCoils::GetDXCoilIndex(state, HeatingCoilName, thisFurnace.HeatingCoilIndex, IsNotOK);
    2838           32 :                     if (IsNotOK) {
    2839            0 :                         ShowContinueError(state, format("...occurs {} = {}", CurrentModuleObject, Alphas(1)));
    2840            0 :                         ErrorsFound = true;
    2841              :                     }
    2842              : 
    2843              :                     // Get the Heating Coil Node Names
    2844           32 :                     errFlag = false;
    2845           32 :                     HeatingCoilInletNode = DXCoils::GetCoilInletNode(state, HeatingCoilType, HeatingCoilName, errFlag);
    2846           32 :                     HeatingCoilOutletNode = DXCoils::GetCoilOutletNode(state, HeatingCoilType, HeatingCoilName, errFlag);
    2847           32 :                     if (errFlag) {
    2848            0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2849            0 :                         ErrorsFound = true;
    2850              :                     }
    2851              : 
    2852              :                     // Get the design heating capacity
    2853           32 :                     errFlag = false;
    2854           32 :                     thisFurnace.DesignHeatingCapacity = DXCoils::GetCoilCapacity(state, HeatingCoilType, HeatingCoilName, errFlag);
    2855           32 :                     if (errFlag) {
    2856            0 :                         ShowContinueError(state, format("...occurs in {} ={}", CurrentModuleObject, Alphas(1)));
    2857            0 :                         ErrorsFound = true;
    2858              :                     }
    2859              : 
    2860              :                 } // IF (IsNotOK) THEN
    2861            3 :             } else if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingAirToAirVariableSpeed) {
    2862            3 :                 ValidateComponent(state, HeatingCoilType, HeatingCoilName, IsNotOK, CurrentModuleObject);
    2863            3 :                 if (IsNotOK) {
    2864            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2865            0 :                     ErrorsFound = true;
    2866              :                 } else {
    2867            3 :                     if (thisFurnace.bIsIHP) {
    2868            1 :                         thisFurnace.HeatingCoilIndex = IntegratedHeatPump::GetCoilIndexIHP(state, HeatingCoilType, HeatingCoilName, errFlag);
    2869            1 :                         IHPCoilIndex = thisFurnace.HeatingCoilIndex;
    2870            1 :                         IHPCoilName = state.dataIntegratedHP->IntegratedHeatPumps(IHPCoilIndex).SHCoilName;
    2871              :                         HeatingCoilInletNode =
    2872            2 :                             VariableSpeedCoils::GetCoilInletNodeVariableSpeed(state, "COIL:HEATING:DX:VARIABLESPEED", IHPCoilName, errFlag);
    2873              :                         HeatingCoilOutletNode =
    2874            2 :                             VariableSpeedCoils::GetCoilOutletNodeVariableSpeed(state, "COIL:HEATING:DX:VARIABLESPEED", IHPCoilName, errFlag);
    2875              :                     } else {
    2876            2 :                         thisFurnace.HeatingCoilIndex =
    2877            2 :                             VariableSpeedCoils::GetCoilIndexVariableSpeed(state, HeatingCoilType, HeatingCoilName, errFlag);
    2878            2 :                         HeatingCoilInletNode = VariableSpeedCoils::GetCoilInletNodeVariableSpeed(state, HeatingCoilType, HeatingCoilName, errFlag);
    2879            2 :                         HeatingCoilOutletNode = VariableSpeedCoils::GetCoilOutletNodeVariableSpeed(state, HeatingCoilType, HeatingCoilName, errFlag);
    2880              :                     }
    2881              :                 }
    2882              :             } else {
    2883            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    2884            0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(8), Alphas(8)));
    2885            0 :                 ErrorsFound = true;
    2886              :             }
    2887              : 
    2888              :             // Get Cooling Coil Information if available
    2889           35 :             CoolingCoilType = Alphas(10);
    2890           35 :             CoolingCoilName = Alphas(11);
    2891              : 
    2892           68 :             if (Util::SameString(CoolingCoilType, "COIL:COOLING:DX:VARIABLESPEED") ||
    2893           68 :                 Util::SameString(CoolingCoilType, "COILSYSTEM:INTEGRATEDHEATPUMP:AIRSOURCE")) {
    2894            3 :                 thisFurnace.CoolingCoilType_Num = HVAC::Coil_CoolingAirToAirVariableSpeed;
    2895            3 :                 if (Util::SameString(CoolingCoilType, "COILSYSTEM:INTEGRATEDHEATPUMP:AIRSOURCE")) {
    2896            1 :                     thisFurnace.bIsIHP = true;
    2897              :                 }
    2898              :             }
    2899              : 
    2900           35 :             ValidateComponent(state, CoolingCoilType, CoolingCoilName, IsNotOK, CurrentModuleObject);
    2901              : 
    2902           35 :             if (IsNotOK) {
    2903            0 :                 ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2904            0 :                 ErrorsFound = true;
    2905              : 
    2906              :             } else { // mine data from DX cooling coil
    2907              : 
    2908           35 :                 errFlag = false;
    2909           35 :                 PrintMessage = false;
    2910              : 
    2911           35 :                 if (thisFurnace.CoolingCoilType_Num != HVAC::Coil_CoolingAirToAirVariableSpeed) {
    2912           32 :                     thisFurnace.CoolingCoilType_Num = DXCoils::GetCoilTypeNum(state, CoolingCoilType, CoolingCoilName, errFlag, PrintMessage);
    2913              :                 }
    2914              : 
    2915              :                 // If coil type not found, check to see if a HX assisted cooling coil is used.
    2916           35 :                 if (thisFurnace.CoolingCoilType_Num == 0) {
    2917            0 :                     errFlag = false;
    2918            0 :                     PrintMessage = false;
    2919            0 :                     thisFurnace.CoolingCoilType_Num =
    2920            0 :                         HVACHXAssistedCoolingCoil::GetCoilGroupTypeNum(state, CoolingCoilType, CoolingCoilName, errFlag, PrintMessage);
    2921              :                 }
    2922              : 
    2923           35 :                 if (thisFurnace.CoolingCoilType_Num == HVAC::CoilDX_CoolingSingleSpeed) {
    2924              : 
    2925              :                     // Get the cooling coil node numbers
    2926           32 :                     errFlag = false;
    2927           32 :                     DXCoils::GetDXCoilIndex(state, CoolingCoilName, thisFurnace.CoolingCoilIndex, errFlag);
    2928           32 :                     CoolingCoilInletNode = DXCoils::GetCoilInletNode(state, CoolingCoilType, CoolingCoilName, errFlag);
    2929           32 :                     CoolingCoilOutletNode = DXCoils::GetCoilOutletNode(state, CoolingCoilType, CoolingCoilName, errFlag);
    2930           32 :                     if (errFlag) {
    2931            0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2932            0 :                         ErrorsFound = true;
    2933              :                     }
    2934              : 
    2935              :                     // Get the DX cooling coil design capacity
    2936           32 :                     errFlag = false;
    2937           32 :                     thisFurnace.DesignCoolingCapacity = DXCoils::GetCoilCapacity(state, CoolingCoilType, CoolingCoilName, errFlag);
    2938           32 :                     if (errFlag) {
    2939            0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2940            0 :                         ErrorsFound = true;
    2941              :                     }
    2942              : 
    2943            3 :                 } else if (thisFurnace.CoolingCoilType_Num == HVAC::CoilDX_CoolingHXAssisted) {
    2944              : 
    2945              :                     // Get the cooling coil node numbers
    2946            0 :                     errFlag = false;
    2947            0 :                     HVACHXAssistedCoolingCoil::GetHXDXCoilIndex(state, CoolingCoilName, thisFurnace.CoolingCoilIndex, errFlag);
    2948            0 :                     CoolingCoilInletNode = HVACHXAssistedCoolingCoil::GetCoilInletNode(state, CoolingCoilType, CoolingCoilName, errFlag);
    2949            0 :                     CoolingCoilOutletNode = HVACHXAssistedCoolingCoil::GetCoilOutletNode(state, CoolingCoilType, CoolingCoilName, errFlag);
    2950            0 :                     if (errFlag) {
    2951            0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2952            0 :                         ErrorsFound = true;
    2953              :                     }
    2954              : 
    2955              :                     // Get the heat exchanger assisted cooling coil design capacity
    2956            0 :                     errFlag = false;
    2957            0 :                     thisFurnace.DesignCoolingCapacity = HVACHXAssistedCoolingCoil::GetCoilCapacity(state, CoolingCoilType, CoolingCoilName, errFlag);
    2958            0 :                     if (errFlag) {
    2959            0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2960            0 :                         ErrorsFound = true;
    2961              :                     }
    2962              : 
    2963              :                     // get the actual index to the DX cooling coil object
    2964            0 :                     DXCoilIndex = HVACHXAssistedCoolingCoil::GetActualDXCoilIndex(state, CoolingCoilType, CoolingCoilName, ErrorsFound);
    2965            0 :                     thisFurnace.ActualDXCoilIndexForHXAssisted = DXCoilIndex;
    2966              : 
    2967            3 :                 } else if (thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingAirToAirVariableSpeed) {
    2968              :                     // BOS ADDED, AUG/2012, VARIIABLE SPEED DX COOLING COIL
    2969              :                     //  Furnace(FurnaceNum)%DXCoolCoilType = 'COIL:COOLING:DX:VARIABLESPEED'
    2970              :                     //  Furnace(FurnaceNum)%DXCoolCoilName = CoolingCoilName
    2971            3 :                     ValidateComponent(state, CoolingCoilType, CoolingCoilName, IsNotOK, CurrentModuleObject);
    2972            3 :                     if (IsNotOK) {
    2973            0 :                         ShowContinueError(state, format("...specified in {}=\"{}\".", CurrentModuleObject, Alphas(1)));
    2974            0 :                         ErrorsFound = true;
    2975              :                     } else {
    2976            3 :                         errFlag = false;
    2977            3 :                         if (thisFurnace.bIsIHP) {
    2978            1 :                             thisFurnace.CoolingCoilIndex = IntegratedHeatPump::GetCoilIndexIHP(state, CoolingCoilType, CoolingCoilName, errFlag);
    2979            1 :                             IHPCoilName = state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).SCCoilName;
    2980              :                         } else {
    2981            2 :                             thisFurnace.CoolingCoilIndex =
    2982            2 :                                 VariableSpeedCoils::GetCoilIndexVariableSpeed(state, CoolingCoilType, CoolingCoilName, errFlag);
    2983            2 :                             IHPCoilName = CoolingCoilName;
    2984              :                         }
    2985              : 
    2986            3 :                         if (errFlag) {
    2987            0 :                             ShowContinueError(state, format("...specified in {}=\"{}\".", CurrentModuleObject, Alphas(1)));
    2988            0 :                             ErrorsFound = true;
    2989              :                         }
    2990              : 
    2991            3 :                         if (thisFurnace.bIsIHP) {
    2992              :                             CoolingCoilInletNode =
    2993            2 :                                 VariableSpeedCoils::GetCoilInletNodeVariableSpeed(state, "COIL:COOLING:DX:VARIABLESPEED", IHPCoilName, errFlag);
    2994              :                             CoolingCoilOutletNode =
    2995            1 :                                 VariableSpeedCoils::GetCoilOutletNodeVariableSpeed(state, "COIL:COOLING:DX:VARIABLESPEED", IHPCoilName, errFlag);
    2996            1 :                             thisFurnace.CondenserNodeNum = VariableSpeedCoils::GetVSCoilCondenserInletNode(state, IHPCoilName, errFlag);
    2997              :                         } else {
    2998              :                             CoolingCoilInletNode =
    2999            2 :                                 VariableSpeedCoils::GetCoilInletNodeVariableSpeed(state, CoolingCoilType, CoolingCoilName, errFlag);
    3000              :                             CoolingCoilOutletNode =
    3001            2 :                                 VariableSpeedCoils::GetCoilOutletNodeVariableSpeed(state, CoolingCoilType, CoolingCoilName, errFlag);
    3002            2 :                             thisFurnace.CondenserNodeNum = VariableSpeedCoils::GetVSCoilCondenserInletNode(state, CoolingCoilName, errFlag);
    3003              :                         }
    3004              : 
    3005            3 :                         if (errFlag) {
    3006            0 :                             ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3007            0 :                             ErrorsFound = true;
    3008              :                         }
    3009              :                     }
    3010              :                 } else {
    3011            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3012            0 :                     ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(10), Alphas(10)));
    3013            0 :                     ErrorsFound = true;
    3014              :                 }
    3015              :             }
    3016              : 
    3017           35 :             if (thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingAirToAirVariableSpeed &&
    3018            3 :                 thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingAirToAirVariableSpeed) {
    3019              :                 // Furnace(FurnaceNum)%WatertoAirHPType = WatertoAir_VarSpeedEquationFit
    3020            3 :                 if (thisFurnace.bIsIHP) {
    3021            3 :                     VariableSpeedCoils::SetVarSpeedCoilData(state,
    3022            1 :                                                             state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).SCCoilIndex,
    3023              :                                                             ErrorsFound,
    3024              :                                                             _,
    3025            1 :                                                             state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).SHCoilIndex);
    3026              :                 } else {
    3027            2 :                     VariableSpeedCoils::SetVarSpeedCoilData(state, thisFurnace.CoolingCoilIndex, ErrorsFound, _, thisFurnace.HeatingCoilIndex);
    3028              :                 }
    3029              :             }
    3030              : 
    3031              :             // Get supplemental heating coil information
    3032           35 :             SuppHeatCoilType = Alphas(12);
    3033           35 :             SuppHeatCoilName = Alphas(13);
    3034           35 :             thisFurnace.SuppHeatCoilType = SuppHeatCoilType;
    3035           35 :             thisFurnace.SuppHeatCoilName = SuppHeatCoilName;
    3036           35 :             errFlag = false;
    3037           35 :             if (Util::SameString(SuppHeatCoilType, "Coil:Heating:Fuel") || Util::SameString(SuppHeatCoilType, "Coil:Heating:Electric")) {
    3038              : 
    3039           34 :                 thisFurnace.SuppHeatCoilType_Num = HeatingCoils::GetHeatingCoilTypeNum(state, SuppHeatCoilType, SuppHeatCoilName, errFlag);
    3040           34 :                 if (errFlag) {
    3041            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3042            0 :                     ErrorsFound = true;
    3043              :                 } else {
    3044           34 :                     IsNotOK = false;
    3045           34 :                     ValidateComponent(state, SuppHeatCoilType, SuppHeatCoilName, IsNotOK, CurrentModuleObject);
    3046           34 :                     if (IsNotOK) {
    3047            0 :                         ShowContinueError(state, format("In {} \"{}\"", CurrentModuleObject, Alphas(1)));
    3048            0 :                         ErrorsFound = true;
    3049              : 
    3050              :                     } else { // mine data from the supplemental heating coil
    3051              : 
    3052           34 :                         HeatingCoils::GetCoilIndex(state, SuppHeatCoilName, thisFurnace.SuppHeatCoilIndex, IsNotOK);
    3053           34 :                         if (IsNotOK) {
    3054            0 :                             ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3055            0 :                             ErrorsFound = true;
    3056              :                         }
    3057              : 
    3058              :                         // Get the Supplemental Heating Coil Inlet Node Number
    3059           34 :                         errFlag = false;
    3060           34 :                         SupHeatCoilInletNode = HeatingCoils::GetCoilInletNode(state, SuppHeatCoilType, SuppHeatCoilName, errFlag);
    3061           34 :                         if (errFlag) {
    3062            0 :                             ShowContinueError(state, format("...occurs in {} \"{}\"", CurrentModuleObject, Alphas(1)));
    3063            0 :                             ErrorsFound = true;
    3064              :                         }
    3065              : 
    3066              :                         // Get the Supplemental Heating Coil Outlet Node Number
    3067           34 :                         errFlag = false;
    3068           34 :                         SupHeatCoilOutletNode = HeatingCoils::GetCoilOutletNode(state, SuppHeatCoilType, SuppHeatCoilName, errFlag);
    3069              : 
    3070           34 :                         if (errFlag) {
    3071            0 :                             ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3072            0 :                             ErrorsFound = true;
    3073              :                         }
    3074              : 
    3075              :                         // Get the supplemental heating coil design capacity
    3076           34 :                         errFlag = false;
    3077           34 :                         thisFurnace.DesignSuppHeatingCapacity = HeatingCoils::GetCoilCapacity(state, SuppHeatCoilType, SuppHeatCoilName, errFlag);
    3078           34 :                         if (errFlag) {
    3079            0 :                             ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3080            0 :                             ErrorsFound = true;
    3081              :                         }
    3082              : 
    3083              :                     } // IF (IsNotOK) THEN
    3084              :                 }
    3085            1 :             } else if (Util::SameString(SuppHeatCoilType, "Coil:Heating:Water")) {
    3086            1 :                 thisFurnace.SuppHeatCoilType_Num = HVAC::Coil_HeatingWater;
    3087            1 :                 ValidateComponent(state, SuppHeatCoilType, SuppHeatCoilName, IsNotOK, CurrentModuleObject);
    3088            1 :                 if (IsNotOK) {
    3089            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3090            0 :                     ErrorsFound = true;
    3091              :                 } else { // mine data from heating coil object
    3092              : 
    3093              :                     // Get the Heating Coil water Inlet or control Node number
    3094            1 :                     errFlag = false;
    3095            1 :                     thisFurnace.SuppCoilControlNode = WaterCoils::GetCoilWaterInletNode(state, "Coil:Heating:Water", SuppHeatCoilName, errFlag);
    3096            1 :                     if (errFlag) {
    3097            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3098            0 :                         ErrorsFound = true;
    3099              :                     }
    3100              : 
    3101              :                     // Get the ReHeat Coil hot water max volume flow rate
    3102            1 :                     errFlag = false;
    3103            1 :                     thisFurnace.MaxSuppCoilFluidFlow = WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", SuppHeatCoilName, errFlag);
    3104            1 :                     if (errFlag) {
    3105            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3106            0 :                         ErrorsFound = true;
    3107              :                     }
    3108              : 
    3109              :                     // Get the ReHeat Coil Inlet Node
    3110            1 :                     errFlag = false;
    3111            1 :                     SupHeatCoilInletNode = WaterCoils::GetCoilInletNode(state, "Coil:Heating:Water", SuppHeatCoilName, errFlag);
    3112            1 :                     thisFurnace.SuppCoilAirInletNode = SupHeatCoilInletNode;
    3113            1 :                     if (errFlag) {
    3114            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3115            0 :                         ErrorsFound = true;
    3116              :                     }
    3117              : 
    3118              :                     // Get the ReHeat Coil Outlet Node
    3119            1 :                     errFlag = false;
    3120            1 :                     SupHeatCoilOutletNode = WaterCoils::GetCoilOutletNode(state, "Coil:Heating:Water", SuppHeatCoilName, errFlag);
    3121            1 :                     thisFurnace.SuppCoilAirOutletNode = SupHeatCoilOutletNode;
    3122            1 :                     if (errFlag) {
    3123            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3124            0 :                         ErrorsFound = true;
    3125              :                     }
    3126            1 :                     errFlag = false;
    3127            1 :                     HVACControllers::CheckCoilWaterInletNode(state, thisFurnace.CoilControlNode, errFlag);
    3128            1 :                     if (!errFlag) { // then did find a controller so that is bad
    3129            0 :                         ShowSevereError(state,
    3130            0 :                                         format("{} = {} has a conflicting Controller:WaterCoil object", CurrentModuleObject, thisFurnace.Name));
    3131            0 :                         ShowContinueError(state, "Hot water coils are controlled directly by unitary and furnace systems.");
    3132            0 :                         ShowContinueError(state, "No water coil controller should be input for the coil.");
    3133            0 :                         ErrorsFound = true;
    3134              :                     }
    3135              :                 }
    3136              : 
    3137            0 :             } else if (Util::SameString(SuppHeatCoilType, "Coil:Heating:Steam")) {
    3138            0 :                 thisFurnace.SuppHeatCoilType_Num = HVAC::Coil_HeatingSteam;
    3139            0 :                 ValidateComponent(state, SuppHeatCoilType, SuppHeatCoilName, IsNotOK, CurrentModuleObject);
    3140            0 :                 if (IsNotOK) {
    3141            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3142            0 :                     ErrorsFound = true;
    3143              :                 } else { // mine data from heating coil object
    3144              : 
    3145            0 :                     errFlag = false;
    3146            0 :                     thisFurnace.SuppHeatCoilIndex = SteamCoils::GetSteamCoilIndex(state, "COIL:HEATING:STEAM", SuppHeatCoilName, errFlag);
    3147            0 :                     if (thisFurnace.SuppHeatCoilIndex == 0) {
    3148            0 :                         ShowSevereError(state, format("{} illegal {} = {}", CurrentModuleObject, cAlphaFields(12), SuppHeatCoilName));
    3149            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3150            0 :                         ErrorsFound = true;
    3151              :                     }
    3152              : 
    3153              :                     // Get the Heating Coil steam inlet node number
    3154            0 :                     errFlag = false;
    3155            0 :                     thisFurnace.SuppCoilControlNode = SteamCoils::GetCoilSteamInletNode(state, "Coil:Heating:Steam", SuppHeatCoilName, errFlag);
    3156            0 :                     if (errFlag) {
    3157            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3158            0 :                         ErrorsFound = true;
    3159              :                     }
    3160              : 
    3161              :                     // Get the Heating Coil steam max volume flow rate
    3162            0 :                     thisFurnace.MaxSuppCoilFluidFlow = SteamCoils::GetCoilMaxSteamFlowRate(state, thisFurnace.SuppHeatCoilIndex, errFlag);
    3163            0 :                     if (thisFurnace.MaxSuppCoilFluidFlow > 0.0) {
    3164              :                         SteamDensity =
    3165            0 :                             Fluid::GetSteam(state)->getSatDensity(state, state.dataFurnaces->TempSteamIn, 1.0, getAirLoopHVACHeatCoolInput);
    3166            0 :                         thisFurnace.MaxSuppCoilFluidFlow =
    3167            0 :                             SteamCoils::GetCoilMaxSteamFlowRate(state, thisFurnace.SuppHeatCoilIndex, errFlag) * SteamDensity;
    3168              :                     }
    3169              : 
    3170              :                     // Get the Heating Coil Inlet Node
    3171            0 :                     errFlag = false;
    3172            0 :                     SupHeatCoilInletNode = SteamCoils::GetCoilAirInletNode(state, thisFurnace.SuppHeatCoilIndex, SuppHeatCoilName, errFlag);
    3173            0 :                     thisFurnace.SuppCoilAirInletNode = SupHeatCoilInletNode;
    3174            0 :                     if (errFlag) {
    3175            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3176            0 :                         ErrorsFound = true;
    3177              :                     }
    3178              : 
    3179              :                     // Get the Heating Coil Outlet Node
    3180            0 :                     errFlag = false;
    3181            0 :                     SupHeatCoilOutletNode = SteamCoils::GetCoilAirOutletNode(state, thisFurnace.SuppHeatCoilIndex, SuppHeatCoilName, errFlag);
    3182            0 :                     thisFurnace.SuppCoilAirOutletNode = SupHeatCoilOutletNode;
    3183            0 :                     if (errFlag) {
    3184            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3185            0 :                         ErrorsFound = true;
    3186              :                     }
    3187              :                 }
    3188              : 
    3189              :             } else {
    3190            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3191            0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(12), Alphas(12)));
    3192            0 :                 ErrorsFound = true;
    3193              :             } // IF (Furnace(FurnaceNum)%HeatingCoilType_Num == Coil_HeatingGasOrOtherFuel .OR. &, etc.
    3194              : 
    3195           35 :             thisFurnace.fanPlace = static_cast<HVAC::FanPlace>(getEnumValue(HVAC::fanPlaceNamesUC, Alphas(14)));
    3196           35 :             assert(thisFurnace.fanPlace != HVAC::FanPlace::Invalid);
    3197              : 
    3198           35 :             if (lAlphaBlanks(15)) {
    3199            0 :                 thisFurnace.fanOp = HVAC::FanOp::Cycling;
    3200            0 :                 if (thisFurnace.fanType != HVAC::FanType::OnOff) {
    3201            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, thisFurnace.Name));
    3202            0 :                     ShowContinueError(state, format("{} = {}", cAlphaFields(6), Alphas(6)));
    3203            0 :                     ShowContinueError(state, format("Fan type must be Fan:OnOff when {} = Blank.", cAlphaFields(15)));
    3204            0 :                     ErrorsFound = true;
    3205              :                 }
    3206           35 :             } else if ((thisFurnace.fanOpModeSched = Sched::GetSchedule(state, Alphas(15))) == nullptr) {
    3207            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(15), Alphas(15));
    3208            0 :                 ErrorsFound = true;
    3209              :             }
    3210              : 
    3211           35 :             if (thisFurnace.fanType == HVAC::FanType::Constant && thisFurnace.fanOpModeSched != nullptr &&
    3212            0 :                 !thisFurnace.fanOpModeSched->checkMinMaxVals(state, Clusive::In, 0.0, Clusive::In, 1.0)) {
    3213            0 :                 Sched::ShowSevereBadMinMax(
    3214              :                     state,
    3215              :                     eoh,
    3216            0 :                     cAlphaFields(15),
    3217            0 :                     Alphas(15),
    3218              :                     Clusive::In,
    3219              :                     0.0,
    3220              :                     Clusive::In,
    3221              :                     1.0,
    3222            0 :                     format("For {} = {}, fan operating mode must be continuous (schedule values > 0)", cAlphaFields(7), Alphas(7)));
    3223            0 :                 ErrorsFound = true;
    3224              :             }
    3225              : 
    3226              :             // Dehumidification Control Type
    3227           35 :             if (Util::SameString(Alphas(16), "None") || Util::SameString(Alphas(16), "Multimode") || Util::SameString(Alphas(16), "CoolReheat")) {
    3228           35 :                 AirNodeFound = false;
    3229           35 :                 if (Util::SameString(Alphas(16), "Multimode")) {
    3230            0 :                     thisFurnace.DehumidControlType_Num = DehumidificationControlMode::Multimode;
    3231            0 :                     thisFurnace.Humidistat = true;
    3232            0 :                     if (thisFurnace.CoolingCoilType_Num != HVAC::CoilDX_CoolingHXAssisted) {
    3233            0 :                         ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3234            0 :                         ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(16), Alphas(16)));
    3235            0 :                         ShowContinueError(state, "Multimode control must be used with a Heat Exchanger Assisted Cooling Coil.");
    3236            0 :                         ErrorsFound = true;
    3237              :                     }
    3238              :                 }
    3239           35 :                 if (Util::SameString(Alphas(16), "CoolReheat")) {
    3240            3 :                     thisFurnace.DehumidControlType_Num = DehumidificationControlMode::CoolReheat;
    3241            3 :                     thisFurnace.Humidistat = true;
    3242              :                 }
    3243           35 :                 if (Util::SameString(Alphas(16), "None")) {
    3244           32 :                     thisFurnace.DehumidControlType_Num = DehumidificationControlMode::None;
    3245           32 :                     thisFurnace.Humidistat = false;
    3246              :                 }
    3247           35 :                 if (thisFurnace.Humidistat) {
    3248            6 :                     for (HStatZoneNum = 1; HStatZoneNum <= state.dataZoneCtrls->NumHumidityControlZones; ++HStatZoneNum) {
    3249            3 :                         if (state.dataZoneCtrls->HumidityControlZone(HStatZoneNum).ActualZoneNum != thisFurnace.ControlZoneNum) {
    3250            0 :                             continue;
    3251              :                         }
    3252            3 :                         AirNodeFound = true;
    3253              :                     }
    3254            3 :                     if (!AirNodeFound) {
    3255            0 :                         ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3256            0 :                         ShowContinueError(state, "Did not find Air Node (Zone with Humidistat).");
    3257            0 :                         ShowContinueError(state, format("Specified {} = {}", cAlphaFields(5), Alphas(5)));
    3258            0 :                         ErrorsFound = true;
    3259              :                     }
    3260              :                 }
    3261              :             } else { // invalid input or blank
    3262            0 :                 if (!lAlphaBlanks(16)) {
    3263            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3264            0 :                     ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(16), Alphas(16)));
    3265            0 :                     ErrorsFound = true;
    3266              :                 } else {
    3267            0 :                     thisFurnace.Humidistat = false;
    3268            0 :                     thisFurnace.DehumidControlType_Num = DehumidificationControlMode::None;
    3269              :                 }
    3270              :             }
    3271              : 
    3272              :             // Check node names for child components
    3273           35 :             if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
    3274           35 :                 if (FanInletNode != thisFurnace.FurnaceInletNodeNum) {
    3275            0 :                     ShowSevereError(state, format("For {} \"{}\"", CurrentModuleObject, Alphas(1)));
    3276            0 :                     ShowContinueError(
    3277              :                         state,
    3278              :                         "When a blow through fan is specified, the fan inlet node name must be the same as the unitary system inlet node name.");
    3279            0 :                     ShowContinueError(state, format("...Fan inlet node name            = {}", state.dataLoopNodes->NodeID(FanInletNode)));
    3280            0 :                     ShowContinueError(state,
    3281            0 :                                       format("...Unitary system inlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceInletNodeNum)));
    3282            0 :                     ErrorsFound = true;
    3283              :                 }
    3284           35 :                 if (FanOutletNode != CoolingCoilInletNode) {
    3285            0 :                     ShowSevereError(state, format("For {} \"{}\"", CurrentModuleObject, Alphas(1)));
    3286            0 :                     ShowContinueError(
    3287              :                         state,
    3288              :                         "When a blow through fan is specified, the fan outlet node name must be the same as the cooling coil inlet node name.");
    3289            0 :                     ShowContinueError(state, format("...Fan outlet node name         = {}", state.dataLoopNodes->NodeID(FanOutletNode)));
    3290            0 :                     ShowContinueError(state, format("...Cooling coil inlet node name = {}", state.dataLoopNodes->NodeID(CoolingCoilInletNode)));
    3291            0 :                     ErrorsFound = true;
    3292              :                 }
    3293           35 :                 if (CoolingCoilOutletNode != HeatingCoilInletNode) {
    3294            0 :                     ShowSevereError(state, format("For {} \"{}\"", CurrentModuleObject, Alphas(1)));
    3295            0 :                     ShowContinueError(state, "The cooling coil outlet node name must be the same as the heating coil inlet node name.");
    3296            0 :                     ShowContinueError(state, format("...Cooling coil outlet node name = {}", state.dataLoopNodes->NodeID(CoolingCoilOutletNode)));
    3297            0 :                     ShowContinueError(state, format("...Heating coil inlet node name  = {}", state.dataLoopNodes->NodeID(HeatingCoilInletNode)));
    3298            0 :                     ErrorsFound = true;
    3299              :                 }
    3300           35 :                 if (HeatingCoilOutletNode != SupHeatCoilInletNode) {
    3301            0 :                     ShowSevereError(state, format("For {} \"{}\"", CurrentModuleObject, Alphas(1)));
    3302            0 :                     ShowContinueError(state,
    3303              :                                       "When a blow through fan is specified, the heating coil outlet node name must be the same as the supplemental "
    3304              :                                       "heating coil inlet node name.");
    3305            0 :                     ShowContinueError(
    3306            0 :                         state, format("...Heating coil outlet node name              = {}", state.dataLoopNodes->NodeID(HeatingCoilOutletNode)));
    3307            0 :                     ShowContinueError(
    3308            0 :                         state, format("...Supplemental heating coil inlet node name  = {}", state.dataLoopNodes->NodeID(SupHeatCoilInletNode)));
    3309            0 :                     ErrorsFound = true;
    3310              :                 }
    3311           35 :                 if (SupHeatCoilOutletNode != thisFurnace.FurnaceOutletNodeNum) {
    3312            0 :                     ShowSevereError(state, format("For {} \"{}\"", CurrentModuleObject, Alphas(1)));
    3313            0 :                     ShowContinueError(state,
    3314              :                                       "The supplemental heating coil outlet node name must be the same as the unitary system outlet node name.");
    3315            0 :                     ShowContinueError(
    3316            0 :                         state, format("...Supplemental heating coil outlet node name = {}", state.dataLoopNodes->NodeID(SupHeatCoilOutletNode)));
    3317            0 :                     ShowContinueError(
    3318              :                         state,
    3319            0 :                         format("...Unitary system outlet node name            = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    3320            0 :                     ErrorsFound = true;
    3321              :                 }
    3322              :             } else {
    3323            0 :                 if (CoolingCoilInletNode != thisFurnace.FurnaceInletNodeNum) {
    3324            0 :                     ShowSevereError(state, format("For {} \"{}\"", CurrentModuleObject, Alphas(1)));
    3325            0 :                     ShowContinueError(state,
    3326              :                                       "When a draw through fan is specified, the cooling coil inlet node name must be the same as the unitary system "
    3327              :                                       "inlet node name.");
    3328            0 :                     ShowContinueError(state, format("...Cooling coil inlet node name   = {}", state.dataLoopNodes->NodeID(CoolingCoilInletNode)));
    3329            0 :                     ShowContinueError(state,
    3330            0 :                                       format("...Unitary system inlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceInletNodeNum)));
    3331            0 :                     ErrorsFound = true;
    3332              :                 }
    3333            0 :                 if (CoolingCoilOutletNode != HeatingCoilInletNode) {
    3334            0 :                     ShowSevereError(state, format("For {} \"{}\"", CurrentModuleObject, Alphas(1)));
    3335            0 :                     ShowContinueError(state, "The cooling coil outlet node name must be the same as the heating coil inlet node name.");
    3336            0 :                     ShowContinueError(state, format("...Cooling coil outlet node name = {}", state.dataLoopNodes->NodeID(CoolingCoilOutletNode)));
    3337            0 :                     ShowContinueError(state, format("...Heating coil inlet node name  = {}", state.dataLoopNodes->NodeID(HeatingCoilInletNode)));
    3338            0 :                     ErrorsFound = true;
    3339              :                 }
    3340            0 :                 if (HeatingCoilOutletNode != FanInletNode) {
    3341            0 :                     ShowSevereError(state, format("For {} \"{}\"", CurrentModuleObject, Alphas(1)));
    3342            0 :                     ShowContinueError(
    3343              :                         state,
    3344              :                         "When a draw through fan is specified, the heating coil outlet node name must be the same as the fan inlet node name.");
    3345            0 :                     ShowContinueError(state, format("...Heating coil outlet node name = {}", state.dataLoopNodes->NodeID(HeatingCoilOutletNode)));
    3346            0 :                     ShowContinueError(state, format("...Fan inlet node name           = {}", state.dataLoopNodes->NodeID(FanInletNode)));
    3347            0 :                     ErrorsFound = true;
    3348              :                 }
    3349            0 :                 if (FanOutletNode != SupHeatCoilInletNode) {
    3350            0 :                     ShowSevereError(state, format("For {} \"{}\"", CurrentModuleObject, Alphas(1)));
    3351            0 :                     ShowContinueError(state,
    3352              :                                       "When a draw through fan is specified, the fan outlet node name must be the same as the supplemental heating "
    3353              :                                       "coil inlet node name.");
    3354            0 :                     ShowContinueError(state,
    3355            0 :                                       format("...Fan outlet node name                       = {}", state.dataLoopNodes->NodeID(FanOutletNode)));
    3356            0 :                     ShowContinueError(
    3357            0 :                         state, format("...Supplemental heating coil inlet node name  = {}", state.dataLoopNodes->NodeID(SupHeatCoilInletNode)));
    3358            0 :                     ErrorsFound = true;
    3359              :                 }
    3360            0 :                 if (SupHeatCoilOutletNode != thisFurnace.FurnaceOutletNodeNum) {
    3361            0 :                     ShowSevereError(state, format("For {} \"{}\"", CurrentModuleObject, Alphas(1)));
    3362            0 :                     ShowContinueError(state,
    3363              :                                       "The supplemental heating coil outlet node name must be the same as the unitary system outlet node name.");
    3364            0 :                     ShowContinueError(
    3365            0 :                         state, format("...Supplemental heating coil outlet node name = {}", state.dataLoopNodes->NodeID(SupHeatCoilOutletNode)));
    3366            0 :                     ShowContinueError(
    3367              :                         state,
    3368            0 :                         format("...Unitary system outlet node name            = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    3369            0 :                     ErrorsFound = true;
    3370              :                 }
    3371              :             }
    3372              : 
    3373              :             // Add component sets array
    3374           35 :             if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
    3375           35 :                 CompSetFanInlet = Alphas(3);
    3376           35 :                 CompSetCoolInlet = "UNDEFINED";
    3377              :             } else {
    3378            0 :                 CompSetFanInlet = "UNDEFINED";
    3379            0 :                 CompSetCoolInlet = Alphas(3);
    3380              :             }
    3381           35 :             BranchNodeConnections::SetUpCompSets(state, CurrentModuleObject, Alphas(1), Alphas(6), Alphas(7), CompSetFanInlet, "UNDEFINED");
    3382              : 
    3383              :             // Add DX cooling coil to component sets array
    3384           35 :             if (thisFurnace.bIsIHP) {
    3385            3 :                 BranchNodeConnections::SetUpCompSets(
    3386            3 :                     state, CurrentModuleObject, Alphas(1), Alphas(10), Alphas(11) + " Cooling Coil", CompSetCoolInlet, "UNDEFINED");
    3387              :             } else {
    3388           34 :                 BranchNodeConnections::SetUpCompSets(state, CurrentModuleObject, Alphas(1), Alphas(10), Alphas(11), CompSetCoolInlet, "UNDEFINED");
    3389              :             }
    3390              :             // Add DX heating coil to component sets array
    3391           35 :             if (thisFurnace.bIsIHP) {
    3392            3 :                 BranchNodeConnections::SetUpCompSets(
    3393            3 :                     state, CurrentModuleObject, Alphas(1), Alphas(8), Alphas(9) + " Heating Coil", "UNDEFINED", "UNDEFINED");
    3394              :             } else {
    3395           34 :                 BranchNodeConnections::SetUpCompSets(state, CurrentModuleObject, Alphas(1), Alphas(8), Alphas(9), "UNDEFINED", "UNDEFINED");
    3396              :             }
    3397              : 
    3398              :             // Add supplemental heating coil to component sets array
    3399           35 :             BranchNodeConnections::SetUpCompSets(state, CurrentModuleObject, Alphas(1), Alphas(12), Alphas(13), "UNDEFINED", Alphas(4));
    3400              : 
    3401           35 :             thisFurnace.MaxCoolAirVolFlow = Numbers(1);
    3402           35 :             if (thisFurnace.MaxCoolAirVolFlow <= 0 && thisFurnace.MaxCoolAirVolFlow != DataSizing::AutoSize) {
    3403            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3404            0 :                 ShowContinueError(state, format("Illegal {} = {:.7T}", cNumericFields(1), Numbers(1)));
    3405            0 :                 ErrorsFound = true;
    3406              :             }
    3407              : 
    3408           35 :             thisFurnace.MaxHeatAirVolFlow = Numbers(2);
    3409           35 :             if (thisFurnace.MaxHeatAirVolFlow <= 0 && thisFurnace.MaxHeatAirVolFlow != DataSizing::AutoSize) {
    3410            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3411            0 :                 ShowContinueError(state, format("Illegal {} = {:.7T}", cNumericFields(2), Numbers(2)));
    3412            0 :                 ErrorsFound = true;
    3413              :             }
    3414              : 
    3415           35 :             thisFurnace.MaxNoCoolHeatAirVolFlow = Numbers(3);
    3416           35 :             if (thisFurnace.MaxNoCoolHeatAirVolFlow < 0 && thisFurnace.MaxNoCoolHeatAirVolFlow != DataSizing::AutoSize) {
    3417            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3418            0 :                 ShowContinueError(state, format("Illegal {} = {:.7T}", cNumericFields(3), Numbers(3)));
    3419            0 :                 ErrorsFound = true;
    3420              :             }
    3421              : 
    3422           35 :             if (thisFurnace.fanOpModeSched != nullptr) {
    3423           35 :                 if (!thisFurnace.fanOpModeSched->checkMinMaxVals(state, Clusive::In, 0.0, Clusive::In, 0.0)) { // Autodesk:Note Range is 0 to 0?
    3424              :                     //           set air flow control mode:
    3425              :                     //             UseCompressorOnFlow = operate at last cooling or heating air flow requested when compressor is off
    3426              :                     //             UseCompressorOffFlow = operate at value specified by user
    3427              :                     //           AirFlowControl only valid if fan opmode = ContFanCycComp
    3428           16 :                     if (thisFurnace.MaxNoCoolHeatAirVolFlow == 0.0) {
    3429            0 :                         thisFurnace.AirFlowControl = AirFlowControlConstFan::UseCompressorOnFlow;
    3430              :                     } else {
    3431           16 :                         thisFurnace.AirFlowControl = AirFlowControlConstFan::UseCompressorOffFlow;
    3432              :                     }
    3433              :                 }
    3434              :             }
    3435              : 
    3436           35 :             if (Numbers(1) != DataSizing::AutoSize && Numbers(2) != DataSizing::AutoSize && Numbers(3) != DataSizing::AutoSize) {
    3437           21 :                 thisFurnace.DesignFanVolFlowRate = max(Numbers(1), Numbers(2), Numbers(3));
    3438              :             } else {
    3439           14 :                 thisFurnace.DesignFanVolFlowRate = DataSizing::AutoSize;
    3440              :             }
    3441              : 
    3442           35 :             if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingAirToAirVariableSpeed) {
    3443            3 :                 errFlag = false;
    3444              : 
    3445            3 :                 if (thisFurnace.bIsIHP) {
    3446            1 :                     IHPCoilName = state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).SHCoilName;
    3447            1 :                     thisFurnace.MaxHeatAirVolFlow =
    3448            1 :                         VariableSpeedCoils::GetCoilAirFlowRateVariableSpeed(state, "COIL:HEATING:DX:VARIABLESPEED", IHPCoilName, errFlag);
    3449            1 :                     IHPCoilName = state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).SCCoilName;
    3450            1 :                     thisFurnace.MaxCoolAirVolFlow =
    3451            2 :                         VariableSpeedCoils::GetCoilAirFlowRateVariableSpeed(state, "COIL:COOLING:DX:VARIABLESPEED", IHPCoilName, errFlag);
    3452              :                 } else {
    3453            2 :                     thisFurnace.MaxHeatAirVolFlow =
    3454            2 :                         VariableSpeedCoils::GetCoilAirFlowRateVariableSpeed(state, HeatingCoilType, HeatingCoilName, errFlag);
    3455            2 :                     thisFurnace.MaxCoolAirVolFlow =
    3456            2 :                         VariableSpeedCoils::GetCoilAirFlowRateVariableSpeed(state, CoolingCoilType, CoolingCoilName, errFlag);
    3457              :                 }
    3458              : 
    3459            3 :                 if (errFlag) {
    3460            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3461            0 :                     ErrorsFound = true;
    3462              :                 }
    3463              : 
    3464            3 :                 thisFurnace.MaxNoCoolHeatAirVolFlow = min(thisFurnace.MaxHeatAirVolFlow, thisFurnace.MaxCoolAirVolFlow);
    3465            3 :                 if (thisFurnace.MaxHeatAirVolFlow != DataSizing::AutoSize && thisFurnace.MaxCoolAirVolFlow != DataSizing::AutoSize) {
    3466            3 :                     thisFurnace.DesignFanVolFlowRate = max(thisFurnace.MaxHeatAirVolFlow, thisFurnace.MaxCoolAirVolFlow);
    3467              :                 } else {
    3468            0 :                     thisFurnace.DesignFanVolFlowRate = DataSizing::AutoSize;
    3469              :                 }
    3470              :             }
    3471              : 
    3472           35 :             if (thisFurnace.ActualFanVolFlowRate != DataSizing::AutoSize) {
    3473           21 :                 if (thisFurnace.ActualFanVolFlowRate < thisFurnace.MaxCoolAirVolFlow && thisFurnace.MaxCoolAirVolFlow != DataSizing::AutoSize) {
    3474            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3475            0 :                     ShowContinueError(
    3476              :                         state,
    3477            0 :                         format("... air flow rate = {:.7T} in fan object {} is less than the maximum HVAC system air flow rate in cooling mode.",
    3478            0 :                                thisFurnace.ActualFanVolFlowRate,
    3479              :                                FanName));
    3480            0 :                     ShowContinueError(state, format(" The {} is reset to the fan flow rate and the simulation continues.", cNumericFields(1)));
    3481            0 :                     thisFurnace.MaxCoolAirVolFlow = thisFurnace.ActualFanVolFlowRate;
    3482            0 :                     thisFurnace.DesignFanVolFlowRate = thisFurnace.ActualFanVolFlowRate;
    3483              :                 }
    3484           21 :                 if (thisFurnace.ActualFanVolFlowRate < thisFurnace.MaxHeatAirVolFlow && thisFurnace.MaxHeatAirVolFlow != DataSizing::AutoSize) {
    3485            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3486            0 :                     ShowContinueError(
    3487              :                         state,
    3488            0 :                         format("... air flow rate = {:.7T} in fan object {} is less than the maximum HVAC system air flow rate in heating mode.",
    3489            0 :                                thisFurnace.ActualFanVolFlowRate,
    3490              :                                FanName));
    3491            0 :                     ShowContinueError(state, format(" The {} is reset to the fan flow rate and the simulation continues.", cNumericFields(2)));
    3492            0 :                     thisFurnace.MaxHeatAirVolFlow = thisFurnace.ActualFanVolFlowRate;
    3493            0 :                     thisFurnace.DesignFanVolFlowRate = thisFurnace.ActualFanVolFlowRate;
    3494              :                 }
    3495              :             }
    3496              : 
    3497              :             // Set heating convergence tolerance
    3498           35 :             thisFurnace.HeatingConvergenceTolerance = 0.001;
    3499              : 
    3500              :             //       Mine heatpump outdoor condenser node from DX coil object
    3501           35 :             errFlag = false;
    3502           35 :             if (thisFurnace.CoolingCoilType_Num == HVAC::CoilDX_CoolingSingleSpeed) {
    3503           32 :                 thisFurnace.CondenserNodeNum = DXCoils::GetCoilCondenserInletNode(state, CoolingCoilType, CoolingCoilName, errFlag);
    3504            3 :             } else if (thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingAirToAirVariableSpeed) {
    3505            3 :                 if (thisFurnace.bIsIHP) {
    3506            1 :                     IHPCoilName = state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).SCCoilName;
    3507            1 :                     thisFurnace.CondenserNodeNum = VariableSpeedCoils::GetVSCoilCondenserInletNode(state, IHPCoilName, errFlag);
    3508              :                 } else {
    3509            2 :                     thisFurnace.CondenserNodeNum = VariableSpeedCoils::GetVSCoilCondenserInletNode(state, CoolingCoilName, errFlag);
    3510              :                 }
    3511              :             } else {
    3512            0 :                 thisFurnace.CondenserNodeNum =
    3513            0 :                     DXCoils::GetCoilCondenserInletNode(state,
    3514              :                                                        "Coil:Cooling:DX:SingleSpeed",
    3515            0 :                                                        HVACHXAssistedCoolingCoil::GetHXDXCoilName(state, CoolingCoilType, CoolingCoilName, errFlag),
    3516              :                                                        errFlag);
    3517              :             }
    3518           35 :             if (errFlag) {
    3519            0 :                 ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3520            0 :                 ErrorsFound = true;
    3521              :             }
    3522              : 
    3523           35 :             if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingAirToAirVariableSpeed) {
    3524            3 :                 errFlag = false;
    3525            3 :                 if (thisFurnace.bIsIHP) {
    3526            1 :                     IHPCoilName = state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).SHCoilName;
    3527            1 :                     thisFurnace.DesignHeatingCapacity =
    3528            2 :                         VariableSpeedCoils::GetCoilCapacityVariableSpeed(state, "Coil:Heating:DX:VariableSpeed", IHPCoilName, errFlag);
    3529              :                 } else {
    3530            2 :                     thisFurnace.DesignHeatingCapacity =
    3531            2 :                         VariableSpeedCoils::GetCoilCapacityVariableSpeed(state, HeatingCoilType, HeatingCoilName, errFlag);
    3532              :                 }
    3533              : 
    3534            3 :                 if (errFlag) {
    3535            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3536            0 :                     ErrorsFound = true;
    3537              :                 }
    3538              :             }
    3539              : 
    3540           35 :             if (thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingAirToAirVariableSpeed) {
    3541            3 :                 errFlag = false;
    3542            3 :                 if (thisFurnace.bIsIHP) {
    3543            1 :                     IHPCoilName = state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).SCCoilName;
    3544            1 :                     thisFurnace.DesignCoolingCapacity =
    3545            2 :                         VariableSpeedCoils::GetCoilCapacityVariableSpeed(state, "COIL:COOLING:DX:VARIABLESPEED", IHPCoilName, errFlag);
    3546              :                 } else {
    3547            2 :                     thisFurnace.DesignCoolingCapacity =
    3548            2 :                         VariableSpeedCoils::GetCoilCapacityVariableSpeed(state, CoolingCoilType, CoolingCoilName, errFlag);
    3549              :                 }
    3550              : 
    3551            3 :                 if (errFlag) {
    3552            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3553            0 :                     ErrorsFound = true;
    3554              :                 }
    3555              :             }
    3556              : 
    3557              :             // Set cooling convergence tolerance
    3558           35 :             thisFurnace.CoolingConvergenceTolerance = 0.001;
    3559              : 
    3560              :             // Set the furnace max outlet temperature
    3561           35 :             thisFurnace.DesignMaxOutletTemp = Numbers(4);
    3562              : 
    3563              :             // Set maximum supply air temperature for supplemental heating coil
    3564           35 :             thisFurnace.MaxOATSuppHeat = Numbers(5);
    3565           70 :             OutputReportPredefined::PreDefTableEntry(
    3566           35 :                 state, state.dataOutRptPredefined->pdchDXHeatCoilSuppHiT, HeatingCoilName, thisFurnace.MaxOATSuppHeat);
    3567              : 
    3568              :             // set minimum outdoor temperature for compressor operation
    3569           35 :             SetMinOATCompressor(state, FurnaceNum, cCurrentModuleObject, ErrorsFound);
    3570              : 
    3571              :         } // End of the Unitary System HeatPump Loop
    3572              : 
    3573              :         // Get the Input for the Water to Air Heat Pump (UnitarySystem:HeatPump:WaterToAir)
    3574          236 :         for (int HeatPumpNum = 1; HeatPumpNum <= NumWaterToAirHeatPump; ++HeatPumpNum) {
    3575              : 
    3576          139 :             CurrentModuleObject = "AirLoopHVAC:UnitaryHeatPump:WaterToAir";
    3577          139 :             FanInletNode = 0;
    3578          139 :             FanOutletNode = 0;
    3579          139 :             CoolingCoilInletNode = 0;
    3580          139 :             CoolingCoilOutletNode = 0;
    3581          139 :             HeatingCoilInletNode = 0;
    3582          139 :             HeatingCoilOutletNode = 0;
    3583          139 :             SupHeatCoilInletNode = 0;
    3584          139 :             SupHeatCoilOutletNode = 0;
    3585          139 :             CoolingCoilType = ' ';
    3586          139 :             CoolingCoilName = ' ';
    3587          139 :             HeatingCoilType = ' ';
    3588          139 :             HeatingCoilName = ' ';
    3589              : 
    3590          139 :             FurnaceNum = NumHeatOnly + NumHeatCool + NumUnitaryHeatOnly + NumUnitaryHeatCool + NumHeatPump + HeatPumpNum;
    3591          139 :             auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    3592          139 :             thisFurnace.iterationMode.allocate(3);
    3593              : 
    3594          139 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    3595              :                                                                      CurrentModuleObject,
    3596              :                                                                      HeatPumpNum,
    3597              :                                                                      Alphas,
    3598              :                                                                      NumAlphas,
    3599              :                                                                      Numbers,
    3600              :                                                                      NumNumbers,
    3601              :                                                                      IOStatus,
    3602              :                                                                      lNumericBlanks,
    3603              :                                                                      lAlphaBlanks,
    3604              :                                                                      cAlphaFields,
    3605              :                                                                      cNumericFields);
    3606              : 
    3607          278 :             GlobalNames::VerifyUniqueInterObjectName(
    3608          139 :                 state, state.dataFurnaces->UniqueFurnaceNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
    3609              : 
    3610          139 :             thisFurnace.type = HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir;
    3611          139 :             thisFurnace.Name = Alphas(1);
    3612              : 
    3613          139 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, thisFurnace.Name};
    3614              : 
    3615          139 :             if (lAlphaBlanks(2)) {
    3616            0 :                 thisFurnace.availSched = Sched::GetScheduleAlwaysOn(state);
    3617          139 :             } else if ((thisFurnace.availSched = Sched::GetSchedule(state, Alphas(2))) == nullptr) {
    3618            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(2), Alphas(2));
    3619            0 :                 ErrorsFound = true;
    3620              :             }
    3621              : 
    3622          139 :             thisFurnace.FurnaceInletNodeNum =
    3623          139 :                 NodeInputManager::GetOnlySingleNode(state,
    3624          139 :                                                     Alphas(3),
    3625              :                                                     ErrorsFound,
    3626              :                                                     DataLoopNode::ConnectionObjectType::AirLoopHVACUnitaryHeatPumpWaterToAir,
    3627          139 :                                                     Alphas(1),
    3628              :                                                     DataLoopNode::NodeFluidType::Air,
    3629              :                                                     DataLoopNode::ConnectionType::Inlet,
    3630              :                                                     NodeInputManager::CompFluidStream::Primary,
    3631              :                                                     DataLoopNode::ObjectIsParent);
    3632              : 
    3633          139 :             thisFurnace.FurnaceOutletNodeNum =
    3634          278 :                 NodeInputManager::GetOnlySingleNode(state,
    3635          139 :                                                     Alphas(4),
    3636              :                                                     ErrorsFound,
    3637              :                                                     DataLoopNode::ConnectionObjectType::AirLoopHVACUnitaryHeatPumpWaterToAir,
    3638          139 :                                                     Alphas(1),
    3639              :                                                     DataLoopNode::NodeFluidType::Air,
    3640              :                                                     DataLoopNode::ConnectionType::Outlet,
    3641              :                                                     NodeInputManager::CompFluidStream::Primary,
    3642              :                                                     DataLoopNode::ObjectIsParent);
    3643              : 
    3644          139 :             BranchNodeConnections::TestCompSet(state, CurrentModuleObject, Alphas(1), Alphas(3), Alphas(4), "Air Nodes");
    3645              : 
    3646              :             // Get the Controlling Zone or Location of the Furnace Thermostat
    3647          139 :             thisFurnace.ControlZoneNum = Util::FindItemInList(Alphas(5), state.dataHeatBal->Zone);
    3648          139 :             if (thisFurnace.ControlZoneNum == 0) {
    3649            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3650            0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(5), Alphas(5)));
    3651            0 :                 ErrorsFound = true;
    3652              :             }
    3653              : 
    3654              :             // Get the node number for the zone with the thermostat
    3655          139 :             if (thisFurnace.ControlZoneNum > 0) {
    3656          139 :                 AirNodeFound = false;
    3657          139 :                 AirLoopFound = false;
    3658          139 :                 int ControlledZoneNum = thisFurnace.ControlZoneNum;
    3659              :                 //             Find the controlled zone number for the specified thermostat location
    3660          139 :                 thisFurnace.NodeNumOfControlledZone = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).ZoneNode;
    3661              :                 //             Determine if furnace is on air loop served by the thermostat location specified
    3662          139 :                 for (int zoneInNode = 1; zoneInNode <= state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).NumInletNodes; ++zoneInNode) {
    3663          139 :                     int AirLoopNumber = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).InletNodeAirLoopNum(zoneInNode);
    3664          139 :                     if (AirLoopNumber > 0) {
    3665          139 :                         for (int BranchNum = 1; BranchNum <= state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).NumBranches; ++BranchNum) {
    3666          268 :                             for (int CompNum = 1;
    3667          268 :                                  CompNum <= state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).Branch(BranchNum).TotalComponents;
    3668              :                                  ++CompNum) {
    3669          268 :                                 if (!Util::SameString(state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).Branch(BranchNum).Comp(CompNum).Name,
    3670          675 :                                                       Alphas(1)) ||
    3671          139 :                                     !Util::SameString(
    3672          139 :                                         state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).Branch(BranchNum).Comp(CompNum).TypeOf,
    3673              :                                         CurrentModuleObject)) {
    3674          129 :                                     continue;
    3675              :                                 }
    3676          139 :                                 AirLoopFound = true;
    3677          139 :                                 thisFurnace.ZoneInletNode = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).InletNode(zoneInNode);
    3678          139 :                                 break;
    3679              :                             }
    3680          139 :                             if (AirLoopFound) {
    3681          139 :                                 break;
    3682              :                             }
    3683              :                         }
    3684         7066 :                         for (TstatZoneNum = 1; TstatZoneNum <= state.dataZoneCtrls->NumTempControlledZones; ++TstatZoneNum) {
    3685         6927 :                             if (state.dataZoneCtrls->TempControlledZone(TstatZoneNum).ActualZoneNum != thisFurnace.ControlZoneNum) {
    3686         6788 :                                 continue;
    3687              :                             }
    3688          139 :                             AirNodeFound = true;
    3689              :                         }
    3690          139 :                         for (TstatZoneNum = 1; TstatZoneNum <= state.dataZoneCtrls->NumComfortControlledZones; ++TstatZoneNum) {
    3691            0 :                             if (state.dataZoneCtrls->ComfortControlledZone(TstatZoneNum).ActualZoneNum != thisFurnace.ControlZoneNum) {
    3692            0 :                                 continue;
    3693              :                             }
    3694            0 :                             AirNodeFound = true;
    3695              :                         }
    3696              :                     }
    3697          139 :                     if (AirLoopFound) {
    3698          139 :                         break;
    3699              :                     }
    3700              :                 }
    3701          139 :                 if (!AirNodeFound) {
    3702            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3703            0 :                     ShowContinueError(state, "Did not find air node (zone with thermostat).");
    3704            0 :                     ShowContinueError(state, format("Specified {} = {}", cAlphaFields(5), Alphas(5)));
    3705            0 :                     ShowContinueError(
    3706              :                         state, "Both a ZoneHVAC:EquipmentConnections object and a ZoneControl:Thermostat object must be specified for this zone.");
    3707            0 :                     ErrorsFound = true;
    3708              :                 }
    3709          139 :                 if (!AirLoopFound) {
    3710            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3711            0 :                     ShowContinueError(state, "Did not find correct AirLoopHVAC.");
    3712            0 :                     ShowContinueError(state, format("Specified {} = {}", cAlphaFields(5), Alphas(5)));
    3713            0 :                     ErrorsFound = true;
    3714              :                 }
    3715              :             }
    3716              : 
    3717              :             // Get fan data
    3718          139 :             FanName = Alphas(7);
    3719          139 :             errFlag = false;
    3720          139 :             thisFurnace.fanType = static_cast<HVAC::FanType>(getEnumValue(HVAC::fanTypeNamesUC, Alphas(6)));
    3721              : 
    3722          139 :             if (thisFurnace.fanType != HVAC::FanType::OnOff) {
    3723            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3724            0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(6), Alphas(6)));
    3725            0 :                 ErrorsFound = true;
    3726              : 
    3727          139 :             } else if ((thisFurnace.FanIndex = Fans::GetFanIndex(state, FanName)) == 0) {
    3728            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(7), FanName);
    3729            0 :                 ErrorsFound = true;
    3730              : 
    3731              :             } else {
    3732          139 :                 auto *fan = state.dataFans->fans(thisFurnace.FanIndex);
    3733          139 :                 FanInletNode = fan->inletNodeNum;
    3734          139 :                 FanOutletNode = fan->outletNodeNum;
    3735          139 :                 thisFurnace.fanAvailSched = fan->availSched;
    3736              :             }
    3737              : 
    3738              :             // Get heating coil type and name data
    3739          139 :             if (Alphas(8) == "COIL:HEATING:WATERTOAIRHEATPUMP:PARAMETERESTIMATION") {
    3740           14 :                 HeatingCoilType = Alphas(8);
    3741           14 :                 thisFurnace.HeatingCoilType_Num = HVAC::Coil_HeatingWaterToAirHP;
    3742           14 :                 HeatingCoilName = Alphas(9);
    3743           14 :                 ValidateComponent(state, HeatingCoilType, HeatingCoilName, IsNotOK, CurrentModuleObject);
    3744           14 :                 if (IsNotOK) {
    3745            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3746            0 :                     ErrorsFound = true;
    3747              :                 } else {
    3748           14 :                     thisFurnace.HeatingCoilIndex = WaterToAirHeatPump::GetCoilIndex(state, HeatingCoilType, HeatingCoilName, errFlag);
    3749           14 :                     HeatingCoilInletNode = WaterToAirHeatPump::GetCoilInletNode(state, HeatingCoilType, HeatingCoilName, errFlag);
    3750           14 :                     HeatingCoilOutletNode = WaterToAirHeatPump::GetCoilOutletNode(state, HeatingCoilType, HeatingCoilName, errFlag);
    3751              :                 }
    3752          125 :             } else if (Alphas(8) == "COIL:HEATING:WATERTOAIRHEATPUMP:EQUATIONFIT") {
    3753          111 :                 HeatingCoilType = Alphas(8);
    3754          111 :                 thisFurnace.HeatingCoilType_Num = HVAC::Coil_HeatingWaterToAirHPSimple;
    3755          111 :                 HeatingCoilName = Alphas(9);
    3756          111 :                 ValidateComponent(state, HeatingCoilType, HeatingCoilName, IsNotOK, CurrentModuleObject);
    3757          111 :                 if (IsNotOK) {
    3758            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3759            0 :                     ErrorsFound = true;
    3760              :                 } else {
    3761          111 :                     thisFurnace.HeatingCoilIndex = WaterToAirHeatPumpSimple::GetCoilIndex(state, HeatingCoilType, HeatingCoilName, errFlag);
    3762          111 :                     HeatingCoilInletNode = WaterToAirHeatPumpSimple::GetCoilInletNode(state, HeatingCoilType, HeatingCoilName, errFlag);
    3763          111 :                     HeatingCoilOutletNode = WaterToAirHeatPumpSimple::GetCoilOutletNode(state, HeatingCoilType, HeatingCoilName, errFlag);
    3764              :                 }
    3765           14 :             } else if (Alphas(8) == "COIL:HEATING:WATERTOAIRHEATPUMP:VARIABLESPEEDEQUATIONFIT") {
    3766           14 :                 HeatingCoilType = Alphas(8);
    3767           14 :                 thisFurnace.HeatingCoilType_Num = HVAC::Coil_HeatingWaterToAirHPVSEquationFit;
    3768           14 :                 HeatingCoilName = Alphas(9);
    3769           14 :                 ValidateComponent(state, HeatingCoilType, HeatingCoilName, IsNotOK, CurrentModuleObject);
    3770           14 :                 if (IsNotOK) {
    3771            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3772            0 :                     ErrorsFound = true;
    3773              :                 } else {
    3774           14 :                     thisFurnace.HeatingCoilIndex = VariableSpeedCoils::GetCoilIndexVariableSpeed(state, HeatingCoilType, HeatingCoilName, errFlag);
    3775           14 :                     HeatingCoilInletNode = VariableSpeedCoils::GetCoilInletNodeVariableSpeed(state, HeatingCoilType, HeatingCoilName, errFlag);
    3776           14 :                     HeatingCoilOutletNode = VariableSpeedCoils::GetCoilOutletNodeVariableSpeed(state, HeatingCoilType, HeatingCoilName, errFlag);
    3777              :                 }
    3778              :             } else {
    3779            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3780            0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(8), Alphas(8)));
    3781            0 :                 ErrorsFound = true;
    3782              :             }
    3783              : 
    3784              :             // Get Cooling Coil Information if available
    3785          139 :             if (Alphas(10) == "COIL:COOLING:WATERTOAIRHEATPUMP:PARAMETERESTIMATION") {
    3786           14 :                 CoolingCoilType = Alphas(10);
    3787           14 :                 thisFurnace.CoolingCoilType_Num = HVAC::Coil_CoolingWaterToAirHP;
    3788           14 :                 CoolingCoilName = Alphas(11);
    3789           14 :                 ValidateComponent(state, CoolingCoilType, CoolingCoilName, IsNotOK, CurrentModuleObject);
    3790           14 :                 if (IsNotOK) {
    3791            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3792            0 :                     ErrorsFound = true;
    3793              :                 } else {
    3794           14 :                     thisFurnace.CoolingCoilIndex = WaterToAirHeatPump::GetCoilIndex(state, CoolingCoilType, CoolingCoilName, errFlag);
    3795           14 :                     CoolingCoilInletNode = WaterToAirHeatPump::GetCoilInletNode(state, CoolingCoilType, CoolingCoilName, errFlag);
    3796           14 :                     CoolingCoilOutletNode = WaterToAirHeatPump::GetCoilOutletNode(state, CoolingCoilType, CoolingCoilName, errFlag);
    3797              :                 }
    3798          125 :             } else if (Alphas(10) == "COIL:COOLING:WATERTOAIRHEATPUMP:EQUATIONFIT") {
    3799          111 :                 CoolingCoilType = Alphas(10);
    3800          111 :                 thisFurnace.CoolingCoilType_Num = HVAC::Coil_CoolingWaterToAirHPSimple;
    3801          111 :                 CoolingCoilName = Alphas(11);
    3802          111 :                 ValidateComponent(state, CoolingCoilType, CoolingCoilName, IsNotOK, CurrentModuleObject);
    3803          111 :                 if (IsNotOK) {
    3804            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3805            0 :                     ErrorsFound = true;
    3806              :                 } else {
    3807          111 :                     thisFurnace.CoolingCoilIndex = WaterToAirHeatPumpSimple::GetCoilIndex(state, CoolingCoilType, CoolingCoilName, errFlag);
    3808          111 :                     CoolingCoilInletNode = WaterToAirHeatPumpSimple::GetCoilInletNode(state, CoolingCoilType, CoolingCoilName, errFlag);
    3809          111 :                     CoolingCoilOutletNode = WaterToAirHeatPumpSimple::GetCoilOutletNode(state, CoolingCoilType, CoolingCoilName, errFlag);
    3810              :                 }
    3811           14 :             } else if (Alphas(10) == "COIL:COOLING:WATERTOAIRHEATPUMP:VARIABLESPEEDEQUATIONFIT") {
    3812           14 :                 CoolingCoilType = Alphas(10);
    3813           14 :                 thisFurnace.CoolingCoilType_Num = HVAC::Coil_CoolingWaterToAirHPVSEquationFit;
    3814           14 :                 CoolingCoilName = Alphas(11);
    3815           14 :                 ValidateComponent(state, CoolingCoilType, CoolingCoilName, IsNotOK, CurrentModuleObject);
    3816           14 :                 if (IsNotOK) {
    3817            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3818            0 :                     ErrorsFound = true;
    3819              :                 } else {
    3820           14 :                     thisFurnace.CoolingCoilIndex = VariableSpeedCoils::GetCoilIndexVariableSpeed(state, CoolingCoilType, CoolingCoilName, errFlag);
    3821           14 :                     CoolingCoilInletNode = VariableSpeedCoils::GetCoilInletNodeVariableSpeed(state, CoolingCoilType, CoolingCoilName, errFlag);
    3822           14 :                     CoolingCoilOutletNode = VariableSpeedCoils::GetCoilOutletNodeVariableSpeed(state, CoolingCoilType, CoolingCoilName, errFlag);
    3823              :                 }
    3824              :             } else {
    3825            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3826            0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(10), Alphas(10)));
    3827            0 :                 ErrorsFound = true;
    3828              :             }
    3829              : 
    3830            0 :             thisFurnace.WaterCyclingMode = (NumAlphas < 18 || lAlphaBlanks(18))
    3831          139 :                                                ? HVAC::WaterFlow::Cycling
    3832            0 :                                                : static_cast<HVAC::WaterFlow>(getEnumValue(HVAC::waterFlowNamesUC, Alphas(18)));
    3833              : 
    3834              :             // end get water flow mode info
    3835          139 :             if (Alphas(8) == "COIL:HEATING:WATERTOAIRHEATPUMP:EQUATIONFIT" && Alphas(10) == "COIL:COOLING:WATERTOAIRHEATPUMP:EQUATIONFIT") {
    3836          111 :                 thisFurnace.WatertoAirHPType = WAHPCoilType::Simple;
    3837          111 :                 WaterToAirHeatPumpSimple::SetSimpleWSHPData(
    3838          111 :                     state, thisFurnace.CoolingCoilIndex, ErrorsFound, thisFurnace.WaterCyclingMode, _, thisFurnace.HeatingCoilIndex);
    3839           42 :             } else if (Alphas(8) == "COIL:HEATING:WATERTOAIRHEATPUMP:PARAMETERESTIMATION" &&
    3840           14 :                        Alphas(10) == "COIL:COOLING:WATERTOAIRHEATPUMP:PARAMETERESTIMATION") {
    3841           14 :                 thisFurnace.WatertoAirHPType = WAHPCoilType::ParEst;
    3842           28 :             } else if (Alphas(8) == "COIL:HEATING:WATERTOAIRHEATPUMP:VARIABLESPEEDEQUATIONFIT" &&
    3843           14 :                        Alphas(10) == "COIL:COOLING:WATERTOAIRHEATPUMP:VARIABLESPEEDEQUATIONFIT") {
    3844           14 :                 thisFurnace.WatertoAirHPType = WAHPCoilType::VarSpeedEquationFit;
    3845           14 :                 VariableSpeedCoils::SetVarSpeedCoilData(state, thisFurnace.CoolingCoilIndex, ErrorsFound, _, thisFurnace.HeatingCoilIndex);
    3846              :             } else {
    3847            0 :                 ShowContinueError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    3848            0 :                 ShowContinueError(state, "Cooling coil and heating coil should be of same general type");
    3849            0 :                 ErrorsFound = true;
    3850              :             }
    3851              : 
    3852              :             // Get supplemental heating coil information
    3853              : 
    3854          139 :             SuppHeatCoilType = Alphas(12);
    3855          139 :             SuppHeatCoilName = Alphas(13);
    3856          139 :             thisFurnace.SuppHeatCoilType = SuppHeatCoilType;
    3857          139 :             thisFurnace.SuppHeatCoilName = SuppHeatCoilName;
    3858          139 :             errFlag = false;
    3859          139 :             if (Util::SameString(SuppHeatCoilType, "Coil:Heating:Fuel") || Util::SameString(SuppHeatCoilType, "Coil:Heating:Electric")) {
    3860              : 
    3861          139 :                 thisFurnace.SuppHeatCoilType_Num = HeatingCoils::GetHeatingCoilTypeNum(state, SuppHeatCoilType, SuppHeatCoilName, errFlag);
    3862          139 :                 if (errFlag) {
    3863            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3864            0 :                     ErrorsFound = true;
    3865              :                 } else {
    3866          139 :                     IsNotOK = false;
    3867          139 :                     ValidateComponent(state, SuppHeatCoilType, SuppHeatCoilName, IsNotOK, CurrentModuleObject);
    3868          139 :                     if (IsNotOK) {
    3869            0 :                         ShowContinueError(state, format("In {} \"{}\"", CurrentModuleObject, Alphas(1)));
    3870            0 :                         ErrorsFound = true;
    3871              : 
    3872              :                     } else { // mine data from the supplemental heating coil
    3873              : 
    3874          139 :                         HeatingCoils::GetCoilIndex(state, SuppHeatCoilName, thisFurnace.SuppHeatCoilIndex, IsNotOK);
    3875          139 :                         if (IsNotOK) {
    3876            0 :                             ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3877            0 :                             ErrorsFound = true;
    3878              :                         }
    3879              : 
    3880              :                         // Get the Supplemental Heating Coil Inlet Node Number
    3881          139 :                         errFlag = false;
    3882          139 :                         SupHeatCoilInletNode = HeatingCoils::GetCoilInletNode(state, SuppHeatCoilType, SuppHeatCoilName, errFlag);
    3883          139 :                         if (errFlag) {
    3884            0 :                             ShowContinueError(state, format("...occurs in {} \"{}\"", CurrentModuleObject, Alphas(1)));
    3885            0 :                             ErrorsFound = true;
    3886              :                         }
    3887              : 
    3888              :                         // Get the Supplemental Heating Coil Outlet Node Number
    3889          139 :                         errFlag = false;
    3890          139 :                         SupHeatCoilOutletNode = HeatingCoils::GetCoilOutletNode(state, SuppHeatCoilType, SuppHeatCoilName, errFlag);
    3891          139 :                         if (errFlag) {
    3892            0 :                             ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3893            0 :                             ErrorsFound = true;
    3894              :                         }
    3895              : 
    3896              :                         // Get the supplemental heating coil design capacity
    3897          139 :                         errFlag = false;
    3898          139 :                         thisFurnace.DesignSuppHeatingCapacity = HeatingCoils::GetCoilCapacity(state, SuppHeatCoilType, SuppHeatCoilName, errFlag);
    3899          139 :                         if (errFlag) {
    3900            0 :                             ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3901            0 :                             ErrorsFound = true;
    3902              :                         }
    3903              : 
    3904              :                     } // IF (IsNotOK) THEN
    3905              :                 }
    3906            0 :             } else if (Util::SameString(SuppHeatCoilType, "Coil:Heating:Water")) {
    3907            0 :                 thisFurnace.SuppHeatCoilType_Num = HVAC::Coil_HeatingWater;
    3908            0 :                 ValidateComponent(state, SuppHeatCoilType, SuppHeatCoilName, IsNotOK, CurrentModuleObject);
    3909            0 :                 if (IsNotOK) {
    3910            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3911            0 :                     ErrorsFound = true;
    3912              :                 } else { // mine data from heating coil object
    3913              : 
    3914              :                     // Get the Heating Coil water Inlet or control Node number
    3915            0 :                     errFlag = false;
    3916            0 :                     thisFurnace.SuppCoilControlNode = WaterCoils::GetCoilWaterInletNode(state, "Coil:Heating:Water", SuppHeatCoilName, errFlag);
    3917            0 :                     if (errFlag) {
    3918            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3919            0 :                         ErrorsFound = true;
    3920              :                     }
    3921              : 
    3922              :                     // Get the ReHeat Coil hot water max volume flow rate
    3923            0 :                     errFlag = false;
    3924            0 :                     thisFurnace.MaxSuppCoilFluidFlow = WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", SuppHeatCoilName, errFlag);
    3925            0 :                     if (errFlag) {
    3926            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3927            0 :                         ErrorsFound = true;
    3928              :                     }
    3929              : 
    3930              :                     // Get the ReHeat Coil Inlet Node
    3931            0 :                     errFlag = false;
    3932            0 :                     SupHeatCoilInletNode = WaterCoils::GetCoilInletNode(state, "Coil:Heating:Water", SuppHeatCoilName, errFlag);
    3933            0 :                     thisFurnace.SuppCoilAirInletNode = SupHeatCoilInletNode;
    3934            0 :                     if (errFlag) {
    3935            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3936            0 :                         ErrorsFound = true;
    3937              :                     }
    3938              : 
    3939              :                     // Get the ReHeat Coil Outlet Node
    3940            0 :                     errFlag = false;
    3941            0 :                     SupHeatCoilOutletNode = WaterCoils::GetCoilOutletNode(state, "Coil:Heating:Water", SuppHeatCoilName, errFlag);
    3942            0 :                     thisFurnace.SuppCoilAirOutletNode = SupHeatCoilOutletNode;
    3943            0 :                     if (errFlag) {
    3944            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3945            0 :                         ErrorsFound = true;
    3946              :                     }
    3947              : 
    3948            0 :                     errFlag = false;
    3949            0 :                     HVACControllers::CheckCoilWaterInletNode(state, thisFurnace.CoilControlNode, errFlag);
    3950            0 :                     if (!errFlag) { // then did find a controller so that is bad
    3951            0 :                         ShowSevereError(state,
    3952            0 :                                         format("{} = {} has a conflicting Controller:WaterCoil object", CurrentModuleObject, thisFurnace.Name));
    3953            0 :                         ShowContinueError(state, "Hot water coils are controlled directly by unitary and furnace systems.");
    3954            0 :                         ShowContinueError(state, "No water coil controller should be input for the coil.");
    3955            0 :                         ErrorsFound = true;
    3956              :                     }
    3957              :                 }
    3958              : 
    3959            0 :             } else if (Util::SameString(SuppHeatCoilType, "Coil:Heating:Steam")) {
    3960            0 :                 thisFurnace.SuppHeatCoilType_Num = HVAC::Coil_HeatingSteam;
    3961            0 :                 ValidateComponent(state, SuppHeatCoilType, SuppHeatCoilName, IsNotOK, CurrentModuleObject);
    3962            0 :                 if (IsNotOK) {
    3963            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3964            0 :                     ErrorsFound = true;
    3965              :                 } else { // mine data from heating coil object
    3966              : 
    3967            0 :                     errFlag = false;
    3968            0 :                     thisFurnace.SuppHeatCoilIndex = SteamCoils::GetSteamCoilIndex(state, SuppHeatCoilType, SuppHeatCoilName, errFlag);
    3969            0 :                     if (thisFurnace.SuppHeatCoilIndex == 0) {
    3970            0 :                         ShowSevereError(state, format("{} illegal {} = {}", CurrentModuleObject, cAlphaFields(12), SuppHeatCoilName));
    3971            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3972            0 :                         ErrorsFound = true;
    3973              :                     }
    3974              : 
    3975              :                     // Get the Heating Coil steam inlet node number
    3976            0 :                     errFlag = false;
    3977            0 :                     thisFurnace.SuppCoilControlNode = SteamCoils::GetCoilSteamInletNode(state, "Coil:Heating:Steam", SuppHeatCoilName, errFlag);
    3978            0 :                     if (errFlag) {
    3979            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3980            0 :                         ErrorsFound = true;
    3981              :                     }
    3982              : 
    3983              :                     // Get the Heating Coil steam max volume flow rate
    3984            0 :                     thisFurnace.MaxSuppCoilFluidFlow = SteamCoils::GetCoilMaxSteamFlowRate(state, thisFurnace.SuppHeatCoilIndex, errFlag);
    3985            0 :                     if (thisFurnace.MaxSuppCoilFluidFlow > 0.0) {
    3986              :                         SteamDensity =
    3987            0 :                             Fluid::GetSteam(state)->getSatDensity(state, state.dataFurnaces->TempSteamIn, 1.0, getAirLoopHVACHeatCoolInput);
    3988            0 :                         thisFurnace.MaxSuppCoilFluidFlow =
    3989            0 :                             SteamCoils::GetCoilMaxSteamFlowRate(state, thisFurnace.SuppHeatCoilIndex, errFlag) * SteamDensity;
    3990              :                     }
    3991              : 
    3992              :                     // Get the Heating Coil Inlet Node
    3993            0 :                     errFlag = false;
    3994            0 :                     SupHeatCoilInletNode = SteamCoils::GetCoilAirInletNode(state, thisFurnace.SuppHeatCoilIndex, SuppHeatCoilName, errFlag);
    3995            0 :                     thisFurnace.SuppCoilAirInletNode = SupHeatCoilInletNode;
    3996            0 :                     if (errFlag) {
    3997            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3998            0 :                         ErrorsFound = true;
    3999              :                     }
    4000              : 
    4001              :                     // Get the Heating Coil Outlet Node
    4002            0 :                     errFlag = false;
    4003            0 :                     SupHeatCoilOutletNode = SteamCoils::GetCoilAirOutletNode(state, thisFurnace.SuppHeatCoilIndex, SuppHeatCoilName, errFlag);
    4004            0 :                     thisFurnace.SuppCoilAirOutletNode = SupHeatCoilOutletNode;
    4005            0 :                     if (errFlag) {
    4006            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    4007            0 :                         ErrorsFound = true;
    4008              :                     }
    4009              :                 }
    4010              : 
    4011              :             } else {
    4012            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    4013            0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(12), Alphas(12)));
    4014            0 :                 ErrorsFound = true;
    4015              :             } // IF (Furnace(FurnaceNum)%HeatingCoilType_Num == Coil_HeatingGasOrOtherFuel .OR. &, etc.
    4016              : 
    4017          139 :             if (lAlphaBlanks(14)) {
    4018            0 :                 thisFurnace.CondenserNodeNum = 0;
    4019              :             } else {
    4020          139 :                 thisFurnace.CondenserNodeNum =
    4021          139 :                     NodeInputManager::GetOnlySingleNode(state,
    4022          139 :                                                         Alphas(14),
    4023              :                                                         ErrorsFound,
    4024              :                                                         DataLoopNode::ConnectionObjectType::AirLoopHVACUnitaryHeatPumpWaterToAir,
    4025          139 :                                                         Alphas(1),
    4026              :                                                         DataLoopNode::NodeFluidType::Air,
    4027              :                                                         DataLoopNode::ConnectionType::OutsideAirReference,
    4028              :                                                         NodeInputManager::CompFluidStream::Primary,
    4029              :                                                         DataLoopNode::ObjectIsNotParent);
    4030              :                 // need better verification.
    4031          139 :                 if (!OutAirNodeManager::CheckOutAirNodeNumber(state, thisFurnace.CondenserNodeNum)) {
    4032            0 :                     ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    4033            0 :                     ShowContinueError(state, format(" Node name of outdoor dry-bulb temperature sensor not valid outdoor air node= {}", Alphas(14)));
    4034            0 :                     ShowContinueError(state, "...does not appear in an OutdoorAir:NodeList or as an OutdoorAir:Node.");
    4035            0 :                     ErrorsFound = true;
    4036              :                 }
    4037              :             }
    4038              : 
    4039          139 :             thisFurnace.fanPlace = static_cast<HVAC::FanPlace>(getEnumValue(HVAC::fanPlaceNamesUC, Alphas(15)));
    4040          139 :             assert(thisFurnace.fanPlace != HVAC::FanPlace::Invalid);
    4041              : 
    4042          139 :             if (lAlphaBlanks(16)) {
    4043            0 :                 thisFurnace.fanOp = HVAC::FanOp::Cycling;
    4044            0 :                 if (thisFurnace.fanType != HVAC::FanType::OnOff) {
    4045            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, thisFurnace.Name));
    4046            0 :                     ShowContinueError(state, format("{} = {}", cAlphaFields(6), Alphas(6)));
    4047            0 :                     ShowContinueError(state, format("Fan type must be Fan:OnOff when {} = Blank.", cAlphaFields(16)));
    4048            0 :                     ErrorsFound = true;
    4049              :                 }
    4050          139 :             } else if ((thisFurnace.fanOpModeSched = Sched::GetSchedule(state, Alphas(16))) == nullptr) {
    4051            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(16), Alphas(16));
    4052            0 :                 ErrorsFound = true;
    4053              :             }
    4054              : 
    4055              :             // add the Dehumidification Type
    4056          139 :             if (Util::SameString(Alphas(17), "None") || Util::SameString(Alphas(17), "CoolReheat")) {
    4057          139 :                 AirNodeFound = false;
    4058          139 :                 if (Util::SameString(Alphas(17), "CoolReheat")) {
    4059           10 :                     thisFurnace.DehumidControlType_Num = DehumidificationControlMode::CoolReheat;
    4060           10 :                     thisFurnace.Humidistat = true;
    4061           10 :                     if (lAlphaBlanks(17)) {
    4062            0 :                         ShowWarningError(state, format("{} \"{}\"", CurrentModuleObject, Alphas(1)));
    4063            0 :                         ShowContinueError(state,
    4064              :                                           "Dehumidification control type is assumed to be None since a supplemental reheat coil has not been "
    4065              :                                           "specified and the simulation continues.");
    4066            0 :                         thisFurnace.Humidistat = false;
    4067            0 :                         thisFurnace.DehumidControlType_Num = DehumidificationControlMode::None;
    4068              :                     }
    4069              :                 }
    4070          139 :                 if (Util::SameString(Alphas(17), "None")) {
    4071          129 :                     thisFurnace.DehumidControlType_Num = DehumidificationControlMode::None;
    4072          129 :                     thisFurnace.Humidistat = false;
    4073              :                 }
    4074          139 :                 if (thisFurnace.Humidistat) {
    4075           60 :                     for (HStatZoneNum = 1; HStatZoneNum <= state.dataZoneCtrls->NumHumidityControlZones; ++HStatZoneNum) {
    4076           50 :                         if (state.dataZoneCtrls->HumidityControlZone(HStatZoneNum).ActualZoneNum != thisFurnace.ControlZoneNum) {
    4077           40 :                             continue;
    4078              :                         }
    4079           10 :                         AirNodeFound = true;
    4080              :                     }
    4081           10 :                     if (!AirNodeFound) {
    4082            0 :                         ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    4083            0 :                         ShowContinueError(state, "Did not find Air Node (Zone with Humidistat).");
    4084            0 :                         ShowContinueError(state, format("Specified {} = {}", cAlphaFields(5), Alphas(5)));
    4085            0 :                         ErrorsFound = true;
    4086              :                     }
    4087              :                 }
    4088              :             } else { // invalid input or blank
    4089            0 :                 if (!lAlphaBlanks(17)) {
    4090            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    4091            0 :                     ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(17), Alphas(17)));
    4092            0 :                     ErrorsFound = true;
    4093              :                 } else {
    4094            0 :                     thisFurnace.Humidistat = false;
    4095            0 :                     thisFurnace.DehumidControlType_Num = DehumidificationControlMode::None;
    4096              :                 }
    4097              :             }
    4098              : 
    4099              :             // Add fan to component sets array
    4100              : 
    4101          139 :             if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
    4102          139 :                 CompSetFanInlet = Alphas(3);
    4103          139 :                 CompSetCoolInlet = "UNDEFINED";
    4104          139 :                 if (FanInletNode != thisFurnace.FurnaceInletNodeNum) {
    4105            0 :                     ShowSevereError(
    4106            0 :                         state, format("For {} = {}, Mismatch between unitary system inlet node and fan inlet node.", CurrentModuleObject, Alphas(1)));
    4107            0 :                     ShowContinueError(state, "..For \"BlowThrough\" fan, the inlet node name for the HeatPump should match the fan inlet node name.");
    4108            0 :                     ShowContinueError(state, format("..HeatPump Inlet Node = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceInletNodeNum)));
    4109            0 :                     ShowContinueError(state, format("..Fan Inlet Node      = {}", state.dataLoopNodes->NodeID(FanInletNode)));
    4110            0 :                     ErrorsFound = true;
    4111              :                 }
    4112          139 :                 if (FanOutletNode != CoolingCoilInletNode) {
    4113            0 :                     ShowSevereError(
    4114            0 :                         state, format("For {} = {}, Mismatch between fan outlet node and cooling coil inlet node.", CurrentModuleObject, Alphas(1)));
    4115            0 :                     ShowContinueError(state, "..For \"BlowThrough\" fan, the fan outlet node name must match the cooling coil inlet node name.");
    4116            0 :                     ShowContinueError(state, format("..Fan outlet node         = {}", state.dataLoopNodes->NodeID(FanOutletNode)));
    4117            0 :                     ShowContinueError(state, format("..Cooling coil inlet node = {}", state.dataLoopNodes->NodeID(CoolingCoilInletNode)));
    4118            0 :                     ErrorsFound = true;
    4119              :                 }
    4120          139 :                 if (CoolingCoilOutletNode != HeatingCoilInletNode) {
    4121            0 :                     ShowSevereError(state,
    4122            0 :                                     format("For {} = {}, Mismatch between cooling coil outlet node and heating coil inlet node.",
    4123              :                                            CurrentModuleObject,
    4124              :                                            Alphas(1)));
    4125            0 :                     ShowContinueError(state, "..The cooling coil outlet node name must match the heating coil inlet node name.");
    4126            0 :                     ShowContinueError(state, format("..Cooling coil outlet node = {}", state.dataLoopNodes->NodeID(CoolingCoilOutletNode)));
    4127            0 :                     ShowContinueError(state, format("..Heating coil inlet node  = {}", state.dataLoopNodes->NodeID(HeatingCoilInletNode)));
    4128            0 :                     ErrorsFound = true;
    4129              :                 }
    4130          139 :                 if (HeatingCoilOutletNode != SupHeatCoilInletNode) {
    4131            0 :                     ShowSevereError(state,
    4132            0 :                                     format("For {} = {}, Mismatch between heating coil outlet node and supplemental heating coil inlet node.",
    4133              :                                            CurrentModuleObject,
    4134              :                                            Alphas(1)));
    4135            0 :                     ShowContinueError(
    4136              :                         state,
    4137              :                         "..For \"BlowThrough\" fan, the heating coil outlet node name must match the supplemental heating coil inlet node name.");
    4138            0 :                     ShowContinueError(state,
    4139            0 :                                       format("..Heating coil outlet node             = {}", state.dataLoopNodes->NodeID(HeatingCoilOutletNode)));
    4140            0 :                     ShowContinueError(state,
    4141            0 :                                       format("..Supplemental heating coil inlet node = {}", state.dataLoopNodes->NodeID(SupHeatCoilInletNode)));
    4142            0 :                     ErrorsFound = true;
    4143              :                 }
    4144          139 :                 if (SupHeatCoilOutletNode != thisFurnace.FurnaceOutletNodeNum) {
    4145            0 :                     ShowSevereError(state,
    4146            0 :                                     format("For {} = {}, Mismatch between supplemental heating coil outlet node and HeatPump outlet node.",
    4147              :                                            CurrentModuleObject,
    4148              :                                            Alphas(1)));
    4149            0 :                     ShowContinueError(state, "..The supplemental heating coil outlet node name must match the HeatPump outlet node name.");
    4150            0 :                     ShowContinueError(state,
    4151            0 :                                       format("..Supplemental heating coil outlet node = {}", state.dataLoopNodes->NodeID(SupHeatCoilOutletNode)));
    4152            0 :                     ShowContinueError(
    4153            0 :                         state, format("..HeatPump outlet node                  = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    4154            0 :                     ErrorsFound = true;
    4155              :                 }
    4156              :             } else {
    4157            0 :                 CompSetFanInlet = "UNDEFINED";
    4158            0 :                 CompSetCoolInlet = Alphas(3);
    4159            0 :                 if (CoolingCoilInletNode != thisFurnace.FurnaceInletNodeNum) {
    4160            0 :                     ShowSevereError(state,
    4161            0 :                                     format("For {} = {}, Mismatch between unitary system inlet node and cooling coil inlet node.",
    4162              :                                            CurrentModuleObject,
    4163              :                                            Alphas(1)));
    4164            0 :                     ShowContinueError(
    4165              :                         state, "..For \"DrawThrough\" fan, the inlet node name for the HeatPump should match the cooling coil inlet node name.");
    4166            0 :                     ShowContinueError(state, format("..HeatPump inlet node     = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceInletNodeNum)));
    4167            0 :                     ShowContinueError(state, format("..Cooling coil inlet node = {}", state.dataLoopNodes->NodeID(CoolingCoilInletNode)));
    4168            0 :                     ErrorsFound = true;
    4169              :                 }
    4170            0 :                 if (CoolingCoilOutletNode != HeatingCoilInletNode) {
    4171            0 :                     ShowSevereError(state,
    4172            0 :                                     format("For {} = {}, Mismatch between cooling coil outlet node and heating coil inlet node.",
    4173              :                                            CurrentModuleObject,
    4174              :                                            Alphas(1)));
    4175            0 :                     ShowContinueError(state, "..The outlet node name for the cooling coil should match the heating coil inlet node name.");
    4176            0 :                     ShowContinueError(state, format("..Cooling coil outlet node = {}", state.dataLoopNodes->NodeID(CoolingCoilOutletNode)));
    4177            0 :                     ShowContinueError(state, format("..Heating coil inlet node  = {}", state.dataLoopNodes->NodeID(HeatingCoilInletNode)));
    4178            0 :                     ErrorsFound = true;
    4179              :                 }
    4180            0 :                 if (HeatingCoilOutletNode != FanInletNode) {
    4181            0 :                     ShowSevereError(
    4182            0 :                         state, format("For {} = {}, Mismatch between heating coil outlet node and fan inlet node.", CurrentModuleObject, Alphas(1)));
    4183            0 :                     ShowContinueError(state,
    4184              :                                       "..For \"DrawThrough\" fan, the outlet node name for the heating coil should match the fan inlet node name.");
    4185            0 :                     ShowContinueError(state, format("..Heating coil outlet node = {}", state.dataLoopNodes->NodeID(HeatingCoilOutletNode)));
    4186            0 :                     ShowContinueError(state, format("..Fan inlet node           = {}", state.dataLoopNodes->NodeID(FanInletNode)));
    4187            0 :                     ErrorsFound = true;
    4188              :                 }
    4189            0 :                 if (FanOutletNode != SupHeatCoilInletNode) {
    4190            0 :                     ShowSevereError(state,
    4191            0 :                                     format("For {} = {}, Mismatch between fan outlet node and supplemental heating coil inlet node.",
    4192              :                                            CurrentModuleObject,
    4193              :                                            Alphas(1)));
    4194            0 :                     ShowContinueError(
    4195              :                         state,
    4196              :                         "..For \"DrawThrough\" fan, the outlet node name for the fan should match the supplemental heating coil inlet node name.");
    4197            0 :                     ShowContinueError(state, format("..Fan outlet node                      = {}", state.dataLoopNodes->NodeID(FanOutletNode)));
    4198            0 :                     ShowContinueError(state,
    4199            0 :                                       format("..Supplemental heating coil inlet node = {}", state.dataLoopNodes->NodeID(SupHeatCoilInletNode)));
    4200            0 :                     ErrorsFound = true;
    4201              :                 }
    4202            0 :                 if (SupHeatCoilOutletNode != thisFurnace.FurnaceOutletNodeNum) {
    4203            0 :                     ShowSevereError(state,
    4204            0 :                                     format("For {} = {}, Mismatch between supplemental heating coil outlet node and HeatPump outlet node.",
    4205              :                                            CurrentModuleObject,
    4206              :                                            Alphas(1)));
    4207            0 :                     ShowContinueError(state, "..The supplemental heating coil outlet node name must match the HeatPump outlet node name.");
    4208            0 :                     ShowContinueError(state,
    4209            0 :                                       format("..Supplemental heating coil outlet node = {}", state.dataLoopNodes->NodeID(SupHeatCoilOutletNode)));
    4210            0 :                     ShowContinueError(
    4211            0 :                         state, format("..HeatPump outlet node                  = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    4212            0 :                     ErrorsFound = true;
    4213              :                 }
    4214              :             }
    4215              :             //  (Set up validation here for the fan or cooling coil inlet?)
    4216          139 :             BranchNodeConnections::SetUpCompSets(state, CurrentModuleObject, Alphas(1), Alphas(6), Alphas(7), CompSetFanInlet, "UNDEFINED");
    4217              : 
    4218              :             // Add DX heating coil to component sets array
    4219          139 :             BranchNodeConnections::SetUpCompSets(state, CurrentModuleObject, Alphas(1), Alphas(8), Alphas(9), "UNDEFINED", "UNDEFINED");
    4220              : 
    4221              :             // Add DX cooling coil to component sets array
    4222          139 :             BranchNodeConnections::SetUpCompSets(state, CurrentModuleObject, Alphas(1), Alphas(10), Alphas(11), CompSetCoolInlet, "UNDEFINED");
    4223              : 
    4224              :             // Add supplemental heating coil to component sets array
    4225          139 :             BranchNodeConnections::SetUpCompSets(state, CurrentModuleObject, Alphas(1), Alphas(12), Alphas(13), "UNDEFINED", Alphas(4));
    4226              : 
    4227              :             // Set the Design Fan Volume Flow Rate
    4228          139 :             thisFurnace.ActualFanVolFlowRate = state.dataFans->fans(thisFurnace.FanIndex)->maxAirFlowRate;
    4229              : 
    4230              :             // CR8094 - simple water to air heat pump MUST operate at the same flow rate specified in the coil objects
    4231              :             //        Furnace(FurnaceNum)%DesignFanVolFlowRate = Numbers(1)
    4232              :             //        Furnace(FurnaceNum)%MaxHeatAirVolFlow    = Furnace(FurnaceNum)%DesignFanVolFlowRate
    4233              :             //        Furnace(FurnaceNum)%MaxCoolAirVolFlow    = Furnace(FurnaceNum)%DesignFanVolFlowRate
    4234              : 
    4235              :             // parameter estimate model only specifies air flow rate in parent object
    4236          139 :             if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingWaterToAirHP) {
    4237           14 :                 thisFurnace.MaxHeatAirVolFlow = Numbers(1);
    4238           14 :                 thisFurnace.MaxCoolAirVolFlow = Numbers(1);
    4239              :                 // simple HP model specifies air flow rate in both the parent and child coils. Use coil air flow rates.
    4240              :                 // simple HP model air flow rate input will not be used.
    4241          125 :             } else if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingWaterToAirHPSimple) {
    4242          111 :                 errFlag = false;
    4243          111 :                 thisFurnace.MaxHeatAirVolFlow = WaterToAirHeatPumpSimple::GetCoilAirFlowRate(state, HeatingCoilType, HeatingCoilName, errFlag);
    4244          111 :                 thisFurnace.MaxCoolAirVolFlow = WaterToAirHeatPumpSimple::GetCoilAirFlowRate(state, CoolingCoilType, CoolingCoilName, errFlag);
    4245          111 :                 if (errFlag) {
    4246            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    4247            0 :                     ErrorsFound = true;
    4248              :                 }
    4249           14 :             } else if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingWaterToAirHPVSEquationFit) {
    4250           14 :                 errFlag = false;
    4251           14 :                 thisFurnace.MaxHeatAirVolFlow = VariableSpeedCoils::GetCoilAirFlowRateVariableSpeed(state, HeatingCoilType, HeatingCoilName, errFlag);
    4252           14 :                 thisFurnace.MaxCoolAirVolFlow = VariableSpeedCoils::GetCoilAirFlowRateVariableSpeed(state, CoolingCoilType, CoolingCoilName, errFlag);
    4253           14 :                 if (errFlag) {
    4254            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    4255            0 :                     ErrorsFound = true;
    4256              :                 }
    4257              :             }
    4258              : 
    4259          139 :             thisFurnace.MaxNoCoolHeatAirVolFlow = min(thisFurnace.MaxHeatAirVolFlow, thisFurnace.MaxCoolAirVolFlow);
    4260          139 :             if (thisFurnace.MaxHeatAirVolFlow != DataSizing::AutoSize && thisFurnace.MaxCoolAirVolFlow != DataSizing::AutoSize) {
    4261           43 :                 thisFurnace.DesignFanVolFlowRate = max(thisFurnace.MaxHeatAirVolFlow, thisFurnace.MaxCoolAirVolFlow);
    4262              :             } else {
    4263           96 :                 thisFurnace.DesignFanVolFlowRate = DataSizing::AutoSize;
    4264              :             }
    4265              : 
    4266          139 :             thisFurnace.AirFlowControl = AirFlowControlConstFan::UseCompressorOnFlow;
    4267              : 
    4268          139 :             if (thisFurnace.ActualFanVolFlowRate != DataSizing::AutoSize && thisFurnace.DesignFanVolFlowRate != DataSizing::AutoSize) {
    4269           43 :                 if (thisFurnace.DesignFanVolFlowRate > thisFurnace.ActualFanVolFlowRate) {
    4270            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    4271            0 :                     ShowContinueError(state, "... has a Cooling or Heating Air Flow Rate > Max Fan Volume Flow Rate, should be <=.");
    4272            0 :                     ShowContinueError(state,
    4273            0 :                                       format("... Entered value={:.2R}... Fan [{}:{}] Max Value={:.2R}",
    4274            0 :                                              thisFurnace.DesignFanVolFlowRate,
    4275            0 :                                              HVAC::fanTypeNames[(int)thisFurnace.fanType],
    4276              :                                              FanName,
    4277            0 :                                              thisFurnace.ActualFanVolFlowRate));
    4278              :                 }
    4279              :             }
    4280          139 :             if (thisFurnace.ActualFanVolFlowRate != DataSizing::AutoSize && thisFurnace.DesignFanVolFlowRate != DataSizing::AutoSize) {
    4281           43 :                 if (thisFurnace.DesignFanVolFlowRate <= 0.0) {
    4282            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    4283            0 :                     ShowContinueError(state, "... has a Design Fan Flow Rate <= 0.0, it must be >0.0");
    4284            0 :                     ShowContinueError(state, format("... Entered value={:.2R}", thisFurnace.DesignFanVolFlowRate));
    4285            0 :                     ErrorsFound = true;
    4286              :                 }
    4287              :             }
    4288              : 
    4289              :             // Set the heat pump heating coil capacity
    4290              :             //  Get from coil module.
    4291          139 :             if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingWaterToAirHP) {
    4292           14 :                 errFlag = false;
    4293           14 :                 thisFurnace.DesignHeatingCapacity = WaterToAirHeatPump::GetCoilCapacity(state, HeatingCoilType, HeatingCoilName, errFlag);
    4294           14 :                 if (errFlag) {
    4295            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    4296            0 :                     ErrorsFound = true;
    4297              :                 }
    4298          125 :             } else if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingWaterToAirHPSimple) {
    4299          111 :                 errFlag = false;
    4300          111 :                 thisFurnace.DesignHeatingCapacity = WaterToAirHeatPumpSimple::GetCoilCapacity(state, HeatingCoilType, HeatingCoilName, errFlag);
    4301          111 :                 if (errFlag) {
    4302            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    4303            0 :                     ErrorsFound = true;
    4304              :                 }
    4305           14 :             } else if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingWaterToAirHPVSEquationFit) {
    4306           14 :                 errFlag = false;
    4307           14 :                 thisFurnace.DesignHeatingCapacity =
    4308           14 :                     VariableSpeedCoils::GetCoilCapacityVariableSpeed(state, HeatingCoilType, HeatingCoilName, errFlag);
    4309           14 :                 if (errFlag) {
    4310            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    4311            0 :                     ErrorsFound = true;
    4312              :                 }
    4313              :             }
    4314              :             // Set the heat pump heating coil convergence
    4315          139 :             thisFurnace.HeatingConvergenceTolerance = Numbers(2);
    4316              :             // Set the heat pump cooling coil capacity (Total capacity)
    4317              :             //  Get from coil module.
    4318          139 :             if (thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingWaterToAirHP) {
    4319           14 :                 errFlag = false;
    4320           14 :                 thisFurnace.DesignCoolingCapacity = WaterToAirHeatPump::GetCoilCapacity(state, CoolingCoilType, CoolingCoilName, errFlag);
    4321           14 :                 if (errFlag) {
    4322            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    4323            0 :                     ErrorsFound = true;
    4324              :                 }
    4325          125 :             } else if (thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingWaterToAirHPSimple) {
    4326          111 :                 errFlag = false;
    4327          111 :                 thisFurnace.DesignCoolingCapacity = WaterToAirHeatPumpSimple::GetCoilCapacity(state, CoolingCoilType, CoolingCoilName, errFlag);
    4328          111 :                 if (errFlag) {
    4329            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    4330            0 :                     ErrorsFound = true;
    4331              :                 }
    4332           14 :             } else if (thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingWaterToAirHPVSEquationFit) {
    4333           14 :                 errFlag = false;
    4334           14 :                 thisFurnace.DesignCoolingCapacity =
    4335           14 :                     VariableSpeedCoils::GetCoilCapacityVariableSpeed(state, CoolingCoilType, CoolingCoilName, errFlag);
    4336           14 :                 if (errFlag) {
    4337            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    4338            0 :                     ErrorsFound = true;
    4339              :                 }
    4340              :             }
    4341              :             // Set the heat pump cooling coil convergence
    4342          139 :             thisFurnace.CoolingConvergenceTolerance = Numbers(3);
    4343              : 
    4344              :             // Set the heatpump design supplemental heating capacity
    4345              :             //  Get from coil module.
    4346              : 
    4347              :             // Set the heatpump max outlet temperature
    4348          139 :             thisFurnace.DesignMaxOutletTemp = Numbers(4);
    4349              : 
    4350              :             // Set maximum supply air temperature for supplemental heating coil
    4351          139 :             thisFurnace.MaxOATSuppHeat = Numbers(5);
    4352          278 :             OutputReportPredefined::PreDefTableEntry(
    4353          139 :                 state, state.dataOutRptPredefined->pdchDXHeatCoilSuppHiT, HeatingCoilName, thisFurnace.MaxOATSuppHeat);
    4354              : 
    4355              :             // set minimum outdoor temperature for compressor operation
    4356          139 :             SetMinOATCompressor(state, FurnaceNum, cCurrentModuleObject, ErrorsFound);
    4357              : 
    4358              :         } // End of the Unitary System WaterToAirHeatPump Loop
    4359              : 
    4360           97 :         Alphas.deallocate();
    4361           97 :         Numbers.deallocate();
    4362              : 
    4363           97 :         if (ErrorsFound) {
    4364            0 :             ShowFatalError(state, "Errors found in getting Furnace or Unitary System input.");
    4365              :         }
    4366              : 
    4367          100 :         for (int HeatOnlyNum = 1; HeatOnlyNum <= NumHeatOnly; ++HeatOnlyNum) {
    4368            3 :             FurnaceNum = HeatOnlyNum;
    4369            3 :             auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    4370              :             // Setup Report variables for the Furnace that are not reported in the components themselves
    4371            6 :             SetupOutputVariable(state,
    4372              :                                 "Unitary System Fan Part Load Ratio",
    4373              :                                 Constant::Units::None,
    4374            3 :                                 thisFurnace.FanPartLoadRatio,
    4375              :                                 OutputProcessor::TimeStepType::System,
    4376              :                                 OutputProcessor::StoreType::Average,
    4377            3 :                                 thisFurnace.Name);
    4378            3 :             if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
    4379            0 :                 SetupEMSActuator(state,
    4380              :                                  "AirLoopHVAC:Unitary:Furnace:HeatOnly",
    4381              :                                  thisFurnace.Name,
    4382              :                                  "Autosized Supply Air Flow Rate",
    4383              :                                  "[m3/s]",
    4384            0 :                                  thisFurnace.DesignFanVolFlowRateEMSOverrideOn,
    4385            0 :                                  thisFurnace.DesignFanVolFlowRateEMSOverrideValue);
    4386              :             }
    4387              :         }
    4388              : 
    4389           98 :         for (int UnitaryHeatOnlyNum = NumHeatOnly + 1; UnitaryHeatOnlyNum <= NumHeatOnly + NumUnitaryHeatOnly; ++UnitaryHeatOnlyNum) {
    4390            1 :             FurnaceNum = UnitaryHeatOnlyNum;
    4391            1 :             auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    4392              :             // Setup Report variables for Unitary System that are not reported in the components themselves
    4393            2 :             SetupOutputVariable(state,
    4394              :                                 "Unitary System Fan Part Load Ratio",
    4395              :                                 Constant::Units::None,
    4396            1 :                                 thisFurnace.FanPartLoadRatio,
    4397              :                                 OutputProcessor::TimeStepType::System,
    4398              :                                 OutputProcessor::StoreType::Average,
    4399            1 :                                 thisFurnace.Name);
    4400            1 :             if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
    4401            0 :                 SetupEMSActuator(state,
    4402              :                                  "AirLoopHVAC:UnitaryHeatOnly",
    4403              :                                  thisFurnace.Name,
    4404              :                                  "Autosized Supply Air Flow Rate",
    4405              :                                  "[m3/s]",
    4406            0 :                                  thisFurnace.DesignFanVolFlowRateEMSOverrideOn,
    4407            0 :                                  thisFurnace.DesignFanVolFlowRateEMSOverrideValue);
    4408              :             }
    4409              :         }
    4410              : 
    4411          205 :         for (int HeatCoolNum = NumHeatOnly + NumUnitaryHeatOnly + 1; HeatCoolNum <= NumHeatOnly + NumUnitaryHeatOnly + NumHeatCool; ++HeatCoolNum) {
    4412          108 :             FurnaceNum = HeatCoolNum;
    4413          108 :             auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    4414              :             // Setup Report variables for the Furnace that are not reported in the components themselves
    4415          216 :             SetupOutputVariable(state,
    4416              :                                 "Unitary System Fan Part Load Ratio",
    4417              :                                 Constant::Units::None,
    4418          108 :                                 thisFurnace.FanPartLoadRatio,
    4419              :                                 OutputProcessor::TimeStepType::System,
    4420              :                                 OutputProcessor::StoreType::Average,
    4421          108 :                                 thisFurnace.Name);
    4422          216 :             SetupOutputVariable(state,
    4423              :                                 "Unitary System Compressor Part Load Ratio",
    4424              :                                 Constant::Units::None,
    4425          108 :                                 thisFurnace.CompPartLoadRatio,
    4426              :                                 OutputProcessor::TimeStepType::System,
    4427              :                                 OutputProcessor::StoreType::Average,
    4428          108 :                                 thisFurnace.Name);
    4429              : 
    4430          108 :             if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
    4431           24 :                 SetupEMSActuator(state,
    4432              :                                  "AirLoopHVAC:Unitary:Furnace:HeatCool",
    4433              :                                  thisFurnace.Name,
    4434              :                                  "Autosized Supply Air Flow Rate",
    4435              :                                  "[m3/s]",
    4436           24 :                                  thisFurnace.DesignFanVolFlowRateEMSOverrideOn,
    4437           24 :                                  thisFurnace.DesignFanVolFlowRateEMSOverrideValue);
    4438           24 :                 SetupEMSActuator(state,
    4439              :                                  "AirLoopHVAC:Unitary:Furnace:HeatCool",
    4440              :                                  thisFurnace.Name,
    4441              :                                  "Autosized Supply Air Flow Rate During Cooling Operation",
    4442              :                                  "[m3/s]",
    4443           24 :                                  thisFurnace.MaxCoolAirVolFlowEMSOverrideOn,
    4444           24 :                                  thisFurnace.MaxCoolAirVolFlowEMSOverrideValue);
    4445           24 :                 SetupEMSActuator(state,
    4446              :                                  "AirLoopHVAC:Unitary:Furnace:HeatCool",
    4447              :                                  thisFurnace.Name,
    4448              :                                  "Autosized Supply Air Flow Rate During Heating Operation",
    4449              :                                  "[m3/s]",
    4450           24 :                                  thisFurnace.MaxHeatAirVolFlowEMSOverrideOn,
    4451           24 :                                  thisFurnace.MaxHeatAirVolFlowEMSOverrideValue);
    4452           24 :                 SetupEMSActuator(state,
    4453              :                                  "AirLoopHVAC:Unitary:Furnace:HeatCool",
    4454              :                                  thisFurnace.Name,
    4455              :                                  "Autosized Supply Air Flow Rate During No Heating or Cooling Operation",
    4456              :                                  "[m3/s]",
    4457           24 :                                  thisFurnace.MaxNoCoolHeatAirVolFlowEMSOverrideOn,
    4458           24 :                                  thisFurnace.MaxNoCoolHeatAirVolFlowEMSOverrideValue);
    4459              :             }
    4460              :         }
    4461              : 
    4462          170 :         for (int UnitaryHeatCoolNum = NumHeatOnly + NumHeatCool + NumUnitaryHeatOnly + 1;
    4463          170 :              UnitaryHeatCoolNum <= NumHeatOnly + NumHeatCool + NumUnitaryHeatOnly + NumUnitaryHeatCool;
    4464              :              ++UnitaryHeatCoolNum) {
    4465           73 :             FurnaceNum = UnitaryHeatCoolNum;
    4466           73 :             auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    4467              :             // Setup Report variables for Unitary System that are not reported in the components themselves
    4468          146 :             SetupOutputVariable(state,
    4469              :                                 "Unitary System Fan Part Load Ratio",
    4470              :                                 Constant::Units::None,
    4471           73 :                                 thisFurnace.FanPartLoadRatio,
    4472              :                                 OutputProcessor::TimeStepType::System,
    4473              :                                 OutputProcessor::StoreType::Average,
    4474           73 :                                 thisFurnace.Name);
    4475          146 :             SetupOutputVariable(state,
    4476              :                                 "Unitary System Compressor Part Load Ratio",
    4477              :                                 Constant::Units::None,
    4478           73 :                                 thisFurnace.CompPartLoadRatio,
    4479              :                                 OutputProcessor::TimeStepType::System,
    4480              :                                 OutputProcessor::StoreType::Average,
    4481           73 :                                 thisFurnace.Name);
    4482           73 :             if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
    4483           20 :                 SetupEMSActuator(state,
    4484              :                                  "AirLoopHVAC:UnitaryHeatCool",
    4485              :                                  thisFurnace.Name,
    4486              :                                  "Autosized Supply Air Flow Rate",
    4487              :                                  "[m3/s]",
    4488           20 :                                  thisFurnace.DesignFanVolFlowRateEMSOverrideOn,
    4489           20 :                                  thisFurnace.DesignFanVolFlowRateEMSOverrideValue);
    4490           20 :                 SetupEMSActuator(state,
    4491              :                                  "AirLoopHVAC:UnitaryHeatCool",
    4492              :                                  thisFurnace.Name,
    4493              :                                  "Autosized Supply Air Flow Rate During Cooling Operation",
    4494              :                                  "[m3/s]",
    4495           20 :                                  thisFurnace.MaxCoolAirVolFlowEMSOverrideOn,
    4496           20 :                                  thisFurnace.MaxCoolAirVolFlowEMSOverrideValue);
    4497           20 :                 SetupEMSActuator(state,
    4498              :                                  "AirLoopHVAC:UnitaryHeatCool",
    4499              :                                  thisFurnace.Name,
    4500              :                                  "Autosized Supply Air Flow Rate During Heating Operation",
    4501              :                                  "[m3/s]",
    4502           20 :                                  thisFurnace.MaxHeatAirVolFlowEMSOverrideOn,
    4503           20 :                                  thisFurnace.MaxHeatAirVolFlowEMSOverrideValue);
    4504           20 :                 SetupEMSActuator(state,
    4505              :                                  "AirLoopHVAC:UnitaryHeatCool",
    4506              :                                  thisFurnace.Name,
    4507              :                                  "Autosized Supply Air Flow Rate During No Heating or Cooling Operation",
    4508              :                                  "[m3/s]",
    4509           20 :                                  thisFurnace.MaxNoCoolHeatAirVolFlowEMSOverrideOn,
    4510           20 :                                  thisFurnace.MaxNoCoolHeatAirVolFlowEMSOverrideValue);
    4511              :             }
    4512              :         }
    4513              : 
    4514          132 :         for (int HeatPumpNum = NumHeatOnly + NumHeatCool + NumUnitaryHeatOnly + NumUnitaryHeatCool + 1;
    4515          132 :              HeatPumpNum <= state.dataFurnaces->NumFurnaces - NumWaterToAirHeatPump;
    4516              :              ++HeatPumpNum) {
    4517           35 :             FurnaceNum = HeatPumpNum;
    4518           35 :             auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    4519              :             // Setup Report variables for Unitary System that are not reported in the components themselves
    4520           70 :             SetupOutputVariable(state,
    4521              :                                 "Unitary System Fan Part Load Ratio",
    4522              :                                 Constant::Units::None,
    4523           35 :                                 thisFurnace.FanPartLoadRatio,
    4524              :                                 OutputProcessor::TimeStepType::System,
    4525              :                                 OutputProcessor::StoreType::Average,
    4526           35 :                                 thisFurnace.Name);
    4527           70 :             SetupOutputVariable(state,
    4528              :                                 "Unitary System Compressor Part Load Ratio",
    4529              :                                 Constant::Units::None,
    4530           35 :                                 thisFurnace.CompPartLoadRatio,
    4531              :                                 OutputProcessor::TimeStepType::System,
    4532              :                                 OutputProcessor::StoreType::Average,
    4533           35 :                                 thisFurnace.Name);
    4534           70 :             SetupOutputVariable(state,
    4535              :                                 "Unitary System Dehumidification Induced Heating Demand Rate",
    4536              :                                 Constant::Units::W,
    4537           35 :                                 thisFurnace.DehumidInducedHeatingDemandRate,
    4538              :                                 OutputProcessor::TimeStepType::System,
    4539              :                                 OutputProcessor::StoreType::Average,
    4540           35 :                                 thisFurnace.Name);
    4541              : 
    4542           35 :             if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
    4543            5 :                 SetupEMSActuator(state,
    4544              :                                  "AirLoopHVAC:UnitaryHeatPump:AirToAir",
    4545              :                                  thisFurnace.Name,
    4546              :                                  "Autosized Supply Air Flow Rate",
    4547              :                                  "[m3/s]",
    4548            5 :                                  thisFurnace.DesignFanVolFlowRateEMSOverrideOn,
    4549            5 :                                  thisFurnace.DesignFanVolFlowRateEMSOverrideValue);
    4550              :             }
    4551              :         }
    4552              : 
    4553          236 :         for (int HeatPumpNum = NumHeatOnly + NumHeatCool + NumUnitaryHeatOnly + NumUnitaryHeatCool + NumHeatPump + 1;
    4554          236 :              HeatPumpNum <= state.dataFurnaces->NumFurnaces;
    4555              :              ++HeatPumpNum) {
    4556          139 :             FurnaceNum = HeatPumpNum;
    4557          139 :             auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    4558              :             // Setup Report variables for Unitary System that are not reported in the components themselves
    4559          278 :             SetupOutputVariable(state,
    4560              :                                 "Unitary System Fan Part Load Ratio",
    4561              :                                 Constant::Units::None,
    4562          139 :                                 thisFurnace.FanPartLoadRatio,
    4563              :                                 OutputProcessor::TimeStepType::System,
    4564              :                                 OutputProcessor::StoreType::Average,
    4565          139 :                                 thisFurnace.Name);
    4566          278 :             SetupOutputVariable(state,
    4567              :                                 "Unitary System Compressor Part Load Ratio",
    4568              :                                 Constant::Units::None,
    4569          139 :                                 thisFurnace.CompPartLoadRatio,
    4570              :                                 OutputProcessor::TimeStepType::System,
    4571              :                                 OutputProcessor::StoreType::Average,
    4572          139 :                                 thisFurnace.Name);
    4573          278 :             SetupOutputVariable(state,
    4574              :                                 "Unitary System Requested Sensible Cooling Rate",
    4575              :                                 Constant::Units::W,
    4576          139 :                                 thisFurnace.CoolingCoilSensDemand,
    4577              :                                 OutputProcessor::TimeStepType::System,
    4578              :                                 OutputProcessor::StoreType::Average,
    4579          139 :                                 thisFurnace.Name);
    4580          278 :             SetupOutputVariable(state,
    4581              :                                 "Unitary System Requested Latent Cooling Rate",
    4582              :                                 Constant::Units::W,
    4583          139 :                                 thisFurnace.CoolingCoilLatentDemand,
    4584              :                                 OutputProcessor::TimeStepType::System,
    4585              :                                 OutputProcessor::StoreType::Average,
    4586          139 :                                 thisFurnace.Name);
    4587          278 :             SetupOutputVariable(state,
    4588              :                                 "Unitary System Requested Heating Rate",
    4589              :                                 Constant::Units::W,
    4590          139 :                                 thisFurnace.HeatingCoilSensDemand,
    4591              :                                 OutputProcessor::TimeStepType::System,
    4592              :                                 OutputProcessor::StoreType::Average,
    4593          139 :                                 thisFurnace.Name);
    4594          278 :             SetupOutputVariable(state,
    4595              :                                 "Unitary System Dehumidification Induced Heating Demand Rate",
    4596              :                                 Constant::Units::W,
    4597          139 :                                 thisFurnace.DehumidInducedHeatingDemandRate,
    4598              :                                 OutputProcessor::TimeStepType::System,
    4599              :                                 OutputProcessor::StoreType::Average,
    4600          139 :                                 thisFurnace.Name);
    4601              : 
    4602          139 :             if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
    4603           96 :                 SetupEMSActuator(state,
    4604              :                                  "AirLoopHVAC:UnitaryHeatPump:WaterToAir",
    4605              :                                  thisFurnace.Name,
    4606              :                                  "Autosized Supply Air Flow Rate",
    4607              :                                  "[m3/s]",
    4608           96 :                                  thisFurnace.DesignFanVolFlowRateEMSOverrideOn,
    4609           96 :                                  thisFurnace.DesignFanVolFlowRateEMSOverrideValue);
    4610              :             }
    4611              :         }
    4612              : 
    4613           97 :         if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
    4614          154 :             for (FurnaceNum = 1; FurnaceNum <= state.dataFurnaces->NumFurnaces; ++FurnaceNum) {
    4615          145 :                 auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    4616          145 :                 SetupEMSInternalVariable(state, "Unitary HVAC Design Heating Capacity", thisFurnace.Name, "[W]", thisFurnace.DesignHeatingCapacity);
    4617          145 :                 SetupEMSInternalVariable(state, "Unitary HVAC Design Cooling Capacity", thisFurnace.Name, "[W]", thisFurnace.DesignCoolingCapacity);
    4618          145 :                 SetupEMSActuator(state,
    4619              :                                  "Unitary HVAC",
    4620              :                                  thisFurnace.Name,
    4621              :                                  "Sensible Load Request",
    4622              :                                  "[W]",
    4623          145 :                                  thisFurnace.EMSOverrideSensZoneLoadRequest,
    4624          145 :                                  thisFurnace.EMSSensibleZoneLoadValue);
    4625          145 :                 SetupEMSActuator(state,
    4626              :                                  "Unitary HVAC",
    4627              :                                  thisFurnace.Name,
    4628              :                                  "Moisture Load Request",
    4629              :                                  "[W]",
    4630          145 :                                  thisFurnace.EMSOverrideMoistZoneLoadRequest,
    4631          145 :                                  thisFurnace.EMSMoistureZoneLoadValue);
    4632              :             }
    4633              :         }
    4634              :         bool anyRan;
    4635           97 :         EMSManager::ManageEMS(state, EMSManager::EMSCallFrom::ComponentGetInput, anyRan, ObjexxFCL::Optional_int_const());
    4636           97 :     }
    4637              : 
    4638              :     // End of Get Input subroutines for this Module
    4639              :     //******************************************************************************
    4640              : 
    4641              :     // Beginning Initialization Section of the Module
    4642              :     //******************************************************************************
    4643              : 
    4644      6219025 :     void InitFurnace(EnergyPlusData &state,
    4645              :                      int const FurnaceNum,         // index to Furnace
    4646              :                      int const AirLoopNum,         // index to air loop
    4647              :                      Real64 &OnOffAirFlowRatio,    // ratio of on to off air mass flow rate
    4648              :                      HVAC::FanOp &fanOp,           // fan operating mode
    4649              :                      Real64 &ZoneLoad,             // zone sensible load to be met (modified here as needed) (W)
    4650              :                      Real64 &MoistureLoad,         // zone moisture load (W)
    4651              :                      bool const FirstHVACIteration // TRUE if first HVAC iteration
    4652              :     )
    4653              :     {
    4654              : 
    4655              :         // SUBROUTINE INFORMATION:
    4656              :         //       AUTHOR         Richard J. Liesen
    4657              :         //       DATE WRITTEN   Feb 2001
    4658              :         //       MODIFIED       Oct 2001, Richard Raustad
    4659              :         //                      Sep 2008, R. Raustad - revised logic to determine load to be met
    4660              :         //                      Bereket Nigusse, June 2010 - added a procedure to calculate supply air flow fraction
    4661              :         //                      through controlled zone
    4662              :         //                      Bo Shen, March 2012 - for VS WSHP
    4663              :         //                      Bo Shen, ORNL, July 2012 - added variable-speed air source heat pump cooling and heating coils, using curve-fits
    4664              : 
    4665              :         // PURPOSE OF THIS SUBROUTINE:
    4666              :         // This subroutine is for initializations of the Furnace Components.
    4667              : 
    4668              :         // METHODOLOGY EMPLOYED:
    4669              :         // Uses the status flags to trigger initializations.
    4670              :         // The HeatCool furnace/unitarysystem and air-to-air heat pump may have alternate air flow rates
    4671              :         // in cooling, heating, and when no cooling or heating is needed. Set up the coil (comp) ON and OFF
    4672              :         // air flow rates during InitFurnace. Use these flow rates during the Calc routines to set the
    4673              :         // average mass flow rates based on PLR.
    4674              : 
    4675              :         // SUBROUTINE PARAMETER DEFINITIONS:
    4676      6219025 :         Real64 constexpr Small5WLoad(5.0);
    4677      6219025 :         std::string_view constexpr RoutineName("InitFurnace");
    4678              : 
    4679              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    4680              :         bool errFlag;          // error flag for mining functions
    4681              :         Real64 QZnReq;         // furnace load based on control zone frac (W)
    4682              :         Real64 PartLoadRatio;  // furnace part-load ratio
    4683              :         Real64 SensibleOutput; // no load sensible output (coils off) (W)
    4684              :         Real64 LatentOutput;   // no load latent output (coils off) (W)
    4685              :         Real64 QToCoolSetPt;   // sensible load to cooling setpoint (W)
    4686              :         Real64 QToHeatSetPt;   // sensible load to heating setpoint (W)
    4687              :         // calculation (kg/kg)
    4688              :         Real64 DeltaMassRate; // Difference of mass flow rate between
    4689              :         // inlet node and system outlet node
    4690              :         Real64 MassFlowRate; // mass flow rate to calculate loss
    4691              : 
    4692      6219025 :         Real64 SumOfMassFlowRateMax(0.0);                 // the sum of mass flow rates at inlet to zones in an airloop
    4693      6219025 :         Real64 CntrlZoneTerminalUnitMassFlowRateMax(0.0); // Maximum mass flow rate through controlled zone terminal unit
    4694              : 
    4695      6219025 :         bool ErrorsFound(false);                 // flag returned from mining call
    4696      6219025 :         Real64 mdot(0.0);                        // local temporary for mass flow rate (kg/s)
    4697      6219025 :         Real64 rho(0.0);                         // local for fluid density
    4698      6219025 :         Real64 SteamDensity(0.0);                // density of steam at 100C, used for steam heating coils
    4699      6219025 :         Real64 CoilMaxVolFlowRate(0.0);          // coil fluid maximum volume flow rate
    4700      6219025 :         Real64 QActual(0.0);                     // coil actual capacity
    4701      6219025 :         Real64 SUPHEATERLOAD(0.0);               // SUPPLEMENTAL HEATER LOAD
    4702              :         Real64 RhoAir;                           // Air density at InNode
    4703              :         Furnaces::ModeOfOperation OperatingMode; // track cooling, heating, and no cooling or heating modes
    4704              :         Furnaces::ModeOfOperation OperatingModeMinusOne;
    4705              :         Furnaces::ModeOfOperation OperatingModeMinusTwo;
    4706              :         bool Oscillate; // detection of oscillating operating modes
    4707              : 
    4708      6219025 :         auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    4709      6219025 :         int InNode = thisFurnace.FurnaceInletNodeNum;
    4710      6219025 :         int OutNode = thisFurnace.FurnaceOutletNodeNum;
    4711              : 
    4712      6219025 :         if (state.dataFurnaces->InitFurnaceMyOneTimeFlag) {
    4713              :             // initialize the environment and sizing flags
    4714           97 :             state.dataFurnaces->MyEnvrnFlag.allocate(state.dataFurnaces->NumFurnaces);
    4715           97 :             state.dataFurnaces->MySizeFlag.allocate(state.dataFurnaces->NumFurnaces);
    4716           97 :             state.dataFurnaces->MySecondOneTimeFlag.allocate(state.dataFurnaces->NumFurnaces);
    4717           97 :             state.dataFurnaces->MyFanFlag.allocate(state.dataFurnaces->NumFurnaces);
    4718           97 :             state.dataFurnaces->MyCheckFlag.allocate(state.dataFurnaces->NumFurnaces);
    4719           97 :             state.dataFurnaces->MyFlowFracFlag.allocate(state.dataFurnaces->NumFurnaces);
    4720           97 :             state.dataFurnaces->MyPlantScanFlag.allocate(state.dataFurnaces->NumFurnaces);
    4721           97 :             state.dataFurnaces->MySuppCoilPlantScanFlag.allocate(state.dataFurnaces->NumFurnaces);
    4722           97 :             state.dataFurnaces->MyEnvrnFlag = true;
    4723           97 :             state.dataFurnaces->MySizeFlag = true;
    4724           97 :             state.dataFurnaces->MySecondOneTimeFlag = true;
    4725           97 :             state.dataFurnaces->MyFanFlag = true;
    4726           97 :             state.dataFurnaces->MyCheckFlag = true;
    4727           97 :             state.dataFurnaces->MyFlowFracFlag = true;
    4728           97 :             state.dataFurnaces->InitFurnaceMyOneTimeFlag = false;
    4729           97 :             state.dataFurnaces->MyPlantScanFlag = true;
    4730           97 :             state.dataFurnaces->MySuppCoilPlantScanFlag = true;
    4731              :         }
    4732              : 
    4733      6219025 :         if (state.dataGlobal->BeginEnvrnFlag && state.dataFurnaces->MyAirLoopPass) {
    4734          588 :             state.dataFurnaces->AirLoopPass = 0;
    4735          588 :             state.dataFurnaces->MyAirLoopPass = false;
    4736              :         }
    4737      6219025 :         if (!state.dataGlobal->BeginEnvrnFlag) {
    4738      6198848 :             state.dataFurnaces->MyAirLoopPass = true;
    4739              :         }
    4740              : 
    4741      6219025 :         ++state.dataFurnaces->AirLoopPass;
    4742      6219025 :         if (state.dataFurnaces->AirLoopPass > 2) {
    4743      3108932 :             state.dataFurnaces->AirLoopPass = 1;
    4744              :         }
    4745              : 
    4746      6219025 :         if (!state.dataGlobal->SysSizingCalc && state.dataFurnaces->MySizeFlag(FurnaceNum)) {
    4747              :             // for each furnace, do the sizing once.
    4748          359 :             SizeFurnace(state, FurnaceNum, FirstHVACIteration);
    4749          359 :             thisFurnace.ControlZoneMassFlowFrac = 1.0;
    4750              : 
    4751          359 :             state.dataFurnaces->MySizeFlag(FurnaceNum) = false;
    4752              :             // Pass the fan cycling schedule index up to the air loop. Set the air loop unitary system flag.
    4753          359 :             state.dataAirLoop->AirLoopControlInfo(AirLoopNum).cycFanSched = thisFurnace.fanOpModeSched;
    4754          359 :             state.dataAirLoop->AirLoopControlInfo(AirLoopNum).UnitarySys = true;
    4755              :             // RR this is wrong, Op mode needs to be updated each time atep
    4756          359 :             state.dataAirLoop->AirLoopControlInfo(AirLoopNum).fanOp = thisFurnace.fanOp;
    4757              : 
    4758              :             // Check that heat pump heating capacity is within 20% of cooling capacity
    4759          359 :             if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_AirToAir) {
    4760           35 :                 if (std::abs(thisFurnace.DesignCoolingCapacity - thisFurnace.DesignHeatingCapacity) / thisFurnace.DesignCoolingCapacity > 0.2) {
    4761            0 :                     ShowWarningError(state,
    4762            0 :                                      format("{} \"{}\" heating capacity is disproportionate (> 20% different) to total cooling capacity",
    4763            0 :                                             HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    4764            0 :                                             thisFurnace.Name));
    4765              :                 }
    4766              :             }
    4767              :         }
    4768              : 
    4769      6219025 :         if (!state.dataGlobal->DoingSizing && state.dataFurnaces->MySecondOneTimeFlag(FurnaceNum)) {
    4770              :             // sizing all done.  check fan air flow rates
    4771          625 :             thisFurnace.ActualFanVolFlowRate = state.dataFans->fans(thisFurnace.FanIndex)->maxAirFlowRate;
    4772          625 :             if (thisFurnace.ActualFanVolFlowRate != DataSizing::AutoSize) {
    4773          359 :                 if (thisFurnace.DesignFanVolFlowRate > thisFurnace.ActualFanVolFlowRate) {
    4774            0 :                     ShowWarningError(state,
    4775            0 :                                      format("{}={} has a Design Fan Volume Flow Rate > Max Fan Volume Flow Rate, should be <=",
    4776            0 :                                             HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    4777            0 :                                             thisFurnace.Name));
    4778            0 :                     ShowContinueError(state,
    4779            0 :                                       format("... Entered value={:.2R}... Fan [{}] Max Value={:.2R}",
    4780            0 :                                              thisFurnace.DesignFanVolFlowRate,
    4781            0 :                                              HVAC::fanTypeNames[(int)thisFurnace.fanType],
    4782            0 :                                              thisFurnace.ActualFanVolFlowRate));
    4783              :                 }
    4784          359 :                 if (thisFurnace.DesignFanVolFlowRate <= 0.0) {
    4785            0 :                     ShowSevereError(state,
    4786            0 :                                     format("{}={} has a Design Fan Volume Flow Rate <= 0.0, it must be >0.0",
    4787            0 :                                            HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    4788            0 :                                            thisFurnace.Name));
    4789            0 :                     ShowContinueError(state, format("... Entered value={:.2R}", thisFurnace.DesignFanVolFlowRate));
    4790              :                 }
    4791              : 
    4792          359 :                 state.dataFurnaces->MySecondOneTimeFlag(FurnaceNum) = false;
    4793              :             }
    4794              :         }
    4795              : 
    4796              :         // Scan hot water and steam heating coil plant components for one time initializations
    4797      6219025 :         if (state.dataFurnaces->MyPlantScanFlag(FurnaceNum) && allocated(state.dataPlnt->PlantLoop)) {
    4798          359 :             if ((thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingWater) || (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingSteam)) {
    4799              : 
    4800            0 :                 if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingWater) {
    4801              : 
    4802            0 :                     errFlag = false;
    4803            0 :                     PlantUtilities::ScanPlantLoopsForObject(state,
    4804              :                                                             thisFurnace.HeatingCoilName,
    4805              :                                                             DataPlant::PlantEquipmentType::CoilWaterSimpleHeating,
    4806            0 :                                                             thisFurnace.plantLoc,
    4807              :                                                             errFlag,
    4808              :                                                             _,
    4809              :                                                             _,
    4810              :                                                             _,
    4811              :                                                             _,
    4812              :                                                             _);
    4813            0 :                     if (errFlag) {
    4814            0 :                         ShowFatalError(state, "InitFurnace: Program terminated for previous conditions.");
    4815              :                     }
    4816            0 :                     thisFurnace.MaxHeatCoilFluidFlow =
    4817            0 :                         WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", thisFurnace.HeatingCoilName, ErrorsFound);
    4818            0 :                     if (thisFurnace.MaxHeatCoilFluidFlow > 0.0) {
    4819              :                         rho =
    4820            0 :                             state.dataPlnt->PlantLoop(thisFurnace.plantLoc.loopNum).glycol->getDensity(state, Constant::HWInitConvTemp, RoutineName);
    4821            0 :                         thisFurnace.MaxHeatCoilFluidFlow *= rho;
    4822              :                     }
    4823            0 :                 } else if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingSteam) {
    4824              : 
    4825            0 :                     errFlag = false;
    4826            0 :                     PlantUtilities::ScanPlantLoopsForObject(state,
    4827              :                                                             thisFurnace.HeatingCoilName,
    4828              :                                                             DataPlant::PlantEquipmentType::CoilSteamAirHeating,
    4829            0 :                                                             thisFurnace.plantLoc,
    4830              :                                                             errFlag,
    4831              :                                                             _,
    4832              :                                                             _,
    4833              :                                                             _,
    4834              :                                                             _,
    4835              :                                                             _);
    4836            0 :                     if (errFlag) {
    4837            0 :                         ShowFatalError(state, "InitFurnace: Program terminated for previous conditions.");
    4838              :                     }
    4839            0 :                     thisFurnace.MaxHeatCoilFluidFlow = SteamCoils::GetCoilMaxSteamFlowRate(state, thisFurnace.HeatingCoilIndex, ErrorsFound);
    4840            0 :                     if (thisFurnace.MaxHeatCoilFluidFlow > 0.0) {
    4841            0 :                         SteamDensity = Fluid::GetSteam(state)->getSatDensity(state, state.dataFurnaces->TempSteamIn, 1.0, RoutineName);
    4842            0 :                         thisFurnace.MaxHeatCoilFluidFlow *= SteamDensity;
    4843              :                     }
    4844              :                 }
    4845              :                 // fill outlet node for coil
    4846            0 :                 thisFurnace.CoilOutletNode = DataPlant::CompData::getPlantComponent(state, thisFurnace.plantLoc).NodeNumOut;
    4847            0 :                 state.dataFurnaces->MyPlantScanFlag(FurnaceNum) = false;
    4848              :             } else { // pthp not connected to plant
    4849          359 :                 state.dataFurnaces->MyPlantScanFlag(FurnaceNum) = false;
    4850              :             }
    4851      6218666 :         } else if (state.dataFurnaces->MyPlantScanFlag(FurnaceNum) && !state.dataGlobal->AnyPlantInModel) {
    4852            0 :             state.dataFurnaces->MyPlantScanFlag(FurnaceNum) = false;
    4853              :         }
    4854              : 
    4855              :         // Scan Supplemental hot water and steam heating coil plant components for one time initializations
    4856      6219025 :         if (state.dataFurnaces->MySuppCoilPlantScanFlag(FurnaceNum) && allocated(state.dataPlnt->PlantLoop)) {
    4857          359 :             if ((thisFurnace.SuppHeatCoilType_Num == HVAC::Coil_HeatingWater) || (thisFurnace.SuppHeatCoilType_Num == HVAC::Coil_HeatingSteam)) {
    4858              : 
    4859            1 :                 if (thisFurnace.SuppHeatCoilType_Num == HVAC::Coil_HeatingWater) {
    4860            1 :                     errFlag = false;
    4861            2 :                     PlantUtilities::ScanPlantLoopsForObject(state,
    4862              :                                                             thisFurnace.SuppHeatCoilName,
    4863              :                                                             DataPlant::PlantEquipmentType::CoilWaterSimpleHeating,
    4864            1 :                                                             thisFurnace.SuppPlantLoc,
    4865              :                                                             errFlag,
    4866              :                                                             _,
    4867              :                                                             _,
    4868              :                                                             _,
    4869              :                                                             _,
    4870              :                                                             _);
    4871            1 :                     if (errFlag) {
    4872            0 :                         ShowFatalError(state, "InitFurnace: Program terminated for previous conditions.");
    4873              :                     }
    4874            1 :                     thisFurnace.MaxSuppCoilFluidFlow =
    4875            1 :                         WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", thisFurnace.SuppHeatCoilName, ErrorsFound);
    4876            1 :                     if (thisFurnace.MaxSuppCoilFluidFlow > 0.0) {
    4877            1 :                         rho = state.dataPlnt->PlantLoop(thisFurnace.SuppPlantLoc.loopNum)
    4878            1 :                                   .glycol->getDensity(state, Constant::HWInitConvTemp, RoutineName);
    4879            1 :                         thisFurnace.MaxSuppCoilFluidFlow *= rho;
    4880              :                     }
    4881            0 :                 } else if (thisFurnace.SuppHeatCoilType_Num == HVAC::Coil_HeatingSteam) {
    4882            0 :                     errFlag = false;
    4883            0 :                     PlantUtilities::ScanPlantLoopsForObject(state,
    4884              :                                                             thisFurnace.SuppHeatCoilName,
    4885              :                                                             DataPlant::PlantEquipmentType::CoilSteamAirHeating,
    4886            0 :                                                             thisFurnace.SuppPlantLoc,
    4887              :                                                             errFlag,
    4888              :                                                             _,
    4889              :                                                             _,
    4890              :                                                             _,
    4891              :                                                             _,
    4892              :                                                             _);
    4893            0 :                     if (errFlag) {
    4894            0 :                         ShowFatalError(state, "InitFurnace: Program terminated for previous conditions.");
    4895              :                     }
    4896            0 :                     thisFurnace.MaxSuppCoilFluidFlow = SteamCoils::GetCoilMaxSteamFlowRate(state, thisFurnace.SuppHeatCoilIndex, ErrorsFound);
    4897            0 :                     if (thisFurnace.MaxSuppCoilFluidFlow > 0.0) {
    4898            0 :                         SteamDensity = Fluid::GetSteam(state)->getSatDensity(state, state.dataFurnaces->TempSteamIn, 1.0, RoutineName);
    4899            0 :                         thisFurnace.MaxSuppCoilFluidFlow *= SteamDensity;
    4900              :                     }
    4901              :                 }
    4902              :                 // fill outlet node for coil
    4903            1 :                 thisFurnace.SuppCoilOutletNode = DataPlant::CompData::getPlantComponent(state, thisFurnace.SuppPlantLoc).NodeNumOut;
    4904            1 :                 state.dataFurnaces->MySuppCoilPlantScanFlag(FurnaceNum) = false;
    4905              :             } else { // pthp not connected to plant
    4906          358 :                 state.dataFurnaces->MySuppCoilPlantScanFlag(FurnaceNum) = false;
    4907              :             }
    4908              : 
    4909      6218666 :         } else if (state.dataFurnaces->MySuppCoilPlantScanFlag(FurnaceNum) && !state.dataGlobal->AnyPlantInModel) {
    4910            0 :             state.dataFurnaces->MySuppCoilPlantScanFlag(FurnaceNum) = false;
    4911              :         }
    4912              : 
    4913              :         // Do the Begin Environment initializations
    4914      6219025 :         if (state.dataGlobal->BeginEnvrnFlag && state.dataFurnaces->MyEnvrnFlag(FurnaceNum)) {
    4915              :             // Change the Volume Flow Rates to Mass Flow Rates
    4916         2286 :             thisFurnace.DesignMassFlowRate = thisFurnace.DesignFanVolFlowRate * state.dataEnvrn->StdRhoAir;
    4917         2286 :             thisFurnace.MaxCoolAirMassFlow = thisFurnace.MaxCoolAirVolFlow * state.dataEnvrn->StdRhoAir;
    4918         2286 :             thisFurnace.MaxHeatAirMassFlow = thisFurnace.MaxHeatAirVolFlow * state.dataEnvrn->StdRhoAir;
    4919         2286 :             thisFurnace.MaxNoCoolHeatAirMassFlow = thisFurnace.MaxNoCoolHeatAirVolFlow * state.dataEnvrn->StdRhoAir;
    4920         2286 :             thisFurnace.CompPartLoadRatio = 0.0;
    4921         2286 :             thisFurnace.CoolingCoilSensDemand = 0.0;
    4922         2286 :             thisFurnace.CoolingCoilLatentDemand = 0.0;
    4923         2286 :             thisFurnace.HeatingCoilSensDemand = 0.0;
    4924              : 
    4925         2286 :             thisFurnace.SenLoadLoss = 0.0;
    4926         2286 :             if (thisFurnace.Humidistat) {
    4927          351 :                 thisFurnace.LatLoadLoss = 0.0;
    4928              :             }
    4929              : 
    4930              :             //   set fluid-side hardware limits
    4931         2286 :             if (thisFurnace.CoilControlNode > 0) {
    4932              : 
    4933            0 :                 if (thisFurnace.MaxHeatCoilFluidFlow == DataSizing::AutoSize) {
    4934              :                     // If water coil max water flow rate is autosized, simulate once in order to mine max flow rate
    4935            0 :                     if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingWater) {
    4936            0 :                         WaterCoils::SimulateWaterCoilComponents(state, thisFurnace.HeatingCoilName, FirstHVACIteration, thisFurnace.HeatingCoilIndex);
    4937              :                         CoilMaxVolFlowRate =
    4938            0 :                             WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", thisFurnace.HeatingCoilName, ErrorsFound);
    4939            0 :                         if (CoilMaxVolFlowRate != DataSizing::AutoSize) {
    4940            0 :                             rho = state.dataPlnt->PlantLoop(thisFurnace.plantLoc.loopNum)
    4941            0 :                                       .glycol->getDensity(state, Constant::HWInitConvTemp, RoutineName);
    4942            0 :                             thisFurnace.MaxHeatCoilFluidFlow = CoilMaxVolFlowRate * rho;
    4943              :                         }
    4944              :                     }
    4945              :                     // If steam coil max steam flow rate is autosized, simulate once in order to mine max flow rate
    4946            0 :                     if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingSteam) {
    4947            0 :                         SteamCoils::SimulateSteamCoilComponents(state,
    4948              :                                                                 thisFurnace.HeatingCoilName,
    4949              :                                                                 FirstHVACIteration,
    4950            0 :                                                                 thisFurnace.HeatingCoilIndex,
    4951            0 :                                                                 1.0,
    4952              :                                                                 QActual); // QCoilReq, simulate any load > 0 to get max capacity
    4953            0 :                         CoilMaxVolFlowRate = SteamCoils::GetCoilMaxSteamFlowRate(state, thisFurnace.HeatingCoilIndex, ErrorsFound);
    4954            0 :                         if (CoilMaxVolFlowRate != DataSizing::AutoSize) {
    4955            0 :                             SteamDensity = Fluid::GetSteam(state)->getSatDensity(state, state.dataFurnaces->TempSteamIn, 1.0, RoutineName);
    4956            0 :                             thisFurnace.MaxHeatCoilFluidFlow = CoilMaxVolFlowRate * SteamDensity;
    4957              :                         }
    4958              :                     }
    4959              :                 }
    4960              : 
    4961            0 :                 PlantUtilities::InitComponentNodes(
    4962              :                     state, 0.0, thisFurnace.MaxHeatCoilFluidFlow, thisFurnace.CoilControlNode, thisFurnace.CoilOutletNode);
    4963              :             }
    4964         2286 :             if (thisFurnace.SuppCoilControlNode > 0) {
    4965            7 :                 if (thisFurnace.MaxSuppCoilFluidFlow == DataSizing::AutoSize) {
    4966            0 :                     if (thisFurnace.SuppHeatCoilType_Num == HVAC::Coil_HeatingWater) {
    4967              :                         // If water coil max water flow rate is autosized, simulate once in order to mine max flow rate
    4968            0 :                         WaterCoils::SimulateWaterCoilComponents(
    4969            0 :                             state, thisFurnace.SuppHeatCoilName, FirstHVACIteration, thisFurnace.SuppHeatCoilIndex);
    4970              :                         CoilMaxVolFlowRate =
    4971            0 :                             WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", thisFurnace.SuppHeatCoilName, ErrorsFound);
    4972            0 :                         if (CoilMaxVolFlowRate != DataSizing::AutoSize) {
    4973            0 :                             rho = state.dataPlnt->PlantLoop(thisFurnace.SuppPlantLoc.loopNum)
    4974            0 :                                       .glycol->getDensity(state, Constant::HWInitConvTemp, RoutineName);
    4975            0 :                             thisFurnace.MaxSuppCoilFluidFlow = CoilMaxVolFlowRate * rho;
    4976              :                         }
    4977              :                     }
    4978            0 :                     if (thisFurnace.SuppHeatCoilType_Num == HVAC::Coil_HeatingSteam) {
    4979            0 :                         SteamCoils::SimulateSteamCoilComponents(state,
    4980              :                                                                 thisFurnace.SuppHeatCoilName,
    4981              :                                                                 FirstHVACIteration,
    4982            0 :                                                                 thisFurnace.SuppHeatCoilIndex,
    4983            0 :                                                                 1.0,
    4984              :                                                                 QActual); // QCoilReq, simulate any load > 0 to get max capacity
    4985            0 :                         CoilMaxVolFlowRate = SteamCoils::GetCoilMaxSteamFlowRate(state, thisFurnace.SuppHeatCoilIndex, ErrorsFound);
    4986            0 :                         if (CoilMaxVolFlowRate != DataSizing::AutoSize) {
    4987            0 :                             SteamDensity = Fluid::GetSteam(state)->getSatDensity(state, state.dataFurnaces->TempSteamIn, 1.0, RoutineName);
    4988            0 :                             thisFurnace.MaxSuppCoilFluidFlow = CoilMaxVolFlowRate * SteamDensity;
    4989              :                         }
    4990              :                     }
    4991            0 :                     PlantUtilities::InitComponentNodes(
    4992              :                         state, 0.0, thisFurnace.MaxSuppCoilFluidFlow, thisFurnace.SuppCoilControlNode, thisFurnace.SuppCoilOutletNode);
    4993              :                 }
    4994              :             }
    4995         2286 :             state.dataFurnaces->MyEnvrnFlag(FurnaceNum) = false;
    4996              :         }
    4997              : 
    4998      6219025 :         if (!state.dataGlobal->BeginEnvrnFlag) {
    4999      6198848 :             state.dataFurnaces->MyEnvrnFlag(FurnaceNum) = true;
    5000              :         }
    5001              : 
    5002      6219025 :         if (state.dataFurnaces->MyFanFlag(FurnaceNum)) {
    5003          625 :             if (thisFurnace.ActualFanVolFlowRate != DataSizing::AutoSize) {
    5004          359 :                 if (thisFurnace.ActualFanVolFlowRate > 0.0) {
    5005          359 :                     thisFurnace.HeatingSpeedRatio = thisFurnace.MaxHeatAirVolFlow / thisFurnace.ActualFanVolFlowRate;
    5006          359 :                     thisFurnace.CoolingSpeedRatio = thisFurnace.MaxCoolAirVolFlow / thisFurnace.ActualFanVolFlowRate;
    5007          359 :                     thisFurnace.NoHeatCoolSpeedRatio = thisFurnace.MaxNoCoolHeatAirVolFlow / thisFurnace.ActualFanVolFlowRate;
    5008              :                 }
    5009          359 :                 if (dynamic_cast<Fans::FanComponent *>(state.dataFans->fans(thisFurnace.FanIndex))->powerRatioAtSpeedRatioCurveNum > 0) {
    5010            0 :                     if (thisFurnace.ActualFanVolFlowRate == thisFurnace.MaxHeatAirVolFlow &&
    5011            0 :                         thisFurnace.ActualFanVolFlowRate == thisFurnace.MaxCoolAirVolFlow &&
    5012            0 :                         thisFurnace.ActualFanVolFlowRate == thisFurnace.MaxNoCoolHeatAirVolFlow) {
    5013            0 :                         std::string FanName = state.dataFans->fans(thisFurnace.FanIndex)->Name;
    5014            0 :                         ShowWarningError(state, format("{} \"{}\"", HVAC::unitarySysTypeNames[(int)thisFurnace.type], thisFurnace.Name));
    5015            0 :                         ShowContinueError(state,
    5016            0 :                                           format("...For fan type and name = {} \"{}\"", HVAC::fanTypeNames[(int)thisFurnace.fanType], FanName));
    5017            0 :                         ShowContinueError(state,
    5018              :                                           "...Fan power ratio function of speed ratio curve has no impact if fan volumetric flow rate is the same as "
    5019              :                                           "the unitary system volumetric flow rate.");
    5020            0 :                         ShowContinueError(state, format("...Fan volumetric flow rate            = {:.5R} m3/s.", thisFurnace.ActualFanVolFlowRate));
    5021            0 :                         ShowContinueError(state, format("...Unitary system volumetric flow rate = {:.5R} m3/s.", thisFurnace.MaxHeatAirVolFlow));
    5022            0 :                     }
    5023              :                 }
    5024          359 :                 state.dataFurnaces->MyFanFlag(FurnaceNum) = false;
    5025              :             } else {
    5026          266 :                 thisFurnace.ActualFanVolFlowRate = state.dataFans->fans(thisFurnace.FanIndex)->maxAirFlowRate;
    5027              :             }
    5028              :         }
    5029              : 
    5030      6219025 :         if (allocated(state.dataZoneEquip->ZoneEquipConfig) && state.dataFurnaces->MyCheckFlag(FurnaceNum)) {
    5031          359 :             int zoneNum = thisFurnace.ControlZoneNum;
    5032          359 :             int zoneInlet = thisFurnace.ZoneInletNode;
    5033              :             // setup furnace zone equipment sequence information based on finding matching air terminal
    5034          359 :             if (state.dataZoneEquip->ZoneEquipConfig(zoneNum).EquipListIndex > 0) {
    5035          359 :                 int coolingPriority = 0;
    5036          359 :                 int heatingPriority = 0;
    5037          359 :                 state.dataZoneEquip->ZoneEquipList(state.dataZoneEquip->ZoneEquipConfig(zoneNum).EquipListIndex)
    5038          359 :                     .getPrioritiesForInletNode(state, zoneInlet, coolingPriority, heatingPriority);
    5039          359 :                 thisFurnace.ZoneSequenceCoolingNum = coolingPriority;
    5040          359 :                 thisFurnace.ZoneSequenceHeatingNum = heatingPriority;
    5041              :             }
    5042          359 :             state.dataFurnaces->MyCheckFlag(FurnaceNum) = false;
    5043          359 :             if (thisFurnace.ZoneSequenceCoolingNum == 0 || thisFurnace.ZoneSequenceHeatingNum == 0) {
    5044            0 :                 ShowSevereError(state,
    5045            0 :                                 format("{} \"{}\": Airloop air terminal in the zone equipment list for zone = {} not found or is not allowed Zone "
    5046              :                                        "Equipment Cooling or Heating Sequence = 0.",
    5047            0 :                                        HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    5048            0 :                                        thisFurnace.Name,
    5049            0 :                                        state.dataHeatBal->Zone(thisFurnace.ControlZoneNum).Name));
    5050            0 :                 ShowFatalError(state,
    5051            0 :                                format("Subroutine InitFurnace: Errors found in getting {} input.  Preceding condition(s) causes termination.",
    5052            0 :                                       HVAC::unitarySysTypeNames[(int)thisFurnace.type]));
    5053              :             }
    5054              :         }
    5055              : 
    5056              :         // Find the number of zones (zone Inlet Nodes) attached to an air loop from the air loop number
    5057              :         int NumAirLoopZones =
    5058      6219025 :             state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).NumZonesCooled + state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).NumZonesHeated;
    5059      6219025 :         if (allocated(state.dataAirLoop->AirToZoneNodeInfo) && state.dataFurnaces->MyFlowFracFlag(FurnaceNum)) {
    5060          359 :             state.dataFurnaces->FlowFracFlagReady = true;
    5061          799 :             for (int ZoneInSysIndex = 1; ZoneInSysIndex <= NumAirLoopZones; ++ZoneInSysIndex) {
    5062              :                 // zone inlet nodes for cooling
    5063          440 :                 if (state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).NumZonesCooled > 0) {
    5064          440 :                     if (state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).TermUnitCoolInletNodes(ZoneInSysIndex) == -999) {
    5065              :                         // the data structure for the zones inlet nodes has not been filled
    5066            0 :                         state.dataFurnaces->FlowFracFlagReady = false;
    5067              :                     }
    5068              :                 }
    5069              :                 // zone inlet nodes for heating
    5070          440 :                 if (state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).NumZonesHeated > 0) {
    5071            0 :                     if (state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).TermUnitHeatInletNodes(ZoneInSysIndex) == -999) {
    5072              :                         // the data structure for the zones inlet nodes has not been filled
    5073            0 :                         state.dataFurnaces->FlowFracFlagReady = false;
    5074              :                     }
    5075              :                 }
    5076              :             }
    5077              :         }
    5078              : 
    5079      6219025 :         if (state.dataFurnaces->MyFlowFracFlag(FurnaceNum)) {
    5080          359 :             if (allocated(state.dataAirLoop->AirToZoneNodeInfo) && state.dataFurnaces->FlowFracFlagReady) {
    5081          359 :                 SumOfMassFlowRateMax = 0.0; // initialize the sum of the maximum flows
    5082          799 :                 for (int ZoneInSysIndex = 1; ZoneInSysIndex <= NumAirLoopZones; ++ZoneInSysIndex) {
    5083          440 :                     int ZoneInletNodeNum = state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).TermUnitCoolInletNodes(ZoneInSysIndex);
    5084          440 :                     SumOfMassFlowRateMax += state.dataLoopNodes->Node(ZoneInletNodeNum).MassFlowRateMax;
    5085          440 :                     if (state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).CoolCtrlZoneNums(ZoneInSysIndex) == thisFurnace.ControlZoneNum) {
    5086          359 :                         CntrlZoneTerminalUnitMassFlowRateMax = state.dataLoopNodes->Node(ZoneInletNodeNum).MassFlowRateMax;
    5087              :                     }
    5088              :                 }
    5089          359 :                 if (SumOfMassFlowRateMax != 0.0) {
    5090          359 :                     if (CntrlZoneTerminalUnitMassFlowRateMax >= HVAC::SmallAirVolFlow) {
    5091          359 :                         thisFurnace.ControlZoneMassFlowFrac = CntrlZoneTerminalUnitMassFlowRateMax / SumOfMassFlowRateMax;
    5092              :                     } else {
    5093            0 :                         ShowSevereError(state, format("{} = {}", HVAC::unitarySysTypeNames[(int)thisFurnace.type], thisFurnace.Name));
    5094            0 :                         ShowContinueError(state, " The Fraction of Supply Air Flow That Goes Through the Controlling Zone is set to 1.");
    5095              :                     }
    5096          718 :                     BaseSizer::reportSizerOutput(state,
    5097          359 :                                                  HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    5098              :                                                  thisFurnace.Name,
    5099              :                                                  "Fraction of Supply Air Flow That Goes Through the Controlling Zone",
    5100              :                                                  thisFurnace.ControlZoneMassFlowFrac);
    5101          359 :                     state.dataFurnaces->MyFlowFracFlag(FurnaceNum) = false;
    5102              :                 }
    5103              :             }
    5104              :         }
    5105              : 
    5106              :         // Calculate air distribution losses
    5107      6219025 :         if (!FirstHVACIteration && state.dataFurnaces->AirLoopPass == 1) {
    5108      2230794 :             int ZoneInNode = thisFurnace.ZoneInletNode;
    5109      2230794 :             MassFlowRate = state.dataLoopNodes->Node(ZoneInNode).MassFlowRate / thisFurnace.ControlZoneMassFlowFrac;
    5110      2230794 :             if (state.afn->distribution_simulated) {
    5111        72768 :                 DeltaMassRate = state.dataLoopNodes->Node(thisFurnace.FurnaceOutletNodeNum).MassFlowRate -
    5112        72768 :                                 state.dataLoopNodes->Node(ZoneInNode).MassFlowRate / thisFurnace.ControlZoneMassFlowFrac;
    5113        72768 :                 if (DeltaMassRate < 0.0) {
    5114           54 :                     DeltaMassRate = 0.0;
    5115              :                 }
    5116              :             } else {
    5117      2158026 :                 MassFlowRate = state.dataLoopNodes->Node(thisFurnace.FurnaceOutletNodeNum).MassFlowRate;
    5118      2158026 :                 DeltaMassRate = 0.0;
    5119              :             }
    5120      2230794 :             Real64 TotalOutput(0.0);         // total output rate, {W}
    5121      2230794 :             Real64 SensibleOutputDelta(0.0); // delta sensible output rate, {W}
    5122      2230794 :             Real64 LatentOutputDelta(0.0);   // delta latent output rate, {W}
    5123      2230794 :             Real64 TotalOutputDelta(0.0);    // delta total output rate, {W}
    5124      8923176 :             CalcZoneSensibleLatentOutput(MassFlowRate,
    5125      2230794 :                                          state.dataLoopNodes->Node(thisFurnace.FurnaceOutletNodeNum).Temp,
    5126      2230794 :                                          state.dataLoopNodes->Node(thisFurnace.FurnaceOutletNodeNum).HumRat,
    5127      2230794 :                                          state.dataLoopNodes->Node(ZoneInNode).Temp,
    5128      2230794 :                                          state.dataLoopNodes->Node(ZoneInNode).HumRat,
    5129      2230794 :                                          thisFurnace.SenLoadLoss,
    5130      2230794 :                                          thisFurnace.LatLoadLoss,
    5131              :                                          TotalOutput);
    5132      8923176 :             CalcZoneSensibleLatentOutput(DeltaMassRate,
    5133      2230794 :                                          state.dataLoopNodes->Node(thisFurnace.FurnaceOutletNodeNum).Temp,
    5134      2230794 :                                          state.dataLoopNodes->Node(thisFurnace.FurnaceOutletNodeNum).HumRat,
    5135      2230794 :                                          state.dataLoopNodes->Node(thisFurnace.NodeNumOfControlledZone).Temp,
    5136      2230794 :                                          state.dataLoopNodes->Node(thisFurnace.NodeNumOfControlledZone).HumRat,
    5137              :                                          SensibleOutputDelta,
    5138              :                                          LatentOutputDelta,
    5139              :                                          TotalOutputDelta);
    5140      2230794 :             thisFurnace.SenLoadLoss = thisFurnace.SenLoadLoss + SensibleOutputDelta;
    5141      2230794 :             if (std::abs(thisFurnace.SensibleLoadMet) > 0.0) {
    5142      1401645 :                 if (std::abs(thisFurnace.SenLoadLoss / thisFurnace.SensibleLoadMet) < 0.001) {
    5143      1297941 :                     thisFurnace.SenLoadLoss = 0.0;
    5144              :                 }
    5145              :             }
    5146      2230794 :             if (thisFurnace.Humidistat) {
    5147       260797 :                 thisFurnace.LatLoadLoss = thisFurnace.LatLoadLoss + LatentOutputDelta;
    5148       260797 :                 if (std::abs(thisFurnace.LatentLoadMet) > 0.0) {
    5149       231001 :                     if (std::abs(thisFurnace.LatLoadLoss / thisFurnace.LatentLoadMet) < 0.001) {
    5150       224306 :                         thisFurnace.LatLoadLoss = 0.0;
    5151              :                     }
    5152              :                 }
    5153              :             }
    5154              :         }
    5155              : 
    5156      6219025 :         if (thisFurnace.fanOpModeSched != nullptr) {
    5157      5861505 :             thisFurnace.fanOp = (thisFurnace.fanOpModeSched->getCurrentVal() == 0.0) ? HVAC::FanOp::Cycling : HVAC::FanOp::Continuous;
    5158      5861505 :             if (AirLoopNum > 0) {
    5159      5861505 :                 state.dataAirLoop->AirLoopControlInfo(AirLoopNum).fanOp = thisFurnace.fanOp;
    5160              :             }
    5161              :         }
    5162              : 
    5163      6219025 :         fanOp = thisFurnace.fanOp;
    5164      6219025 :         state.dataFurnaces->EconomizerFlag = state.dataAirLoop->AirLoopControlInfo(AirLoopNum).EconoActive;
    5165              : 
    5166      6219025 :         if (thisFurnace.ControlZoneMassFlowFrac > 0.0) {
    5167      6219025 :             QZnReq = ZoneLoad / thisFurnace.ControlZoneMassFlowFrac;
    5168      6219025 :             MoistureLoad /= thisFurnace.ControlZoneMassFlowFrac;
    5169      6219025 :             ZoneLoad = QZnReq;
    5170              :         } else {
    5171            0 :             QZnReq = ZoneLoad;
    5172              :         }
    5173              : 
    5174              :         // Original thermostat control logic (works only for cycling fan systems)
    5175      8245691 :         if (QZnReq > HVAC::SmallLoad && QZnReq > (Small5WLoad / thisFurnace.ControlZoneMassFlowFrac) &&
    5176      2026666 :             !state.dataZoneEnergyDemand->CurDeadBandOrSetback(thisFurnace.ControlZoneNum)) {
    5177      2014394 :             state.dataFurnaces->HeatingLoad = true;
    5178      2014394 :             state.dataFurnaces->CoolingLoad = false;
    5179      7238229 :         } else if (QZnReq < -HVAC::SmallLoad && std::abs(QZnReq) > (Small5WLoad / thisFurnace.ControlZoneMassFlowFrac) &&
    5180      3033598 :                    !state.dataZoneEnergyDemand->CurDeadBandOrSetback(thisFurnace.ControlZoneNum)) {
    5181      3033474 :             state.dataFurnaces->HeatingLoad = false;
    5182      3033474 :             state.dataFurnaces->CoolingLoad = true;
    5183              :         } else {
    5184      1171157 :             state.dataFurnaces->HeatingLoad = false;
    5185      1171157 :             state.dataFurnaces->CoolingLoad = false;
    5186              :         }
    5187              : 
    5188      6219025 :         if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_AirToAir ||
    5189      5797233 :             (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir &&
    5190      2034588 :              (thisFurnace.WatertoAirHPType == WAHPCoilType::Simple || thisFurnace.WatertoAirHPType == WAHPCoilType::VarSpeedEquationFit))) {
    5191      2337110 :             if (MoistureLoad < 0.0 && thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat) {
    5192       125668 :                 state.dataFurnaces->HPDehumidificationLoadFlag = true;
    5193       125668 :                 state.dataFurnaces->HeatingLoad = false;
    5194       125668 :                 state.dataFurnaces->CoolingLoad = true;
    5195              :             } else {
    5196      2211442 :                 state.dataFurnaces->HPDehumidificationLoadFlag = false;
    5197              :             }
    5198              :         }
    5199              : 
    5200              :         // Check for heat only furnace
    5201      6219025 :         if (thisFurnace.type != HVAC::UnitarySysType::Furnace_HeatOnly && thisFurnace.type != HVAC::UnitarySysType::Unitary_HeatOnly) {
    5202              : 
    5203     12389162 :             if (thisFurnace.availSched->getCurrentVal() > 0.0) {
    5204      5954536 :                 if ((state.dataFurnaces->HeatingLoad || state.dataFurnaces->CoolingLoad) || (thisFurnace.Humidistat && MoistureLoad < 0.0)) {
    5205      5259446 :                     PartLoadRatio = 1.0;
    5206              :                 } else {
    5207       695090 :                     PartLoadRatio = 0.0;
    5208              :                 }
    5209              :             } else {
    5210       240045 :                 PartLoadRatio = 0.0;
    5211              :             }
    5212              :         } else {
    5213        24444 :             PartLoadRatio = 1.0;
    5214              :         }
    5215              : 
    5216              :         // get current time step operating capacity of water and steam coils
    5217              :         // (dependent on entering water and steam temperature)
    5218      6219025 :         if (FirstHVACIteration) {
    5219      1724095 :             if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingWater) {
    5220              :                 // set water-side mass flow rates
    5221            0 :                 state.dataLoopNodes->Node(thisFurnace.HWCoilAirInletNode).MassFlowRate = state.dataFurnaces->CompOnMassFlow;
    5222            0 :                 mdot = thisFurnace.MaxHeatCoilFluidFlow;
    5223            0 :                 PlantUtilities::SetComponentFlowRate(state, mdot, thisFurnace.CoilControlNode, thisFurnace.CoilOutletNode, thisFurnace.plantLoc);
    5224              :                 //     simulate water coil to find operating capacity
    5225            0 :                 WaterCoils::SimulateWaterCoilComponents(
    5226            0 :                     state, thisFurnace.HeatingCoilName, FirstHVACIteration, thisFurnace.HeatingCoilIndex, QActual);
    5227            0 :                 thisFurnace.DesignHeatingCapacity = QActual;
    5228              : 
    5229              :             } // from IF(furnace%HeatingCoilType_Num == Coil_HeatingWater) THEN
    5230              : 
    5231      1724095 :             if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingSteam) {
    5232              :                 // set air-side and steam-side mass flow rates
    5233            0 :                 state.dataLoopNodes->Node(thisFurnace.HWCoilAirInletNode).MassFlowRate = state.dataFurnaces->CompOnMassFlow;
    5234            0 :                 mdot = thisFurnace.MaxHeatCoilFluidFlow;
    5235            0 :                 PlantUtilities::SetComponentFlowRate(state, mdot, thisFurnace.CoilControlNode, thisFurnace.CoilOutletNode, thisFurnace.plantLoc);
    5236              : 
    5237              :                 //     simulate steam coil to find operating capacity
    5238            0 :                 SteamCoils::SimulateSteamCoilComponents(state,
    5239              :                                                         thisFurnace.HeatingCoilName,
    5240              :                                                         FirstHVACIteration,
    5241            0 :                                                         thisFurnace.HeatingCoilIndex,
    5242            0 :                                                         1.0,
    5243              :                                                         QActual); // QCoilReq, simulate any load > 0 to get max capacity of steam coil
    5244            0 :                 thisFurnace.DesignHeatingCapacity =
    5245            0 :                     SteamCoils::GetCoilCapacity(state, thisFurnace.HeatingCoilType, thisFurnace.HeatingCoilName, ErrorsFound);
    5246              : 
    5247              :             } // from IF(Furnace(FurnaceNum)%HeatingCoilType_Num == Coil_HeatingSteam) THEN
    5248              : 
    5249      1724095 :             if (thisFurnace.SuppHeatCoilType_Num == HVAC::Coil_HeatingWater) {
    5250              : 
    5251              :                 //     set air-side and steam-side mass flow rates
    5252         3678 :                 state.dataLoopNodes->Node(thisFurnace.SuppCoilAirInletNode).MassFlowRate = state.dataFurnaces->CompOnMassFlow;
    5253         3678 :                 mdot = thisFurnace.MaxSuppCoilFluidFlow;
    5254         3678 :                 PlantUtilities::SetComponentFlowRate(
    5255         3678 :                     state, mdot, thisFurnace.SuppCoilControlNode, thisFurnace.SuppCoilOutletNode, thisFurnace.SuppPlantLoc);
    5256              : 
    5257              :                 //     simulate water coil to find operating capacity
    5258         7356 :                 WaterCoils::SimulateWaterCoilComponents(
    5259         3678 :                     state, thisFurnace.SuppHeatCoilName, FirstHVACIteration, thisFurnace.SuppHeatCoilIndex, QActual);
    5260         3678 :                 thisFurnace.DesignSuppHeatingCapacity = QActual;
    5261              : 
    5262              :             } // from IF(Furnace(FurnaceNum)%SuppHeatCoilType_Num == Coil_HeatingWater) THEN
    5263      1724095 :             if (thisFurnace.SuppHeatCoilType_Num == HVAC::Coil_HeatingSteam) {
    5264              :                 //     set air-side and steam-side mass flow rates
    5265            0 :                 state.dataLoopNodes->Node(thisFurnace.SuppCoilAirInletNode).MassFlowRate = state.dataFurnaces->CompOnMassFlow;
    5266            0 :                 mdot = thisFurnace.MaxSuppCoilFluidFlow;
    5267            0 :                 PlantUtilities::SetComponentFlowRate(
    5268            0 :                     state, mdot, thisFurnace.SuppCoilControlNode, thisFurnace.SuppCoilOutletNode, thisFurnace.SuppPlantLoc);
    5269              : 
    5270              :                 //     simulate steam coil to find operating capacity
    5271            0 :                 SteamCoils::SimulateSteamCoilComponents(state,
    5272              :                                                         thisFurnace.SuppHeatCoilName,
    5273              :                                                         FirstHVACIteration,
    5274            0 :                                                         thisFurnace.SuppHeatCoilIndex,
    5275            0 :                                                         1.0,
    5276              :                                                         QActual); // QCoilReq, simulate any load > 0 to get max capacity of steam coil
    5277            0 :                 thisFurnace.DesignSuppHeatingCapacity =
    5278            0 :                     SteamCoils::GetCoilCapacity(state, thisFurnace.SuppHeatCoilType, thisFurnace.SuppHeatCoilName, ErrorsFound);
    5279              : 
    5280              :             } // from IF(Furnace(FurnaceNum)%SuppHeatCoilType_Num == Coil_HeatingSteam) THEN
    5281              :         } // from IF( FirstHVACIteration ) THEN
    5282              : 
    5283      6219025 :         if (thisFurnace.NumOfSpeedCooling > 0) { // BoS, variable-speed water source hp
    5284              :             // Furnace(FurnaceNum)%IdleMassFlowRate = RhoAir*Furnace(FurnaceNum)%IdleVolumeAirRate
    5285      1507624 :             int NumOfSpeedCooling = thisFurnace.NumOfSpeedCooling;
    5286      1507624 :             int NumOfSpeedHeating = thisFurnace.NumOfSpeedHeating;
    5287              :             // IF MSHP system was not autosized and the fan is autosized, check that fan volumetric flow rate is greater than MSHP flow rates
    5288      1507624 :             if (thisFurnace.CheckFanFlow) {
    5289           21 :                 state.dataFurnaces->CurrentModuleObject = "AirLoopHVAC:UnitaryHeatPump:VariableSpeed";
    5290           21 :                 thisFurnace.FanVolFlow = state.dataFans->fans(thisFurnace.FanIndex)->maxAirFlowRate;
    5291              : 
    5292           21 :                 if (thisFurnace.FanVolFlow != DataSizing::AutoSize) {
    5293              :                     //     Check fan versus system supply air flow rates
    5294           17 :                     if (thisFurnace.FanVolFlow + 1e-10 < thisFurnace.CoolVolumeFlowRate(NumOfSpeedCooling)) {
    5295            0 :                         ShowWarningError(state,
    5296            0 :                                          format("{} - air flow rate = {:.7T} in fan object is less than the MSHP system air flow rate when cooling "
    5297              :                                                 "is required ({:.7T}).",
    5298            0 :                                                 state.dataFurnaces->CurrentModuleObject,
    5299            0 :                                                 thisFurnace.FanVolFlow,
    5300              :                                                 thisFurnace.CoolVolumeFlowRate(NumOfSpeedCooling)));
    5301            0 :                         ShowContinueError(
    5302              :                             state, " The MSHP system flow rate when cooling is required is reset to the fan flow rate and the simulation continues.");
    5303            0 :                         ShowContinueError(state, format(" Occurs in {} = {}", state.dataFurnaces->CurrentModuleObject, thisFurnace.Name));
    5304            0 :                         thisFurnace.CoolVolumeFlowRate(NumOfSpeedCooling) = thisFurnace.FanVolFlow;
    5305              : 
    5306            0 :                         if (thisFurnace.bIsIHP) // set max fan flow rate to the IHP collection
    5307              :                         {
    5308            0 :                             state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).MaxCoolAirVolFlow = thisFurnace.FanVolFlow;
    5309            0 :                             state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).MaxCoolAirMassFlow =
    5310            0 :                                 thisFurnace.FanVolFlow * state.dataEnvrn->StdRhoAir;
    5311              :                         }
    5312              : 
    5313              :                         // Check flow rates in other speeds and ensure flow rates are not above the max flow rate
    5314            0 :                         for (int i = NumOfSpeedCooling - 1; i >= 1; --i) {
    5315            0 :                             if (thisFurnace.CoolVolumeFlowRate(i) > thisFurnace.CoolVolumeFlowRate(i + 1)) {
    5316            0 :                                 ShowContinueError(state,
    5317            0 :                                                   format(" The MSHP system flow rate when cooling is required is reset to the flow rate at higher "
    5318              :                                                          "speed and the simulation continues at Speed{}.",
    5319              :                                                          i));
    5320            0 :                                 ShowContinueError(state, format(" Occurs in {} = {}", state.dataFurnaces->CurrentModuleObject, thisFurnace.Name));
    5321            0 :                                 thisFurnace.CoolVolumeFlowRate(i) = thisFurnace.CoolVolumeFlowRate(i + 1);
    5322              :                             }
    5323              :                         }
    5324              :                     }
    5325           17 :                     if (NumOfSpeedHeating > 0) {
    5326           17 :                         if (thisFurnace.FanVolFlow + 1e-10 < thisFurnace.HeatVolumeFlowRate(NumOfSpeedHeating)) {
    5327            0 :                             ShowWarningError(state,
    5328            0 :                                              format("{} - air flow rate = {:.7T} in fan object is less than the MSHP system air flow rate when "
    5329              :                                                     "heating is required ({:.7T}).",
    5330            0 :                                                     state.dataFurnaces->CurrentModuleObject,
    5331            0 :                                                     thisFurnace.FanVolFlow,
    5332              :                                                     thisFurnace.HeatVolumeFlowRate(NumOfSpeedHeating)));
    5333            0 :                             ShowContinueError(
    5334              :                                 state,
    5335              :                                 " The MSHP system flow rate when heating is required is reset to the fan flow rate and the simulation continues.");
    5336            0 :                             ShowContinueError(state, format(" Occurs in {} = {}", state.dataFurnaces->CurrentModuleObject, thisFurnace.Name));
    5337            0 :                             thisFurnace.HeatVolumeFlowRate(NumOfSpeedHeating) = thisFurnace.FanVolFlow;
    5338              : 
    5339            0 :                             if (thisFurnace.bIsIHP) // set max fan flow rate to the IHP collection
    5340              :                             {
    5341            0 :                                 state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).MaxHeatAirVolFlow = thisFurnace.FanVolFlow;
    5342            0 :                                 state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).MaxHeatAirMassFlow =
    5343            0 :                                     thisFurnace.FanVolFlow * state.dataEnvrn->StdRhoAir;
    5344              :                             }
    5345              : 
    5346            0 :                             for (int i = NumOfSpeedHeating - 1; i >= 1; --i) {
    5347            0 :                                 if (thisFurnace.HeatVolumeFlowRate(i) > thisFurnace.HeatVolumeFlowRate(i + 1)) {
    5348            0 :                                     ShowContinueError(state,
    5349            0 :                                                       format(" The MSHP system flow rate when heating is required is reset to the flow rate at "
    5350              :                                                              "higher speed and the simulation continues at Speed{}.",
    5351              :                                                              i));
    5352            0 :                                     ShowContinueError(state,
    5353            0 :                                                       format(" Occurs in {} system = {}", state.dataFurnaces->CurrentModuleObject, thisFurnace.Name));
    5354            0 :                                     thisFurnace.HeatVolumeFlowRate(i) = thisFurnace.HeatVolumeFlowRate(i + 1);
    5355              :                                 }
    5356              :                             }
    5357              :                         }
    5358              :                     }
    5359           17 :                     if (thisFurnace.FanVolFlow < thisFurnace.IdleVolumeAirRate && thisFurnace.IdleVolumeAirRate != 0.0) {
    5360            0 :                         ShowWarningError(state,
    5361            0 :                                          format("{} - air flow rate = {:.7T} in fan object is less than the MSHP system air flow rate when no "
    5362              :                                                 "heating or cooling is needed ({:.7T}).",
    5363            0 :                                                 state.dataFurnaces->CurrentModuleObject,
    5364            0 :                                                 thisFurnace.FanVolFlow,
    5365            0 :                                                 thisFurnace.IdleVolumeAirRate));
    5366            0 :                         ShowContinueError(state,
    5367              :                                           " The MSHP system flow rate when no heating or cooling is needed is reset to the fan flow rate and the "
    5368              :                                           "simulation continues.");
    5369            0 :                         ShowContinueError(state, format(" Occurs in {} = {}", state.dataFurnaces->CurrentModuleObject, thisFurnace.Name));
    5370            0 :                         thisFurnace.IdleVolumeAirRate = thisFurnace.FanVolFlow;
    5371              :                     }
    5372           17 :                     RhoAir = state.dataEnvrn->StdRhoAir;
    5373              :                     // set the mass flow rates from the reset volume flow rates
    5374          187 :                     for (int i = 1; i <= NumOfSpeedCooling; ++i) {
    5375          170 :                         thisFurnace.CoolMassFlowRate(i) = RhoAir * thisFurnace.CoolVolumeFlowRate(i);
    5376          170 :                         if (thisFurnace.FanVolFlow > 0.0) {
    5377          170 :                             thisFurnace.MSCoolingSpeedRatio(i) = thisFurnace.CoolVolumeFlowRate(i) / thisFurnace.FanVolFlow;
    5378              :                         }
    5379              :                     }
    5380          187 :                     for (int i = 1; i <= NumOfSpeedHeating; ++i) {
    5381          170 :                         thisFurnace.HeatMassFlowRate(i) = RhoAir * thisFurnace.HeatVolumeFlowRate(i);
    5382          170 :                         if (thisFurnace.FanVolFlow > 0.0) {
    5383          170 :                             thisFurnace.MSHeatingSpeedRatio(i) = thisFurnace.HeatVolumeFlowRate(i) / thisFurnace.FanVolFlow;
    5384              :                         }
    5385              :                     }
    5386           17 :                     thisFurnace.IdleMassFlowRate = RhoAir * thisFurnace.IdleVolumeAirRate;
    5387           17 :                     if (thisFurnace.FanVolFlow > 0.0) {
    5388           17 :                         thisFurnace.IdleSpeedRatio = thisFurnace.IdleVolumeAirRate / thisFurnace.FanVolFlow;
    5389              :                     }
    5390              :                     // set the node max and min mass flow rates based on reset volume flow rates
    5391           17 :                     if (NumOfSpeedCooling > 0 && NumOfSpeedHeating == 0) {
    5392            0 :                         state.dataLoopNodes->Node(InNode).MassFlowRateMax =
    5393            0 :                             max(thisFurnace.CoolMassFlowRate(NumOfSpeedCooling), thisFurnace.MaxHeatAirMassFlow);
    5394            0 :                         state.dataLoopNodes->Node(InNode).MassFlowRateMaxAvail =
    5395            0 :                             max(thisFurnace.CoolMassFlowRate(NumOfSpeedCooling), thisFurnace.MaxHeatAirMassFlow);
    5396           17 :                     } else if (NumOfSpeedCooling == 0 && NumOfSpeedHeating > 0) {
    5397            0 :                         state.dataLoopNodes->Node(InNode).MassFlowRateMax =
    5398            0 :                             max(thisFurnace.MaxCoolAirMassFlow, thisFurnace.HeatMassFlowRate(NumOfSpeedHeating));
    5399            0 :                         state.dataLoopNodes->Node(InNode).MassFlowRateMaxAvail =
    5400            0 :                             max(thisFurnace.MaxCoolAirMassFlow, thisFurnace.HeatMassFlowRate(NumOfSpeedHeating));
    5401              :                     } else {
    5402           17 :                         state.dataLoopNodes->Node(InNode).MassFlowRateMax =
    5403           17 :                             max(thisFurnace.CoolMassFlowRate(NumOfSpeedCooling), thisFurnace.HeatMassFlowRate(NumOfSpeedHeating));
    5404           17 :                         state.dataLoopNodes->Node(InNode).MassFlowRateMaxAvail =
    5405           17 :                             max(thisFurnace.CoolMassFlowRate(NumOfSpeedCooling), thisFurnace.HeatMassFlowRate(NumOfSpeedHeating));
    5406              :                     }
    5407           17 :                     state.dataLoopNodes->Node(InNode).MassFlowRateMin = 0.0;
    5408           17 :                     state.dataLoopNodes->Node(InNode).MassFlowRateMinAvail = 0.0;
    5409           17 :                     state.dataLoopNodes->Node(OutNode) = state.dataLoopNodes->Node(InNode);
    5410              :                 }
    5411              :             }
    5412              : 
    5413      1507624 :             thisFurnace.CheckFanFlow = false;
    5414              :         }
    5415      6219025 :         SetOnOffMassFlowRate(state, FurnaceNum, AirLoopNum, OnOffAirFlowRatio, fanOp, QZnReq, MoistureLoad, PartLoadRatio);
    5416              : 
    5417              :         // Check ventilation/fan load for constant fan systems to see if load to be met changes
    5418              :         // Same IF logic used in Subroutine SetAverageAirFlow to determine if unit is ON or OFF
    5419              : 
    5420      6219025 :         QToCoolSetPt = 0.0;
    5421      6219025 :         QToHeatSetPt = 0.0;
    5422     12522293 :         if (fanOp == HVAC::FanOp::Continuous && thisFurnace.availSched->getCurrentVal() > 0.0 &&
    5423      6303268 :             ((thisFurnace.fanAvailSched->getCurrentVal() > 0.0 || state.dataHVACGlobal->TurnFansOn) && !state.dataHVACGlobal->TurnFansOff)) {
    5424              : 
    5425      3141086 :             if (thisFurnace.NumOfSpeedCooling > 0) {
    5426      1465806 :                 CalcVarSpeedHeatPump(state,
    5427              :                                      FurnaceNum,
    5428              :                                      false,
    5429              :                                      HVAC::CompressorOp::Off,
    5430              :                                      1,
    5431              :                                      0.0,
    5432              :                                      0.0,
    5433              :                                      SensibleOutput,
    5434              :                                      LatentOutput,
    5435              :                                      0.0,
    5436              :                                      0.0,
    5437              :                                      OnOffAirFlowRatio,
    5438              :                                      SUPHEATERLOAD);
    5439              :             } else {
    5440      1675280 :                 CalcFurnaceOutput(state,
    5441              :                                   FurnaceNum,
    5442              :                                   false,
    5443              :                                   HVAC::FanOp::Invalid, // Looks like Invalid is used to mean that the fan is off here?
    5444              :                                   HVAC::CompressorOp::Off,
    5445              :                                   0.0,
    5446              :                                   0.0,
    5447              :                                   0.0,
    5448              :                                   0.0,
    5449              :                                   SensibleOutput,
    5450              :                                   LatentOutput,
    5451              :                                   OnOffAirFlowRatio,
    5452              :                                   false);
    5453              :             }
    5454              : 
    5455      3141086 :             if (thisFurnace.ControlZoneMassFlowFrac > 0.0) {
    5456      3141086 :                 if (thisFurnace.ZoneSequenceCoolingNum > 0 && thisFurnace.ZoneSequenceHeatingNum > 0) {
    5457      3141086 :                     QToCoolSetPt = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(thisFurnace.ControlZoneNum)
    5458      3141086 :                                        .SequencedOutputRequiredToCoolingSP(thisFurnace.ZoneSequenceCoolingNum) /
    5459      3141086 :                                    thisFurnace.ControlZoneMassFlowFrac;
    5460      3141086 :                     QToHeatSetPt = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(thisFurnace.ControlZoneNum)
    5461      3141086 :                                        .SequencedOutputRequiredToHeatingSP(thisFurnace.ZoneSequenceHeatingNum) /
    5462      3141086 :                                    thisFurnace.ControlZoneMassFlowFrac;
    5463              :                 } else {
    5464            0 :                     QToCoolSetPt = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(thisFurnace.ControlZoneNum).OutputRequiredToCoolingSP /
    5465            0 :                                    thisFurnace.ControlZoneMassFlowFrac;
    5466            0 :                     QToHeatSetPt = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(thisFurnace.ControlZoneNum).OutputRequiredToHeatingSP /
    5467            0 :                                    thisFurnace.ControlZoneMassFlowFrac;
    5468              :                 }
    5469              :                 //     If the furnace has a net cooling capacity (SensibleOutput < 0) and
    5470              :                 //     the zone temp is above the Tstat heating setpoint (QToHeatSetPt < 0) and
    5471              :                 //     the net cooling capacity does not just offset the cooling load
    5472      3835360 :                 if (SensibleOutput < 0.0 && QToHeatSetPt < 0.0 &&
    5473       694274 :                     std::abs(QToCoolSetPt - SensibleOutput) > (Small5WLoad / thisFurnace.ControlZoneMassFlowFrac)) {
    5474              :                     //       Only switch modes when humidistat is not used or no moisture load exists, otherwise let
    5475              :                     //       reheat coil pick up load
    5476              :                     //        IF((SensibleOutput .LT. QToHeatSetPt .AND. .NOT. Furnace(FurnaceNum)%Humidistat) .OR. &
    5477              :                     //           (SensibleOutput .LT. QToHeatSetPt .AND. Furnace(FurnaceNum)%Humidistat .AND. MoistureLoad .GE. 0.0))THEN
    5478       693577 :                     if ((SensibleOutput < QToHeatSetPt && !thisFurnace.Humidistat) ||
    5479       689561 :                         (SensibleOutput < QToHeatSetPt && thisFurnace.Humidistat && MoistureLoad >= 0.0)) {
    5480         4562 :                         QZnReq = QToHeatSetPt;
    5481         4562 :                         state.dataFurnaces->CoolingLoad = false;
    5482              :                         //         Don't set mode TRUE unless mode is allowed. Also check for floating zone.
    5483         9122 :                         if (state.dataHeatBalFanSys->TempControlType(thisFurnace.ControlZoneNum) == HVAC::SetptType::SingleCool ||
    5484         4560 :                             state.dataHeatBalFanSys->TempControlType(thisFurnace.ControlZoneNum) == HVAC::SetptType::Uncontrolled) {
    5485            2 :                             state.dataFurnaces->HeatingLoad = false;
    5486              :                         } else {
    5487         4560 :                             state.dataFurnaces->HeatingLoad = true;
    5488              :                         }
    5489              : 
    5490         4562 :                         SetOnOffMassFlowRate(state, FurnaceNum, AirLoopNum, OnOffAirFlowRatio, fanOp, QZnReq, MoistureLoad, PartLoadRatio);
    5491         4562 :                         if (thisFurnace.NumOfSpeedCooling > 0) {
    5492          338 :                             CalcVarSpeedHeatPump(state,
    5493              :                                                  FurnaceNum,
    5494              :                                                  false,
    5495              :                                                  HVAC::CompressorOp::Off,
    5496              :                                                  1,
    5497              :                                                  0.0,
    5498              :                                                  0.0,
    5499              :                                                  SensibleOutput,
    5500              :                                                  LatentOutput,
    5501              :                                                  0.0,
    5502              :                                                  0.0,
    5503              :                                                  OnOffAirFlowRatio,
    5504              :                                                  SUPHEATERLOAD);
    5505              :                         } else {
    5506         4224 :                             CalcFurnaceOutput(state,
    5507              :                                               FurnaceNum,
    5508              :                                               false,
    5509              :                                               HVAC::FanOp::Invalid,
    5510              :                                               HVAC::CompressorOp::Off,
    5511              :                                               0.0,
    5512              :                                               0.0,
    5513              :                                               0.0,
    5514              :                                               0.0,
    5515              :                                               SensibleOutput,
    5516              :                                               LatentOutput,
    5517              :                                               OnOffAirFlowRatio,
    5518              :                                               false);
    5519              :                         }
    5520         4562 :                         if (SensibleOutput > QToHeatSetPt) {
    5521              :                             // If changing operating mode (flow rates) does not overshoot heating setpoint, turn off heating
    5522            0 :                             QZnReq = 0.0;
    5523            0 :                             state.dataFurnaces->HeatingLoad = false;
    5524            0 :                             SetOnOffMassFlowRate(state, FurnaceNum, AirLoopNum, OnOffAirFlowRatio, fanOp, QZnReq, MoistureLoad, PartLoadRatio);
    5525              :                         }
    5526       689015 :                     } else if (SensibleOutput < QZnReq) {
    5527              :                         //         If the net cooling capacity meets the zone cooling load but does not overshoot heating setpoint, turn off cooling
    5528              :                         //         (dehumidification may still occur)
    5529        63386 :                         QZnReq = 0.0;
    5530        63386 :                         state.dataFurnaces->CoolingLoad = false;
    5531        63386 :                         if (state.dataFurnaces->HPDehumidificationLoadFlag) {
    5532          134 :                             state.dataFurnaces->CoolingLoad = true;
    5533          134 :                             state.dataFurnaces->HeatingLoad = false;
    5534              :                         }
    5535        63386 :                         SetOnOffMassFlowRate(state, FurnaceNum, AirLoopNum, OnOffAirFlowRatio, fanOp, QZnReq, MoistureLoad, PartLoadRatio);
    5536              :                     }
    5537              :                     // the net cooling capacity just offsets the cooling load, turn off cooling
    5538      2448206 :                 } else if (SensibleOutput < 0.0 && QToCoolSetPt < 0.0 &&
    5539          697 :                            std::abs(QToCoolSetPt - SensibleOutput) < (Small5WLoad / thisFurnace.ControlZoneMassFlowFrac)) {
    5540          697 :                     state.dataFurnaces->CoolingLoad = false;
    5541          697 :                     if (state.dataFurnaces->HPDehumidificationLoadFlag) {
    5542            0 :                         state.dataFurnaces->CoolingLoad = true;
    5543            0 :                         state.dataFurnaces->HeatingLoad = false;
    5544              :                     }
    5545              :                 } // SensibleOutput .LT. 0.0d0 .AND. QToHeatSetPt .LT. 0.0d0
    5546              : 
    5547              :                 //     If the furnace has a net heating capacity and the zone temp is below the Tstat cooling setpoint and
    5548              :                 //     the net heating capacity does not just offset the heating load
    5549      3976683 :                 if (SensibleOutput > 0.0 && QToCoolSetPt > 0.0 &&
    5550       835597 :                     std::abs(SensibleOutput - QToHeatSetPt) > (Small5WLoad / thisFurnace.ControlZoneMassFlowFrac)) {
    5551       835340 :                     if (SensibleOutput > QToCoolSetPt) {
    5552        92546 :                         QZnReq = QToCoolSetPt;
    5553              :                         //         Don't set mode TRUE unless mode is allowed. Also check for floating zone.
    5554       185042 :                         if (state.dataHeatBalFanSys->TempControlType(thisFurnace.ControlZoneNum) == HVAC::SetptType::SingleHeat ||
    5555        92496 :                             state.dataHeatBalFanSys->TempControlType(thisFurnace.ControlZoneNum) == HVAC::SetptType::Uncontrolled) {
    5556           50 :                             state.dataFurnaces->CoolingLoad = false;
    5557              :                         } else {
    5558        92496 :                             state.dataFurnaces->CoolingLoad = true;
    5559              :                         }
    5560        92546 :                         state.dataFurnaces->HeatingLoad = false;
    5561              : 
    5562        92546 :                         SetOnOffMassFlowRate(state, FurnaceNum, AirLoopNum, OnOffAirFlowRatio, fanOp, QZnReq, MoistureLoad, PartLoadRatio);
    5563        92546 :                         if (thisFurnace.NumOfSpeedCooling > 0) {
    5564         6895 :                             CalcVarSpeedHeatPump(state,
    5565              :                                                  FurnaceNum,
    5566              :                                                  false,
    5567              :                                                  HVAC::CompressorOp::Off,
    5568              :                                                  1,
    5569              :                                                  0.0,
    5570              :                                                  0.0,
    5571              :                                                  SensibleOutput,
    5572              :                                                  LatentOutput,
    5573              :                                                  0.0,
    5574              :                                                  0.0,
    5575              :                                                  OnOffAirFlowRatio,
    5576              :                                                  SUPHEATERLOAD);
    5577              :                         } else {
    5578        85651 :                             CalcFurnaceOutput(state,
    5579              :                                               FurnaceNum,
    5580              :                                               false,
    5581              :                                               HVAC::FanOp::Invalid,
    5582              :                                               HVAC::CompressorOp::Off,
    5583              :                                               0.0,
    5584              :                                               0.0,
    5585              :                                               0.0,
    5586              :                                               0.0,
    5587              :                                               SensibleOutput,
    5588              :                                               LatentOutput,
    5589              :                                               OnOffAirFlowRatio,
    5590              :                                               false);
    5591              :                         }
    5592        92546 :                         if (SensibleOutput < QToCoolSetPt) {
    5593              :                             //           If changing operating mode (flow rates) does not overshoot cooling setpoint, turn off cooling
    5594            0 :                             if (state.dataFurnaces->HPDehumidificationLoadFlag) {
    5595            0 :                                 state.dataFurnaces->CoolingLoad = true;
    5596            0 :                                 state.dataFurnaces->HeatingLoad = false;
    5597              :                             } else {
    5598            0 :                                 QZnReq = 0.0;
    5599            0 :                                 state.dataFurnaces->CoolingLoad = false;
    5600              :                             }
    5601            0 :                             SetOnOffMassFlowRate(state, FurnaceNum, AirLoopNum, OnOffAirFlowRatio, fanOp, QZnReq, MoistureLoad, PartLoadRatio);
    5602              :                         }
    5603       742794 :                     } else if (SensibleOutput > QZnReq) {
    5604              :                         //         If the net heating capacity meets the zone heating load but does not overshoot, turn off heating
    5605       646586 :                         QZnReq = 0.0;
    5606       646586 :                         state.dataFurnaces->HeatingLoad = false;
    5607       646586 :                         SetOnOffMassFlowRate(state, FurnaceNum, AirLoopNum, OnOffAirFlowRatio, fanOp, QZnReq, MoistureLoad, PartLoadRatio);
    5608              :                     }
    5609              :                     //     the net heating capacity just offsets the heating load, turn off heating
    5610      2306003 :                 } else if (SensibleOutput > 0.0 && QToHeatSetPt > 0.0 &&
    5611          257 :                            std::abs(SensibleOutput - QToHeatSetPt) < (Small5WLoad / thisFurnace.ControlZoneMassFlowFrac)) {
    5612          257 :                     state.dataFurnaces->HeatingLoad = false;
    5613              :                 } // SensibleOutput .GT. 0.0d0 .AND. QToCoolSetPt .GT. 0.0d0
    5614              :             } // Furnace(FurnaceNum)%ControlZoneMassFlowFrac .GT. 0.0d0
    5615      3141086 :             ZoneLoad = QZnReq;
    5616              :         } // fanOp .EQ. FanOp::Continuous
    5617              : 
    5618      6219025 :         if (FirstHVACIteration) {
    5619      1724095 :             thisFurnace.iterationCounter = 0;
    5620      1724095 :             thisFurnace.iterationMode = Furnaces::ModeOfOperation::NoCoolHeat;
    5621              :         }
    5622      6219025 :         thisFurnace.iterationCounter += 1;
    5623              : 
    5624              :         // push iteration mode stack and set current mode
    5625      6219025 :         thisFurnace.iterationMode(3) = thisFurnace.iterationMode(2);
    5626      6219025 :         thisFurnace.iterationMode(2) = thisFurnace.iterationMode(1);
    5627      6219025 :         if (state.dataFurnaces->CoolingLoad) {
    5628      3225722 :             thisFurnace.iterationMode(1) = Furnaces::ModeOfOperation::CoolingMode;
    5629      2993303 :         } else if (state.dataFurnaces->HeatingLoad) {
    5630      1974343 :             thisFurnace.iterationMode(1) = Furnaces::ModeOfOperation::HeatingMode;
    5631              :         } else {
    5632      1018960 :             thisFurnace.iterationMode(1) = Furnaces::ModeOfOperation::NoCoolHeat;
    5633              :         }
    5634              : 
    5635              :         // IF small loads to meet or not converging, just shut down unit
    5636      6219025 :         if (std::abs(ZoneLoad) < Small5WLoad) {
    5637      1091416 :             ZoneLoad = 0.0;
    5638      1091416 :             state.dataFurnaces->CoolingLoad = false;
    5639      1091416 :             state.dataFurnaces->HeatingLoad = false;
    5640      5127609 :         } else if (thisFurnace.iterationCounter > (state.dataHVACGlobal->MinAirLoopIterationsAfterFirst + 4)) {
    5641              :             // attempt to lock output (air flow) if oscillations are detected
    5642      1972741 :             OperatingMode = thisFurnace.iterationMode(1);
    5643      1972741 :             OperatingModeMinusOne = thisFurnace.iterationMode(2);
    5644      1972741 :             OperatingModeMinusTwo = thisFurnace.iterationMode(3);
    5645      1972741 :             Oscillate = true;
    5646      1972741 :             if (OperatingMode == OperatingModeMinusOne && OperatingMode == OperatingModeMinusTwo) {
    5647      1972697 :                 Oscillate = false;
    5648              :             }
    5649      1972741 :             if (Oscillate) {
    5650           44 :                 if (QToCoolSetPt < 0.0) {
    5651            8 :                     state.dataFurnaces->HeatingLoad = false;
    5652            8 :                     state.dataFurnaces->CoolingLoad = true;
    5653            8 :                     ZoneLoad = QToCoolSetPt;
    5654           36 :                 } else if (QToHeatSetPt > 0.0) {
    5655           12 :                     state.dataFurnaces->HeatingLoad = true;
    5656           12 :                     state.dataFurnaces->CoolingLoad = false;
    5657           12 :                     ZoneLoad = QToHeatSetPt;
    5658              :                 } else {
    5659           24 :                     state.dataFurnaces->HeatingLoad = false;
    5660           24 :                     state.dataFurnaces->CoolingLoad = false;
    5661           24 :                     ZoneLoad = 0.0;
    5662              :                 }
    5663              :             }
    5664              :         }
    5665              : 
    5666              :         // EMS override point
    5667      6219025 :         if (thisFurnace.EMSOverrideSensZoneLoadRequest) {
    5668            0 :             ZoneLoad = thisFurnace.EMSSensibleZoneLoadValue;
    5669              :         }
    5670      6219025 :         if (thisFurnace.EMSOverrideMoistZoneLoadRequest) {
    5671            0 :             MoistureLoad = thisFurnace.EMSMoistureZoneLoadValue;
    5672              :         }
    5673      6219025 :         if (thisFurnace.EMSOverrideSensZoneLoadRequest || thisFurnace.EMSOverrideMoistZoneLoadRequest) {
    5674            0 :             if ((ZoneLoad != 0.0) && (thisFurnace.EMSOverrideSensZoneLoadRequest)) {
    5675            0 :                 PartLoadRatio = 1.0;
    5676            0 :             } else if ((MoistureLoad != 0.0) && (thisFurnace.EMSOverrideMoistZoneLoadRequest)) {
    5677            0 :                 PartLoadRatio = 1.0;
    5678              :             } else {
    5679            0 :                 PartLoadRatio = 0.0;
    5680              :             }
    5681            0 :             if (thisFurnace.NumOfSpeedCooling > 0) {
    5682            0 :                 SetOnOffMassFlowRate(state, FurnaceNum, AirLoopNum, OnOffAirFlowRatio, fanOp, QZnReq, MoistureLoad, PartLoadRatio);
    5683              :             } else {
    5684              :                 // This line is suspicious - all other calls to SetOnOffMassFlowRate pass in QZnReq, not ZoneLoad
    5685              :                 // either way, it seems these two should be using the same parameters.
    5686            0 :                 SetOnOffMassFlowRate(state, FurnaceNum, AirLoopNum, OnOffAirFlowRatio, fanOp, ZoneLoad, MoistureLoad, PartLoadRatio);
    5687              :             }
    5688              :         }
    5689              : 
    5690              :         // AirflowNetwork global variable
    5691      6219025 :         if (state.afn->distribution_simulated) {
    5692       214495 :             state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).AFNLoopHeatingCoilMaxRTF = 0.0;
    5693              :         }
    5694      6219025 :     }
    5695              : 
    5696      7026105 :     void SetOnOffMassFlowRate(EnergyPlusData &state,
    5697              :                               int const FurnaceNum,                   // index to furnace
    5698              :                               [[maybe_unused]] int const AirLoopNum,  // index to air loop !unused1208
    5699              :                               Real64 &OnOffAirFlowRatio,              // ratio of coil on to coil off air flow rate
    5700              :                               HVAC::FanOp const fanOp,                // fan operating mode
    5701              :                               [[maybe_unused]] Real64 const ZoneLoad, // sensible load to be met (W) !unused1208
    5702              :                               Real64 const MoistureLoad,              // moisture load to be met (W)
    5703              :                               Real64 const PartLoadRatio              // coil part-load ratio
    5704              :     )
    5705              :     {
    5706              : 
    5707              :         // SUBROUTINE INFORMATION:
    5708              :         //       AUTHOR         Richard Raustad
    5709              :         //       DATE WRITTEN   Sep 2008
    5710              : 
    5711              :         // PURPOSE OF THIS SUBROUTINE:
    5712              :         // This subroutine is for initializations of the Furnace Components.
    5713              : 
    5714              :         // METHODOLOGY EMPLOYED:
    5715              :         // The HeatCool furnace/unitarysystem and air-to-air heat pump may have alternate air flow rates
    5716              :         // in cooling, heating, and when no cooling or heating is needed. Set up the coil (comp) ON and OFF
    5717              :         // air flow rates. Use these flow rates during the Calc routines to set the average mass flow rates
    5718              :         // based on PLR.
    5719              : 
    5720      7026105 :         auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    5721              :         // Check for heat only furnace
    5722      7026105 :         if (thisFurnace.type != HVAC::UnitarySysType::Furnace_HeatOnly && thisFurnace.type != HVAC::UnitarySysType::Unitary_HeatOnly) {
    5723              : 
    5724              :             // Set the system mass flow rates
    5725      7001661 :             if (fanOp == HVAC::FanOp::Continuous) {
    5726              :                 // Set the compressor or coil ON mass flow rate
    5727              :                 // constant fan mode
    5728      4167131 :                 if (state.dataFurnaces->HeatingLoad) {
    5729              :                     //       IF a heating and moisture load exists, operate at the cooling mass flow rate ELSE operate at the heating flow rate
    5730       466631 :                     if (MoistureLoad < 0.0 && thisFurnace.Humidistat &&
    5731         7419 :                         thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat) {
    5732         6429 :                         state.dataFurnaces->CompOnMassFlow = thisFurnace.MaxCoolAirMassFlow;
    5733         6429 :                         state.dataFurnaces->CompOnFlowRatio = thisFurnace.CoolingSpeedRatio;
    5734              :                     } else {
    5735       460202 :                         state.dataFurnaces->CompOnMassFlow = thisFurnace.MaxHeatAirMassFlow;
    5736       460202 :                         state.dataFurnaces->CompOnFlowRatio = thisFurnace.HeatingSpeedRatio;
    5737              :                     }
    5738       466631 :                     thisFurnace.LastMode = Furnaces::ModeOfOperation::HeatingMode;
    5739              :                     //     IF a cooling load exists, operate at the cooling mass flow rate
    5740      3700500 :                 } else if (state.dataFurnaces->CoolingLoad) {
    5741      2189250 :                     state.dataFurnaces->CompOnMassFlow = thisFurnace.MaxCoolAirMassFlow;
    5742      2189250 :                     state.dataFurnaces->CompOnFlowRatio = thisFurnace.CoolingSpeedRatio;
    5743      2189250 :                     thisFurnace.LastMode = Furnaces::ModeOfOperation::CoolingMode;
    5744              :                     //     If no load exists, set the compressor on mass flow rate.
    5745              :                     //     Set equal the mass flow rate when no heating or cooling is needed if no moisture load exists.
    5746              :                     //     If the user has set the off mass flow rate to 0, set according to the last operating mode.
    5747              :                 } else {
    5748      1511250 :                     if (MoistureLoad < 0.0 && thisFurnace.Humidistat &&
    5749       513049 :                         thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat) {
    5750       482878 :                         state.dataFurnaces->CompOnMassFlow = thisFurnace.MaxCoolAirMassFlow;
    5751       482878 :                         state.dataFurnaces->CompOnFlowRatio = thisFurnace.CoolingSpeedRatio;
    5752              :                     } else {
    5753      1028372 :                         state.dataFurnaces->CompOnMassFlow = thisFurnace.MaxNoCoolHeatAirMassFlow;
    5754      1028372 :                         state.dataFurnaces->CompOnFlowRatio = thisFurnace.HeatingSpeedRatio;
    5755              :                         //         User may have entered a 0 for MaxNoCoolHeatAirMassFlow
    5756      1028372 :                         if (state.dataFurnaces->CompOnMassFlow == 0.0) {
    5757        33239 :                             if (thisFurnace.LastMode == Furnaces::ModeOfOperation::HeatingMode) {
    5758         3390 :                                 state.dataFurnaces->CompOnMassFlow = thisFurnace.MaxHeatAirMassFlow;
    5759         3390 :                                 state.dataFurnaces->CompOnFlowRatio = thisFurnace.HeatingSpeedRatio;
    5760              :                             } else {
    5761        29849 :                                 state.dataFurnaces->CompOnMassFlow = thisFurnace.MaxCoolAirMassFlow;
    5762        29849 :                                 state.dataFurnaces->CompOnFlowRatio = thisFurnace.CoolingSpeedRatio;
    5763              :                             }
    5764              :                         }
    5765              :                     }
    5766              :                 }
    5767              : 
    5768              :                 //     Set the compressor or coil OFF mass flow rate based on LOGICAL flag
    5769              :                 //     UseCompressorOnFlow is used when the user does not enter a value for no cooling or heating flow rate
    5770      4167131 :                 if (thisFurnace.AirFlowControl == AirFlowControlConstFan::UseCompressorOnFlow) {
    5771      1017402 :                     if (thisFurnace.LastMode == Furnaces::ModeOfOperation::HeatingMode) {
    5772       152149 :                         if (MoistureLoad < 0.0 && thisFurnace.Humidistat &&
    5773         4344 :                             thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat) {
    5774            0 :                             state.dataFurnaces->CompOffMassFlow = thisFurnace.MaxCoolAirMassFlow;
    5775            0 :                             state.dataFurnaces->CompOffFlowRatio = thisFurnace.CoolingSpeedRatio;
    5776              :                         } else {
    5777       152149 :                             state.dataFurnaces->CompOffMassFlow = thisFurnace.MaxHeatAirMassFlow;
    5778       152149 :                             state.dataFurnaces->CompOffFlowRatio = thisFurnace.HeatingSpeedRatio;
    5779              :                         }
    5780              :                     } else {
    5781       865253 :                         state.dataFurnaces->CompOffMassFlow = thisFurnace.MaxCoolAirMassFlow;
    5782       865253 :                         state.dataFurnaces->CompOffFlowRatio = thisFurnace.CoolingSpeedRatio;
    5783              :                     }
    5784              :                     //     ELSE use the user specified value
    5785              :                 } else {
    5786      3149729 :                     state.dataFurnaces->CompOffMassFlow = thisFurnace.MaxNoCoolHeatAirMassFlow;
    5787      3149729 :                     state.dataFurnaces->CompOffFlowRatio = thisFurnace.NoHeatCoolSpeedRatio;
    5788              :                 }
    5789              :             } else {
    5790              :                 //     cycling fan mode
    5791      4168116 :                 if (state.dataFurnaces->HeatingLoad ||
    5792      1333586 :                     (thisFurnace.Humidistat && MoistureLoad < 0.0 && thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat)) {
    5793              : 
    5794      1502100 :                     if (thisFurnace.Humidistat && MoistureLoad < 0.0 &&
    5795         4584 :                         thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat) {
    5796         1160 :                         state.dataFurnaces->CompOnMassFlow = thisFurnace.MaxCoolAirMassFlow;
    5797         1160 :                         state.dataFurnaces->CompOnFlowRatio = thisFurnace.CoolingSpeedRatio;
    5798         1160 :                         thisFurnace.LastMode = Furnaces::ModeOfOperation::CoolingMode;
    5799              :                     } else {
    5800      1500940 :                         state.dataFurnaces->CompOnMassFlow = thisFurnace.MaxHeatAirMassFlow;
    5801      1500940 :                         state.dataFurnaces->CompOnFlowRatio = thisFurnace.HeatingSpeedRatio;
    5802      1500940 :                         thisFurnace.LastMode = Furnaces::ModeOfOperation::HeatingMode;
    5803              :                     }
    5804      1332430 :                 } else if (state.dataFurnaces->CoolingLoad) {
    5805      1126036 :                     state.dataFurnaces->CompOnMassFlow = thisFurnace.MaxCoolAirMassFlow;
    5806      1126036 :                     state.dataFurnaces->CompOnFlowRatio = thisFurnace.CoolingSpeedRatio;
    5807              :                 } else {
    5808       206394 :                     state.dataFurnaces->CompOnMassFlow = 0.0;
    5809       206394 :                     state.dataFurnaces->CompOnFlowRatio = 0.0;
    5810              :                 }
    5811      2834530 :                 state.dataFurnaces->CompOffMassFlow = 0.0;
    5812      2834530 :                 state.dataFurnaces->CompOffFlowRatio = 0.0;
    5813              :             }
    5814              :         } else { //  Is a HeatOnly furnace
    5815              : 
    5816        24444 :             state.dataFurnaces->CompOnMassFlow = thisFurnace.DesignMassFlowRate;
    5817        24444 :             state.dataFurnaces->CompOnFlowRatio = thisFurnace.HeatingSpeedRatio;
    5818        24444 :             if (fanOp == HVAC::FanOp::Continuous) {
    5819            0 :                 state.dataFurnaces->CompOffMassFlow = thisFurnace.MaxNoCoolHeatAirMassFlow;
    5820            0 :                 state.dataFurnaces->CompOffFlowRatio = thisFurnace.HeatingSpeedRatio;
    5821              :             } else {
    5822        24444 :                 state.dataFurnaces->CompOffMassFlow = 0.0;
    5823        24444 :                 state.dataFurnaces->CompOffFlowRatio = 0.0;
    5824              :             }
    5825              : 
    5826              :         } // End check for heat only furnace or water-to-air heat pump
    5827              : 
    5828              :         // Set the system mass flow rates
    5829      7026105 :         SetAverageAirFlow(state, FurnaceNum, PartLoadRatio, OnOffAirFlowRatio);
    5830      7026105 :     }
    5831              : 
    5832          359 :     void SizeFurnace(EnergyPlusData &state, int const FurnaceNum, bool const FirstHVACIteration)
    5833              :     {
    5834              : 
    5835              :         // SUBROUTINE INFORMATION:
    5836              :         //       AUTHOR         Fred Buhl
    5837              :         //       DATE WRITTEN   January 2002
    5838              :         //       MODIFIED       Bereket Nigusse, May 2010, removed the autosize option for the input field supply air
    5839              :         //                                                 flow fraction through controlled zone.
    5840              :         //                      Bo Shen, March 2012, size the air flow rates at individual speed levels for VS WSHP
    5841              :         //                      Bo Shen, ORNL, July 2012 - added variable-speed air source heat pump cooling and heating coils, using curve-fits
    5842              : 
    5843              :         // PURPOSE OF THIS SUBROUTINE:
    5844              :         // This subroutine is for sizing Furnace Components for which nominal capacities
    5845              :         // and flow rates have not been specified in the input
    5846              : 
    5847              :         // METHODOLOGY EMPLOYED:
    5848              :         // Obtains heating capacities and flow rates from the zone or system sizing arrays.
    5849              :         // NOTE: In UNITARYSYSTEM:HEATPUMP:AIRTOAIR we are sizing the heating capacity to be
    5850              :         // equal to the cooling capacity.  Thus the cooling and
    5851              :         // and heating capacities of a DX heat pump system will be identical. In real life the ARI
    5852              :         // heating and cooling capacities are close but not identical.
    5853              : 
    5854              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    5855              :         int Iter;                 // iteration count
    5856              :         Real64 MulSpeedFlowScale; // variable speed air flow scaling factor
    5857              :         int IHPCoilIndex;         // refer to cooling or heating coil in IHP
    5858          359 :         Real64 dummy(0.0);
    5859              :         bool anyRan;
    5860          359 :         EMSManager::ManageEMS(state, EMSManager::EMSCallFrom::UnitarySystemSizing, anyRan, ObjexxFCL::Optional_int_const()); // calling point
    5861              : 
    5862          359 :         state.dataSize->DXCoolCap = 0.0;
    5863          359 :         state.dataSize->UnitaryHeatCap = 0.0;
    5864          359 :         state.dataSize->SuppHeatCap = 0.0;
    5865          359 :         auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    5866              : 
    5867          359 :         state.dataAirSystemsData->PrimaryAirSystems(state.dataSize->CurSysNum).supFanNum = thisFurnace.FanIndex;
    5868          359 :         state.dataAirSystemsData->PrimaryAirSystems(state.dataSize->CurSysNum).supFanType = thisFurnace.fanType;
    5869          359 :         state.dataSize->DataFanType = thisFurnace.fanType;
    5870          359 :         state.dataSize->DataFanIndex = thisFurnace.FanIndex;
    5871              : 
    5872          359 :         state.dataAirSystemsData->PrimaryAirSystems(state.dataSize->CurSysNum).supFanPlace = thisFurnace.fanPlace;
    5873              : 
    5874          359 :         if (thisFurnace.CoolingCoilType_Num == HVAC::CoilDX_CoolingSingleSpeed) {
    5875          206 :             DXCoils::SimDXCoil(state, BlankString, HVAC::CompressorOp::On, true, thisFurnace.CoolingCoilIndex, HVAC::FanOp::Cycling, 0.0);
    5876          153 :         } else if (thisFurnace.CoolingCoilType_Num == HVAC::CoilDX_CoolingHXAssisted) {
    5877            3 :             int HXCC_Index = thisFurnace.CoolingCoilIndex;
    5878            3 :             int childCCType_Num = state.dataHVACAssistedCC->HXAssistedCoil(HXCC_Index).CoolingCoilType_Num;
    5879            3 :             if (childCCType_Num == HVAC::CoilDX_Cooling) {
    5880            1 :                 int childCCIndex = state.dataHVACAssistedCC->HXAssistedCoil(HXCC_Index).CoolingCoilIndex;
    5881            1 :                 if (childCCIndex < 0) {
    5882            0 :                     ShowContinueError(state, "Occurs in sizing HeatExchangerAssistedCoolingCoil.");
    5883              :                 }
    5884            1 :                 auto &newCoil = state.dataCoilCoolingDX->coilCoolingDXs[childCCIndex];
    5885            1 :                 newCoil.size(state);
    5886              :             }
    5887            9 :             HVACHXAssistedCoolingCoil::SimHXAssistedCoolingCoil(
    5888            6 :                 state, BlankString, true, HVAC::CompressorOp::On, 0.0, thisFurnace.CoolingCoilIndex, HVAC::FanOp::Cycling, false, 1.0, false);
    5889          150 :         } else if (thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingWaterToAirHPSimple) {
    5890          111 :             WaterToAirHeatPumpSimple::SimWatertoAirHPSimple(state,
    5891              :                                                             BlankString,
    5892          111 :                                                             thisFurnace.CoolingCoilIndex,
    5893              :                                                             thisFurnace.CoolingCoilSensDemand,
    5894              :                                                             thisFurnace.CoolingCoilLatentDemand,
    5895              :                                                             HVAC::FanOp::Invalid, // Using invalid to mean off?
    5896              :                                                             HVAC::CompressorOp::Off,
    5897              :                                                             0.0,
    5898              :                                                             FirstHVACIteration); // CoolPartLoadRatio
    5899          111 :             if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingWaterToAirHPSimple) {
    5900          111 :                 WaterToAirHeatPumpSimple::SimWatertoAirHPSimple(state,
    5901              :                                                                 BlankString,
    5902          111 :                                                                 thisFurnace.HeatingCoilIndex,
    5903              :                                                                 thisFurnace.HeatingCoilSensDemand,
    5904              :                                                                 dummy,
    5905              :                                                                 HVAC::FanOp::Invalid, // using Invalid to mean off?
    5906              :                                                                 HVAC::CompressorOp::Off,
    5907              :                                                                 0.0,
    5908              :                                                                 FirstHVACIteration);
    5909              :             }
    5910           39 :         } else if (thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingWaterToAirHPVSEquationFit ||
    5911           25 :                    thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingAirToAirVariableSpeed) {
    5912           21 :             if (thisFurnace.bIsIHP) {
    5913            1 :                 IntegratedHeatPump::SizeIHP(state, thisFurnace.CoolingCoilIndex);
    5914            1 :                 IHPCoilIndex = state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).SCCoilIndex;
    5915            1 :                 thisFurnace.NumOfSpeedCooling = state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex).NumOfSpeeds;
    5916            1 :                 MulSpeedFlowScale = state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex).RatedAirVolFlowRate /
    5917            1 :                                     state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex)
    5918            1 :                                         .MSRatedAirVolFlowRate(state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex).NormSpedLevel);
    5919            1 :                 state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).CoolVolFlowScale = MulSpeedFlowScale;
    5920              :             } else {
    5921           20 :                 VariableSpeedCoils::SimVariableSpeedCoils(state,
    5922              :                                                           BlankString,
    5923           20 :                                                           thisFurnace.CoolingCoilIndex,
    5924              :                                                           HVAC::FanOp::Invalid, // USing Invalid for off?
    5925              :                                                           HVAC::CompressorOp::Off,
    5926              :                                                           0.0,
    5927              :                                                           1,
    5928              :                                                           0.0,
    5929              :                                                           0.0,
    5930              :                                                           0.0,
    5931              :                                                           0.0); // conduct the sizing operation in the VS WSHP
    5932           20 :                 thisFurnace.NumOfSpeedCooling = state.dataVariableSpeedCoils->VarSpeedCoil(thisFurnace.CoolingCoilIndex).NumOfSpeeds;
    5933           20 :                 MulSpeedFlowScale =
    5934           20 :                     state.dataVariableSpeedCoils->VarSpeedCoil(thisFurnace.CoolingCoilIndex).RatedAirVolFlowRate /
    5935           20 :                     state.dataVariableSpeedCoils->VarSpeedCoil(thisFurnace.CoolingCoilIndex)
    5936           20 :                         .MSRatedAirVolFlowRate(state.dataVariableSpeedCoils->VarSpeedCoil(thisFurnace.CoolingCoilIndex).NormSpedLevel);
    5937           20 :                 IHPCoilIndex = thisFurnace.CoolingCoilIndex;
    5938              :             }
    5939              : 
    5940          231 :             for (Iter = 1; Iter <= thisFurnace.NumOfSpeedCooling; ++Iter) {
    5941          420 :                 thisFurnace.CoolVolumeFlowRate(Iter) =
    5942          210 :                     state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex).MSRatedAirVolFlowRate(Iter) * MulSpeedFlowScale;
    5943          420 :                 thisFurnace.CoolMassFlowRate(Iter) =
    5944          210 :                     state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex).MSRatedAirMassFlowRate(Iter) * MulSpeedFlowScale;
    5945          210 :                 thisFurnace.MSCoolingSpeedRatio(Iter) =
    5946          210 :                     state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex).MSRatedAirVolFlowRate(Iter) /
    5947          210 :                     state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex).MSRatedAirVolFlowRate(thisFurnace.NumOfSpeedCooling);
    5948              :             }
    5949              : 
    5950           21 :             if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingWaterToAirHPVSEquationFit ||
    5951            7 :                 thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingAirToAirVariableSpeed) {
    5952              : 
    5953           17 :                 if (thisFurnace.bIsIHP) {
    5954            1 :                     IntegratedHeatPump::SizeIHP(state, thisFurnace.CoolingCoilIndex);
    5955            1 :                     IHPCoilIndex = state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).SHCoilIndex;
    5956            1 :                     thisFurnace.NumOfSpeedHeating = state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex).NumOfSpeeds;
    5957            1 :                     MulSpeedFlowScale = state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex).RatedAirVolFlowRate /
    5958            1 :                                         state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex)
    5959            1 :                                             .MSRatedAirVolFlowRate(state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex).NormSpedLevel);
    5960            1 :                     state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).HeatVolFlowScale = MulSpeedFlowScale;
    5961              :                 } else {
    5962           16 :                     VariableSpeedCoils::SimVariableSpeedCoils(state,
    5963              :                                                               BlankString,
    5964           16 :                                                               thisFurnace.HeatingCoilIndex,
    5965              :                                                               HVAC::FanOp::Invalid, // Invalid for off?
    5966              :                                                               HVAC::CompressorOp::Off,
    5967              :                                                               0.0,
    5968              :                                                               1,
    5969              :                                                               0.0,
    5970              :                                                               0.0,
    5971              :                                                               0.0,
    5972              :                                                               0.0); // conduct the sizing operation in the VS WSHP
    5973           16 :                     thisFurnace.NumOfSpeedHeating = state.dataVariableSpeedCoils->VarSpeedCoil(thisFurnace.HeatingCoilIndex).NumOfSpeeds;
    5974           16 :                     MulSpeedFlowScale =
    5975           16 :                         state.dataVariableSpeedCoils->VarSpeedCoil(thisFurnace.HeatingCoilIndex).RatedAirVolFlowRate /
    5976           16 :                         state.dataVariableSpeedCoils->VarSpeedCoil(thisFurnace.HeatingCoilIndex)
    5977           16 :                             .MSRatedAirVolFlowRate(state.dataVariableSpeedCoils->VarSpeedCoil(thisFurnace.HeatingCoilIndex).NormSpedLevel);
    5978           16 :                     IHPCoilIndex = thisFurnace.HeatingCoilIndex;
    5979              :                 }
    5980              : 
    5981          187 :                 for (Iter = 1; Iter <= thisFurnace.NumOfSpeedHeating; ++Iter) {
    5982          340 :                     thisFurnace.HeatVolumeFlowRate(Iter) =
    5983          170 :                         state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex).MSRatedAirVolFlowRate(Iter) * MulSpeedFlowScale;
    5984          340 :                     thisFurnace.HeatMassFlowRate(Iter) =
    5985          170 :                         state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex).MSRatedAirMassFlowRate(Iter) * MulSpeedFlowScale;
    5986          170 :                     thisFurnace.MSHeatingSpeedRatio(Iter) =
    5987          170 :                         state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex).MSRatedAirVolFlowRate(Iter) /
    5988          170 :                         state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex).MSRatedAirVolFlowRate(thisFurnace.NumOfSpeedHeating);
    5989              :                 }
    5990              :             }
    5991              : 
    5992           21 :             if (thisFurnace.NumOfSpeedHeating > 0) {
    5993           17 :                 thisFurnace.IdleMassFlowRate = min(thisFurnace.HeatMassFlowRate(1), thisFurnace.CoolMassFlowRate(1));
    5994           17 :                 thisFurnace.IdleSpeedRatio = min(thisFurnace.MSHeatingSpeedRatio(1), thisFurnace.MSCoolingSpeedRatio(1));
    5995           17 :                 thisFurnace.IdleVolumeAirRate = min(thisFurnace.HeatVolumeFlowRate(1), thisFurnace.CoolVolumeFlowRate(1));
    5996              :             } else {
    5997            4 :                 thisFurnace.IdleMassFlowRate = thisFurnace.CoolMassFlowRate(1);
    5998            4 :                 thisFurnace.IdleSpeedRatio = thisFurnace.MSCoolingSpeedRatio(1);
    5999            4 :                 thisFurnace.IdleVolumeAirRate = thisFurnace.CoolVolumeFlowRate(1);
    6000              :             }
    6001              : 
    6002           21 :             if (thisFurnace.fanOp == HVAC::FanOp::Continuous) {
    6003            0 :                 thisFurnace.MaxNoCoolHeatAirVolFlow = thisFurnace.IdleVolumeAirRate;
    6004            0 :                 thisFurnace.MaxNoCoolHeatAirMassFlow = thisFurnace.IdleMassFlowRate;
    6005            0 :                 thisFurnace.NoHeatCoolSpeedRatio = thisFurnace.IdleSpeedRatio;
    6006              :             }
    6007              :         }
    6008              : 
    6009          359 :         if (thisFurnace.DesignFanVolFlowRate == DataSizing::AutoSize) {
    6010              : 
    6011          266 :             if (state.dataSize->CurSysNum > 0) {
    6012              : 
    6013          266 :                 CheckSysSizing(state, HVAC::unitarySysTypeNames[(int)thisFurnace.type], thisFurnace.Name);
    6014          266 :                 if (state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesMainVolFlow >= HVAC::SmallAirVolFlow) {
    6015          266 :                     thisFurnace.DesignFanVolFlowRate = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesMainVolFlow;
    6016              :                 } else {
    6017            0 :                     thisFurnace.DesignFanVolFlowRate = 0.0;
    6018              :                 }
    6019              : 
    6020          266 :                 if (thisFurnace.DesignFanVolFlowRateEMSOverrideOn) {
    6021            0 :                     thisFurnace.DesignFanVolFlowRate = thisFurnace.DesignFanVolFlowRateEMSOverrideValue;
    6022              :                 }
    6023              : 
    6024          532 :                 BaseSizer::reportSizerOutput(state,
    6025          266 :                                              HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    6026              :                                              thisFurnace.Name,
    6027              :                                              "Supply Air Flow Rate [m3/s]",
    6028              :                                              thisFurnace.DesignFanVolFlowRate);
    6029              :             }
    6030              :         }
    6031              : 
    6032          359 :         if (thisFurnace.MaxHeatAirVolFlow == DataSizing::AutoSize) {
    6033              : 
    6034          266 :             if (state.dataSize->CurSysNum > 0) {
    6035              : 
    6036          266 :                 CheckSysSizing(state, HVAC::unitarySysTypeNames[(int)thisFurnace.type], thisFurnace.Name);
    6037          266 :                 if (state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesMainVolFlow >= HVAC::SmallAirVolFlow) {
    6038          266 :                     thisFurnace.MaxHeatAirVolFlow = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesMainVolFlow;
    6039              :                 } else {
    6040            0 :                     thisFurnace.MaxHeatAirVolFlow = 0.0;
    6041              :                 }
    6042              : 
    6043          266 :                 if (thisFurnace.MaxHeatAirVolFlowEMSOverrideOn) {
    6044            0 :                     thisFurnace.MaxHeatAirVolFlow = thisFurnace.MaxHeatAirVolFlowEMSOverrideValue;
    6045              :                 }
    6046          532 :                 BaseSizer::reportSizerOutput(state,
    6047          266 :                                              HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    6048              :                                              thisFurnace.Name,
    6049              :                                              "Supply Air Flow Rate During Heating Operation [m3/s]",
    6050              :                                              thisFurnace.MaxHeatAirVolFlow);
    6051              :             }
    6052              :         }
    6053              : 
    6054          359 :         if (thisFurnace.MaxCoolAirVolFlow == DataSizing::AutoSize) {
    6055              : 
    6056          266 :             if (state.dataSize->CurSysNum > 0) {
    6057              : 
    6058          266 :                 CheckSysSizing(state, HVAC::unitarySysTypeNames[(int)thisFurnace.type], thisFurnace.Name);
    6059          266 :                 if (state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesMainVolFlow >= HVAC::SmallAirVolFlow) {
    6060          266 :                     thisFurnace.MaxCoolAirVolFlow = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesMainVolFlow;
    6061              :                 } else {
    6062            0 :                     thisFurnace.MaxCoolAirVolFlow = 0.0;
    6063              :                 }
    6064              : 
    6065          266 :                 if (thisFurnace.MaxCoolAirVolFlowEMSOverrideOn) {
    6066            0 :                     thisFurnace.MaxCoolAirVolFlow = thisFurnace.MaxCoolAirVolFlowEMSOverrideValue;
    6067              :                 }
    6068              : 
    6069          532 :                 BaseSizer::reportSizerOutput(state,
    6070          266 :                                              HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    6071              :                                              thisFurnace.Name,
    6072              :                                              "Supply Air Flow Rate During Cooling Operation [m3/s]",
    6073              :                                              thisFurnace.MaxCoolAirVolFlow);
    6074              :             }
    6075              :         }
    6076              : 
    6077          359 :         if (thisFurnace.MaxNoCoolHeatAirVolFlow == DataSizing::AutoSize) {
    6078              : 
    6079          261 :             if (state.dataSize->CurSysNum > 0) {
    6080              : 
    6081          261 :                 CheckSysSizing(state, HVAC::unitarySysTypeNames[(int)thisFurnace.type], thisFurnace.Name);
    6082          261 :                 if (state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesMainVolFlow >= HVAC::SmallAirVolFlow) {
    6083          261 :                     thisFurnace.MaxNoCoolHeatAirVolFlow = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesMainVolFlow;
    6084              :                 } else {
    6085            0 :                     thisFurnace.MaxNoCoolHeatAirVolFlow = 0.0;
    6086              :                 }
    6087              : 
    6088          261 :                 if (thisFurnace.MaxNoCoolHeatAirVolFlowEMSOverrideOn) {
    6089            0 :                     thisFurnace.MaxNoCoolHeatAirVolFlow = thisFurnace.MaxNoCoolHeatAirVolFlowEMSOverrideValue;
    6090              :                 }
    6091              : 
    6092          522 :                 BaseSizer::reportSizerOutput(state,
    6093          261 :                                              HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    6094              :                                              thisFurnace.Name,
    6095              :                                              "Supply Air Flow Rate When No Cooling or Heating is Needed [m3/s]",
    6096              :                                              thisFurnace.MaxNoCoolHeatAirVolFlow);
    6097              :             }
    6098              :         }
    6099              : 
    6100          359 :         if (thisFurnace.DesignHeatingCapacity == DataSizing::AutoSize) {
    6101              : 
    6102          266 :             if (state.dataSize->CurSysNum > 0) {
    6103              : 
    6104          266 :                 if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_AirToAir ||
    6105          252 :                     thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir) {
    6106              : 
    6107          110 :                     CheckSysSizing(state, HVAC::unitarySysTypeNames[(int)thisFurnace.type], thisFurnace.Name);
    6108              : 
    6109          110 :                     if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingWaterToAirHPSimple) {
    6110           96 :                         thisFurnace.DesignHeatingCapacity =
    6111           96 :                             state.dataWaterToAirHeatPumpSimple->SimpleWatertoAirHP(thisFurnace.HeatingCoilIndex).RatedCapHeat;
    6112              :                     } else {
    6113           14 :                         thisFurnace.DesignHeatingCapacity = state.dataSize->DXCoolCap;
    6114              :                     }
    6115              : 
    6116              :                 } else {
    6117              : 
    6118          156 :                     CheckSysSizing(state, HVAC::unitarySysTypeNames[(int)thisFurnace.type], thisFurnace.Name);
    6119              : 
    6120          156 :                     thisFurnace.DesignHeatingCapacity = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).HeatCap;
    6121              :                 }
    6122              : 
    6123          266 :                 if (thisFurnace.DesignHeatingCapacity < HVAC::SmallLoad) {
    6124            0 :                     thisFurnace.DesignHeatingCapacity = 0.0;
    6125              :                 }
    6126              : 
    6127          532 :                 BaseSizer::reportSizerOutput(state,
    6128          266 :                                              HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    6129              :                                              thisFurnace.Name,
    6130              :                                              "Nominal Heating Capacity [W]",
    6131              :                                              thisFurnace.DesignHeatingCapacity);
    6132              :             }
    6133              :         }
    6134              : 
    6135          359 :         if (thisFurnace.DesignCoolingCapacity == DataSizing::AutoSize) {
    6136              : 
    6137          266 :             if (state.dataSize->CurSysNum > 0) {
    6138              : 
    6139          266 :                 CheckSysSizing(state, HVAC::unitarySysTypeNames[(int)thisFurnace.type], thisFurnace.Name);
    6140          266 :                 if (state.dataSize->DXCoolCap >= HVAC::SmallLoad) {
    6141          266 :                     thisFurnace.DesignCoolingCapacity = state.dataSize->DXCoolCap;
    6142              :                 } else {
    6143            0 :                     thisFurnace.DesignCoolingCapacity = 0.0;
    6144              :                 }
    6145          532 :                 BaseSizer::reportSizerOutput(state,
    6146          266 :                                              HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    6147              :                                              thisFurnace.Name,
    6148              :                                              "Nominal Cooling Capacity [W]",
    6149              :                                              thisFurnace.DesignCoolingCapacity);
    6150              :             }
    6151              :         }
    6152              : 
    6153          359 :         if (thisFurnace.DesignMaxOutletTemp == DataSizing::AutoSize) {
    6154              : 
    6155           83 :             if (state.dataSize->CurSysNum > 0) {
    6156              : 
    6157           83 :                 CheckSysSizing(state, HVAC::unitarySysTypeNames[(int)thisFurnace.type], thisFurnace.Name);
    6158           83 :                 thisFurnace.DesignMaxOutletTemp = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).HeatSupTemp;
    6159          166 :                 BaseSizer::reportSizerOutput(state,
    6160           83 :                                              HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    6161              :                                              thisFurnace.Name,
    6162              :                                              "Maximum Supply Air Temperature from Supplemental Heater [C]",
    6163              :                                              thisFurnace.DesignMaxOutletTemp);
    6164              :             }
    6165              :         }
    6166              : 
    6167          359 :         if (thisFurnace.DesignSuppHeatingCapacity == DataSizing::AutoSize) {
    6168              : 
    6169          110 :             if (state.dataSize->CurSysNum > 0) {
    6170              : 
    6171          110 :                 CheckSysSizing(state, HVAC::unitarySysTypeNames[(int)thisFurnace.type], thisFurnace.Name);
    6172          110 :                 if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_AirToAir ||
    6173           96 :                     thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir) {
    6174              :                     // set the supplemental heating capacity to the actual heating load
    6175          110 :                     thisFurnace.DesignSuppHeatingCapacity = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).HeatCap;
    6176              :                     // if reheat needed for humidity control, make sure supplemental heating is at least as big
    6177              :                     // as the cooling capacity
    6178          110 :                     if (thisFurnace.Humidistat && thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat) {
    6179            0 :                         thisFurnace.DesignSuppHeatingCapacity = max(thisFurnace.DesignSuppHeatingCapacity, thisFurnace.DesignCoolingCapacity);
    6180            0 :                         if (thisFurnace.DesignSuppHeatingCapacity < HVAC::SmallLoad) {
    6181            0 :                             thisFurnace.DesignSuppHeatingCapacity = 0.0;
    6182              :                         }
    6183              :                     }
    6184              : 
    6185              :                 } else {
    6186              : 
    6187            0 :                     if (thisFurnace.Humidistat && thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat) {
    6188            0 :                         thisFurnace.DesignSuppHeatingCapacity = thisFurnace.DesignCoolingCapacity;
    6189              :                     } else {
    6190            0 :                         thisFurnace.DesignSuppHeatingCapacity = 0.0;
    6191              :                     }
    6192              :                 }
    6193              : 
    6194          220 :                 BaseSizer::reportSizerOutput(state,
    6195          110 :                                              HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    6196              :                                              thisFurnace.Name,
    6197              :                                              "Supplemental Heating Coil Nominal Capacity [W]",
    6198              :                                              thisFurnace.DesignSuppHeatingCapacity);
    6199              :             }
    6200              :         }
    6201              : 
    6202          359 :         state.dataSize->UnitaryHeatCap = thisFurnace.DesignHeatingCapacity;
    6203          359 :         state.dataSize->SuppHeatCap = thisFurnace.DesignSuppHeatingCapacity;
    6204          359 :     }
    6205              : 
    6206              :     // End Initialization Section of the Module
    6207              :     //******************************************************************************
    6208              : 
    6209              :     // Beginning of Update subroutines for the Furnace Module
    6210              :     // *****************************************************************************
    6211              : 
    6212        24444 :     void CalcNewZoneHeatOnlyFlowRates(EnergyPlusData &state,
    6213              :                                       int const FurnaceNum,          // Index to furnace
    6214              :                                       bool const FirstHVACIteration, // Iteration flag
    6215              :                                       Real64 const ZoneLoad,         // load to be met by furnace (W)
    6216              :                                       Real64 &HeatCoilLoad,          // actual load passed to heating coil (W)
    6217              :                                       Real64 &OnOffAirFlowRatio      // ratio of coil on to coil off air flow rate
    6218              :     )
    6219              :     {
    6220              :         // SUBROUTINE INFORMATION:
    6221              :         //       AUTHOR         Richard Liesen
    6222              :         //       DATE WRITTEN   Feb 2001
    6223              :         //       MODIFIED       Don Shirey and R. Raustad, Mar 2001 & Mar 2003
    6224              : 
    6225              :         // PURPOSE OF THIS SUBROUTINE:
    6226              :         // This subroutine updates the coil outlet nodes by simulating a heat-only
    6227              :         // furnace or unitary system.
    6228              : 
    6229              :         // METHODOLOGY EMPLOYED:
    6230              :         // Determine the operating PLR to meet the zone sensible load.
    6231              : 
    6232              :         // SUBROUTINE PARAMETER DEFINITIONS:
    6233        24444 :         int constexpr MaxIter(15);    // maximum number of iterations
    6234        24444 :         Real64 constexpr MinPLR(0.0); // minimum part load ratio allowed
    6235              : 
    6236              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    6237        24444 :         Real64 Error(1.0);
    6238              :         Real64 SystemSensibleLoad;   // Sensible load to be met by furnace (W)
    6239              :         Real64 FullSensibleOutput;   // Full sensible output of furnace (W)
    6240              :         Real64 FullLatentOutput;     // Full latent output of furnace = 0 (W)
    6241              :         Real64 NoSensibleOutput;     // Sensible output of furnace with no heating allowed (W)
    6242              :         Real64 NoLatentOutput;       // Latent output of furnace = 0 (W)
    6243              :         Real64 PartLoadRatio;        // Part load ratio of furnace
    6244              :         Real64 HeatErrorToler;       // Error tolerance in heating mode
    6245              :         Real64 IterRelax;            // Relaxation factor for iterations
    6246              :         Real64 ActualSensibleOutput; // Actual furnace sensible capacity
    6247              :         Real64 ActualLatentOutput;   // Actual furnace latent capacity = 0
    6248              :         Real64 deltaT;               // Heater outlet temp minus design heater outlet temp
    6249              : 
    6250        24444 :         auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    6251              :         // Retrieve the load on the controlled zone
    6252        24444 :         auto &furnaceInNode = state.dataLoopNodes->Node(thisFurnace.FurnaceInletNodeNum);
    6253        24444 :         auto const &furnaceOutNode = state.dataLoopNodes->Node(thisFurnace.FurnaceOutletNodeNum);
    6254        24444 :         int ControlZoneNode = thisFurnace.NodeNumOfControlledZone;
    6255        24444 :         HVAC::FanOp fanOp = thisFurnace.fanOp; // fan operating mode
    6256        24444 :         thisFurnace.MdotFurnace = thisFurnace.DesignMassFlowRate;
    6257        24444 :         thisFurnace.CoolPartLoadRatio = 0.0;
    6258              : 
    6259              :         // Calculate the Cp Air of zone
    6260        24444 :         Real64 cpair = Psychrometrics::PsyCpAirFnW(state.dataLoopNodes->Node(ControlZoneNode).HumRat);
    6261              : 
    6262        24444 :         if (FirstHVACIteration) {
    6263        10592 :             HeatCoilLoad = ZoneLoad;
    6264        10592 :             state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
    6265              :         } else {
    6266              :             // If Furnace runs then set HeatCoilLoad on Heating Coil and the Mass Flow
    6267        13852 :             if ((thisFurnace.availSched->getCurrentVal() > 0.0) && (furnaceInNode.MassFlowRate > 0.0) && (state.dataFurnaces->HeatingLoad)) {
    6268              : 
    6269         5599 :                 furnaceInNode.MassFlowRate = thisFurnace.MdotFurnace;
    6270         5599 :                 HeatCoilLoad = thisFurnace.DesignHeatingCapacity;
    6271         5599 :                 SystemSensibleLoad = ZoneLoad;
    6272              : 
    6273              :                 // Get no load result
    6274         5599 :                 if (fanOp == HVAC::FanOp::Cycling) {
    6275         5599 :                     furnaceInNode.MassFlowRate = 0.0;
    6276              :                 }
    6277         5599 :                 if (fanOp == HVAC::FanOp::Continuous) {
    6278            0 :                     state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0; // The on/off fan will not cycle, so set part-load fraction = 1
    6279              :                 }
    6280              : 
    6281              :                 //     Set the inlet mass flow rate based on user specified coil OFF flow rate
    6282         5599 :                 PartLoadRatio = 0.0;
    6283         5599 :                 SetAverageAirFlow(state, FurnaceNum, PartLoadRatio, OnOffAirFlowRatio);
    6284              : 
    6285         5599 :                 CalcFurnaceOutput(state,
    6286              :                                   FurnaceNum,
    6287              :                                   FirstHVACIteration,
    6288              :                                   fanOp,
    6289              :                                   HVAC::CompressorOp::On,
    6290              :                                   0.0,
    6291              :                                   0.0,
    6292              :                                   0.0,
    6293              :                                   0.0,
    6294              :                                   NoSensibleOutput,
    6295              :                                   NoLatentOutput,
    6296              :                                   OnOffAirFlowRatio,
    6297              :                                   false);
    6298              : 
    6299         5599 :                 furnaceInNode.MassFlowRate = thisFurnace.MdotFurnace;
    6300              : 
    6301              :                 // Set fan part-load fraction equal to 1 while getting full load result
    6302         5599 :                 state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
    6303         5599 :                 OnOffAirFlowRatio = 1.0;
    6304              : 
    6305              :                 // Get full load result
    6306         5599 :                 CalcFurnaceOutput(state,
    6307              :                                   FurnaceNum,
    6308              :                                   FirstHVACIteration,
    6309              :                                   fanOp,
    6310              :                                   HVAC::CompressorOp::On,
    6311              :                                   0.0,
    6312              :                                   1.0,
    6313              :                                   HeatCoilLoad,
    6314              :                                   0.0,
    6315              :                                   FullSensibleOutput,
    6316              :                                   FullLatentOutput,
    6317              :                                   OnOffAirFlowRatio,
    6318              :                                   false);
    6319              : 
    6320              :                 // Since we are heating, we expect FullSensibleOutput to be > 0 and FullSensibleOutput > NoSensibleOutput
    6321              :                 // Check that this is the case; if not set PartLoadRatio = 0.0d0 (off) and return
    6322              : 
    6323         5599 :                 if (FullSensibleOutput > NoSensibleOutput) {
    6324              :                     PartLoadRatio =
    6325         5599 :                         max(MinPLR, min(1.0, std::abs(SystemSensibleLoad - NoSensibleOutput) / std::abs(FullSensibleOutput - NoSensibleOutput)));
    6326         5599 :                     if (fanOp == HVAC::FanOp::Cycling) {
    6327         5599 :                         furnaceInNode.MassFlowRate = thisFurnace.MdotFurnace * PartLoadRatio;
    6328         5599 :                         HeatCoilLoad = thisFurnace.DesignHeatingCapacity * PartLoadRatio;
    6329              :                     } else { // FanOp::Continuous
    6330            0 :                         if (furnaceOutNode.Temp > thisFurnace.DesignMaxOutletTemp) {
    6331            0 :                             deltaT = furnaceOutNode.Temp - thisFurnace.DesignMaxOutletTemp;
    6332            0 :                             if (HeatCoilLoad > thisFurnace.DesignHeatingCapacity) {
    6333            0 :                                 HeatCoilLoad = thisFurnace.DesignHeatingCapacity;
    6334              :                             }
    6335            0 :                             HeatCoilLoad -= furnaceInNode.MassFlowRate * cpair * deltaT;
    6336              :                         } else {
    6337            0 :                             HeatCoilLoad = SystemSensibleLoad - NoSensibleOutput;
    6338              :                         }
    6339              :                     }
    6340              : 
    6341              :                     // Calculate the part load ratio through iteration
    6342         5599 :                     HeatErrorToler = thisFurnace.HeatingConvergenceTolerance; // Error tolerance for convergence from input deck
    6343         5599 :                     Error = 1.0;                                              // initialize error value for comparison against tolerance
    6344         5599 :                     state.dataFurnaces->Iter = 0;                             // initialize iteration counter
    6345         5599 :                     IterRelax = 0.9;                                          // relaxation factor for iterations
    6346         6589 :                     while (state.dataFurnaces->Iter <= MaxIter) {
    6347              : 
    6348         6589 :                         if (fanOp == HVAC::FanOp::Cycling) {
    6349         6589 :                             furnaceInNode.MassFlowRate = thisFurnace.MdotFurnace * PartLoadRatio;
    6350              :                         }
    6351         6589 :                         CalcFurnaceOutput(state,
    6352              :                                           FurnaceNum,
    6353              :                                           FirstHVACIteration,
    6354              :                                           fanOp,
    6355              :                                           HVAC::CompressorOp::On,
    6356              :                                           0.0,
    6357              :                                           PartLoadRatio,
    6358              :                                           HeatCoilLoad,
    6359              :                                           0.0,
    6360              :                                           ActualSensibleOutput,
    6361              :                                           ActualLatentOutput,
    6362              :                                           OnOffAirFlowRatio,
    6363              :                                           false);
    6364              : 
    6365         6589 :                         if (SystemSensibleLoad != 0.0) {
    6366         6589 :                             Error = (SystemSensibleLoad - ActualSensibleOutput) / (SystemSensibleLoad);
    6367              :                         }
    6368         6589 :                         if (std::abs(Error) <= HeatErrorToler) {
    6369         5137 :                             break;
    6370              :                         }
    6371         1452 :                         PartLoadRatio = max(
    6372              :                             MinPLR,
    6373              :                             min(1.0,
    6374         1452 :                                 PartLoadRatio + IterRelax * (SystemSensibleLoad - ActualSensibleOutput) / (FullSensibleOutput - NoSensibleOutput)));
    6375              : 
    6376              :                         // limit the heating coil outlet air temperature to DesignMaxOutletTemp
    6377         1452 :                         if (furnaceOutNode.Temp > thisFurnace.DesignMaxOutletTemp) {
    6378            0 :                             deltaT = furnaceOutNode.Temp - thisFurnace.DesignMaxOutletTemp;
    6379            0 :                             if (HeatCoilLoad > thisFurnace.DesignHeatingCapacity) {
    6380            0 :                                 HeatCoilLoad = thisFurnace.DesignHeatingCapacity;
    6381              :                             }
    6382            0 :                             HeatCoilLoad -= furnaceInNode.MassFlowRate * cpair * deltaT;
    6383            0 :                             CalcFurnaceOutput(state,
    6384              :                                               FurnaceNum,
    6385              :                                               FirstHVACIteration,
    6386              :                                               fanOp,
    6387              :                                               HVAC::CompressorOp::On,
    6388              :                                               0.0,
    6389              :                                               PartLoadRatio,
    6390              :                                               HeatCoilLoad,
    6391              :                                               0.0,
    6392              :                                               ActualSensibleOutput,
    6393              :                                               ActualLatentOutput,
    6394              :                                               OnOffAirFlowRatio,
    6395              :                                               false);
    6396              : 
    6397            0 :                             if (SystemSensibleLoad != 0.0) {
    6398            0 :                                 Error = (SystemSensibleLoad - ActualSensibleOutput) / (SystemSensibleLoad);
    6399              :                             }
    6400            0 :                             PartLoadRatio = max(MinPLR,
    6401              :                                                 min(1.0,
    6402            0 :                                                     PartLoadRatio + IterRelax * (SystemSensibleLoad - ActualSensibleOutput) /
    6403            0 :                                                                         (FullSensibleOutput - NoSensibleOutput)));
    6404              :                         } else {
    6405         1452 :                             HeatCoilLoad = thisFurnace.DesignHeatingCapacity * PartLoadRatio;
    6406              :                         }
    6407              : 
    6408         1452 :                         if (PartLoadRatio == MinPLR) {
    6409            0 :                             break;
    6410              :                         }
    6411         1452 :                         if (PartLoadRatio == 1.0) {
    6412          462 :                             break;
    6413              :                         }
    6414          990 :                         ++state.dataFurnaces->Iter;
    6415          990 :                         if (state.dataFurnaces->Iter == 7) {
    6416            0 :                             IterRelax = 0.7;
    6417              :                         }
    6418          990 :                         if (state.dataFurnaces->Iter == 15) {
    6419            0 :                             IterRelax = 0.4;
    6420              :                         }
    6421              :                     }
    6422              : 
    6423         5599 :                     if (state.dataFurnaces->Iter > MaxIter) {
    6424            0 :                         if (thisFurnace.HeatingMaxIterIndex2 == 0) {
    6425            0 :                             ShowWarningMessage(state,
    6426            0 :                                                format("{} \"{}\" -- Exceeded max heating iterations ({}) while adjusting furnace runtime.",
    6427            0 :                                                       HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    6428            0 :                                                       thisFurnace.Name,
    6429              :                                                       MaxIter));
    6430            0 :                             ShowContinueErrorTimeStamp(state, "");
    6431              :                         }
    6432            0 :                         ShowRecurringWarningErrorAtEnd(state,
    6433            0 :                                                        format("{} \"{}\" -- Exceeded max heating iterations error continues...",
    6434            0 :                                                               HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    6435            0 :                                                               thisFurnace.Name),
    6436            0 :                                                        thisFurnace.HeatingMaxIterIndex2);
    6437              :                     }
    6438              : 
    6439              :                 } else { // ELSE from IF(FullSensibleOutput.GT.NoSensibleOutput)THEN above
    6440              :                     // Set part load ratio to 1 and run heater at design heating capacity
    6441            0 :                     PartLoadRatio = 1.0;
    6442            0 :                     HeatCoilLoad = thisFurnace.DesignHeatingCapacity;
    6443              :                 }
    6444              :                 // Set the final results
    6445              :                 //      IF (fanOp .EQ. FanOp::Cycling) THEN
    6446              :                 //        Furnace(FurnaceNum)%MdotFurnace = Furnace(FurnaceNum)%MdotFurnace * PartLoadRatio
    6447              :                 //      END IF
    6448         5599 :                 thisFurnace.MdotFurnace = furnaceInNode.MassFlowRate;
    6449              : 
    6450         8253 :             } else if ((thisFurnace.availSched->getCurrentVal() > 0.0) && (furnaceInNode.MassFlowRate > 0.0) && (fanOp == HVAC::FanOp::Continuous)) {
    6451            0 :                 HeatCoilLoad = 0.0;
    6452              :             } else { // no heating and no flow
    6453         8253 :                 thisFurnace.MdotFurnace = 0.0;
    6454         8253 :                 HeatCoilLoad = 0.0;
    6455              :             } // End of the Scheduled Furnace If block
    6456              : 
    6457              :         } // End of the FirstHVACIteration control of the mass flow If block
    6458              : 
    6459              :         // Set the fan inlet node flow rates
    6460        24444 :         furnaceInNode.MassFlowRateMaxAvail = thisFurnace.MdotFurnace;
    6461        24444 :         furnaceInNode.MassFlowRate = thisFurnace.MdotFurnace;
    6462        24444 :     }
    6463              : 
    6464      4573491 :     void CalcNewZoneHeatCoolFlowRates(EnergyPlusData &state,
    6465              :                                       int const FurnaceNum,
    6466              :                                       bool const FirstHVACIteration,
    6467              :                                       HVAC::CompressorOp const compressorOp, // compressor operation flag (1=On, 0=Off)
    6468              :                                       Real64 const ZoneLoad,                 // the control zone load (watts)
    6469              :                                       Real64 const MoistureLoad,             // the control zone latent load (watts)
    6470              :                                       Real64 &HeatCoilLoad,                  // Heating load to be met by heating coil ( excluding heat pump DX coil)
    6471              :                                       Real64 &ReheatCoilLoad,    // Heating load to be met by reheat coil using hstat (excluding HP DX coil)
    6472              :                                       Real64 &OnOffAirFlowRatio, // Ratio of compressor ON air flow to AVERAGE air flow over time step
    6473              :                                       bool &HXUnitOn             // flag to control HX based on zone moisture load
    6474              :     )
    6475              :     {
    6476              :         // SUBROUTINE INFORMATION:
    6477              :         //       AUTHOR         Richard Liesen
    6478              :         //       DATE WRITTEN   Feb 2001
    6479              :         //       MODIFIED       R. Raustad and D. Shirey, Feb/Mar/Sept/Oct/Dec 2001, Jan/Oct 2002
    6480              :         //       RE-ENGINEERED  R. Raustad, Feb. 2005 (added RegulaFalsi for iteration technique)
    6481              : 
    6482              :         // PURPOSE OF THIS SUBROUTINE:
    6483              :         // This subroutine updates the coil outlet nodes.
    6484              : 
    6485              :         // METHODOLOGY EMPLOYED:
    6486              :         // Determine the operating PLR to meet the zone sensible load. If a humidistat is specified, determine
    6487              :         // the operating PLR (greater of the sensible and latent PLR) to meet the zone SENSIBLE load
    6488              :         // (Multimode dehumidification control) or zone LATENT load (CoolReheat dehumidification control).
    6489              :         // For dehumidification control type COOLREHEAT, both a sensible and latent PLR may exist for a
    6490              :         // single time step (heating and dehumidification can occur). For all other system types,
    6491              :         // only a single PLR is allowed for any given time step.
    6492              :         // Order of simulation depends on dehumidification control option as described below.
    6493              :         // Dehumidification control options:
    6494              :         // Dehumidification Control NONE:   Cooling performance is simulated first and then heating performance. If a HX
    6495              :         //                                  assisted cooling coil is selected, the HX is always active.
    6496              :         // Dehumidification Control COOLREHEAT: Continuous Fan Operation:
    6497              :         //                                      For cooling operation, the sensible and latent capacities are calculated to
    6498              :         //                                      meet the thermostat setpoint. If a HX assisted cooling coil is selected,
    6499              :         //                                      the HX is always active. If the latent load is not met by operating the
    6500              :         //                                      system at the sensible PLR, a new PLR is calculated to meet the humidistat
    6501              :         //                                      setpoint. The reheat coil load is then calculated to meet the HEATING
    6502              :         //                                      setpoint temperature.
    6503              :         //                                      Cycling Fan Operation:
    6504              :         //                                      The heating part-load ratio is calculated first. Since the fan will be
    6505              :         //                                      controlled at the higher of the heating or cooling PLR's, a ratio of the
    6506              :         //                                      cooling to heating PLR is used to pass to the cooling coil (MAX=1). This allows
    6507              :         //                                      the cooling coil to operate at the heating PLR when the heating PLR is
    6508              :         //                                      higher than the cooling PLR. The sensible and latent capacities are then
    6509              :         //                                      calculated to meet the thermostat setpoint.
    6510              :         //                                      If a HX assisted cooling coil is selected, the HX is always active.
    6511              :         //                                      If the latent load is not met by operating the system at the sensible PLR,
    6512              :         //                                      a new PLR is calculated to meet the humidistat setpoint.
    6513              :         //                                      The reheat coil load is then calculated to meet the HEATING setpoint temperature.
    6514              :         // Dehumidification Control MULTIMODE: For cooling operation, the sensible and latent capacities are calculated to
    6515              :         //                                     meet the thermostat setpoint. If a HX assisted cooling coil is selected,
    6516              :         //                                     the HX is off for this calculation. If the latent load is not met by operating
    6517              :         //                                     the system at the sensible PLR, a new PLR is calculated with the HX operating
    6518              :         //                                     and the target is the thermostat setpoint. Humidity is not controlled in this
    6519              :         //                                     mode. No reheat coil is used in this configuration.
    6520              :         //  Note: A supplemental heater augments the heating capacity for air-to-air heat pumps.
    6521              :         //        A reheat coil is used for the HeatCool furnace/unitarysystem to offset the sensible cooling when the
    6522              :         //        dehumidification control type is COOLREHEAT. Both the supplemental and reheat heating coil load is calculated
    6523              :         //        in the Calc routines. The actual simulation of these coils is performed in the SimFurnace routine (i.e. the
    6524              :         //        supplemental and reheat coil loads are passed as 0 to CalcFurnaceOutput).
    6525              : 
    6526              :         // SUBROUTINE PARAMETER DEFINITIONS:
    6527      4573491 :         int constexpr MaxIter(100);   // maximum number of iterations
    6528      4573491 :         Real64 constexpr MinPLR(0.0); // minimum part load ratio allowed
    6529              : 
    6530              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    6531              :         Real64 SystemMoistureLoad;   // Total latent load to be removed by furnace/unitary system
    6532              :         Real64 deltaT;               // Temperature rise across heating coil (C)
    6533              :         Real64 TempOutHeatingCoil;   // Temperature leaving heating coil (C)
    6534              :         Real64 FullSensibleOutput;   // Full sensible output of AC (W)
    6535              :         Real64 FullLatentOutput;     // Full latent output of AC (W)
    6536              :         Real64 NoCoolOutput;         // Sensible output of AC with no cooling allowed (W)
    6537              :         Real64 NoHeatOutput;         // Sensible output of heater with no heating allowed (W)
    6538              :         Real64 NoLatentOutput;       // Latent output of AC with no cooling allowed (W)
    6539              :         Real64 CoolErrorToler;       // Error tolerance in cooling mode
    6540              :         Real64 HeatErrorToler;       // Error tolerance in heating mode
    6541              :         Real64 ActualSensibleOutput; // Actual furnace sensible capacity
    6542              :         Real64 ActualLatentOutput;   // Actual furnace latent capacity
    6543              :         Real64 PartLoadRatio;        // Part load ratio (greater of sensible or latent part load ratio for cooling,
    6544              :         // or heating PLR)
    6545              :         Real64 LatentPartLoadRatio; // Part load ratio to meet dehumidification load
    6546              :         Real64 TempCoolOutput;      // Temporary Sensible output of AC while iterating on PLR (W)
    6547              :         Real64 TempHeatOutput;      // Temporary Sensible output of heating coil while iterating on PLR (W)
    6548              :         Real64 TempLatentOutput;    // Temporary Latent output of AC at increasing PLR (W)
    6549              :         //                                           ! (Temp variables are used to find min PLR for positive latent removal)
    6550              :         Real64 TempMinPLR;             // Temporary min latent PLR when hum control is required and iter is exceeded
    6551              :         Real64 TempMinPLR2;            // Temporary min latent PLR when cyc fan hum control is required and iter is exceeded
    6552              :         Real64 TempMaxPLR;             // Temporary max latent PLR when hum control is required and iter is exceeded
    6553              :         Real64 QToHeatSetPt;           // Load required to meet heating setpoint temp (>0 is a heating load)
    6554              :         Real64 CoolingHeatingPLRRatio; // ratio of cooling to heating PLR (MAX=1). Used in heating mode.
    6555              :         Real64 HeatingSensibleOutput;
    6556              :         Real64 HeatingLatentOutput;
    6557              :         Real64 OutdoorDryBulbTemp; // secondary coil (condenser) entering dry bulb temperature
    6558              : 
    6559      4573491 :         Real64 &SystemSensibleLoad = state.dataFurnaces->SystemSensibleLoad;
    6560      4573491 :         auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    6561              :         // Set local variables
    6562      4573491 :         int FurnaceOutletNode = thisFurnace.FurnaceOutletNodeNum;
    6563      4573491 :         int FurnaceInletNode = thisFurnace.FurnaceInletNodeNum;
    6564      4573491 :         int ControlZoneNode = thisFurnace.NodeNumOfControlledZone;
    6565      4573491 :         HVAC::FanOp fanOp = thisFurnace.fanOp; // fan operating mode
    6566      4573491 :         bool HumControl = false;
    6567              :         // Calculate the Cp Air of zone
    6568      4573491 :         Real64 cpair = Psychrometrics::PsyCpAirFnW(state.dataLoopNodes->Node(ControlZoneNode).HumRat);
    6569      4573491 :         NoHeatOutput = 0.0;
    6570      4573491 :         SystemSensibleLoad = 0.0;
    6571      4573491 :         ReheatCoilLoad = 0.0;
    6572      4573491 :         HeatCoilLoad = 0.0;
    6573      4573491 :         ReheatCoilLoad = 0.0;
    6574      4573491 :         PartLoadRatio = 0.0;
    6575              : 
    6576      4573491 :         if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_AirToAir) {
    6577       391662 :             if (state.dataDXCoils->DXCoil(thisFurnace.HeatingCoilIndex)
    6578       391662 :                     .IsSecondaryDXCoilInZone) { // assumes compressor is in same location as secondary coil
    6579        16288 :                 OutdoorDryBulbTemp =
    6580        16288 :                     state.dataZoneTempPredictorCorrector->zoneHeatBalance(state.dataDXCoils->DXCoil(thisFurnace.HeatingCoilIndex).SecZonePtr).ZT;
    6581       375374 :             } else if (state.dataDXCoils->DXCoil(thisFurnace.CoolingCoilIndex).IsSecondaryDXCoilInZone) {
    6582            0 :                 OutdoorDryBulbTemp =
    6583            0 :                     state.dataZoneTempPredictorCorrector->zoneHeatBalance(state.dataDXCoils->DXCoil(thisFurnace.CoolingCoilIndex).SecZonePtr).ZT;
    6584              :             } else {
    6585       375374 :                 if (thisFurnace.CondenserNodeNum > 0) {
    6586        63402 :                     OutdoorDryBulbTemp = state.dataLoopNodes->Node(thisFurnace.CondenserNodeNum).Temp;
    6587              :                 } else {
    6588       311972 :                     OutdoorDryBulbTemp = state.dataEnvrn->OutDryBulbTemp;
    6589              :                 }
    6590              :             }
    6591              :         } else {
    6592      4181829 :             OutdoorDryBulbTemp = state.dataEnvrn->OutDryBulbTemp;
    6593              :         }
    6594      4573491 :         if (FirstHVACIteration) {
    6595              :             // Set selected values during first HVAC iteration
    6596              : 
    6597              :             // Init for heating
    6598      1585819 :             if (state.dataFurnaces->HeatingLoad) {
    6599       572012 :                 if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_AirToAir ||
    6600       515602 :                     (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir && thisFurnace.WatertoAirHPType == WAHPCoilType::Simple)) {
    6601       170850 :                     thisFurnace.HeatPartLoadRatio = 1.0;
    6602       170850 :                     HeatCoilLoad = 0.0;
    6603       170850 :                     thisFurnace.HeatingCoilSensDemand = 0.0;
    6604       170850 :                     thisFurnace.CoolingCoilSensDemand = 0.0;
    6605       170850 :                     thisFurnace.CoolingCoilLatentDemand = 0.0;
    6606              :                 } else { // for furnaces
    6607       401162 :                     thisFurnace.HeatPartLoadRatio = 0.0;
    6608       401162 :                     HeatCoilLoad = ZoneLoad;
    6609       401162 :                     state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = thisFurnace.MdotFurnace;
    6610       401162 :                     thisFurnace.HeatingCoilSensDemand = 0.0;
    6611       401162 :                     thisFurnace.CoolingCoilSensDemand = 0.0;
    6612       401162 :                     thisFurnace.CoolingCoilLatentDemand = 0.0;
    6613              :                 }
    6614       572012 :                 ReheatCoilLoad = 0.0;
    6615       572012 :                 thisFurnace.CoolPartLoadRatio = 0.0;
    6616              : 
    6617              :                 // Init for cooling
    6618      1013807 :             } else if (state.dataFurnaces->CoolingLoad) {
    6619              :                 // air to air heat pumps
    6620       549557 :                 thisFurnace.CoolPartLoadRatio = 1.0;
    6621       549557 :                 thisFurnace.HeatPartLoadRatio = 0.0;
    6622       549557 :                 HeatCoilLoad = 0.0;
    6623       549557 :                 ReheatCoilLoad = 0.0;
    6624              : 
    6625              :                 // Init for moisture load only
    6626              :             } else {
    6627       464250 :                 thisFurnace.CoolPartLoadRatio = 0.0;
    6628       464250 :                 thisFurnace.HeatPartLoadRatio = 0.0;
    6629       464250 :                 HeatCoilLoad = 0.0;
    6630       464250 :                 ReheatCoilLoad = 0.0;
    6631       464250 :                 thisFurnace.HeatingCoilSensDemand = 0.0;
    6632       464250 :                 thisFurnace.CoolingCoilSensDemand = 0.0;
    6633       464250 :                 thisFurnace.CoolingCoilLatentDemand = 0.0;
    6634              :             }
    6635              : 
    6636      1585819 :             SetAverageAirFlow(state, FurnaceNum, max(thisFurnace.HeatPartLoadRatio, thisFurnace.CoolPartLoadRatio), OnOffAirFlowRatio);
    6637              :             //  if dehumidification load exists (for heat pumps) turn on the supplemental heater
    6638      1585819 :             if (state.dataFurnaces->HPDehumidificationLoadFlag) {
    6639        25512 :                 HumControl = true;
    6640              :             }
    6641              :         } else { // not FirstHVACIteration
    6642              :             // Init for heating
    6643      2987672 :             Real64 &CoolCoilLoad = state.dataFurnaces->CoolCoilLoad;
    6644      2987672 :             if (state.dataFurnaces->HeatingLoad) {
    6645      1230288 :                 CoolCoilLoad = 0.0;
    6646      1230288 :                 if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_AirToAir ||
    6647      1138478 :                     (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir && thisFurnace.WatertoAirHPType == WAHPCoilType::Simple)) {
    6648       630470 :                     SystemSensibleLoad = ZoneLoad;
    6649       630470 :                     SystemMoistureLoad = 0.0;
    6650       630470 :                     HeatCoilLoad = 0.0;
    6651       630470 :                     thisFurnace.HeatingCoilSensDemand = SystemSensibleLoad;
    6652       630470 :                     thisFurnace.CoolingCoilSensDemand = 0.0;
    6653       630470 :                     thisFurnace.CoolingCoilLatentDemand = 0.0;
    6654              :                 } else {
    6655       599818 :                     SystemMoistureLoad = MoistureLoad;
    6656       599818 :                     HeatCoilLoad = ZoneLoad;
    6657              :                 }
    6658              : 
    6659              :                 // Init for cooling
    6660      1757384 :             } else if (state.dataFurnaces->CoolingLoad) {
    6661      1242401 :                 CoolCoilLoad = ZoneLoad;
    6662      1242401 :                 SystemMoistureLoad = MoistureLoad;
    6663      1242401 :                 HeatCoilLoad = 0.0;
    6664      1242401 :                 thisFurnace.CoolingCoilSensDemand = std::abs(CoolCoilLoad);
    6665      1242401 :                 thisFurnace.CoolingCoilLatentDemand = std::abs(SystemMoistureLoad);
    6666      1242401 :                 thisFurnace.HeatingCoilSensDemand = 0.0;
    6667              : 
    6668              :                 // Init for latent
    6669              :             } else {
    6670       514983 :                 SystemMoistureLoad = MoistureLoad;
    6671       514983 :                 CoolCoilLoad = 0.0;
    6672       514983 :                 HeatCoilLoad = 0.0;
    6673              :                 // set report variables
    6674       514983 :                 thisFurnace.CoolingCoilSensDemand = 0.0;
    6675       514983 :                 thisFurnace.CoolingCoilLatentDemand = SystemMoistureLoad;
    6676       514983 :                 thisFurnace.HeatingCoilSensDemand = 0.0;
    6677              :             }
    6678      2987672 :             HeatingSensibleOutput = 0.0;
    6679      2987672 :             HeatingLatentOutput = 0.0;
    6680      2987672 :             ReheatCoilLoad = 0.0;
    6681      2987672 :             thisFurnace.CoolPartLoadRatio = 0.0;
    6682      2987672 :             thisFurnace.HeatPartLoadRatio = 0.0;
    6683      2987672 :             thisFurnace.CompPartLoadRatio = 0.0;
    6684      2987672 :             thisFurnace.DehumidInducedHeatingDemandRate = 0.0;
    6685              : 
    6686              :             // When humidity control is used with cycling fan control and a heating load exists, if a moisture load
    6687              :             // also exists, the heating PLR must be available for the cooling coil calculations.
    6688              :             //*********** Heating Section ************
    6689              :             // If Furnace runs with a heating load then set HeatCoilLoad on Heating Coil and the Mass Flow
    6690              :             //         (Node(FurnaceInletNode)%MassFlowRate .gt. 0.0d0) .and. &
    6691      2987672 :             if ((thisFurnace.availSched->getCurrentVal() > 0.0) && (state.dataFurnaces->HeatingLoad)) {
    6692              : 
    6693              :                 //    Heat pumps only calculate a single PLR each time step (i.e. only cooling or heating allowed in a single time step)
    6694      1219760 :                 if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_AirToAir ||
    6695      1127950 :                     (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir && thisFurnace.WatertoAirHPType == WAHPCoilType::Simple)) {
    6696              : 
    6697       630470 :                     state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = thisFurnace.MdotFurnace;
    6698              : 
    6699              :                     // Get no load result
    6700       630470 :                     if (fanOp == HVAC::FanOp::Cycling) {
    6701       593322 :                         state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = 0.0;
    6702              :                     }
    6703              : 
    6704              :                     //     Set the inlet mass flow rate based on user specified coil OFF flow rate
    6705       630470 :                     PartLoadRatio = 0.0;
    6706              : 
    6707       630470 :                     SetAverageAirFlow(state, FurnaceNum, PartLoadRatio, OnOffAirFlowRatio);
    6708              : 
    6709              :                     // Set the input parameters for CalcFurnaceOutput
    6710       630470 :                     thisFurnace.CompPartLoadRatio = 0.0; // compressor off
    6711              : 
    6712       630470 :                     CalcFurnaceOutput(state,
    6713              :                                       FurnaceNum,
    6714              :                                       FirstHVACIteration,
    6715              :                                       fanOp,
    6716              :                                       compressorOp,
    6717              :                                       0.0,
    6718              :                                       MinPLR,
    6719              :                                       0.0,
    6720              :                                       0.0,
    6721              :                                       NoHeatOutput,
    6722              :                                       NoLatentOutput,
    6723              :                                       OnOffAirFlowRatio,
    6724              :                                       false);
    6725              : 
    6726       630470 :                     PartLoadRatio = 1.0;
    6727       630470 :                     state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = thisFurnace.MdotFurnace;
    6728              : 
    6729       630470 :                     thisFurnace.CompPartLoadRatio = 1.0; // compressor ON
    6730              : 
    6731              :                     // Set fan part-load fraction equal to 1 while getting full load result
    6732       630470 :                     state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
    6733       630470 :                     OnOffAirFlowRatio = 1.0;
    6734              : 
    6735              :                     // Get full load result
    6736       630470 :                     CalcFurnaceOutput(state,
    6737              :                                       FurnaceNum,
    6738              :                                       FirstHVACIteration,
    6739              :                                       fanOp,
    6740              :                                       compressorOp,
    6741              :                                       0.0,
    6742              :                                       PartLoadRatio,
    6743              :                                       0.0,
    6744              :                                       0.0,
    6745              :                                       FullSensibleOutput,
    6746              :                                       FullLatentOutput,
    6747              :                                       OnOffAirFlowRatio,
    6748              :                                       false);
    6749              : 
    6750              :                     // Check that SystemSensibleLoad is between FullSensibleOutput and NoHeatOutput
    6751              :                     // If so then calculate PartLoadRatio for the DX Heating coil
    6752       630470 :                     if (SystemSensibleLoad < FullSensibleOutput && SystemSensibleLoad > NoHeatOutput) {
    6753              : 
    6754              :                         // Calculate the part load ratio through iteration
    6755       544890 :                         HeatErrorToler = thisFurnace.HeatingConvergenceTolerance; // Error tolerance for convergence from input deck
    6756              : 
    6757       544890 :                         int SolFlag = 0; // # of iterations if positive, -1 means failed to converge, -2 means bounds are incorrect
    6758              :                         // HeatErrorToler is in fraction of load, MaxIter = 30, SolFalg = # of iterations or error as appropriate
    6759      2700486 :                         auto f = [&state, FurnaceNum, FirstHVACIteration, fanOp, compressorOp, SystemSensibleLoad](Real64 const PartLoadRatio) {
    6760      2155596 :                             return CalcFurnaceResidual(state,
    6761              :                                                        PartLoadRatio,
    6762              :                                                        FurnaceNum,
    6763              :                                                        FirstHVACIteration,
    6764              :                                                        fanOp,
    6765              :                                                        compressorOp,
    6766              :                                                        SystemSensibleLoad,
    6767              :                                                        0.0,  // par6_loadFlag,
    6768              :                                                        1.0,  // par7_sensLatentFlag,
    6769              :                                                        0.0,  // par9_HXOnFlag,
    6770      2155596 :                                                        0.0); // par10_HeatingCoilPLR);
    6771       544890 :                         };
    6772       544890 :                         General::SolveRoot(state, HeatErrorToler, MaxIter, SolFlag, PartLoadRatio, f, 0.0, 1.0);
    6773              :                         //         OnOffAirFlowRatio is updated during the above iteration. Reset to correct value based on PLR.
    6774       544890 :                         OnOffAirFlowRatio = state.dataFurnaces->OnOffAirFlowRatioSave;
    6775       544890 :                         if (SolFlag < 0) {
    6776            0 :                             if (SolFlag == -1) {
    6777            0 :                                 CalcFurnaceOutput(state,
    6778              :                                                   FurnaceNum,
    6779              :                                                   FirstHVACIteration,
    6780              :                                                   fanOp,
    6781              :                                                   compressorOp,
    6782              :                                                   0.0,
    6783              :                                                   PartLoadRatio,
    6784              :                                                   0.0,
    6785              :                                                   0.0,
    6786              :                                                   TempHeatOutput,
    6787              :                                                   TempLatentOutput,
    6788              :                                                   OnOffAirFlowRatio,
    6789              :                                                   false);
    6790            0 :                                 if (std::abs(SystemSensibleLoad - TempHeatOutput) > HVAC::SmallLoad) {
    6791            0 :                                     if (thisFurnace.DXHeatingMaxIterIndex == 0) {
    6792            0 :                                         ShowWarningMessage(state,
    6793            0 :                                                            format("Heating coil control failed to converge for {}:{}",
    6794            0 :                                                                   HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    6795            0 :                                                                   thisFurnace.Name));
    6796            0 :                                         ShowContinueError(state,
    6797              :                                                           "  Iteration limit exceeded in calculating DX heating coil sensible part-load ratio.");
    6798            0 :                                         ShowContinueErrorTimeStamp(
    6799              :                                             state,
    6800            0 :                                             format("Sensible load to be met by DX heating coil = {:.2T} (watts), sensible output of DX heating "
    6801              :                                                    "coil = {:.2T} (watts), and the simulation continues.",
    6802              :                                                    SystemSensibleLoad,
    6803              :                                                    TempHeatOutput));
    6804              :                                     }
    6805            0 :                                     ShowRecurringWarningErrorAtEnd(state,
    6806            0 :                                                                    format("{} \"{}\" - Iteration limit exceeded in calculating DX sensible heating "
    6807              :                                                                           "part-load ratio error continues. "
    6808              :                                                                           "Sensible load statistics:",
    6809            0 :                                                                           HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    6810            0 :                                                                           thisFurnace.Name),
    6811            0 :                                                                    thisFurnace.DXHeatingMaxIterIndex,
    6812              :                                                                    SystemSensibleLoad,
    6813              :                                                                    SystemSensibleLoad);
    6814              :                                 }
    6815            0 :                             } else if (SolFlag == -2) {
    6816            0 :                                 if (thisFurnace.DXHeatingRegulaFalsiFailedIndex == 0) {
    6817            0 :                                     ShowWarningMessage(state,
    6818            0 :                                                        format("Heating coil control failed for {}:{}",
    6819            0 :                                                               HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    6820            0 :                                                               thisFurnace.Name));
    6821            0 :                                     ShowContinueError(state, "  DX sensible heating part-load ratio determined to be outside the range of 0-1.");
    6822            0 :                                     ShowContinueErrorTimeStamp(
    6823              :                                         state,
    6824            0 :                                         format("Sensible load to be met by DX heating coil = {:.2T} (watts), and the simulation continues.",
    6825              :                                                SystemSensibleLoad));
    6826              :                                 }
    6827            0 :                                 ShowRecurringWarningErrorAtEnd(
    6828              :                                     state,
    6829            0 :                                     format("{} \"{}\" -  DX sensible heating part-load ratio out of range error continues. Sensible load statistics:",
    6830            0 :                                            HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    6831            0 :                                            thisFurnace.Name),
    6832            0 :                                     thisFurnace.DXHeatingRegulaFalsiFailedIndex,
    6833              :                                     SystemSensibleLoad,
    6834              :                                     SystemSensibleLoad);
    6835              :                             }
    6836              :                         }
    6837              : 
    6838       544890 :                         thisFurnace.HeatPartLoadRatio = PartLoadRatio;
    6839              :                         //       Check if Heat Pump compressor is allowed to run based on outdoor temperature
    6840       544890 :                         if (OutdoorDryBulbTemp > thisFurnace.MinOATCompressorHeating) {
    6841       544872 :                             thisFurnace.CompPartLoadRatio = PartLoadRatio;
    6842              :                         } else {
    6843           18 :                             thisFurnace.CompPartLoadRatio = 0.0;
    6844              :                         }
    6845       630470 :                     } else if (SystemSensibleLoad > FullSensibleOutput) {
    6846              :                         //       SystemSensibleLoad is greater than full DX Heating coil output so heat pump runs entire
    6847              :                         //       timestep and additional supplemental heating is required
    6848        85580 :                         thisFurnace.HeatPartLoadRatio = 1.0;
    6849        85580 :                         if (OutdoorDryBulbTemp > thisFurnace.MinOATCompressorHeating) {
    6850              :                             //       Check to see if Heat Pump compressor was allowed to run based on outdoor temperature
    6851         4142 :                             thisFurnace.CompPartLoadRatio = 1.0;
    6852              :                         } else {
    6853        81438 :                             thisFurnace.CompPartLoadRatio = 0.0;
    6854              :                         }
    6855            0 :                     } else if (SystemSensibleLoad < NoHeatOutput) {
    6856              :                         //       SystemSensibleLoad is less than minimum DX Heating coil output so heat pump does not run and
    6857              :                         //       the load will be met by the supplemental heater
    6858            0 :                         thisFurnace.CompPartLoadRatio = 0.0;
    6859            0 :                         thisFurnace.HeatPartLoadRatio = 1.0;
    6860              :                     }
    6861       630470 :                     if (thisFurnace.HeatPartLoadRatio == 1.0) {
    6862              :                         //       Determine the load on the supplemental heating coil
    6863        85580 :                         if ((SystemSensibleLoad - FullSensibleOutput) > thisFurnace.DesignSuppHeatingCapacity) {
    6864        24992 :                             HeatCoilLoad = thisFurnace.DesignSuppHeatingCapacity;
    6865        24992 :                             TempOutHeatingCoil = state.dataLoopNodes->Node(FurnaceOutletNode).Temp + HeatCoilLoad / (cpair * thisFurnace.MdotFurnace);
    6866        60588 :                         } else if (SystemSensibleLoad < NoHeatOutput) {
    6867            0 :                             HeatCoilLoad = max(0.0, SystemSensibleLoad); // BG 10/22/2008 need a case for when its all suppl heat
    6868            0 :                             TempOutHeatingCoil = state.dataLoopNodes->Node(FurnaceInletNode).Temp + HeatCoilLoad / (cpair * thisFurnace.MdotFurnace);
    6869              :                         } else {
    6870        60588 :                             HeatCoilLoad = max(0.0, (SystemSensibleLoad - FullSensibleOutput));
    6871        60588 :                             TempOutHeatingCoil = state.dataLoopNodes->Node(FurnaceOutletNode).Temp + HeatCoilLoad / (cpair * thisFurnace.MdotFurnace);
    6872              :                         }
    6873        85580 :                         if (OutdoorDryBulbTemp > thisFurnace.MaxOATSuppHeat) {
    6874            0 :                             HeatCoilLoad = 0.0;
    6875            0 :                             if (SystemSensibleLoad < NoHeatOutput) {
    6876            0 :                                 TempOutHeatingCoil = state.dataLoopNodes->Node(FurnaceInletNode).Temp;
    6877              :                             } else {
    6878            0 :                                 TempOutHeatingCoil = state.dataLoopNodes->Node(FurnaceOutletNode).Temp;
    6879              :                             }
    6880              :                         }
    6881        85580 :                         if ((TempOutHeatingCoil > thisFurnace.DesignMaxOutletTemp) && (HeatCoilLoad > 0.0)) {
    6882              :                             // deltaT = Furnace(FurnaceNum)%DesignMaxOutletTemp - Node(FurnaceOutletNode)%Temp
    6883              :                             // BG 10/22/2008 above made no sense if DX heat is off and its all supplemental,
    6884              :                             //  because Node(FurnaceOutletNode)%Temp will have been calc'd with full DX heat in last faux call to CalcFurnaceOutput
    6885              : 
    6886         1374 :                             Real64 cpairSupply = Psychrometrics::PsyCpAirFnW(state.dataLoopNodes->Node(FurnaceInletNode).HumRat);
    6887         1374 :                             deltaT = (thisFurnace.DesignMaxOutletTemp - TempOutHeatingCoil);
    6888         1374 :                             HeatCoilLoad += (state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate * cpairSupply * deltaT);
    6889         1374 :                             HeatCoilLoad = max(0.0, HeatCoilLoad);
    6890              :                         }
    6891              :                     } else {
    6892       544890 :                         HeatCoilLoad = 0.0;
    6893              :                     }
    6894       630470 :                     PartLoadRatio = 0.0;
    6895              : 
    6896              :                     //   HeatCool systems can have both a sensible and latent PLR in a single time step
    6897              :                     //   (i.e. both cooling and heating can occur in a single time step)
    6898       630470 :                 } else { // else not a heatpump DX coil ** non-HP heating coils are not DX so testing if OutdoorDryBulbTemp < MinOATCompressorHeating
    6899              :                          // is not necessary **
    6900              : 
    6901       589290 :                     state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = thisFurnace.MdotFurnace;
    6902       589290 :                     HeatCoilLoad = thisFurnace.DesignHeatingCapacity;
    6903       589290 :                     SystemSensibleLoad = ZoneLoad;
    6904              : 
    6905              :                     // Get no load result
    6906       589290 :                     if (fanOp == HVAC::FanOp::Cycling) {
    6907       443811 :                         state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = 0.0;
    6908              :                     }
    6909       589290 :                     if (fanOp == HVAC::FanOp::Continuous) {
    6910       145479 :                         state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0; // The on/off fan will not cycle, so set part-load fraction = 1
    6911              :                     }
    6912              : 
    6913              :                     //     Set the inlet mass flow rate based on user specified coil OFF flow rate
    6914       589290 :                     PartLoadRatio = 0.0;
    6915       589290 :                     SetAverageAirFlow(state, FurnaceNum, PartLoadRatio, OnOffAirFlowRatio);
    6916              : 
    6917       589290 :                     CalcFurnaceOutput(state,
    6918              :                                       FurnaceNum,
    6919              :                                       FirstHVACIteration,
    6920              :                                       fanOp,
    6921              :                                       compressorOp,
    6922              :                                       0.0,
    6923              :                                       MinPLR,
    6924              :                                       0.0,
    6925              :                                       0.0,
    6926              :                                       NoHeatOutput,
    6927              :                                       NoLatentOutput,
    6928              :                                       OnOffAirFlowRatio,
    6929              :                                       false);
    6930              : 
    6931       589290 :                     if (NoHeatOutput < SystemSensibleLoad) {
    6932       589290 :                         state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = thisFurnace.MdotFurnace;
    6933              : 
    6934              :                         // Set fan part-load fraction equal to 1 while getting full load result
    6935       589290 :                         state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
    6936       589290 :                         OnOffAirFlowRatio = 1.0;
    6937              : 
    6938              :                         // Get full load result
    6939       589290 :                         CalcFurnaceOutput(state,
    6940              :                                           FurnaceNum,
    6941              :                                           FirstHVACIteration,
    6942              :                                           fanOp,
    6943              :                                           compressorOp,
    6944              :                                           0.0,
    6945              :                                           1.0,
    6946              :                                           HeatCoilLoad,
    6947              :                                           0.0,
    6948              :                                           FullSensibleOutput,
    6949              :                                           FullLatentOutput,
    6950              :                                           OnOffAirFlowRatio,
    6951              :                                           false);
    6952              :                     } else {
    6953            0 :                         FullSensibleOutput = NoHeatOutput + 0.000000001;
    6954              :                     }
    6955              : 
    6956              :                     // Since we are heating, we expect FullSensibleOutput to be > 0 and FullSensibleOutput > NoSensibleOutput
    6957              :                     // Check that this is the case; if not set PartLoadRatio = 0.0 (off) and return
    6958              : 
    6959       589290 :                     if (FullSensibleOutput > NoHeatOutput) {
    6960              : 
    6961              :                         // check bounds on sensible output prior to iteration using RegulaFalsi
    6962       534244 :                         if (FullSensibleOutput <= SystemSensibleLoad) {
    6963        96967 :                             PartLoadRatio = 1.0;
    6964              :                             //         save modified HeatCoilLoad in case it was reset because outlet temp > DesignMaxOutletTemp
    6965        96967 :                             if (state.dataFurnaces->ModifiedHeatCoilLoad > 0.0) {
    6966        14808 :                                 HeatCoilLoad = state.dataFurnaces->ModifiedHeatCoilLoad;
    6967              :                             } else {
    6968        82159 :                                 HeatCoilLoad = thisFurnace.DesignHeatingCapacity;
    6969              :                             }
    6970       437277 :                         } else if (NoHeatOutput >= SystemSensibleLoad) {
    6971            0 :                             PartLoadRatio = 0.0;
    6972            0 :                             HeatCoilLoad = 0.0;
    6973              :                         } else {
    6974              : 
    6975              :                             // Calculate the part load ratio through iteration
    6976       437277 :                             HeatErrorToler = thisFurnace.HeatingConvergenceTolerance; // Error tolerance for convergence from input deck
    6977              : 
    6978       437277 :                             int SolFlag = 0; // # of iterations if positive, -1 means failed to converge, -2 means bounds are incorrect
    6979              :                             // HeatErrorToler is in fraction load, MaxIter = 30, SolFalg = # of iterations or error as appropriate
    6980      1753894 :                             auto f = [&state, FurnaceNum, FirstHVACIteration, fanOp, compressorOp, SystemSensibleLoad](Real64 const PartLoadRatio) {
    6981      1316617 :                                 return CalcFurnaceResidual(state,
    6982              :                                                            PartLoadRatio,
    6983              :                                                            FurnaceNum,
    6984              :                                                            FirstHVACIteration,
    6985              :                                                            fanOp,
    6986              :                                                            compressorOp,
    6987              :                                                            SystemSensibleLoad,
    6988              :                                                            0.0,  // par6_loadFlag,
    6989              :                                                            1.0,  // par7_sensLatentFlag,
    6990              :                                                            0.0,  // par9_HXOnFlag,
    6991      1316617 :                                                            0.0); // par10_HeatingCoilPLR);
    6992       437277 :                             };
    6993       437277 :                             General::SolveRoot(state, HeatErrorToler, MaxIter, SolFlag, PartLoadRatio, f, 0.0, 1.0);
    6994              :                             //         OnOffAirFlowRatio is updated during the above iteration. Reset to correct value based on PLR.
    6995       437277 :                             OnOffAirFlowRatio = state.dataFurnaces->OnOffAirFlowRatioSave;
    6996              :                             //         Reset HeatCoilLoad calculated in CalcFurnaceResidual (in case it was reset because output temp >
    6997              :                             //         DesignMaxOutletTemp)
    6998       437277 :                             if (state.dataFurnaces->ModifiedHeatCoilLoad > 0.0) {
    6999        62506 :                                 HeatCoilLoad = state.dataFurnaces->ModifiedHeatCoilLoad;
    7000              :                             } else {
    7001       374771 :                                 HeatCoilLoad = thisFurnace.DesignHeatingCapacity * PartLoadRatio;
    7002              :                             }
    7003       437277 :                             if (SolFlag == -1) {
    7004              : 
    7005              :                                 //           RegulaFalsi may not find heating PLR when the maximum supply air temperature is exceeded.
    7006              :                                 //           If iteration limit is exceeded, find tighter boundary of solution and repeat RegulaFalsi
    7007            0 :                                 TempMaxPLR = -0.1;
    7008            0 :                                 TempHeatOutput = NoHeatOutput;
    7009            0 :                                 while ((TempHeatOutput - SystemSensibleLoad) < 0.0 && TempMaxPLR < 1.0) {
    7010              :                                     //             find upper limit of HeatingPLR
    7011            0 :                                     TempMaxPLR += 0.1;
    7012            0 :                                     HeatCoilLoad = thisFurnace.DesignHeatingCapacity * TempMaxPLR;
    7013            0 :                                     CalcFurnaceOutput(state,
    7014              :                                                       FurnaceNum,
    7015              :                                                       FirstHVACIteration,
    7016              :                                                       fanOp,
    7017              :                                                       compressorOp,
    7018              :                                                       0.0,
    7019              :                                                       TempMaxPLR,
    7020              :                                                       HeatCoilLoad,
    7021              :                                                       0.0,
    7022              :                                                       TempHeatOutput,
    7023              :                                                       TempLatentOutput,
    7024              :                                                       OnOffAirFlowRatio,
    7025              :                                                       false);
    7026              :                                 }
    7027            0 :                                 TempMinPLR = TempMaxPLR;
    7028            0 :                                 while ((TempHeatOutput - SystemSensibleLoad) > 0.0 && TempMinPLR > 0.0) {
    7029              :                                     //             pull upper limit of HeatingPLR down to last valid limit (i.e. heat output still exceeds
    7030              :                                     //             SystemSensibleLoad)
    7031            0 :                                     TempMaxPLR = TempMinPLR;
    7032              :                                     //             find minimum limit of HeatingPLR
    7033            0 :                                     TempMinPLR -= 0.01;
    7034              : 
    7035            0 :                                     HeatCoilLoad = thisFurnace.DesignHeatingCapacity * TempMinPLR;
    7036            0 :                                     CalcFurnaceOutput(state,
    7037              :                                                       FurnaceNum,
    7038              :                                                       FirstHVACIteration,
    7039              :                                                       fanOp,
    7040              :                                                       compressorOp,
    7041              :                                                       0.0,
    7042              :                                                       TempMinPLR,
    7043              :                                                       HeatCoilLoad,
    7044              :                                                       0.0,
    7045              :                                                       TempHeatOutput,
    7046              :                                                       TempLatentOutput,
    7047              :                                                       OnOffAirFlowRatio,
    7048              :                                                       false);
    7049              :                                 }
    7050              :                                 //           Now solve again with tighter PLR limits
    7051              :                                 auto f2 = // (AUTO_OK_LAMBDA)
    7052            0 :                                     [&state, FurnaceNum, FirstHVACIteration, fanOp, compressorOp, SystemSensibleLoad](Real64 const PartLoadRatio) {
    7053            0 :                                         return CalcFurnaceResidual(state,
    7054              :                                                                    PartLoadRatio,
    7055              :                                                                    FurnaceNum,
    7056              :                                                                    FirstHVACIteration,
    7057              :                                                                    fanOp,
    7058              :                                                                    compressorOp,
    7059              :                                                                    SystemSensibleLoad,
    7060              :                                                                    0.0,  // par6_loadFlag,
    7061              :                                                                    1.0,  // par7_sensLatentFlag,
    7062              :                                                                    0.0,  // par9_HXOnFlag,
    7063            0 :                                                                    0.0); // par10_HeatingCoilPLR);
    7064            0 :                                     };
    7065            0 :                                 General::SolveRoot(state, HeatErrorToler, MaxIter, SolFlag, PartLoadRatio, f2, TempMinPLR, TempMaxPLR);
    7066            0 :                                 if (state.dataFurnaces->ModifiedHeatCoilLoad > 0.0) {
    7067            0 :                                     HeatCoilLoad = state.dataFurnaces->ModifiedHeatCoilLoad;
    7068              :                                 } else {
    7069            0 :                                     HeatCoilLoad = thisFurnace.DesignHeatingCapacity * PartLoadRatio;
    7070              :                                 }
    7071            0 :                                 CalcFurnaceOutput(state,
    7072              :                                                   FurnaceNum,
    7073              :                                                   FirstHVACIteration,
    7074              :                                                   fanOp,
    7075              :                                                   compressorOp,
    7076              :                                                   0.0,
    7077              :                                                   PartLoadRatio,
    7078              :                                                   HeatCoilLoad,
    7079              :                                                   0.0,
    7080              :                                                   TempHeatOutput,
    7081              :                                                   TempLatentOutput,
    7082              :                                                   OnOffAirFlowRatio,
    7083              :                                                   false);
    7084              : 
    7085              :                                 //           After iterating with tighter boundaries, if still out of tolerance, show warning.
    7086            0 :                                 if (SolFlag == -1 && std::abs(SystemSensibleLoad - TempHeatOutput) > HVAC::SmallLoad) {
    7087            0 :                                     if (thisFurnace.HeatingMaxIterIndex == 0) {
    7088            0 :                                         ShowWarningMessage(state,
    7089            0 :                                                            format("Heating coil control failed to converge for {}:{}",
    7090            0 :                                                                   HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    7091            0 :                                                                   thisFurnace.Name));
    7092            0 :                                         ShowContinueError(state, "  Iteration limit exceeded in calculating heating coil sensible part-load ratio.");
    7093            0 :                                         ShowContinueErrorTimeStamp(state,
    7094            0 :                                                                    format("Sensible load to be met by heating coil = {:.2T} (watts), sensible output "
    7095              :                                                                           "of heating coil = {:.2T} (watts), and the simulation continues.",
    7096              :                                                                           SystemSensibleLoad,
    7097              :                                                                           TempHeatOutput));
    7098              :                                     }
    7099            0 :                                     ShowRecurringWarningErrorAtEnd(
    7100              :                                         state,
    7101            0 :                                         format("{} \"{}\" - Iteration limit exceeded in calculating sensible heating part-load "
    7102              :                                                "ratio error continues. Sensible load statistics:",
    7103            0 :                                                HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    7104            0 :                                                thisFurnace.Name),
    7105            0 :                                         thisFurnace.HeatingMaxIterIndex,
    7106              :                                         SystemSensibleLoad,
    7107              :                                         SystemSensibleLoad);
    7108              :                                 }
    7109       437277 :                             } else if (SolFlag == -2) {
    7110            0 :                                 if (thisFurnace.HeatingRegulaFalsiFailedIndex == 0) {
    7111            0 :                                     ShowWarningMessage(state,
    7112            0 :                                                        format("Heating coil control failed for {}:{}",
    7113            0 :                                                               HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    7114            0 :                                                               thisFurnace.Name));
    7115            0 :                                     ShowContinueError(state, "  Sensible heating part-load ratio determined to be outside the range of 0-1.");
    7116            0 :                                     ShowContinueErrorTimeStamp(
    7117              :                                         state,
    7118            0 :                                         format("Sensible load to be met by heating coil = {:.2T} (watts), and the simulation continues.",
    7119              :                                                SystemSensibleLoad));
    7120              :                                 }
    7121            0 :                                 ShowRecurringWarningErrorAtEnd(
    7122              :                                     state,
    7123            0 :                                     format("{} \"{}\" -  Sensible heating part-load ratio out of range error continues. Sensible load statistics:",
    7124            0 :                                            HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    7125            0 :                                            thisFurnace.Name),
    7126            0 :                                     thisFurnace.HeatingRegulaFalsiFailedIndex,
    7127              :                                     SystemSensibleLoad,
    7128              :                                     SystemSensibleLoad);
    7129              :                             }
    7130              :                         }
    7131              : 
    7132              :                     } else { // ELSE from IF(FullSensibleOutput.GT.NoSensibleOutput)THEN above
    7133              :                         // Set part load ratio to 1 and run heater at design heating capacity
    7134        55046 :                         PartLoadRatio = 1.0;
    7135        55046 :                         HeatCoilLoad = thisFurnace.DesignHeatingCapacity;
    7136              :                     }
    7137              : 
    7138              :                 } // End of IF HeatPump
    7139              : 
    7140              :             } // End of IF for heating
    7141              : 
    7142              :             // Non-heat pump systems do not set a heating PLR, set it here for use with the DX cooling coil calculations.
    7143              :             // Set this variable back to 0 for non-heat pump systems at the end of this routine.
    7144      2987672 :             thisFurnace.HeatPartLoadRatio = max(PartLoadRatio, thisFurnace.HeatPartLoadRatio);
    7145      2987672 :             CalcFurnaceOutput(state,
    7146              :                               FurnaceNum,
    7147              :                               FirstHVACIteration,
    7148              :                               fanOp,
    7149              :                               compressorOp,
    7150              :                               0.0,
    7151              :                               thisFurnace.HeatPartLoadRatio,
    7152              :                               HeatCoilLoad,
    7153              :                               0.0,
    7154              :                               HeatingSensibleOutput,
    7155              :                               HeatingLatentOutput,
    7156              :                               OnOffAirFlowRatio,
    7157              :                               false);
    7158              : 
    7159      5727062 :             if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_AirToAir ||
    7160      2739390 :                 (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir && thisFurnace.WatertoAirHPType == WAHPCoilType::Simple &&
    7161      1337832 :                  state.dataFurnaces->CoolingLoad)) {
    7162       932392 :                 HeatingSensibleOutput = 0.0;
    7163       932392 :                 HeatingLatentOutput = 0.0;
    7164              :             }
    7165              :             //***********Cooling Section*****************
    7166              :             // Simulate if scheduled ON and cooling load or if a moisture load exists when using a humidistat
    7167              :             // Check of HeatingLatentOutput is used to reduce overshoot during simultaneous heating and cooling
    7168              :             // Setback flag is used to avoid continued RH control when Tstat is setback (RH should float down)
    7169      4740312 :             if ((thisFurnace.availSched->getCurrentVal() > 0.0 && state.dataFurnaces->CoolingLoad) ||
    7170      1752640 :                 (thisFurnace.Humidistat && thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat &&
    7171       335771 :                  (SystemMoistureLoad < 0.0 || (SystemMoistureLoad >= 0.0 && HeatingLatentOutput > SystemMoistureLoad &&
    7172        10847 :                                                !state.dataZoneEnergyDemand->Setback(thisFurnace.ControlZoneNum))))) {
    7173              : 
    7174              :                 //     For cooling operation, the first step is to set the HX operation flag in case a HX assisted coil is used.
    7175              :                 //      (if a HX assisted coil is not used, this flag is not used. It's only used in the CALL to SimHXAssistedCoolingCoil)
    7176              :                 //     Check the dehumidification control type:
    7177              :                 //           For dehumidification control options CoolReheat and None, the HX is always active (locked ON).
    7178              :                 //           For dehumidification control option Multimode, the system is operated first with the HX off.
    7179              :                 //           If the moisture load is not met, the HX will then be turned on and the system is re-simulated.
    7180              : 
    7181      1395880 :                 if (thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat ||
    7182      1136541 :                     thisFurnace.DehumidControlType_Num == DehumidificationControlMode::None) {
    7183      1387440 :                     HXUnitOn = true;
    7184              :                 } else {
    7185         8440 :                     HXUnitOn = false;
    7186              :                 }
    7187              : 
    7188              :                 //     The next step is to determine the system output at no load (PLR=0) and full load (PLR=1)
    7189              : 
    7190              :                 //     Set the inlet mass flow rate based on user specified coil OFF flow rate
    7191      1395880 :                 PartLoadRatio = 0.0;
    7192              : 
    7193      1395880 :                 thisFurnace.CompPartLoadRatio = 0.0; // compressor off
    7194              : 
    7195              :                 //     SetAverageAirFlow calculates the operating mass flow rate based on PLR and the user specified inputs
    7196              :                 //     for MaxCoolAirMassFlow and MaxNoCoolHeatAirMassFlow.
    7197              :                 //     Air flow rate is set according to max of cooling and heating PLR if heating and latent load exists.
    7198       787692 :                 if (fanOp == HVAC::FanOp::Cycling && thisFurnace.HeatPartLoadRatio > 0.0 && thisFurnace.Humidistat &&
    7199      2183574 :                     thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat &&
    7200            2 :                     (SystemMoistureLoad < 0.0 || (SystemMoistureLoad >= 0.0 && HeatingLatentOutput > SystemMoistureLoad &&
    7201            0 :                                                   !state.dataZoneEnergyDemand->Setback(thisFurnace.ControlZoneNum)))) {
    7202            2 :                     CoolingHeatingPLRRatio = min(1.0, PartLoadRatio / thisFurnace.HeatPartLoadRatio);
    7203            2 :                     SetAverageAirFlow(state, FurnaceNum, max(PartLoadRatio, thisFurnace.HeatPartLoadRatio), OnOffAirFlowRatio);
    7204              : 
    7205              :                 } else {
    7206      1395878 :                     CoolingHeatingPLRRatio = 1.0;
    7207      1395878 :                     SetAverageAirFlow(state, FurnaceNum, PartLoadRatio, OnOffAirFlowRatio);
    7208              :                 }
    7209              : 
    7210              :                 // Get no load result (coils simulated OFF)
    7211      1395880 :                 CalcFurnaceOutput(state,
    7212              :                                   FurnaceNum,
    7213              :                                   FirstHVACIteration,
    7214              :                                   fanOp,
    7215              :                                   compressorOp,
    7216              :                                   MinPLR,
    7217              :                                   PartLoadRatio,
    7218              :                                   0.0,
    7219              :                                   0.0,
    7220              :                                   NoCoolOutput,
    7221              :                                   NoLatentOutput,
    7222              :                                   OnOffAirFlowRatio,
    7223      1395880 :                                   HXUnitOn,
    7224              :                                   CoolingHeatingPLRRatio);
    7225              : 
    7226              :                 //     Don't calculate full load output if no load output can meet sensible load
    7227      1395880 :                 if (NoCoolOutput >= CoolCoilLoad && (CoolCoilLoad != 0.0 || state.dataFurnaces->HPDehumidificationLoadFlag)) {
    7228              :                     //       Set full mass flow rate for full load calculation
    7229      1248278 :                     state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = thisFurnace.MdotFurnace;
    7230              : 
    7231              :                     // Set fan part-load fraction equal to 1 while getting full load result
    7232      1248278 :                     state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
    7233      1248278 :                     OnOffAirFlowRatio = 1.0;
    7234      1248278 :                     PartLoadRatio = 1.0;
    7235      1248278 :                     thisFurnace.CompPartLoadRatio = 1.0; // compressor ON
    7236              : 
    7237              :                     // Get full load result (coils simulated full ON)
    7238      1248278 :                     CalcFurnaceOutput(state,
    7239              :                                       FurnaceNum,
    7240              :                                       FirstHVACIteration,
    7241              :                                       fanOp,
    7242              :                                       compressorOp,
    7243              :                                       PartLoadRatio,
    7244              :                                       0.0,
    7245              :                                       0.0,
    7246              :                                       0.0,
    7247              :                                       FullSensibleOutput,
    7248              :                                       FullLatentOutput,
    7249              :                                       OnOffAirFlowRatio,
    7250      1248278 :                                       HXUnitOn);
    7251              :                 } else {
    7252       147602 :                     FullSensibleOutput = NoCoolOutput - 0.00000001;
    7253              :                 }
    7254              : 
    7255              :                 //     The next step is to compare the results of the full load and no load results
    7256              :                 //     1) Since we are cooling, we expect FullSensibleOutput < NoCoolOutput
    7257              :                 //        Check that this is the case; if not set PartLoadRatio = 0.0 (off)
    7258              :                 //     2) Verify that the load to be met is within the range of available output
    7259              :                 //        (i.e. between FullSensibleOutput and NoCoolOutput)
    7260              :                 //     3) Set PLR if load is out of range or RegulaFalsi on PLR if system can meet the load
    7261      1395880 :                 if (FullSensibleOutput < NoCoolOutput) {
    7262      1391170 :                     if (CoolCoilLoad != 0.0 || state.dataFurnaces->HPDehumidificationLoadFlag) {
    7263              : 
    7264              :                         // check bounds on sensible output prior to iteration using RegulaFalsi
    7265              :                         // Negative value represents cooling load, IF FullSensibleOutput .GT. CoolCoilLoad, load is greater than capacity
    7266      1245634 :                         if (FullSensibleOutput >= CoolCoilLoad) {
    7267       113264 :                             PartLoadRatio = 1.0;
    7268              :                             //           Likewise IF NoCoolOutput .LT. CoolCoilLoad, then load can be met using only the fan (constant fan mode only)
    7269      1132370 :                         } else if (NoCoolOutput <= CoolCoilLoad) {
    7270         2066 :                             PartLoadRatio = 0.0;
    7271              :                             //           ELSE load is between NoCoolOutput and FullSensibleOuput, find PLR required to meet load
    7272              :                         } else {
    7273              : 
    7274              :                             // Calculate the sensible part load ratio through iteration
    7275      1130304 :                             CoolErrorToler = thisFurnace.CoolingConvergenceTolerance; // Error tolerance for convergence from input deck
    7276      1130304 :                             int SolFlag = 0; // # of iterations if positive, -1 means failed to converge, -2 means bounds are incorrect
    7277      1130304 :                             Real64 par8_HXFlag = HXUnitOn ? 1.0 : 0.0;
    7278              :                             // CoolErrorToler is in fraction of load, MaxIter = 30, SolFalg = # of iterations or error as appropriate
    7279              :                             auto f =
    7280      5426240 :                                 [&state, FurnaceNum, FirstHVACIteration, fanOp, compressorOp, CoolCoilLoad, par8_HXFlag](Real64 const PartLoadRatio) {
    7281      4295936 :                                     return CalcFurnaceResidual(state,
    7282              :                                                                PartLoadRatio,
    7283              :                                                                FurnaceNum,
    7284              :                                                                FirstHVACIteration,
    7285              :                                                                fanOp,
    7286              :                                                                compressorOp,
    7287              :                                                                CoolCoilLoad,
    7288              :                                                                1.0,         // par6_loadFlag,
    7289              :                                                                1.0,         // par7_sensLatentFlag,
    7290              :                                                                par8_HXFlag, // par9_HXOnFlag,
    7291      4295936 :                                                                0.0);        // par10_HeatingCoilPLR);
    7292      1130304 :                                 };
    7293      1130304 :                             General::SolveRoot(state, CoolErrorToler, MaxIter, SolFlag, PartLoadRatio, f, 0.0, 1.0);
    7294              :                             //             OnOffAirFlowRatio is updated during the above iteration. Reset to correct value based on PLR.
    7295      1130304 :                             OnOffAirFlowRatio = state.dataFurnaces->OnOffAirFlowRatioSave;
    7296      1130304 :                             if (SolFlag < 0) {
    7297            0 :                                 if (SolFlag == -1) {
    7298            0 :                                     CalcFurnaceOutput(state,
    7299              :                                                       FurnaceNum,
    7300              :                                                       FirstHVACIteration,
    7301              :                                                       fanOp,
    7302              :                                                       compressorOp,
    7303              :                                                       PartLoadRatio,
    7304              :                                                       0.0,
    7305              :                                                       0.0,
    7306              :                                                       0.0,
    7307              :                                                       TempCoolOutput,
    7308              :                                                       TempLatentOutput,
    7309              :                                                       OnOffAirFlowRatio,
    7310            0 :                                                       HXUnitOn);
    7311            0 :                                     if (!state.dataGlobal->WarmupFlag) {
    7312            0 :                                         if (std::abs(CoolCoilLoad - TempCoolOutput) > HVAC::SmallLoad) {
    7313            0 :                                             if (thisFurnace.SensibleMaxIterIndex == 0) {
    7314            0 :                                                 ShowWarningMessage(state,
    7315            0 :                                                                    format("Cooling coil control failed to converge for {}:{}",
    7316            0 :                                                                           HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    7317            0 :                                                                           thisFurnace.Name));
    7318            0 :                                                 ShowContinueError(
    7319              :                                                     state, "  Iteration limit exceeded in calculating DX cooling coil sensible part-load ratio.");
    7320            0 :                                                 ShowContinueErrorTimeStamp(state,
    7321            0 :                                                                            format("Sensible load to be met by DX coil = {:.2T} (watts), sensible "
    7322              :                                                                                   "output of DX coil = {:.2T} (watts), and the simulation continues.",
    7323              :                                                                                   CoolCoilLoad,
    7324              :                                                                                   TempCoolOutput));
    7325              :                                             }
    7326            0 :                                             ShowRecurringWarningErrorAtEnd(
    7327              :                                                 state,
    7328            0 :                                                 format("{} \"{}\" - Iteration limit exceeded in calculating sensible cooling "
    7329              :                                                        "part-load ratio error continues. Sensible load statistics:",
    7330            0 :                                                        HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    7331            0 :                                                        thisFurnace.Name),
    7332            0 :                                                 thisFurnace.SensibleMaxIterIndex,
    7333              :                                                 CoolCoilLoad,
    7334              :                                                 CoolCoilLoad);
    7335              :                                         }
    7336              :                                     }
    7337            0 :                                 } else if (SolFlag == -2) {
    7338            0 :                                     if (!state.dataGlobal->WarmupFlag) {
    7339            0 :                                         if (thisFurnace.SensibleRegulaFalsiFailedIndex == 0) {
    7340            0 :                                             ShowWarningMessage(state,
    7341            0 :                                                                format("Cooling coil control failed for {}:{}",
    7342            0 :                                                                       HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    7343            0 :                                                                       thisFurnace.Name));
    7344            0 :                                             ShowContinueError(state, "  Cooling sensible part-load ratio determined to be outside the range of 0-1.");
    7345            0 :                                             ShowContinueErrorTimeStamp(state, format("  Cooling sensible load = {:.2T}", CoolCoilLoad));
    7346              :                                         }
    7347            0 :                                         ShowRecurringWarningErrorAtEnd(
    7348              :                                             state,
    7349            0 :                                             format("{} \"{}\" - Cooling sensible part-load ratio out of range error continues. Sensible cooling load "
    7350              :                                                    "statistics:",
    7351            0 :                                                    HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    7352            0 :                                                    thisFurnace.Name),
    7353            0 :                                             thisFurnace.SensibleRegulaFalsiFailedIndex,
    7354              :                                             CoolCoilLoad,
    7355              :                                             CoolCoilLoad);
    7356              :                                     }
    7357              :                                 }
    7358              :                             }
    7359              :                         }
    7360              : 
    7361              :                     } else {
    7362       145536 :                         PartLoadRatio = 0.0;
    7363              :                     } // EndIf for IF(CoolCoilLoad.NE.0.0)
    7364              : 
    7365              :                     //       Calculate the delivered capacity from the PLR calculated above
    7366      1391170 :                     CalcFurnaceOutput(state,
    7367              :                                       FurnaceNum,
    7368              :                                       FirstHVACIteration,
    7369              :                                       fanOp,
    7370              :                                       compressorOp,
    7371              :                                       PartLoadRatio,
    7372              :                                       thisFurnace.HeatPartLoadRatio,
    7373              :                                       0.0,
    7374              :                                       0.0,
    7375              :                                       TempCoolOutput,
    7376              :                                       TempLatentOutput,
    7377              :                                       OnOffAirFlowRatio,
    7378      1391170 :                                       HXUnitOn);
    7379              : 
    7380              :                     //       Calculate the latent part load ratio through iteration
    7381              :                     //       Negative SystemMoistureLoad means dehumidification load is present
    7382              :                     //       IF this furnace uses MultiMode control AND there is a moisture load AND the moisture load met by the furnace in
    7383              :                     //       cooling only mode above is sufficient to meet the moisture demand OR there is no sensible load (PLR=0 from above)
    7384              :                     //       then set LatentPartLoadRatio to 0 (no additional dehumidification is required).
    7385      1391170 :                     if (thisFurnace.DehumidControlType_Num == DehumidificationControlMode::Multimode &&
    7386         8440 :                         ((SystemMoistureLoad < 0.0 && TempLatentOutput < SystemMoistureLoad) || PartLoadRatio == 0.0)) {
    7387          634 :                         LatentPartLoadRatio = 0.0;
    7388              :                         //       ELSE calculate a new PLR for valid dehumidification control types if a moisture load exists.
    7389      1657651 :                     } else if (thisFurnace.DehumidControlType_Num != DehumidificationControlMode::None &&
    7390       267115 :                                (SystemMoistureLoad < 0.0 || (SystemMoistureLoad >= 0.0 && TempLatentOutput > SystemMoistureLoad &&
    7391         8816 :                                                              !state.dataZoneEnergyDemand->Setback(thisFurnace.ControlZoneNum)))) {
    7392              : 
    7393              :                         //         IF the furnace uses dehumidification control MultiMode, turn on the HX and calculate the latent output with
    7394              :                         //         the HX ON to compare to the moisture load predicted by the humidistat.
    7395       188058 :                         if (thisFurnace.DehumidControlType_Num == DehumidificationControlMode::Multimode) {
    7396         7580 :                             HXUnitOn = true;
    7397         7580 :                             state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = thisFurnace.MdotFurnace;
    7398              :                             // Set fan part-load fraction equal to 1 while getting full load result
    7399         7580 :                             state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
    7400         7580 :                             OnOffAirFlowRatio = 1.0;
    7401              :                             // Get full load result
    7402         7580 :                             CalcFurnaceOutput(state,
    7403              :                                               FurnaceNum,
    7404              :                                               FirstHVACIteration,
    7405              :                                               fanOp,
    7406              :                                               compressorOp,
    7407              :                                               1.0,
    7408              :                                               0.0,
    7409              :                                               0.0,
    7410              :                                               0.0,
    7411              :                                               TempCoolOutput,
    7412              :                                               TempLatentOutput,
    7413              :                                               OnOffAirFlowRatio,
    7414         7580 :                                               HXUnitOn);
    7415              :                         }
    7416              : 
    7417              :                         //         Set the global cooling to heating PLR ratio. CoolHeatPLRRat = MIN(1,CoolingPLR/HeatingPLR)
    7418       188058 :                         state.dataFurnaces->CoolHeatPLRRat = 1.0; // means cooling dominated operation (applies to cycling fan mode)
    7419              : 
    7420       188058 :                         if (TempLatentOutput > SystemMoistureLoad) {
    7421              :                             //           Set full mass flow rate for full load calculation
    7422       184495 :                             state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = thisFurnace.MdotFurnace;
    7423              : 
    7424              :                             // Set fan part-load fraction equal to 1 while getting full load result
    7425       184495 :                             state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
    7426       184495 :                             OnOffAirFlowRatio = 1.0;
    7427       184495 :                             thisFurnace.CompPartLoadRatio = 1.0; // compressor ON
    7428              : 
    7429              :                             // Get full load result (coils simulated full ON)
    7430       184495 :                             CalcFurnaceOutput(state,
    7431              :                                               FurnaceNum,
    7432              :                                               FirstHVACIteration,
    7433              :                                               fanOp,
    7434              :                                               compressorOp,
    7435              :                                               1.0,
    7436              :                                               0.0,
    7437              :                                               0.0,
    7438              :                                               0.0,
    7439              :                                               TempCoolOutput,
    7440              :                                               TempLatentOutput,
    7441              :                                               OnOffAirFlowRatio,
    7442       184495 :                                               HXUnitOn);
    7443              :                         }
    7444              : 
    7445              :                         // check bounds on latent output prior to iteration using RegulaFalsi
    7446       188058 :                         if (TempLatentOutput > SystemMoistureLoad ||
    7447        55180 :                             (thisFurnace.DehumidControlType_Num == DehumidificationControlMode::Multimode && TempCoolOutput > CoolCoilLoad)) {
    7448       132878 :                             LatentPartLoadRatio = 1.0;
    7449        55180 :                         } else if (NoLatentOutput < SystemMoistureLoad || HeatingLatentOutput < SystemMoistureLoad) {
    7450           94 :                             LatentPartLoadRatio = 0.0;
    7451              :                         } else {
    7452              : 
    7453        55086 :                             CoolErrorToler = thisFurnace.CoolingConvergenceTolerance; // Error tolerance for convergence
    7454              : 
    7455        55086 :                             int SolFlag = 0; // # of iterations if positive, -1 means failed to converge, -2 means bounds are incorrect
    7456              :                             // Multimode always controls to meet the SENSIBLE load (however, HXUnitOn is now TRUE)
    7457              :                             Real64 par4_load;
    7458        55086 :                             if (thisFurnace.DehumidControlType_Num == DehumidificationControlMode::Multimode) {
    7459          772 :                                 par4_load = CoolCoilLoad;
    7460              :                             } else {
    7461        54314 :                                 par4_load = SystemMoistureLoad;
    7462              :                             }
    7463              :                             // Multimode always controls to meet the SENSIBLE load (however, HXUnitOn is now TRUE)
    7464              :                             Real64 par6_LatentSens;
    7465        55086 :                             if (thisFurnace.DehumidControlType_Num == DehumidificationControlMode::Multimode) {
    7466          772 :                                 par6_LatentSens = 1.0;
    7467              :                             } else {
    7468        54314 :                                 par6_LatentSens = 0.0;
    7469              :                             }
    7470        55086 :                             Real64 par8_HXUnit = HXUnitOn ? 1.0 : 0.0;
    7471              :                             Real64 par9_HtgCoilPLR;
    7472        55086 :                             if (fanOp == HVAC::FanOp::Cycling && thisFurnace.HeatPartLoadRatio > 0.0 && par6_LatentSens == 0.0) {
    7473            0 :                                 par9_HtgCoilPLR = thisFurnace.HeatPartLoadRatio;
    7474              :                             } else {
    7475        55086 :                                 par9_HtgCoilPLR = 0.0;
    7476              :                             }
    7477       448688 :                             auto f = [&state,
    7478              :                                       FurnaceNum,
    7479              :                                       FirstHVACIteration,
    7480              :                                       fanOp,
    7481              :                                       compressorOp,
    7482              :                                       par4_load,
    7483              :                                       par6_LatentSens,
    7484              :                                       par8_HXUnit,
    7485              :                                       par9_HtgCoilPLR](Real64 const PartLoadRatio) {
    7486       448688 :                                 return CalcFurnaceResidual(state,
    7487              :                                                            PartLoadRatio,
    7488              :                                                            FurnaceNum,
    7489              :                                                            FirstHVACIteration,
    7490              :                                                            fanOp,
    7491              :                                                            compressorOp,
    7492              :                                                            par4_load,
    7493              :                                                            1.0,              // par6_loadFlag,
    7494              :                                                            par6_LatentSens,  // par7_sensLatentFlag,
    7495              :                                                            par8_HXUnit,      // par9_HXOnFlag,
    7496       448688 :                                                            par9_HtgCoilPLR); // par10_HeatingCoilPLR);
    7497        55086 :                             };
    7498              :                             //           CoolErrorToler is in fraction of load, MaxIter = 30, SolFalg = # of iterations or error as appropriate
    7499        55086 :                             General::SolveRoot(state, CoolErrorToler, MaxIter, SolFlag, LatentPartLoadRatio, f, 0.0, 1.0);
    7500              :                             //           OnOffAirFlowRatio is updated during the above iteration. Reset to correct value based on PLR.
    7501        55086 :                             OnOffAirFlowRatio = state.dataFurnaces->OnOffAirFlowRatioSave;
    7502        55086 :                             if (SolFlag == -1) {
    7503              :                                 //             RegulaFalsi may not find latent PLR when the latent degradation model is used.
    7504              :                                 //             If iteration limit is exceeded, find tighter boundary of solution and repeat RegulaFalsi
    7505           98 :                                 TempMaxPLR = -0.1;
    7506           98 :                                 TempLatentOutput = NoLatentOutput;
    7507          498 :                                 while ((TempLatentOutput - SystemMoistureLoad) > 0.0 && TempMaxPLR < 1.0) {
    7508              :                                     //               find upper limit of LatentPLR
    7509          400 :                                     TempMaxPLR += 0.1;
    7510              : 
    7511              :                                     //               Same calculation as is done in Function CalcFurnaceResidual for latent PLR calculation.
    7512              :                                     //               Set cooling to heating PLR for use with Subroutine CalcFurnaceOutput. IF Par(10) = 0,
    7513              :                                     //               heating PLR = 0 so set the CoolingHeatingPLRRatio to 1 so the cooling PLR is used in the
    7514              :                                     //               DX cooling coil calculations.
    7515          400 :                                     if (par9_HtgCoilPLR > 0.0) {
    7516              :                                         //                 Par(10) = Furnace(FurnaceNum)%HeatPartLoadRatio
    7517              :                                         //                 fanOp = CycFan and Furnace(FurnaceNum)%HeatPartLoadRatio must be > 0 for Part(10) to be
    7518              :                                         //                 greater than 0
    7519            0 :                                         CoolingHeatingPLRRatio = min(1.0, TempMaxPLR / thisFurnace.HeatPartLoadRatio);
    7520              :                                     } else {
    7521          400 :                                         CoolingHeatingPLRRatio = 1.0;
    7522              :                                     }
    7523              : 
    7524          400 :                                     CalcFurnaceOutput(state,
    7525              :                                                       FurnaceNum,
    7526              :                                                       FirstHVACIteration,
    7527              :                                                       fanOp,
    7528              :                                                       compressorOp,
    7529              :                                                       TempMaxPLR,
    7530              :                                                       0.0,
    7531              :                                                       0.0,
    7532              :                                                       0.0,
    7533              :                                                       TempCoolOutput,
    7534              :                                                       TempLatentOutput,
    7535              :                                                       OnOffAirFlowRatio,
    7536          400 :                                                       HXUnitOn,
    7537              :                                                       CoolingHeatingPLRRatio);
    7538              :                                 }
    7539           98 :                                 TempMinPLR = TempMaxPLR;
    7540          876 :                                 while ((TempLatentOutput - SystemMoistureLoad) < 0.0 && TempMinPLR > 0.0) {
    7541              :                                     //               pull upper limit of LatentPLR down to last valid limit (i.e. latent output still exceeds
    7542              :                                     //               SystemMoisuterLoad) CR7558 - relax final limits to allow HX assisted coils to converge
    7543          778 :                                     TempMaxPLR = TempMinPLR + 0.001;
    7544              :                                     //               find minimum limit of Latent PLR
    7545          778 :                                     TempMinPLR -= 0.001;
    7546              : 
    7547              :                                     //               Set cooling to heating PLR for use with Subroutine CalcFurnaceOutput.
    7548          778 :                                     if (par9_HtgCoilPLR > 0.0) {
    7549              :                                         //                 Par(10) = Furnace(FurnaceNum)%HeatPartLoadRatio
    7550              :                                         //                 fanOp = CycFan and Furnace(FurnaceNum)%HeatPartLoadRatio must be > 0 for Part(10) to be
    7551              :                                         //                 greater than 0 Since the latent output of cycling fan systems is 0 at PLR=0, do not allow
    7552              :                                         //                 the PLR to be 0, otherwise RegulaFalsi can fail when a heating and moisture load exists and
    7553              :                                         //                 heating PLR > latent PLR.
    7554            0 :                                         TempMinPLR2 = max(0.0000000001, TempMinPLR);
    7555            0 :                                         CoolingHeatingPLRRatio = min(1.0, TempMinPLR2 / thisFurnace.HeatPartLoadRatio);
    7556              :                                     } else {
    7557          778 :                                         TempMinPLR2 = TempMinPLR;
    7558          778 :                                         CoolingHeatingPLRRatio = 1.0;
    7559              :                                     }
    7560              : 
    7561          778 :                                     CalcFurnaceOutput(state,
    7562              :                                                       FurnaceNum,
    7563              :                                                       FirstHVACIteration,
    7564              :                                                       fanOp,
    7565              :                                                       compressorOp,
    7566              :                                                       TempMinPLR2,
    7567              :                                                       0.0,
    7568              :                                                       0.0,
    7569              :                                                       0.0,
    7570              :                                                       TempCoolOutput,
    7571              :                                                       TempLatentOutput,
    7572              :                                                       OnOffAirFlowRatio,
    7573          778 :                                                       HXUnitOn,
    7574              :                                                       CoolingHeatingPLRRatio);
    7575              :                                 }
    7576              :                                 //             tighter boundary of solution has been found, call RegulaFalsi a second time
    7577          494 :                                 auto f2 = [&state,
    7578              :                                            FurnaceNum,
    7579              :                                            FirstHVACIteration,
    7580              :                                            fanOp,
    7581              :                                            compressorOp,
    7582              :                                            par4_load,
    7583              :                                            par6_LatentSens,
    7584              :                                            par8_HXUnit,
    7585              :                                            par9_HtgCoilPLR](Real64 const PartLoadRatio) {
    7586          494 :                                     return CalcFurnaceResidual(state,
    7587              :                                                                PartLoadRatio,
    7588              :                                                                FurnaceNum,
    7589              :                                                                FirstHVACIteration,
    7590              :                                                                fanOp,
    7591              :                                                                compressorOp,
    7592              :                                                                par4_load,
    7593              :                                                                1.0,              // par6_loadFlag,
    7594              :                                                                par6_LatentSens,  // par7_sensLatentFlag,
    7595              :                                                                par8_HXUnit,      // par9_HXOnFlag,
    7596          494 :                                                                par9_HtgCoilPLR); // par10_HeatingCoilPLR);
    7597           98 :                                 };
    7598           98 :                                 General::SolveRoot(state, CoolErrorToler, MaxIter, SolFlag, LatentPartLoadRatio, f2, TempMinPLR2, TempMaxPLR);
    7599              :                                 //             OnOffAirFlowRatio is updated during the above iteration. Reset to correct value based on PLR.
    7600           98 :                                 OnOffAirFlowRatio = state.dataFurnaces->OnOffAirFlowRatioSave;
    7601           98 :                                 if (SolFlag == -1) {
    7602              : 
    7603              :                                     //               Set cooling to heating PLR for use with Subroutine CalcFurnaceOutput.
    7604           48 :                                     if (par9_HtgCoilPLR > 0.0) {
    7605              :                                         //                 Par(10) = Furnace(FurnaceNum)%HeatPartLoadRatio
    7606              :                                         //                 fanOp = CycFan and Furnace(FurnaceNum)%HeatPartLoadRatio must be > 0 for Part(10) to be
    7607              :                                         //                 greater than 0
    7608            0 :                                         CoolingHeatingPLRRatio = min(1.0, LatentPartLoadRatio / thisFurnace.HeatPartLoadRatio);
    7609              :                                     } else {
    7610           48 :                                         CoolingHeatingPLRRatio = 1.0;
    7611              :                                     }
    7612              : 
    7613           48 :                                     CalcFurnaceOutput(state,
    7614              :                                                       FurnaceNum,
    7615              :                                                       FirstHVACIteration,
    7616              :                                                       fanOp,
    7617              :                                                       compressorOp,
    7618              :                                                       LatentPartLoadRatio,
    7619              :                                                       0.0,
    7620              :                                                       0.0,
    7621              :                                                       0.0,
    7622              :                                                       TempCoolOutput,
    7623              :                                                       TempLatentOutput,
    7624              :                                                       OnOffAirFlowRatio,
    7625           48 :                                                       HXUnitOn,
    7626              :                                                       CoolingHeatingPLRRatio);
    7627           96 :                                     if (std::abs((SystemMoistureLoad - TempLatentOutput) / SystemMoistureLoad) > CoolErrorToler &&
    7628           48 :                                         std::abs(SystemMoistureLoad - TempLatentOutput) > 10.0) {
    7629            0 :                                         if (!state.dataGlobal->WarmupFlag) {
    7630            0 :                                             if (thisFurnace.LatentMaxIterIndex == 0) {
    7631            0 :                                                 ShowWarningMessage(state,
    7632            0 :                                                                    format("Cooling coil control failed to converge for {}:{}",
    7633            0 :                                                                           HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    7634            0 :                                                                           thisFurnace.Name));
    7635            0 :                                                 ShowContinueError(state,
    7636              :                                                                   "  Iteration limit exceeded in calculating cooling coil latent part-load ratio.");
    7637            0 :                                                 ShowContinueError(
    7638              :                                                     state,
    7639            0 :                                                     format("  Latent load convergence error (percent) = {:.2T}",
    7640            0 :                                                            100.0 * std::abs((SystemMoistureLoad - TempLatentOutput) / SystemMoistureLoad)));
    7641            0 :                                                 ShowContinueErrorTimeStamp(state,
    7642            0 :                                                                            format("Moisture load to be met by DX coil = {:.2T} (watts), Latent "
    7643              :                                                                                   "output of DX coil = {:.2T} (watts), and the simulation continues.",
    7644              :                                                                                   SystemMoistureLoad,
    7645              :                                                                                   TempLatentOutput));
    7646              :                                             }
    7647            0 :                                             ShowRecurringWarningErrorAtEnd(
    7648              :                                                 state,
    7649            0 :                                                 format("{} \"{}\" - Iteration limit exceeded in calculating latent part-load ratio error continues. "
    7650              :                                                        "Latent "
    7651              :                                                        "load convergence error (percent) statistics follow.",
    7652            0 :                                                        HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    7653            0 :                                                        thisFurnace.Name),
    7654            0 :                                                 thisFurnace.LatentMaxIterIndex,
    7655            0 :                                                 100.0 * std::abs((SystemMoistureLoad - TempLatentOutput) / SystemMoistureLoad),
    7656            0 :                                                 100.0 * std::abs((SystemMoistureLoad - TempLatentOutput) / SystemMoistureLoad));
    7657              :                                         }
    7658              :                                     }
    7659           50 :                                 } else if (SolFlag == -2) {
    7660            0 :                                     if (thisFurnace.LatentRegulaFalsiFailedIndex2 == 0) {
    7661            0 :                                         ShowWarningMessage(state,
    7662            0 :                                                            format("Cooling coil control failed for {}:{}",
    7663            0 :                                                                   HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    7664            0 :                                                                   thisFurnace.Name));
    7665            0 :                                         ShowContinueError(state,
    7666            0 :                                                           format("  Latent part-load ratio determined to be outside the range of {:.3T} to {:.3T}.",
    7667              :                                                                  TempMinPLR,
    7668              :                                                                  TempMaxPLR));
    7669            0 :                                         ShowContinueErrorTimeStamp(state,
    7670            0 :                                                                    format("A PLR of {:.3T} will be used and the simulation continues.", TempMinPLR));
    7671              :                                     }
    7672            0 :                                     ShowRecurringWarningErrorAtEnd(state,
    7673            0 :                                                                    format("{} \"{}\" - Cooling sensible part-load ratio out of range error "
    7674              :                                                                           "continues. System moisture load statistics:",
    7675            0 :                                                                           HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    7676            0 :                                                                           thisFurnace.Name),
    7677            0 :                                                                    thisFurnace.LatentRegulaFalsiFailedIndex2,
    7678              :                                                                    SystemMoistureLoad,
    7679              :                                                                    SystemMoistureLoad);
    7680            0 :                                     LatentPartLoadRatio = TempMinPLR;
    7681              :                                 }
    7682        54988 :                             } else if (SolFlag == -2) {
    7683            0 :                                 if (thisFurnace.LatentRegulaFalsiFailedIndex == 0) {
    7684            0 :                                     ShowWarningMessage(state,
    7685            0 :                                                        format("Cooling coil control failed for {}:{}",
    7686            0 :                                                               HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    7687            0 :                                                               thisFurnace.Name));
    7688            0 :                                     ShowContinueError(state, "  Latent part-load ratio determined to be outside the range of 0-1.");
    7689            0 :                                     ShowContinueErrorTimeStamp(state, "A PLR of 0 will be used and the simulation continues.");
    7690              :                                 }
    7691            0 :                                 ShowRecurringWarningErrorAtEnd(
    7692              :                                     state,
    7693            0 :                                     format("{} \"{}\" - Latent part-load ratio out of range or 0-1 error continues. System moisture load statistics:",
    7694            0 :                                            HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    7695            0 :                                            thisFurnace.Name),
    7696            0 :                                     thisFurnace.LatentRegulaFalsiFailedIndex,
    7697              :                                     SystemMoistureLoad,
    7698              :                                     SystemMoistureLoad);
    7699            0 :                                 LatentPartLoadRatio = 0.0;
    7700              :                             }
    7701              :                         }
    7702              : 
    7703              :                         //         Cooling to heating PLR ratio is now known as CoolHeatPLRRat (Module level global set in CalcFurnaceOutput
    7704              :                         //         This same variable is use in Subroutine SimFurnace for final calculations.
    7705              :                         //         Get the actual output in case reheat needs to be calculated (HumControl=TRUE [latent PLR > sensible PLR])
    7706       188058 :                         CalcFurnaceOutput(state,
    7707              :                                           FurnaceNum,
    7708              :                                           FirstHVACIteration,
    7709              :                                           fanOp,
    7710              :                                           compressorOp,
    7711              :                                           LatentPartLoadRatio,
    7712              :                                           0.0,
    7713              :                                           0.0,
    7714              :                                           0.0,
    7715              :                                           ActualSensibleOutput,
    7716              :                                           ActualLatentOutput,
    7717              :                                           OnOffAirFlowRatio,
    7718       188058 :                                           HXUnitOn,
    7719       188058 :                                           state.dataFurnaces->CoolHeatPLRRat);
    7720              : 
    7721              :                     } else {
    7722      1202478 :                         LatentPartLoadRatio = 0.0;
    7723              :                     } // ENDIF for valid dehumidification control types
    7724              : 
    7725              :                     //       IF a humidistat is used and there is a moisture load, check if the latent PLR is greater than the (sensible) PLR
    7726              :                     //        IF(LatentPartLoadRatio .GT. PartLoadRatio .and. SystemMoistureLoad .lt. 0.0 .and. Furnace(FurnaceNum)%Humidistat) THEN
    7727      1391170 :                     if (LatentPartLoadRatio > PartLoadRatio && thisFurnace.Humidistat) {
    7728              :                         // For dehumidification mode CoolReheat, compare the Sensible and Latent PLR values, if latentPLR is greater
    7729              :                         // than PLR (sensible), then overcooling is required and reheat will be activated using the HumControl flag.
    7730       185083 :                         if (thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat) {
    7731       177589 :                             PartLoadRatio = LatentPartLoadRatio;
    7732       177589 :                             HumControl = true;
    7733              :                         }
    7734              :                         // For dehumidification mode MultiMode, compare the Sensible and Latent PLR values, if latentPLR is
    7735              :                         // greater than PLR (sensible), then use the latent PLR to control the unit.
    7736              :                         // For MultiMode control, the latent PLR is found by enabling the HX and calculating a PLR required to meet the
    7737              :                         // sensible load. Overcooling is not required, and reheat will not be activated using the HumControl flag.
    7738       185083 :                         if (thisFurnace.DehumidControlType_Num == DehumidificationControlMode::Multimode) {
    7739         7494 :                             PartLoadRatio = LatentPartLoadRatio;
    7740              :                         }
    7741              :                     }
    7742              : 
    7743      1391170 :                     thisFurnace.CoolPartLoadRatio = PartLoadRatio;
    7744      1391170 :                     if (compressorOp == HVAC::CompressorOp::Off) {
    7745         4090 :                         thisFurnace.CompPartLoadRatio = 0.0;
    7746              :                     } else {
    7747      1387080 :                         thisFurnace.CompPartLoadRatio = PartLoadRatio;
    7748              :                     }
    7749              : 
    7750              :                 } else { // ELSE from IF(FullSensibleOutput.LT.NoCoolOutput)THEN above
    7751              :                     // CR8679 - Unitary Heat Cool control problem, will not run to meeting cooling load
    7752              :                     // underlying problem is that FullSensibleOutput is greater than 0 due to very high inlet temp, so the system should be on
    7753              :                     // NoCoolOutput was 0 since the defect file is a cycling fan system and the system was turned off
    7754              : 
    7755              :                     // if FullSensibleOutput > NoCoolOutput, it means the system cannot meet the load and will run full out
    7756              :                     // this same logic for WSHP does not seem to work (only the Unitary Heat Pump Compressor Part-Load Ratio report
    7757              :                     // variable was affected in the HeatPumpWaterToAirRHControl.idf file while other variables showed very small diffs).
    7758              :                     // The defect files meter.csv showed 2% diffs so this IF test is used to keep the results the same in that file.
    7759              :                     // Additional logic is used here to make sure the coil actually turned on, e.g., if DX coil PLR > 0 then set to 1,
    7760              :                     // otherwise 0 (to make sure coil is actually ON and not off due to schedule, OAT, or other reason).
    7761              :                     // The global variable DXCoilPartLoadRatio(DXCoilNum) is not yet used for the WSHP to make the same check.
    7762         4710 :                     if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir) {
    7763          230 :                         thisFurnace.CoolPartLoadRatio = 0.0;
    7764          230 :                         thisFurnace.CompPartLoadRatio = 0.0;
    7765              :                     } else {
    7766         4480 :                         if (thisFurnace.CoolingCoilType_Num == HVAC::CoilDX_CoolingHXAssisted) {
    7767              : 
    7768              :                             // VS coil issue here...
    7769            0 :                             if (state.dataDXCoils->DXCoilPartLoadRatio(thisFurnace.ActualDXCoilIndexForHXAssisted) > 0.0) {
    7770            0 :                                 thisFurnace.CoolPartLoadRatio = 1.0;
    7771            0 :                                 thisFurnace.CompPartLoadRatio = 1.0;
    7772              :                             } else {
    7773            0 :                                 thisFurnace.CoolPartLoadRatio = 0.0;
    7774            0 :                                 thisFurnace.CompPartLoadRatio = 0.0;
    7775              :                             }
    7776              :                         } else {
    7777         4480 :                             if (state.dataDXCoils->DXCoilPartLoadRatio(thisFurnace.CoolingCoilIndex) > 0.0) {
    7778            0 :                                 thisFurnace.CoolPartLoadRatio = 1.0;
    7779            0 :                                 thisFurnace.CompPartLoadRatio = 1.0;
    7780              :                             } else {
    7781         4480 :                                 thisFurnace.CoolPartLoadRatio = 0.0;
    7782         4480 :                                 thisFurnace.CompPartLoadRatio = 0.0;
    7783              :                             }
    7784              :                         }
    7785              :                     }
    7786              :                 }
    7787              : 
    7788              :                 //     Calculate the reheat coil output
    7789      1395880 :                 if (HumControl) { // HumControl = .TRUE. if a Humidistat is installed and dehumidification control type is CoolReheat
    7790       177589 :                     if (thisFurnace.ZoneSequenceHeatingNum > 0) {
    7791       177589 :                         QToHeatSetPt = (state.dataZoneEnergyDemand->ZoneSysEnergyDemand(thisFurnace.ControlZoneNum)
    7792       177589 :                                             .SequencedOutputRequiredToHeatingSP(thisFurnace.ZoneSequenceHeatingNum) /
    7793       177589 :                                         thisFurnace.ControlZoneMassFlowFrac);
    7794              :                     } else {
    7795            0 :                         QToHeatSetPt = (state.dataZoneEnergyDemand->ZoneSysEnergyDemand(thisFurnace.ControlZoneNum).OutputRequiredToHeatingSP /
    7796            0 :                                         thisFurnace.ControlZoneMassFlowFrac);
    7797              :                     }
    7798              :                     //       Cooling mode or floating condition and dehumidification is required
    7799       177589 :                     if (QToHeatSetPt < 0.0) {
    7800              :                         //         Calculate the reheat coil load wrt the heating setpoint temperature. Reheat coil picks up
    7801              :                         //         the entire excess sensible cooling (DX cooling coil and impact of outdoor air).
    7802       165238 :                         ReheatCoilLoad = max(0.0, (QToHeatSetPt - ActualSensibleOutput));
    7803       165238 :                         thisFurnace.DehumidInducedHeatingDemandRate = ReheatCoilLoad;
    7804              :                         //       Heating mode and dehumidification is required
    7805              :                     } else {
    7806              :                         //         Calculate the reheat coil load as the sensible capacity of the DX cooling coil only. Let
    7807              :                         //         the heating coil pick up the load due to outdoor air.
    7808        12351 :                         ReheatCoilLoad = max(0.0, (ActualSensibleOutput - NoCoolOutput) * (-1.0));
    7809              :                         //         Dehumidification is not required
    7810        12351 :                         if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_AirToAir ||
    7811        10293 :                             (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir &&
    7812         7122 :                              thisFurnace.WatertoAirHPType == WAHPCoilType::Simple)) {
    7813         9180 :                             ReheatCoilLoad = max(QToHeatSetPt, QToHeatSetPt - ActualSensibleOutput);
    7814              :                         }
    7815        12351 :                         thisFurnace.DehumidInducedHeatingDemandRate = max(0.0, ActualSensibleOutput * (-1.0));
    7816              :                     }
    7817              :                 } else {
    7818              :                     //       No humidistat installed
    7819      1218291 :                     ReheatCoilLoad = 0.0;
    7820              :                 }
    7821              :             } // End of cooling section IF statement
    7822              : 
    7823      2987672 :             if (NoHeatOutput > SystemSensibleLoad && ReheatCoilLoad > 0.0) {
    7824              :                 // Reduce reheat coil load if you are controlling high humidity but outside air
    7825              :                 // and/or the supply air fan is providing enough heat to meet the system sensible load.
    7826              :                 // This will bring the zone temp closer to the heating setpoint temp.
    7827            0 :                 ReheatCoilLoad = max(0.0, ReheatCoilLoad - (NoHeatOutput - SystemSensibleLoad));
    7828              :             }
    7829              : 
    7830              :             // Set the final air flow. MdotFurnace will be used to set the fan part-load ratio in ReportFurnace
    7831      2987672 :             if (HumControl && SystemMoistureLoad < 0.0) {
    7832       169165 :                 if (fanOp == HVAC::FanOp::Cycling) {
    7833              :                     //       set the flow rate at the maximum of the cooling and heating PLR's
    7834          420 :                     SetAverageAirFlow(state, FurnaceNum, max(thisFurnace.CoolPartLoadRatio, thisFurnace.HeatPartLoadRatio), OnOffAirFlowRatio);
    7835              :                 } else {
    7836              :                     //       ELSE set the flow rate at the cooling PLR
    7837       168745 :                     SetAverageAirFlow(state, FurnaceNum, thisFurnace.CoolPartLoadRatio, OnOffAirFlowRatio);
    7838              :                 }
    7839              :             } else {
    7840      2818507 :                 SetAverageAirFlow(state, FurnaceNum, max(thisFurnace.CoolPartLoadRatio, thisFurnace.HeatPartLoadRatio), OnOffAirFlowRatio);
    7841              :             }
    7842      2987672 :             thisFurnace.MdotFurnace = state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate;
    7843              : 
    7844      2987672 :             if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_AirToAir ||
    7845      2739390 :                 (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir && thisFurnace.WatertoAirHPType == WAHPCoilType::Simple)) {
    7846              :             } else {
    7847              :                 // Non-HeatPump (non-DX) heating coils do not set PLR, reset to 0 here. This variable was set for non-DX
    7848              :                 // coils to allow the SetAverageAirFlow CALL above to set the correct air mass flow rate. See this
    7849              :                 // IF block above in heating section. HeatPLR is not set in the ELSE part of the IF (only HeatCoilLoad is set).
    7850      1401558 :                 thisFurnace.HeatPartLoadRatio = 0.0;
    7851              :             }
    7852              : 
    7853              :             //*********HVAC Scheduled OFF*************
    7854              :             // No heating or cooling or dehumidification
    7855              :             //!!LKL discrepancy with < 0?
    7856      2987672 :             if (thisFurnace.availSched->getCurrentVal() == 0.0 || state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate == 0.0) {
    7857       248712 :                 thisFurnace.MdotFurnace = 0.0;
    7858       248712 :                 CoolCoilLoad = 0.0;
    7859       248712 :                 HeatCoilLoad = 0.0;
    7860       248712 :                 ReheatCoilLoad = 0.0;
    7861       248712 :                 state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0; // System off, so set on/off fan part-load fraction = 1
    7862       248712 :                 thisFurnace.CoolPartLoadRatio = 0.0;
    7863       248712 :                 thisFurnace.HeatPartLoadRatio = 0.0;
    7864       248712 :                 thisFurnace.CompPartLoadRatio = 0.0;
    7865              :                 // set report variables
    7866       248712 :                 thisFurnace.CoolingCoilSensDemand = 0.0;
    7867       248712 :                 thisFurnace.CoolingCoilLatentDemand = 0.0;
    7868       248712 :                 thisFurnace.HeatingCoilSensDemand = 0.0;
    7869              :             }
    7870              : 
    7871              :         } // End of the FirstHVACIteration control of the mass flow If block
    7872              : 
    7873              :         // Set the fan inlet node flow rates
    7874      4573491 :         state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRateMaxAvail = thisFurnace.MdotFurnace;
    7875      4573491 :         state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = thisFurnace.MdotFurnace;
    7876      4573491 :     }
    7877              : 
    7878       119270 :     void CalcWaterToAirHeatPump(EnergyPlusData &state,
    7879              :                                 int const FurnaceNum,                  // index to Furnace
    7880              :                                 bool const FirstHVACIteration,         // TRUE on first HVAC iteration
    7881              :                                 HVAC::CompressorOp const compressorOp, // compressor operation flag (1=On, 0=Off)
    7882              :                                 Real64 const ZoneLoad,                 // the control zone load (watts)
    7883              :                                 Real64 const MoistureLoad              // the control zone latent load (watts)
    7884              :     )
    7885              :     {
    7886              : 
    7887              :         // SUBROUTINE INFORMATION:
    7888              :         //       AUTHOR         Dan Fisher
    7889              :         //       DATE WRITTEN   Feb 2004
    7890              :         //       MODIFIED       R. Raustad (Oct 2006) Revised iteration technique
    7891              : 
    7892              :         // PURPOSE OF THIS SUBROUTINE:
    7893              :         // This subroutine manages the heat pump simulation
    7894              : 
    7895              :         // METHODOLOGY EMPLOYED:
    7896              :         // Calculate the part-load ratio required to meet the zone sensible load.
    7897              : 
    7898              :         // SUBROUTINE PARAMETER DEFINITIONS:
    7899       119270 :         int constexpr MaxIter(600);   // maximum number of iterations
    7900       119270 :         Real64 constexpr MinPLR(0.0); // minimum part load ratio allowed
    7901              : 
    7902              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    7903              :         Real64 ZoneSensLoadMet;             // Actual zone sensible load met by heat pump (W)
    7904              :         Real64 ZoneLatLoadMet;              // Actual zone latent load met by heat pump (W)
    7905              :         Real64 ZoneSensLoadMetFanONCompON;  // Max Zone sensible load heat pump can meet (W)
    7906              :         Real64 ZoneLatLoadMetFanONCompON;   // Max Zone latent load heat pump can meet (W)
    7907              :         Real64 ZoneSensLoadMetFanONCompOFF; // control zone sensible load met using only outside air
    7908              :         // and fan heat (no coil output) (W)
    7909              :         Real64 ZoneLatLoadMetFanONCompOFF; // control zone Latent   load met using only outside air
    7910              :         // and fan heat (no coil output) (W)
    7911              :         Real64 HPCoilSensDemand;   // Heat pump sensible demand
    7912              :         Real64 HPCoilSensCapacity; // Heat pump sensible capacity
    7913              : 
    7914              :         Real64 SuppHeatCoilLoad; // Load passed to supplemental heater (W)
    7915              :         Real64 CoolErrorToler;   // convergence tolerance used in cooling mode
    7916              :         Real64 HeatErrorToler;   // convergence tolerance used in heating mode
    7917              :         int SolFlag;             // flag returned from iteration routine to denote problems
    7918              : 
    7919       119270 :         Real64 &TotalZoneLatentLoad = state.dataFurnaces->TotalZoneLatentLoad;
    7920       119270 :         Real64 &TotalZoneSensLoad = state.dataFurnaces->TotalZoneSensLoad;
    7921       119270 :         Real64 &CoolPartLoadRatio = state.dataFurnaces->CoolPartLoadRatio;
    7922       119270 :         Real64 &HeatPartLoadRatio = state.dataFurnaces->HeatPartLoadRatio;
    7923       119270 :         auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    7924              : 
    7925              :         // Set local variables
    7926       119270 :         Real64 Dummy2 = 0.0;            // used as dummy heat and reheat coil load
    7927       119270 :         Real64 OnOffAirFlowRatio = 1.0; // Ratio of compressor ON air mass flow to AVERAGE air mass flow over time step
    7928       119270 :         int FurnaceInletNode = thisFurnace.FurnaceInletNodeNum;
    7929       119270 :         HVAC::FanOp fanOp = thisFurnace.fanOp; // fan operating mode
    7930       119270 :         thisFurnace.MdotFurnace = thisFurnace.DesignMassFlowRate;
    7931              : 
    7932              :         //*********INITIAL CALCULATIONS****************
    7933              :         // set the fan part load fraction
    7934              :         // Note: OnOffFanPartLoadFraction is passed to the
    7935              :         //       fan module by DataHVACGlobals.  It should be
    7936              :         //     set =1 for all cases except cycling fan/cycling
    7937              :         //     coil. For this case it is set to the part load
    7938              :         //     factor.  In SimOnOffFan, the part load ratio is
    7939              :         //     divided by the part load factor (OnOffFanPartLoadFraction)
    7940              :         //     in order to match the run time fraction of the cycling
    7941              :         //     fan with the run time fraction of the cycling compressor
    7942       119270 :         if (FirstHVACIteration) {
    7943        36438 :             state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
    7944              :         }
    7945              : 
    7946              :         // Calc Zone sensible loads for heating (+) and cooling (-)
    7947       119270 :         TotalZoneSensLoad = ZoneLoad;
    7948              : 
    7949       119270 :         if (state.dataFurnaces->HeatingLoad) {
    7950        55271 :             TotalZoneLatentLoad = 0.0; // Set latent load for heating
    7951              :         } else {
    7952        63999 :             TotalZoneLatentLoad = MoistureLoad; // Set latent load for cooling and no sensible load condition
    7953              :         }
    7954              : 
    7955              :         //*********COOLING CALCULATIONS****************
    7956              :         // IF scheduled on...
    7957              :         // AND air flow rate is greater than zero...
    7958              :         // AND the air system has a cooling load and is not set back or in the deadband...
    7959              :         // OR the system is controlled by a humidistat and there is a latent load
    7960       212252 :         if ((thisFurnace.availSched->getCurrentVal() > 0.0 && state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate > 0.0) &&
    7961        92982 :             ((state.dataFurnaces->CoolingLoad) || (thisFurnace.Humidistat && thisFurnace.CoolingCoilLatentDemand < 0.0))) {
    7962              : 
    7963              :             // Set the air flow rate to the design flow rate and set the fan operation fraction to 1 (continuous operation)
    7964        37711 :             state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = thisFurnace.DesignMassFlowRate;
    7965        37711 :             state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0; // see 'Note' under INITIAL CALCULATIONS
    7966              : 
    7967              :             //         !Set the operation flag to run the fan continuously
    7968              :             //         fanOp = FanOp::Continuous
    7969              : 
    7970              :             // Set the input parameters for CalcFurnaceOutput
    7971        37711 :             thisFurnace.HeatingCoilSensDemand = 0.0;
    7972        37711 :             thisFurnace.CoolingCoilLatentDemand = 0.0;
    7973        37711 :             thisFurnace.CoolingCoilSensDemand = 0.0;
    7974        37711 :             thisFurnace.CompPartLoadRatio = 0.0; // compressor off
    7975        37711 :             thisFurnace.InitHeatPump = true;     // initialization call to Calc Furnace
    7976        37711 :             CoolPartLoadRatio = 0.0;
    7977              : 
    7978              :             // Get no load result in order to calculate the effect of the fan and the mixed air equipment
    7979        37711 :             CalcFurnaceOutput(state,
    7980              :                               FurnaceNum,
    7981              :                               FirstHVACIteration,
    7982              :                               fanOp,
    7983              :                               compressorOp,
    7984              :                               CoolPartLoadRatio,
    7985              :                               HeatPartLoadRatio,
    7986              :                               Dummy2,
    7987              :                               Dummy2,
    7988              :                               ZoneSensLoadMetFanONCompOFF,
    7989              :                               ZoneLatLoadMetFanONCompOFF,
    7990              :                               OnOffAirFlowRatio,
    7991              :                               false);
    7992              : 
    7993              :             // Set the input parameters for CalcFurnaceOutput
    7994        37711 :             thisFurnace.CoolingCoilSensDemand = 1.0;
    7995        37711 :             thisFurnace.CompPartLoadRatio = 1.0; // compressor ON
    7996        37711 :             CoolPartLoadRatio = 1.0;
    7997              : 
    7998              :             // Get full load result in order to estimate the operating part load ratio for continuous fan operation
    7999        37711 :             CalcFurnaceOutput(state,
    8000              :                               FurnaceNum,
    8001              :                               FirstHVACIteration,
    8002              :                               fanOp,
    8003              :                               compressorOp,
    8004              :                               CoolPartLoadRatio,
    8005              :                               HeatPartLoadRatio,
    8006              :                               Dummy2,
    8007              :                               Dummy2,
    8008              :                               ZoneSensLoadMetFanONCompON,
    8009              :                               ZoneLatLoadMetFanONCompON,
    8010              :                               OnOffAirFlowRatio,
    8011              :                               false);
    8012              : 
    8013              :             // Calculate the heating coil demand for continuous fan operation as:
    8014              :             //    (the zone sensible load - the zone sensible load met by fan heat and mixed air)
    8015              :             // Note; The sensible zone load met by fan heat and mixed air is calculated as:
    8016              :             //     mdotsys(control zone inlet enthalpy - control zone outlet enthalpy)
    8017              :             // This accounts for the negative sign in the equation.
    8018        37711 :             HPCoilSensDemand = TotalZoneSensLoad - ZoneSensLoadMetFanONCompOFF;
    8019              : 
    8020              :             // Calculate the heating coil capacity for continuous fan operation as:
    8021              :             //    (the zone sensible load met by fan heat and mixed air and coil
    8022              :             //   - the zone sensible load met by fan heat and mixed air)
    8023        37711 :             HPCoilSensCapacity = ZoneSensLoadMetFanONCompON - ZoneSensLoadMetFanONCompOFF;
    8024              : 
    8025              :             // Calculate the part load ratio for continuous fan operation with cycling coil
    8026        37711 :             if (HPCoilSensCapacity == 0.0) {
    8027            0 :                 CoolPartLoadRatio = 0.0;
    8028              :             } else {
    8029        37711 :                 CoolPartLoadRatio = max(MinPLR, min(1.0, std::abs(HPCoilSensDemand) / std::abs(HPCoilSensCapacity)));
    8030              :             }
    8031              : 
    8032        37711 :             thisFurnace.InitHeatPump = false;
    8033              : 
    8034              :             // check bounds on sensible output prior to iteration using RegulaFalsi
    8035        37711 :             if (ZoneSensLoadMetFanONCompON > TotalZoneSensLoad) {
    8036         2160 :                 CoolPartLoadRatio = 1.0;
    8037         2160 :                 HPCoilSensDemand = std::abs(ZoneSensLoadMetFanONCompON - ZoneSensLoadMetFanONCompOFF);
    8038         2160 :                 thisFurnace.CoolingCoilSensDemand = HPCoilSensDemand;
    8039        35551 :             } else if (ZoneSensLoadMetFanONCompOFF < TotalZoneSensLoad) {
    8040            0 :                 CoolPartLoadRatio = 0.0;
    8041            0 :                 thisFurnace.CompPartLoadRatio = 0.0; // compressor OFF
    8042            0 :                 thisFurnace.CoolingCoilSensDemand = 0.0;
    8043            0 :                 CalcFurnaceOutput(state,
    8044              :                                   FurnaceNum,
    8045              :                                   FirstHVACIteration,
    8046              :                                   fanOp,
    8047              :                                   compressorOp,
    8048              :                                   CoolPartLoadRatio,
    8049              :                                   HeatPartLoadRatio,
    8050              :                                   Dummy2,
    8051              :                                   Dummy2,
    8052              :                                   ZoneSensLoadMetFanONCompOFF,
    8053              :                                   ZoneLatLoadMetFanONCompOFF,
    8054              :                                   OnOffAirFlowRatio,
    8055              :                                   false);
    8056              :             } else {
    8057              :                 //         Calculate the sensible part load ratio through iteration
    8058        35551 :                 CoolErrorToler = thisFurnace.CoolingConvergenceTolerance;
    8059        35551 :                 SolFlag = 0; // # of iterations if positive, -1 means failed to converge, -2 means bounds are incorrect
    8060              :                 // CoolErrorToler is in fraction of load, MaxIter = 600, SolFalg = # of iterations or error as appropriate
    8061       143703 :                 auto f = [&state, FurnaceNum, FirstHVACIteration, fanOp, compressorOp, TotalZoneSensLoad, ZoneSensLoadMetFanONCompOFF](
    8062              :                              Real64 const PartLoadRatio) {
    8063       108152 :                     return CalcWaterToAirResidual(state,
    8064              :                                                   PartLoadRatio,
    8065              :                                                   FurnaceNum,
    8066              :                                                   FirstHVACIteration,
    8067              :                                                   fanOp,
    8068              :                                                   compressorOp,
    8069              :                                                   TotalZoneSensLoad,
    8070              :                                                   1.0,
    8071              :                                                   1.0,
    8072              :                                                   ZoneSensLoadMetFanONCompOFF,
    8073       108152 :                                                   0.0);
    8074        35551 :                 };
    8075        35551 :                 General::SolveRoot(state, CoolErrorToler, MaxIter, SolFlag, CoolPartLoadRatio, f, 0.0, 1.0);
    8076        35551 :                 if (SolFlag == -1 && !state.dataGlobal->WarmupFlag && !FirstHVACIteration) {
    8077           13 :                     state.dataHVACGlobal->OnOffFanPartLoadFraction = state.dataFurnaces->OnOffFanPartLoadFractionSave;
    8078           13 :                     CalcFurnaceOutput(state,
    8079              :                                       FurnaceNum,
    8080              :                                       FirstHVACIteration,
    8081              :                                       fanOp,
    8082              :                                       compressorOp,
    8083              :                                       CoolPartLoadRatio,
    8084              :                                       0.0,
    8085              :                                       0.0,
    8086              :                                       0.0,
    8087              :                                       ZoneSensLoadMet,
    8088              :                                       ZoneLatLoadMet,
    8089              :                                       OnOffAirFlowRatio,
    8090              :                                       false);
    8091           13 :                     if (std::abs(ZoneSensLoadMet - TotalZoneSensLoad) / TotalZoneSensLoad > CoolErrorToler) {
    8092            0 :                         if (thisFurnace.SensibleMaxIterIndex == 0) {
    8093            0 :                             ShowWarningMessage(state,
    8094            0 :                                                format("Cooling coil control failed to converge for {}:{}",
    8095            0 :                                                       HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    8096            0 :                                                       thisFurnace.Name));
    8097            0 :                             ShowContinueError(state, "  Iteration limit exceeded in calculating DX cooling coil sensible part-load ratio.");
    8098            0 :                             ShowContinueErrorTimeStamp(state,
    8099            0 :                                                        format("Sensible load to be met by DX coil = {:.2T} (watts), sensible output of DX coil = "
    8100              :                                                               "{:.2T} (watts), and the simulation continues.",
    8101              :                                                               TotalZoneSensLoad,
    8102              :                                                               ZoneSensLoadMet));
    8103              :                         }
    8104            0 :                         ShowRecurringWarningErrorAtEnd(
    8105              :                             state,
    8106            0 :                             format("{} \"{}\" - Iteration limit exceeded in calculating sensible cooling part-load ratio error "
    8107              :                                    "continues. Sensible load statistics:",
    8108            0 :                                    HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    8109            0 :                                    thisFurnace.Name),
    8110            0 :                             thisFurnace.SensibleMaxIterIndex,
    8111              :                             TotalZoneSensLoad,
    8112              :                             TotalZoneSensLoad);
    8113              :                     }
    8114        35538 :                 } else if (SolFlag == -2 && !state.dataGlobal->WarmupFlag && !FirstHVACIteration) {
    8115            0 :                     CoolPartLoadRatio = max(MinPLR, min(1.0, std::abs(HPCoilSensDemand) / std::abs(HPCoilSensCapacity)));
    8116            0 :                     state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
    8117            0 :                     CalcFurnaceOutput(state,
    8118              :                                       FurnaceNum,
    8119              :                                       FirstHVACIteration,
    8120              :                                       fanOp,
    8121              :                                       compressorOp,
    8122              :                                       CoolPartLoadRatio,
    8123              :                                       0.0,
    8124              :                                       0.0,
    8125              :                                       0.0,
    8126              :                                       ZoneSensLoadMet,
    8127              :                                       ZoneLatLoadMet,
    8128              :                                       OnOffAirFlowRatio,
    8129              :                                       false);
    8130            0 :                     if ((ZoneSensLoadMet - TotalZoneSensLoad) / TotalZoneSensLoad > CoolErrorToler) {
    8131            0 :                         if (thisFurnace.SensibleRegulaFalsiFailedIndex == 0) {
    8132            0 :                             ShowWarningMessage(
    8133              :                                 state,
    8134            0 :                                 format("Cooling coil control failed for {}:{}", HVAC::unitarySysTypeNames[(int)thisFurnace.type], thisFurnace.Name));
    8135            0 :                             ShowContinueError(state, "  Cooling sensible part-load ratio determined to be outside the range of 0-1.");
    8136            0 :                             ShowContinueError(
    8137              :                                 state,
    8138            0 :                                 format("  An estimated part-load ratio = {:.2T} will be used and the simulation continues.", CoolPartLoadRatio));
    8139            0 :                             ShowContinueError(
    8140            0 :                                 state, format("  The estimated part-load ratio provides a cooling sensible capacity = {:.2T}", ZoneSensLoadMet));
    8141            0 :                             ShowContinueErrorTimeStamp(state, format("  Cooling sensible load required = {:.2T}", TotalZoneSensLoad));
    8142              :                         }
    8143            0 :                         ShowRecurringWarningErrorAtEnd(
    8144              :                             state,
    8145            0 :                             format("{} \"{}\" - Cooling sensible part-load ratio out of range error continues. Sensible cooling load statistics:",
    8146            0 :                                    HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    8147            0 :                                    thisFurnace.Name),
    8148            0 :                             thisFurnace.SensibleRegulaFalsiFailedIndex,
    8149              :                             TotalZoneSensLoad,
    8150              :                             TotalZoneSensLoad);
    8151              :                     }
    8152              :                 }
    8153              :             }
    8154              : 
    8155        37711 :             if (fanOp == HVAC::FanOp::Cycling) {
    8156        37711 :                 thisFurnace.MdotFurnace *= CoolPartLoadRatio;
    8157              :             }
    8158              : 
    8159              :             //*********HEATING CALCULATIONS****************
    8160              :             // If Furnace runs with a heating load then set HeatCoilLoad on Heating Coil and the Mass Flow
    8161       136830 :         } else if ((thisFurnace.availSched->getCurrentVal() > 0.0) && (state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate > 0.0) &&
    8162        55271 :                    state.dataFurnaces->HeatingLoad) {
    8163              : 
    8164              :             // Set the air flow rate to the design flow rate and set the fan operation fraction to 1 (continuous operation)
    8165        55271 :             state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = thisFurnace.DesignMassFlowRate;
    8166        55271 :             state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0; // see 'Note' under INITIAL CALCULATIONS
    8167              : 
    8168              :             //         !Set the operation flag to run the fan continuously
    8169              :             //         fanOp = FanOp::Continuous
    8170              : 
    8171              :             // Set the input parameters for CalcFurnaceOutput
    8172        55271 :             thisFurnace.HeatingCoilSensDemand = 0.0;
    8173        55271 :             thisFurnace.CoolingCoilLatentDemand = 0.0;
    8174        55271 :             thisFurnace.CoolingCoilSensDemand = 0.0;
    8175        55271 :             thisFurnace.CompPartLoadRatio = 0.0; // compressor off
    8176        55271 :             thisFurnace.InitHeatPump = true;     // initialization call to Calc Furnace
    8177        55271 :             HeatPartLoadRatio = 0.0;
    8178              : 
    8179              :             // Get no load result in order to calculate the effect of the fan and the mixed air equipment
    8180        55271 :             CalcFurnaceOutput(state,
    8181              :                               FurnaceNum,
    8182              :                               FirstHVACIteration,
    8183              :                               fanOp,
    8184              :                               compressorOp,
    8185              :                               CoolPartLoadRatio,
    8186              :                               HeatPartLoadRatio,
    8187              :                               Dummy2,
    8188              :                               Dummy2,
    8189              :                               ZoneSensLoadMetFanONCompOFF,
    8190              :                               ZoneLatLoadMetFanONCompOFF,
    8191              :                               OnOffAirFlowRatio,
    8192              :                               false);
    8193              : 
    8194              :             // Set the input parameters for CalcFurnaceOutput
    8195        55271 :             thisFurnace.HeatingCoilSensDemand = 1.0;
    8196        55271 :             thisFurnace.CompPartLoadRatio = 1.0; // compressor ON
    8197        55271 :             HeatPartLoadRatio = 1.0;
    8198              : 
    8199              :             // Get full load result in order to estimate the operating part load ratio for continuous fan operation
    8200              : 
    8201        55271 :             CalcFurnaceOutput(state,
    8202              :                               FurnaceNum,
    8203              :                               FirstHVACIteration,
    8204              :                               fanOp,
    8205              :                               compressorOp,
    8206              :                               CoolPartLoadRatio,
    8207              :                               HeatPartLoadRatio,
    8208              :                               Dummy2,
    8209              :                               Dummy2,
    8210              :                               ZoneSensLoadMetFanONCompON,
    8211              :                               ZoneLatLoadMetFanONCompON,
    8212              :                               OnOffAirFlowRatio,
    8213              :                               false);
    8214              : 
    8215              :             // Calculate the heating coil demand for continuous fan operation as:
    8216              :             //    (the zone sensible load - the zone sensible load met by fan heat and mixed air)
    8217              :             // Note; The sensible zone load met by fan heat and mixed air is calculated as:
    8218              :             //     mdotsys(control zone inlet enthalpy - control zone outlet enthalpy)
    8219              :             // This accounts for the negative sign in the equation.
    8220        55271 :             HPCoilSensDemand = TotalZoneSensLoad - ZoneSensLoadMetFanONCompOFF;
    8221              : 
    8222              :             // Calculate the heating coil capacity for continuous fan operation as:
    8223              :             //    (the zone sensible load met by fan heat and mixed air and coil
    8224              :             //   - the zone sensible load met by fan heat and mixed air)
    8225        55271 :             HPCoilSensCapacity = ZoneSensLoadMetFanONCompON - ZoneSensLoadMetFanONCompOFF;
    8226              : 
    8227              :             // Calculate the part load ratio for continuous fan operation with cycling coil
    8228        55271 :             if (HPCoilSensCapacity == 0.0) {
    8229            0 :                 HeatPartLoadRatio = 0.0;
    8230              :             } else {
    8231        55271 :                 HeatPartLoadRatio = max(MinPLR, min(1.0, std::abs(HPCoilSensDemand) / std::abs(HPCoilSensCapacity)));
    8232              :             }
    8233              : 
    8234        55271 :             thisFurnace.InitHeatPump = false;
    8235              : 
    8236              :             // check bounds on sensible output prior to iteration using RegulaFalsi
    8237        55271 :             if (ZoneSensLoadMetFanONCompON < TotalZoneSensLoad) {
    8238         4228 :                 HeatPartLoadRatio = 1.0;
    8239         4228 :                 ZoneSensLoadMet = ZoneSensLoadMetFanONCompON;
    8240         4228 :                 HPCoilSensDemand = std::abs(ZoneSensLoadMetFanONCompON - ZoneSensLoadMetFanONCompOFF);
    8241         4228 :                 thisFurnace.HeatingCoilSensDemand = HPCoilSensDemand;
    8242        51043 :             } else if (ZoneSensLoadMetFanONCompOFF > TotalZoneSensLoad) {
    8243            0 :                 HeatPartLoadRatio = 0.0;
    8244            0 :                 ZoneSensLoadMet = ZoneSensLoadMetFanONCompOFF;
    8245            0 :                 thisFurnace.CompPartLoadRatio = 0.0; // compressor ON
    8246            0 :                 CalcFurnaceOutput(state,
    8247              :                                   FurnaceNum,
    8248              :                                   FirstHVACIteration,
    8249              :                                   fanOp,
    8250              :                                   compressorOp,
    8251              :                                   CoolPartLoadRatio,
    8252              :                                   HeatPartLoadRatio,
    8253              :                                   Dummy2,
    8254              :                                   Dummy2,
    8255              :                                   ZoneSensLoadMet,
    8256              :                                   ZoneLatLoadMet,
    8257              :                                   OnOffAirFlowRatio,
    8258              :                                   false);
    8259              :             } else {
    8260              :                 //         Calculate the sensible part load ratio through iteration
    8261        51043 :                 HeatErrorToler = thisFurnace.HeatingConvergenceTolerance;
    8262        51043 :                 SolFlag = 0; // # of iterations if positive, -1 means failed to converge, -2 means bounds are incorrect
    8263              :                 // HeatErrorToler is in fraction of load, MaxIter = 600, SolFalg = # of iterations or error as appropriate
    8264       204172 :                 auto f = [&state, FurnaceNum, FirstHVACIteration, fanOp, compressorOp, TotalZoneSensLoad, ZoneSensLoadMetFanONCompOFF](
    8265              :                              Real64 const PartLoadRatio) {
    8266       153129 :                     return CalcWaterToAirResidual(state,
    8267              :                                                   PartLoadRatio,
    8268              :                                                   FurnaceNum,
    8269              :                                                   FirstHVACIteration,
    8270              :                                                   fanOp,
    8271              :                                                   compressorOp,
    8272              :                                                   TotalZoneSensLoad,
    8273              :                                                   0.0,
    8274              :                                                   1.0,
    8275              :                                                   ZoneSensLoadMetFanONCompOFF,
    8276       153129 :                                                   0.0);
    8277        51043 :                 };
    8278        51043 :                 General::SolveRoot(state, HeatErrorToler, MaxIter, SolFlag, HeatPartLoadRatio, f, 0.0, 1.0);
    8279        51043 :                 state.dataHVACGlobal->OnOffFanPartLoadFraction = state.dataFurnaces->OnOffFanPartLoadFractionSave;
    8280        51043 :                 CalcFurnaceOutput(state,
    8281              :                                   FurnaceNum,
    8282              :                                   FirstHVACIteration,
    8283              :                                   fanOp,
    8284              :                                   compressorOp,
    8285              :                                   CoolPartLoadRatio,
    8286              :                                   HeatPartLoadRatio,
    8287              :                                   Dummy2,
    8288              :                                   Dummy2,
    8289              :                                   ZoneSensLoadMet,
    8290              :                                   ZoneLatLoadMet,
    8291              :                                   OnOffAirFlowRatio,
    8292              :                                   false);
    8293        51043 :                 if (SolFlag == -1 && !state.dataGlobal->WarmupFlag && !FirstHVACIteration) {
    8294            0 :                     if (std::abs(ZoneSensLoadMet - TotalZoneSensLoad) / TotalZoneSensLoad > HeatErrorToler) {
    8295            0 :                         if (thisFurnace.WSHPHeatMaxIterIndex == 0) {
    8296            0 :                             ShowWarningMessage(state,
    8297            0 :                                                format("Heating coil control failed to converge for {}:{}",
    8298            0 :                                                       HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    8299            0 :                                                       thisFurnace.Name));
    8300            0 :                             ShowContinueError(state, "  Iteration limit exceeded in calculating DX heating coil sensible part-load ratio.");
    8301            0 :                             ShowContinueErrorTimeStamp(state,
    8302            0 :                                                        format("Sensible load to be met by DX coil = {:.2T} (watts), sensible output of DX coil = "
    8303              :                                                               "{:.2T} (watts), and the simulation continues.",
    8304              :                                                               TotalZoneSensLoad,
    8305              :                                                               ZoneSensLoadMet));
    8306              :                         }
    8307            0 :                         ShowRecurringWarningErrorAtEnd(
    8308              :                             state,
    8309            0 :                             format("{} \"{}\" - Iteration limit exceeded in calculating sensible heating part-load ratio error continues.",
    8310            0 :                                    HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    8311            0 :                                    thisFurnace.Name),
    8312            0 :                             thisFurnace.WSHPHeatMaxIterIndex,
    8313              :                             TotalZoneSensLoad,
    8314              :                             TotalZoneSensLoad);
    8315              :                     }
    8316        51043 :                 } else if (SolFlag == -2) {
    8317            0 :                     HeatPartLoadRatio = max(MinPLR, min(1.0, std::abs(HPCoilSensDemand) / std::abs(HPCoilSensCapacity)));
    8318            0 :                     CalcFurnaceOutput(state,
    8319              :                                       FurnaceNum,
    8320              :                                       FirstHVACIteration,
    8321              :                                       fanOp,
    8322              :                                       compressorOp,
    8323              :                                       0.0,
    8324              :                                       HeatPartLoadRatio,
    8325              :                                       0.0,
    8326              :                                       0.0,
    8327              :                                       ZoneSensLoadMet,
    8328              :                                       ZoneLatLoadMet,
    8329              :                                       OnOffAirFlowRatio,
    8330              :                                       false);
    8331            0 :                     if ((ZoneSensLoadMet - TotalZoneSensLoad) / TotalZoneSensLoad > HeatErrorToler) {
    8332            0 :                         if (thisFurnace.WSHPHeatRegulaFalsiFailedIndex == 0) {
    8333            0 :                             ShowWarningError(
    8334              :                                 state,
    8335            0 :                                 format("Heating coil control failed for {}:{}", HVAC::unitarySysTypeNames[(int)thisFurnace.type], thisFurnace.Name));
    8336            0 :                             ShowContinueError(state, "  Heating sensible part-load ratio determined to be outside the range of 0-1.");
    8337            0 :                             ShowContinueError(
    8338              :                                 state,
    8339            0 :                                 format("  An estimated part-load ratio = {:.2T} will be used and the simulation continues.", HeatPartLoadRatio));
    8340            0 :                             ShowContinueError(
    8341            0 :                                 state, format("  The estimated part-load ratio provides a heating sensible capacity = {:.2T}", ZoneSensLoadMet));
    8342            0 :                             ShowContinueErrorTimeStamp(state, format("  Heating sensible load required = {:.2T}", TotalZoneSensLoad));
    8343              :                         }
    8344            0 :                         ShowRecurringWarningErrorAtEnd(state,
    8345            0 :                                                        format("{} \"{}\" - Heating sensible part-load ratio out of range error continues.",
    8346            0 :                                                               HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    8347            0 :                                                               thisFurnace.Name),
    8348            0 :                                                        thisFurnace.WSHPHeatRegulaFalsiFailedIndex,
    8349              :                                                        TotalZoneSensLoad,
    8350              :                                                        TotalZoneSensLoad);
    8351              :                     }
    8352              :                 }
    8353              :             }
    8354              : 
    8355              :             //       CALL supplemental heater if required
    8356        55271 :             if ((TotalZoneSensLoad - ZoneSensLoadMet) > HVAC::SmallLoad && HeatPartLoadRatio >= 1.0) {
    8357         4228 :                 SuppHeatCoilLoad = TotalZoneSensLoad - ZoneSensLoadMet;
    8358         4228 :                 CalcFurnaceOutput(state,
    8359              :                                   FurnaceNum,
    8360              :                                   FirstHVACIteration,
    8361              :                                   fanOp,
    8362              :                                   compressorOp,
    8363              :                                   CoolPartLoadRatio,
    8364              :                                   HeatPartLoadRatio,
    8365              :                                   SuppHeatCoilLoad,
    8366              :                                   Dummy2,
    8367              :                                   ZoneSensLoadMet,
    8368              :                                   ZoneLatLoadMet,
    8369              :                                   OnOffAirFlowRatio,
    8370              :                                   false);
    8371              :             }
    8372              : 
    8373        55271 :             if (fanOp == HVAC::FanOp::Cycling) {
    8374        55271 :                 thisFurnace.MdotFurnace *= HeatPartLoadRatio;
    8375              :             }
    8376              : 
    8377              :             //**********HVAC Scheduled ON, but no cooling, dehumidification or heating load*********
    8378        26288 :         } else if (thisFurnace.availSched->getCurrentVal() > 0.0) {
    8379        12252 :             thisFurnace.InitHeatPump = true; // initialization call to Calc Furnace
    8380        12252 :             HeatPartLoadRatio = 0.0;
    8381        12252 :             CoolPartLoadRatio = 0.0;
    8382        12252 :             state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0; //! see 'Note' under INITIAL CALCULATIONS
    8383              :             // set report variables
    8384        12252 :             thisFurnace.CompPartLoadRatio = 0.0;
    8385        12252 :             thisFurnace.CoolingCoilSensDemand = 0.0;
    8386        12252 :             thisFurnace.CoolingCoilLatentDemand = 0.0;
    8387        12252 :             thisFurnace.HeatingCoilSensDemand = 0.0;
    8388        12252 :             if (fanOp == HVAC::FanOp::Cycling) {
    8389        12252 :                 thisFurnace.MdotFurnace = 0.0;
    8390        12252 :                 state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0; // see 'Note' under INITIAL CALCULATIONS
    8391        12252 :                 CalcFurnaceOutput(state,
    8392              :                                   FurnaceNum,
    8393              :                                   FirstHVACIteration,
    8394              :                                   fanOp,
    8395              :                                   compressorOp,
    8396              :                                   CoolPartLoadRatio,
    8397              :                                   HeatPartLoadRatio,
    8398              :                                   Dummy2,
    8399              :                                   Dummy2,
    8400              :                                   ZoneSensLoadMet,
    8401              :                                   ZoneLatLoadMet,
    8402              :                                   OnOffAirFlowRatio,
    8403              :                                   false);
    8404        12252 :                 thisFurnace.MdotFurnace = 0.0;
    8405              :             } else { // continuous fan, cycling coil
    8406            0 :                 CalcFurnaceOutput(state,
    8407              :                                   FurnaceNum,
    8408              :                                   FirstHVACIteration,
    8409              :                                   fanOp,
    8410              :                                   compressorOp,
    8411              :                                   CoolPartLoadRatio,
    8412              :                                   HeatPartLoadRatio,
    8413              :                                   Dummy2,
    8414              :                                   Dummy2,
    8415              :                                   ZoneSensLoadMet,
    8416              :                                   ZoneLatLoadMet,
    8417              :                                   OnOffAirFlowRatio,
    8418              :                                   false);
    8419              :             }
    8420              :             //*********No heating or cooling or dehumidification*********
    8421              :         } else {
    8422        14036 :             thisFurnace.InitHeatPump = true; // initialization call to Calc Furnace
    8423        14036 :             thisFurnace.MdotFurnace = 0.0;
    8424        14036 :             HeatPartLoadRatio = 0.0;
    8425        14036 :             CoolPartLoadRatio = 0.0;
    8426        14036 :             state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0; // see 'Note' under INITIAL CALCULATIONS
    8427        14036 :             thisFurnace.CompPartLoadRatio = 0.0;
    8428        14036 :             thisFurnace.CoolingCoilSensDemand = 0.0;
    8429        14036 :             thisFurnace.CoolingCoilLatentDemand = 0.0;
    8430        14036 :             thisFurnace.HeatingCoilSensDemand = 0.0;
    8431        14036 :             CalcFurnaceOutput(state,
    8432              :                               FurnaceNum,
    8433              :                               FirstHVACIteration,
    8434              :                               fanOp,
    8435              :                               compressorOp,
    8436              :                               CoolPartLoadRatio,
    8437              :                               HeatPartLoadRatio,
    8438              :                               Dummy2,
    8439              :                               Dummy2,
    8440              :                               ZoneSensLoadMet,
    8441              :                               ZoneLatLoadMet,
    8442              :                               OnOffAirFlowRatio,
    8443              :                               false);
    8444        14036 :             thisFurnace.MdotFurnace = 0.0;
    8445              :         }
    8446              : 
    8447              :         // Set the fan inlet node flow rates
    8448       119270 :         state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRateMaxAvail = thisFurnace.MdotFurnace;
    8449       119270 :         state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = thisFurnace.MdotFurnace;
    8450       119270 :     }
    8451              : 
    8452     20372969 :     void CalcFurnaceOutput(EnergyPlusData &state,
    8453              :                            int const FurnaceNum,
    8454              :                            bool const FirstHVACIteration,
    8455              :                            HVAC::FanOp const fanOp,               // Cycling fan or constant fan
    8456              :                            HVAC::CompressorOp const compressorOp, // Compressor on/off; 1=on, 0=off
    8457              :                            Real64 const CoolPartLoadRatio,        // DX cooling coil part load ratio
    8458              :                            Real64 const HeatPartLoadRatio,        // DX heating coil part load ratio (0 for other heating coil types)
    8459              :                            Real64 const HeatCoilLoad,             // Heating coil load for gas heater
    8460              :                            Real64 const ReheatCoilLoad,           // Reheating coil load for gas heater
    8461              :                            Real64 &SensibleLoadMet,               // Sensible cooling load met (furnace outlet with respect to control zone temp)
    8462              :                            Real64 &LatentLoadMet,              // Latent cooling load met (furnace outlet with respect to control zone humidity ratio)
    8463              :                            Real64 &OnOffAirFlowRatio,          // Ratio of compressor ON mass flow rate to AVERAGE
    8464              :                            bool const HXUnitOn,                // flag to enable HX based on zone moisture load
    8465              :                            Real64 const CoolingHeatingPLRRatio // cooling PLR to heating PLR ratio, used for cycling fan RH control
    8466              :     )
    8467              :     {
    8468              : 
    8469              :         // SUBROUTINE INFORMATION:
    8470              :         //       AUTHOR         Richard Raustad
    8471              :         //       DATE WRITTEN   Sept 2001
    8472              :         //       MODIFIED       Dec 2001
    8473              : 
    8474              :         // PURPOSE OF THIS SUBROUTINE:
    8475              :         // This subroutine calculates to sensible and latent loads met by the DX coils
    8476              :         // specified.  Load met is the outlet node with respect to the control zone's
    8477              :         // temperature and humidity ratio.
    8478              : 
    8479              :         // METHODOLOGY EMPLOYED:
    8480              :         // Simulate each child object in the correct order for each system type. This routine is used in the
    8481              :         // RegulaFalsi function CALL. Air mass flow rate is set each iteration based on PLR.
    8482              : 
    8483     20372969 :         auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    8484     20372969 :         auto &inletNode = state.dataLoopNodes->Node(thisFurnace.FurnaceInletNodeNum);
    8485     20372969 :         int CoolingCoilType_Num = thisFurnace.CoolingCoilType_Num;
    8486     20372969 :         Real64 QActual = 0.0; // heating coil load met or delivered
    8487     20372969 :         state.dataFurnaces->ModifiedHeatCoilLoad = 0.0;
    8488              : 
    8489     20372969 :         state.dataFurnaces->CoolHeatPLRRat = CoolingHeatingPLRRatio;
    8490              : 
    8491              :         // Cooling to Heating PLR Ratio (CoolHeatPLRRat) is used to track the air mass flow rate of both the heating
    8492              :         // and cooling coils when RH control is used and the heating coil operates longer than the cooling coil.
    8493              :         // When CoolPartLoadRatio/CoolHeatPLRRat is used, the PLR calculated is actually the PLR for the heating
    8494              :         // coil (heating PLR is greater than cooling PLR), it is this PLR that determines the air mass flow rate.
    8495              :         // When MAX(HeatPartLoadRatio,CoolPartLoadRatio) is used, only one of these values is non-zero.
    8496     20372969 :         if (fanOp == HVAC::FanOp::Cycling) {
    8497     12941008 :             if (state.dataFurnaces->CoolHeatPLRRat < 1.0) {
    8498            2 :                 if (state.dataFurnaces->CoolHeatPLRRat > 0.0) {
    8499            0 :                     inletNode.MassFlowRate = state.dataFurnaces->CompOnMassFlow * CoolPartLoadRatio / state.dataFurnaces->CoolHeatPLRRat;
    8500            0 :                     if (thisFurnace.type != HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir) {
    8501            0 :                         SetAverageAirFlow(state, FurnaceNum, CoolPartLoadRatio / state.dataFurnaces->CoolHeatPLRRat, OnOffAirFlowRatio);
    8502              :                     }
    8503              :                 } else {
    8504            2 :                     inletNode.MassFlowRate = state.dataFurnaces->CompOnMassFlow * CoolPartLoadRatio;
    8505            2 :                     if (thisFurnace.type != HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir) {
    8506            2 :                         SetAverageAirFlow(state, FurnaceNum, max(HeatPartLoadRatio, CoolPartLoadRatio), OnOffAirFlowRatio);
    8507              :                     }
    8508              :                 }
    8509              :             } else {
    8510     12941006 :                 inletNode.MassFlowRate = state.dataFurnaces->CompOnMassFlow * max(HeatPartLoadRatio, CoolPartLoadRatio);
    8511     12941006 :                 if (thisFurnace.type != HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir) {
    8512      5308941 :                     SetAverageAirFlow(state, FurnaceNum, max(HeatPartLoadRatio, CoolPartLoadRatio), OnOffAirFlowRatio);
    8513              :                 }
    8514              :             }
    8515              :         } else {
    8516      7431961 :             if (thisFurnace.type != HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir) {
    8517      4981695 :                 SetAverageAirFlow(state, FurnaceNum, max(HeatPartLoadRatio, CoolPartLoadRatio), OnOffAirFlowRatio);
    8518              :             }
    8519              :         }
    8520              : 
    8521     20372969 :         inletNode.MassFlowRateMaxAvail = inletNode.MassFlowRate;
    8522              : 
    8523              :         // Simulate the air-to-air heat pump
    8524     20372969 :         if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_AirToAir) {
    8525              :             //   Simulate blow-thru fan and non-linear coils twice to update PLF used by the ONOFF Fan
    8526      1635454 :             if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
    8527      1635454 :                 state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
    8528      1635454 :                 if (CoolingCoilType_Num == HVAC::CoilDX_CoolingHXAssisted) {
    8529            0 :                     HVACHXAssistedCoolingCoil::SimHXAssistedCoolingCoil(state,
    8530              :                                                                         BlankString,
    8531              :                                                                         FirstHVACIteration,
    8532              :                                                                         compressorOp,
    8533              :                                                                         CoolPartLoadRatio,
    8534            0 :                                                                         thisFurnace.CoolingCoilIndex,
    8535              :                                                                         fanOp,
    8536              :                                                                         HXUnitOn,
    8537              :                                                                         OnOffAirFlowRatio,
    8538            0 :                                                                         state.dataFurnaces->EconomizerFlag);
    8539              :                 } else {
    8540      3270908 :                     DXCoils::SimDXCoil(state,
    8541              :                                        BlankString,
    8542              :                                        compressorOp,
    8543              :                                        FirstHVACIteration,
    8544      1635454 :                                        thisFurnace.CoolingCoilIndex,
    8545              :                                        fanOp,
    8546              :                                        CoolPartLoadRatio,
    8547              :                                        OnOffAirFlowRatio);
    8548              :                 }
    8549      3270908 :                 DXCoils::SimDXCoil(
    8550      1635454 :                     state, BlankString, compressorOp, FirstHVACIteration, thisFurnace.HeatingCoilIndex, fanOp, HeatPartLoadRatio, OnOffAirFlowRatio);
    8551      1635454 :                 state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
    8552              :             }
    8553              :             //   Simulate cooling and heating coils
    8554      1635454 :             if (CoolingCoilType_Num == HVAC::CoilDX_CoolingHXAssisted) {
    8555            0 :                 HVACHXAssistedCoolingCoil::SimHXAssistedCoolingCoil(state,
    8556              :                                                                     BlankString,
    8557              :                                                                     FirstHVACIteration,
    8558              :                                                                     compressorOp,
    8559              :                                                                     CoolPartLoadRatio,
    8560            0 :                                                                     thisFurnace.CoolingCoilIndex,
    8561              :                                                                     fanOp,
    8562              :                                                                     HXUnitOn,
    8563              :                                                                     OnOffAirFlowRatio,
    8564            0 :                                                                     state.dataFurnaces->EconomizerFlag);
    8565              :             } else {
    8566      3270908 :                 DXCoils::SimDXCoil(
    8567      1635454 :                     state, BlankString, compressorOp, FirstHVACIteration, thisFurnace.CoolingCoilIndex, fanOp, CoolPartLoadRatio, OnOffAirFlowRatio);
    8568              :             }
    8569      3270908 :             DXCoils::SimDXCoil(
    8570      1635454 :                 state, BlankString, compressorOp, FirstHVACIteration, thisFurnace.HeatingCoilIndex, fanOp, HeatPartLoadRatio, OnOffAirFlowRatio);
    8571              :             //   Simulate the draw-thru fan
    8572      1635454 :             if (thisFurnace.fanPlace == HVAC::FanPlace::DrawThru) {
    8573            0 :                 state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
    8574              :             }
    8575              :             //   Simulate the supplemental heating coil
    8576      1635454 :             if (thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat && ReheatCoilLoad > 0.0) {
    8577            0 :                 bool SuppHeatingCoilFlag = true;
    8578            0 :                 CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, ReheatCoilLoad, fanOp, QActual);
    8579            0 :             } else {
    8580              :                 // equivalent to QCoilReq=0.0d0 or ReHeatCoilLoad = 0.0d0
    8581      1635454 :                 bool SuppHeatingCoilFlag = true;
    8582      1635454 :                 CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, ReheatCoilLoad, fanOp, QActual);
    8583              :             }
    8584              :             // Simulate the parameter estimate water-to-air heat pump
    8585     18737515 :         } else if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir && thisFurnace.WatertoAirHPType == WAHPCoilType::Simple) {
    8586              :             //    Simulate blow-thru fan and non-linear coils twice to update PLF used by the ONOFF Fan
    8587      9553514 :             if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
    8588      9553514 :                 state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
    8589              :                 // COIL:WATERTOAIRHPSIMPLE:COOLING
    8590      9553514 :                 WaterToAirHeatPumpSimple::SimWatertoAirHPSimple(state,
    8591              :                                                                 BlankString,
    8592      9553514 :                                                                 thisFurnace.CoolingCoilIndex,
    8593              :                                                                 thisFurnace.CoolingCoilSensDemand,
    8594              :                                                                 thisFurnace.CoolingCoilLatentDemand,
    8595              :                                                                 fanOp,
    8596              :                                                                 compressorOp,
    8597              :                                                                 CoolPartLoadRatio,
    8598              :                                                                 FirstHVACIteration); // CoolPartLoadRatio
    8599      9553514 :                 Real64 Dummy = 0.0;
    8600              :                 // COIL:WATERTOAIRHPSIMPLE:HEATING
    8601      9553514 :                 WaterToAirHeatPumpSimple::SimWatertoAirHPSimple(state,
    8602              :                                                                 BlankString,
    8603      9553514 :                                                                 thisFurnace.HeatingCoilIndex,
    8604              :                                                                 thisFurnace.HeatingCoilSensDemand,
    8605              :                                                                 Dummy,
    8606              :                                                                 fanOp,
    8607              :                                                                 compressorOp,
    8608              :                                                                 HeatPartLoadRatio,
    8609              :                                                                 FirstHVACIteration); // HeatPartLoadRatio
    8610              :                 //      Simulate the whole thing a second time so that the correct PLF required by the coils is used by the Fan. *******
    8611      9553514 :                 state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
    8612              :             }
    8613              :             //    Simulate the cooling and heating coils
    8614              :             // COIL:WATERTOAIRHPSIMPLE:COOLING
    8615      9553514 :             WaterToAirHeatPumpSimple::SimWatertoAirHPSimple(state,
    8616              :                                                             BlankString,
    8617      9553514 :                                                             thisFurnace.CoolingCoilIndex,
    8618              :                                                             thisFurnace.CoolingCoilSensDemand,
    8619              :                                                             thisFurnace.CoolingCoilLatentDemand,
    8620              :                                                             fanOp,
    8621              :                                                             compressorOp,
    8622              :                                                             CoolPartLoadRatio,
    8623              :                                                             FirstHVACIteration); // CoolPartLoadRatio
    8624      9553514 :             Real64 Dummy = 0.0;
    8625              :             // COIL:WATERTOAIRHPSIMPLE:HEATING
    8626      9553514 :             WaterToAirHeatPumpSimple::SimWatertoAirHPSimple(state,
    8627              :                                                             BlankString,
    8628      9553514 :                                                             thisFurnace.HeatingCoilIndex,
    8629              :                                                             thisFurnace.HeatingCoilSensDemand,
    8630              :                                                             Dummy,
    8631              :                                                             fanOp,
    8632              :                                                             compressorOp,
    8633              :                                                             HeatPartLoadRatio,
    8634              :                                                             FirstHVACIteration); // HeatPartLoadRatio
    8635              :             //     Simulate the draw-thru fan
    8636      9553514 :             if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
    8637      9553514 :                 state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
    8638              :             }
    8639              :             //     Simulate the supplemental heating coil
    8640      9553514 :             if (thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat && ReheatCoilLoad > 0.0) {
    8641            0 :                 bool SuppHeatingCoilFlag = true; // if true simulates supplemental heating coil
    8642            0 :                 CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, ReheatCoilLoad, fanOp, QActual);
    8643            0 :             } else {
    8644      9553514 :                 bool SuppHeatingCoilFlag = true; // if true simulates supplemental heating coil
    8645      9553514 :                 CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, fanOp, QActual);
    8646              :             }
    8647              :             // Simulate the detailed water-to-air heat pump
    8648     18737515 :         } else if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir && thisFurnace.WatertoAirHPType == WAHPCoilType::ParEst) {
    8649              :             //    Simulate the draw-thru fan
    8650       528817 :             if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
    8651       528817 :                 state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
    8652              :             }
    8653              :             //    Simulate the cooling and heating coils
    8654       528817 :             WaterToAirHeatPump::SimWatertoAirHP(state,
    8655              :                                                 BlankString,
    8656       528817 :                                                 thisFurnace.CoolingCoilIndex,
    8657              :                                                 thisFurnace.DesignMassFlowRate,
    8658              :                                                 fanOp,
    8659              :                                                 FirstHVACIteration,
    8660       528817 :                                                 thisFurnace.InitHeatPump,
    8661              :                                                 thisFurnace.CoolingCoilSensDemand,
    8662              :                                                 thisFurnace.CoolingCoilLatentDemand,
    8663              :                                                 compressorOp,
    8664              :                                                 CoolPartLoadRatio);
    8665       528817 :             Real64 Dummy = 0.0;
    8666       528817 :             WaterToAirHeatPump::SimWatertoAirHP(state,
    8667              :                                                 BlankString,
    8668       528817 :                                                 thisFurnace.HeatingCoilIndex,
    8669              :                                                 thisFurnace.DesignMassFlowRate,
    8670              :                                                 fanOp,
    8671              :                                                 FirstHVACIteration,
    8672       528817 :                                                 thisFurnace.InitHeatPump,
    8673              :                                                 thisFurnace.HeatingCoilSensDemand,
    8674              :                                                 Dummy,
    8675              :                                                 compressorOp,
    8676              :                                                 HeatPartLoadRatio);
    8677              :             //    Simulate the draw-thru fan
    8678       528817 :             if (thisFurnace.fanPlace == HVAC::FanPlace::DrawThru) {
    8679            0 :                 state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
    8680              :             }
    8681              :             //    Simulate the supplemental heating coil
    8682      2115268 :             HeatingCoils::SimulateHeatingCoilComponents(
    8683      1586451 :                 state, BlankString, FirstHVACIteration, HeatCoilLoad, thisFurnace.SuppHeatCoilIndex, _, true, fanOp);
    8684              : 
    8685       528817 :         } else { // ELSE it's not a heat pump
    8686              :             //   Simulate blow-thru fan
    8687      8655184 :             if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
    8688              : 
    8689      8455786 :                 state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
    8690              : 
    8691              :                 //     For non-linear coils, simulate coil to update PLF used by the ONOFF Fan
    8692      8455786 :                 if (thisFurnace.fanType == HVAC::FanType::OnOff) {
    8693      6463895 :                     if (thisFurnace.type != HVAC::UnitarySysType::Unitary_HeatOnly && thisFurnace.type != HVAC::UnitarySysType::Furnace_HeatOnly) {
    8694              : 
    8695      6446108 :                         if (!thisFurnace.CoolingCoilUpstream) {
    8696      4244823 :                             bool SuppHeatingCoilFlag = false; // if false simulates heating coil
    8697      4244823 :                             CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, fanOp, QActual);
    8698              :                         }
    8699              : 
    8700      6446108 :                         if (CoolingCoilType_Num == HVAC::CoilDX_CoolingHXAssisted) {
    8701        69930 :                             HVACHXAssistedCoolingCoil::SimHXAssistedCoolingCoil(state,
    8702              :                                                                                 BlankString,
    8703              :                                                                                 FirstHVACIteration,
    8704              :                                                                                 compressorOp,
    8705              :                                                                                 CoolPartLoadRatio,
    8706        23310 :                                                                                 thisFurnace.CoolingCoilIndex,
    8707              :                                                                                 fanOp,
    8708              :                                                                                 HXUnitOn,
    8709              :                                                                                 OnOffAirFlowRatio,
    8710        23310 :                                                                                 state.dataFurnaces->EconomizerFlag);
    8711              :                         } else {
    8712     19268394 :                             DXCoils::SimDXCoil(state,
    8713              :                                                BlankString,
    8714              :                                                compressorOp,
    8715              :                                                FirstHVACIteration,
    8716      6422798 :                                                thisFurnace.CoolingCoilIndex,
    8717              :                                                fanOp,
    8718              :                                                CoolPartLoadRatio,
    8719              :                                                OnOffAirFlowRatio,
    8720      6422798 :                                                state.dataFurnaces->CoolHeatPLRRat);
    8721              :                         }
    8722              :                     }
    8723              : 
    8724      6463895 :                     if (thisFurnace.CoolingCoilUpstream) {
    8725      2219072 :                         bool SuppHeatingCoilFlag = false; // if false simulates heating coil
    8726      2219072 :                         CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, fanOp, QActual);
    8727              :                     }
    8728      6463895 :                     state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
    8729              :                 } // Simple OnOff fan
    8730              : 
    8731              :             } // Blow thru fan
    8732              : 
    8733              :             //   Simulate the cooling and heating coils
    8734      8655184 :             if (thisFurnace.type != HVAC::UnitarySysType::Unitary_HeatOnly && thisFurnace.type != HVAC::UnitarySysType::Furnace_HeatOnly) {
    8735              : 
    8736      8637397 :                 if (!thisFurnace.CoolingCoilUpstream) {
    8737      4307625 :                     bool SuppHeatingCoilFlag = false; // if false simulates heating coil
    8738      4307625 :                     CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, fanOp, QActual);
    8739              :                 }
    8740              : 
    8741      8637397 :                 if (CoolingCoilType_Num == HVAC::CoilDX_CoolingHXAssisted) {
    8742       461826 :                     HVACHXAssistedCoolingCoil::SimHXAssistedCoolingCoil(state,
    8743              :                                                                         BlankString,
    8744              :                                                                         FirstHVACIteration,
    8745              :                                                                         compressorOp,
    8746              :                                                                         CoolPartLoadRatio,
    8747       153942 :                                                                         thisFurnace.CoolingCoilIndex,
    8748              :                                                                         fanOp,
    8749              :                                                                         HXUnitOn,
    8750              :                                                                         OnOffAirFlowRatio,
    8751       153942 :                                                                         state.dataFurnaces->EconomizerFlag);
    8752              :                 } else {
    8753     25450365 :                     DXCoils::SimDXCoil(state,
    8754              :                                        BlankString,
    8755              :                                        compressorOp,
    8756              :                                        FirstHVACIteration,
    8757      8483455 :                                        thisFurnace.CoolingCoilIndex,
    8758              :                                        fanOp,
    8759              :                                        CoolPartLoadRatio,
    8760              :                                        OnOffAirFlowRatio,
    8761      8483455 :                                        state.dataFurnaces->CoolHeatPLRRat);
    8762              :                 }
    8763              :             }
    8764              : 
    8765      8655184 :             if (thisFurnace.CoolingCoilUpstream) {
    8766      4347559 :                 bool SuppHeatingCoilFlag = false; // if false simulates heating coil
    8767      4347559 :                 CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, fanOp, QActual);
    8768              :             }
    8769              :             //   Simulate the draw-thru fan
    8770      8655184 :             if (thisFurnace.fanPlace == HVAC::FanPlace::DrawThru) {
    8771       199398 :                 state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
    8772              :             }
    8773      8655184 :             if (thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat || thisFurnace.SuppHeatCoilIndex > 0) {
    8774      2712851 :                 bool SuppHeatingCoilFlag = true; // if true simulates supplemental heating coil
    8775      2712851 :                 CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, ReheatCoilLoad, fanOp, QActual);
    8776              :             }
    8777              :         } // IF(Furnace(FurnaceNum)%type == UnitarySys_HeatPump_AirToAir)THEN
    8778              : 
    8779              :         // Get mass flow rate after components are simulated
    8780     20372969 :         auto &outletNode = state.dataLoopNodes->Node(thisFurnace.FurnaceOutletNodeNum);
    8781     20372969 :         Real64 AirMassFlow = inletNode.MassFlowRate; // this should be outlet node as in 9897?
    8782              : 
    8783              :         // check the DesignMaxOutletTemp and reset if necessary (for Coil:Gas:Heating or Coil:Electric:Heating only)
    8784     20372969 :         if (outletNode.Temp > thisFurnace.DesignMaxOutletTemp) {
    8785       215214 :             Real64 Wout = outletNode.HumRat;
    8786       215214 :             Real64 Tout = thisFurnace.DesignMaxOutletTemp;
    8787       215214 :             state.dataFurnaces->ModifiedHeatCoilLoad = HeatCoilLoad - (AirMassFlow * Psychrometrics::PsyCpAirFnW(Wout) * (outletNode.Temp - Tout));
    8788       215214 :             outletNode.Temp = Tout;
    8789              :         }
    8790              : 
    8791              :         // If the fan runs continually do not allow coils to set OnOffFanPartLoadRatio.
    8792     20372969 :         if (fanOp == HVAC::FanOp::Continuous) {
    8793      5666806 :             state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
    8794              :         }
    8795              : 
    8796     20372969 :         Real64 SensibleOutput = 0.0; // sensible output rate, {W}
    8797     20372969 :         Real64 LatentOutput = 0.0;   // latent output rate, {W}
    8798     20372969 :         Real64 TotalOutput = 0.0;    // total output rate, {W}
    8799     40745938 :         CalcZoneSensibleLatentOutput(AirMassFlow,
    8800              :                                      outletNode.Temp,
    8801              :                                      outletNode.HumRat,
    8802     20372969 :                                      state.dataLoopNodes->Node(thisFurnace.NodeNumOfControlledZone).Temp,
    8803     20372969 :                                      state.dataLoopNodes->Node(thisFurnace.NodeNumOfControlledZone).HumRat,
    8804              :                                      SensibleOutput,
    8805              :                                      LatentOutput,
    8806              :                                      TotalOutput);
    8807     20372969 :         SensibleLoadMet = SensibleOutput - thisFurnace.SenLoadLoss;
    8808     20372969 :         thisFurnace.SensibleLoadMet = SensibleLoadMet;
    8809              : 
    8810     20372969 :         if (thisFurnace.Humidistat) {
    8811      3388605 :             LatentLoadMet = LatentOutput - thisFurnace.LatLoadLoss;
    8812              :         } else {
    8813     16984364 :             LatentLoadMet = 0.0;
    8814              :         }
    8815     20372969 :         thisFurnace.LatentLoadMet = LatentLoadMet;
    8816     20372969 :     }
    8817              : 
    8818              :     //        End of Update subroutines for the Furnace Module
    8819              :     // *****************************************************************************
    8820              : 
    8821      8217331 :     Real64 CalcFurnaceResidual(EnergyPlusData &state,
    8822              :                                Real64 const PartLoadRatio, // DX cooling coil part load ratio
    8823              :                                int FurnaceNum,
    8824              :                                bool FirstHVACIteration,
    8825              :                                HVAC::FanOp const fanOp,
    8826              :                                HVAC::CompressorOp compressorOp,
    8827              :                                Real64 LoadToBeMet,
    8828              :                                Real64 par6_loadFlag,
    8829              :                                Real64 par7_sensLatentFlag,
    8830              :                                Real64 par9_HXOnFlag,
    8831              :                                Real64 par10_HeatingCoilPLR)
    8832              :     {
    8833              : 
    8834              :         // FUNCTION INFORMATION:
    8835              :         //       AUTHOR         Richard Raustad
    8836              :         //       DATE WRITTEN   Feb 2005
    8837              : 
    8838              :         // PURPOSE OF THIS SUBROUTINE:
    8839              :         // To calculate the part-load ratio for cooling and heating coils
    8840              : 
    8841              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    8842              :         Real64 CoolPartLoadRatio;      // DX cooling coil part load ratio
    8843              :         Real64 HeatPartLoadRatio;      // DX heating coil part load ratio (0 for other heating coil types)
    8844              :         Real64 HeatCoilLoad;           // Heating coil load for gas heater
    8845              :         Real64 SensibleLoadMet;        // Sensible cooling load met (furnace outlet with respect to control zone temp)
    8846              :         Real64 LatentLoadMet;          // Latent cooling load met (furnace outlet with respect to control zone humidity ratio)
    8847              :         Real64 OnOffAirFlowRatio;      // Ratio of compressor ON air mass flow to AVERAGE air mass flow over time step
    8848              :         Real64 CoolingHeatingPLRRatio; // ratio of cooling PLR to heating PLR, used for cycling fan RH control
    8849              :         bool HXUnitOn;                 // flag to enable HX based on zone moisture load
    8850              : 
    8851              :         //        // Convert parameters to usable variables
    8852              :         //        int FurnaceNum = int(Par(1));
    8853              :         //        bool FirstHVACIteration = Par(2) == 1.0;
    8854              :         //        int FanfanOp = int(Par(3));
    8855              :         //        CompressorOperation CompressorOp = static_cast<CompressorOperation>(Par(4));
    8856              :         //        Real64 LoadToBeMet = Par(5);
    8857              :         //        Real64 par6_loadFlag = Par(6);
    8858              :         //        Real64 par7_sensLatentFlag = Par(7);
    8859              :         //        Real64 par9_HXOnFlag = Par(9);
    8860              :         //        Real64 par10_HeatingCoilPLR = Par(10);
    8861              : 
    8862      8217331 :         if (par6_loadFlag == 1.0) {
    8863      4745118 :             CoolPartLoadRatio = PartLoadRatio;
    8864      4745118 :             HeatPartLoadRatio = 0.0;
    8865      4745118 :             HeatCoilLoad = 0.0;
    8866              :         } else {
    8867      3472213 :             CoolPartLoadRatio = 0.0;
    8868      3472213 :             HeatPartLoadRatio = PartLoadRatio;
    8869              : 
    8870      3472213 :             int const HeatingCoilType_Num(state.dataFurnaces->Furnace(FurnaceNum).HeatingCoilType_Num);
    8871      3472213 :             if (HeatingCoilType_Num == HVAC::Coil_HeatingGasOrOtherFuel || HeatingCoilType_Num == HVAC::Coil_HeatingElectric ||
    8872      2155596 :                 HeatingCoilType_Num == HVAC::Coil_HeatingWater || HeatingCoilType_Num == HVAC::Coil_HeatingSteam) {
    8873      1316617 :                 HeatCoilLoad = state.dataFurnaces->Furnace(FurnaceNum).DesignHeatingCapacity * PartLoadRatio;
    8874              :             } else {
    8875      2155596 :                 HeatCoilLoad = 0.0;
    8876              :             }
    8877              :         }
    8878              : 
    8879              :         //  OnOffAirFlowRatio = Par(8)
    8880      8217331 :         if (state.dataFurnaces->Furnace(FurnaceNum).type == HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir) {
    8881      4490100 :             state.dataFurnaces->Furnace(FurnaceNum).CompPartLoadRatio = PartLoadRatio;
    8882              :         }
    8883              : 
    8884      8217331 :         if (par9_HXOnFlag == 1.0) {
    8885      4712298 :             HXUnitOn = true;
    8886              :         } else {
    8887      3505033 :             HXUnitOn = false;
    8888              :         }
    8889              : 
    8890      8217331 :         if (par10_HeatingCoilPLR > 0.0) {
    8891              :             //    Par(10) = Furnace(FurnaceNum)%HeatPartLoadRatio
    8892              :             //    FanOp = CycFan and Furnace(FurnaceNum)%HeatPartLoadRatio must be > 0 for Part(10) to be greater than 0
    8893              :             //    This variable used when in heating mode and dehumidification (cooling) is required.
    8894            0 :             CoolingHeatingPLRRatio = min(1.0, CoolPartLoadRatio / state.dataFurnaces->Furnace(FurnaceNum).HeatPartLoadRatio);
    8895              :         } else {
    8896      8217331 :             CoolingHeatingPLRRatio = 1.0;
    8897              :         }
    8898              : 
    8899              :         // Subroutine arguments
    8900      8217331 :         CalcFurnaceOutput(state,
    8901              :                           FurnaceNum,
    8902              :                           FirstHVACIteration,
    8903              :                           fanOp,
    8904              :                           compressorOp,
    8905              :                           CoolPartLoadRatio,
    8906              :                           HeatPartLoadRatio,
    8907              :                           HeatCoilLoad,
    8908              :                           0.0,
    8909              :                           SensibleLoadMet,
    8910              :                           LatentLoadMet,
    8911              :                           OnOffAirFlowRatio,
    8912              :                           HXUnitOn,
    8913              :                           CoolingHeatingPLRRatio);
    8914              : 
    8915              :         // Calculate residual based on output calculation flag
    8916      8217331 :         if (par7_sensLatentFlag == 1.0) {
    8917      7772551 :             if (LoadToBeMet == 0.0) {
    8918        65344 :                 return (SensibleLoadMet - LoadToBeMet) / 100.0;
    8919              :             } else {
    8920      7707207 :                 return (SensibleLoadMet - LoadToBeMet) / LoadToBeMet;
    8921              :             }
    8922              :         } else {
    8923       444780 :             if (LoadToBeMet == 0.0) {
    8924            0 :                 return (LatentLoadMet - LoadToBeMet) / 100.0;
    8925              :             } else {
    8926       444780 :                 return (LatentLoadMet - LoadToBeMet) / LoadToBeMet;
    8927              :             }
    8928              :         }
    8929              :     }
    8930              : 
    8931       261281 :     Real64 CalcWaterToAirResidual(EnergyPlusData &state,
    8932              :                                   Real64 const PartLoadRatio, // DX cooling coil part load ratio
    8933              :                                   int FurnaceNum,
    8934              :                                   bool FirstHVACIteration,
    8935              :                                   HVAC::FanOp const fanOp,
    8936              :                                   HVAC::CompressorOp compressorOp,
    8937              :                                   Real64 LoadToBeMet,
    8938              :                                   Real64 par6_loadTypeFlag,
    8939              :                                   Real64 par7_latentOrSensible,
    8940              :                                   Real64 ZoneSensLoadMetFanONCompOFF,
    8941              :                                   Real64 par9_HXUnitOne)
    8942              :     {
    8943              : 
    8944              :         // FUNCTION INFORMATION:
    8945              :         //       AUTHOR         Richard Raustad
    8946              :         //       DATE WRITTEN   October 2006
    8947              : 
    8948              :         // PURPOSE OF THIS SUBROUTINE:
    8949              :         // To calculate the part-load ratio for water to air HP's
    8950              :         // this is used for parameter estimation WAHPs but not equation fit WAHPs
    8951              : 
    8952              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    8953              :         Real64 CoolPartLoadRatio; // DX cooling coil part load ratio
    8954              :         Real64 HeatPartLoadRatio; // DX heating coil part load ratio (0 for other heating coil types)
    8955              :         Real64 HeatCoilLoad;      // Heating coil load for gas heater
    8956              :         Real64 ZoneSensLoadMet;   // Sensible cooling load met (furnace outlet with respect to control zone temp)
    8957              :         Real64 ZoneLatLoadMet;    // Latent cooling load met (furnace outlet with respect to control zone humidity ratio)
    8958              :         Real64 Dummy;
    8959              :         Real64 HPCoilSensDemand;
    8960              :         Real64 OnOffAirFlowRatio;
    8961              :         bool HXUnitOn; // flag to enable HX based on zone moisture load (not valid for water-to-air HP's
    8962              : 
    8963              :         // Convert parameters to usable variables
    8964              :         //        int FurnaceNum = int(Par[0]);
    8965              :         //        bool FirstHVACIteration = Par[1] == 1.0;
    8966              :         //        int FanOp = int(Par[2]);
    8967              :         //        CompressorOperation CompressorOp = static_cast<CompressorOperation>(Par[3]);
    8968              :         //        Real64 LoadToBeMet = Par[4];
    8969              :         //        Real64 par6_loadTypeFlag = Par[5];
    8970              :         //        Real64 par7_latentOrSensible = Par[6];
    8971              :         //        Real64 ZoneSensLoadMetFanONCompOFF = Par[7];
    8972              :         //        Real64 par9_HXUnitOne = Par[8];
    8973              : 
    8974              :         int CoilIndex;
    8975       261281 :         if (par6_loadTypeFlag == 1.0) {
    8976       108152 :             CoolPartLoadRatio = PartLoadRatio;
    8977       108152 :             HeatPartLoadRatio = 0.0;
    8978       108152 :             HeatCoilLoad = 0.0;
    8979       108152 :             CoilIndex = state.dataFurnaces->Furnace(FurnaceNum).CoolingCoilIndex;
    8980              :         } else {
    8981       153129 :             CoolPartLoadRatio = 0.0;
    8982       153129 :             HeatPartLoadRatio = PartLoadRatio;
    8983       153129 :             CoilIndex = state.dataFurnaces->Furnace(FurnaceNum).HeatingCoilIndex;
    8984              :         }
    8985              : 
    8986              :         // Get child component RuntimeFrac
    8987              :         Real64 RuntimeFrac;
    8988       261281 :         switch (state.dataFurnaces->Furnace(FurnaceNum).WatertoAirHPType) {
    8989            0 :         case WAHPCoilType::Simple: {
    8990            0 :             RuntimeFrac = state.dataWaterToAirHeatPumpSimple->SimpleWatertoAirHP(CoilIndex).RunFrac;
    8991            0 :             break;
    8992              :         }
    8993       261281 :         case WAHPCoilType::ParEst: {
    8994       261281 :             RuntimeFrac = state.dataWaterToAirHeatPump->WatertoAirHP(CoilIndex).RunFrac;
    8995       261281 :             break;
    8996              :         }
    8997            0 :         case WAHPCoilType::VarSpeedEquationFit: {
    8998            0 :             RuntimeFrac = state.dataVariableSpeedCoils->VarSpeedCoil(CoilIndex).RunFrac;
    8999            0 :             break;
    9000              :         }
    9001            0 :         default:
    9002            0 :             RuntimeFrac = 1.0; // Programming error. Assert failure?
    9003              :         }
    9004              : 
    9005       261281 :         state.dataFurnaces->OnOffFanPartLoadFractionSave = state.dataHVACGlobal->OnOffFanPartLoadFraction;
    9006              :         // update fan and compressor run times
    9007       261281 :         state.dataFurnaces->Furnace(FurnaceNum).CompPartLoadRatio = PartLoadRatio;
    9008              : 
    9009              :         // Calculate the heating coil demand as (the zone sensible load - load met by fan heat and mixed air)
    9010              :         // Note; The load met by fan heat and mixed air is calculated as mdot(zoneinletenthalpy-zoneoutletenthalpy)
    9011              :         // This accounts for the negative sign in the equation.
    9012              : 
    9013              :         // Calculate the heat coil sensible capacity as the load met by the system with the fan and compressor on less
    9014              :         // the load met by the system with the compressor off.
    9015              :         //  HPCoilSensCapacity = ZoneSensLoadMetFanONCompON - ZoneSensLoadMetFanONCompOFF
    9016              : 
    9017              :         // Set input parameters for heat pump coil model
    9018       261281 :         HPCoilSensDemand = LoadToBeMet - RuntimeFrac * ZoneSensLoadMetFanONCompOFF;
    9019              :         //  HPCoilSensDemand = LoadToBeMet  - PartLoadRatio*ZoneSensLoadMetFanONCompOFF
    9020       261281 :         if (par6_loadTypeFlag == 1.0) {
    9021       108152 :             state.dataFurnaces->Furnace(FurnaceNum).HeatingCoilSensDemand = 0.0;
    9022       108152 :             state.dataFurnaces->Furnace(FurnaceNum).CoolingCoilSensDemand = std::abs(HPCoilSensDemand);
    9023              :         } else {
    9024       153129 :             state.dataFurnaces->Furnace(FurnaceNum).HeatingCoilSensDemand = HPCoilSensDemand;
    9025       153129 :             state.dataFurnaces->Furnace(FurnaceNum).CoolingCoilSensDemand = 0.0;
    9026              :         }
    9027       261281 :         state.dataFurnaces->Furnace(FurnaceNum).InitHeatPump = false; // initialization call to Calc Furnace
    9028              : 
    9029              :         // Calculate the zone loads met and the new part load ratio and for the specified run time
    9030       261281 :         Dummy = 0.0;
    9031       261281 :         OnOffAirFlowRatio = 1.0;
    9032       261281 :         if (par9_HXUnitOne == 1.0) {
    9033            0 :             HXUnitOn = true;
    9034              :         } else {
    9035       261281 :             HXUnitOn = false;
    9036              :         }
    9037              : 
    9038              :         //  Subroutine arguments
    9039              :         //  CALL CalcFurnaceOutput(FurnaceNum,FirstHVACIteration,FanOp,compressorOp,CoolPartLoadRatio,&
    9040              :         //                         HeatPartLoadRatio, HeatCoilLoad, ReHeatCoilLoad, SensibleLoadMet, LatentLoadMet, HXUnitOn)
    9041       261281 :         CalcFurnaceOutput(state,
    9042              :                           FurnaceNum,
    9043              :                           FirstHVACIteration,
    9044              :                           fanOp,
    9045              :                           compressorOp,
    9046              :                           CoolPartLoadRatio,
    9047              :                           HeatPartLoadRatio,
    9048              :                           Dummy,
    9049              :                           Dummy,
    9050              :                           ZoneSensLoadMet,
    9051              :                           ZoneLatLoadMet,
    9052              :                           OnOffAirFlowRatio,
    9053              :                           HXUnitOn);
    9054              : 
    9055              :         // Calculate residual based on output calculation flag
    9056       261281 :         if (par7_latentOrSensible == 1.0) {
    9057       261281 :             return (ZoneSensLoadMet - LoadToBeMet) / LoadToBeMet;
    9058              :         } else {
    9059            0 :             return (ZoneLatLoadMet - LoadToBeMet) / LoadToBeMet;
    9060              :         }
    9061              :     }
    9062              : 
    9063     24511473 :     void SetAverageAirFlow(EnergyPlusData &state,
    9064              :                            int const FurnaceNum,       // Unit index
    9065              :                            Real64 const PartLoadRatio, // unit part load ratio
    9066              :                            Real64 &OnOffAirFlowRatio   // ratio of compressor ON airflow to AVERAGE airflow over timestep
    9067              :     )
    9068              :     {
    9069              : 
    9070              :         // SUBROUTINE INFORMATION:
    9071              :         //       AUTHOR         Richard Raustad
    9072              :         //       DATE WRITTEN   July 2005
    9073              : 
    9074              :         // PURPOSE OF THIS SUBROUTINE:
    9075              :         // Set the average air mass flow rates using the part-load fraction of the HVAC system for this time step
    9076              :         // Set OnOffAirFlowRatio to be used by DX coils
    9077              : 
    9078              :         // METHODOLOGY EMPLOYED:
    9079              :         // The air flow rate in cooling, heating, and no cooling or heating can be different.
    9080              :         // Calculate the air flow rate based on initializations made in InitFurnace.
    9081              : 
    9082     24511473 :         int InletNode = state.dataFurnaces->Furnace(FurnaceNum).FurnaceInletNodeNum;
    9083              :         Real64 AverageUnitMassFlow =
    9084     24511473 :             (PartLoadRatio * state.dataFurnaces->CompOnMassFlow) + ((1 - PartLoadRatio) * state.dataFurnaces->CompOffMassFlow);
    9085     24511473 :         if (state.dataFurnaces->CompOffFlowRatio > 0.0) {
    9086     11822330 :             state.dataFurnaces->FanSpeedRatio =
    9087     11822330 :                 (PartLoadRatio * state.dataFurnaces->CompOnFlowRatio) + ((1 - PartLoadRatio) * state.dataFurnaces->CompOffFlowRatio);
    9088              :         } else {
    9089     12689143 :             state.dataFurnaces->FanSpeedRatio = state.dataFurnaces->CompOnFlowRatio;
    9090              :         }
    9091              : 
    9092              :         // IF the furnace is scheduled on or nightime cycle overrides fan schedule. Uses same logic as fan.
    9093     72152709 :         if (state.dataFurnaces->Furnace(FurnaceNum).availSched->getCurrentVal() > 0.0 &&
    9094     25459604 :             ((state.dataFurnaces->Furnace(FurnaceNum).fanAvailSched->getCurrentVal() > 0.0 || state.dataHVACGlobal->TurnFansOn) &&
    9095     23146618 :              !state.dataHVACGlobal->TurnFansOff)) {
    9096     23146618 :             state.dataLoopNodes->Node(InletNode).MassFlowRate = AverageUnitMassFlow;
    9097     23146618 :             state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail = AverageUnitMassFlow;
    9098     23146618 :             if (AverageUnitMassFlow > 0.0) {
    9099     19086371 :                 OnOffAirFlowRatio = state.dataFurnaces->CompOnMassFlow / AverageUnitMassFlow;
    9100              :             } else {
    9101      4060247 :                 OnOffAirFlowRatio = 0.0;
    9102              :             }
    9103              :         } else {
    9104      1364855 :             state.dataLoopNodes->Node(InletNode).MassFlowRate = 0.0;
    9105      1364855 :             OnOffAirFlowRatio = 1.0;
    9106              :         }
    9107              : 
    9108     24511473 :         state.dataFurnaces->Furnace(FurnaceNum).MdotFurnace = state.dataFurnaces->CompOnMassFlow;
    9109     24511473 :         state.dataFurnaces->OnOffAirFlowRatioSave = OnOffAirFlowRatio;
    9110     24511473 :     }
    9111              : 
    9112              :     // Beginning of Reporting subroutines for the Furnace Module
    9113              :     // *****************************************************************************
    9114              : 
    9115      6219025 :     void ReportFurnace(EnergyPlusData &state, int const FurnaceNum, int const AirLoopNum)
    9116              :     {
    9117              : 
    9118              :         // SUBROUTINE INFORMATION:
    9119              :         //       AUTHOR         Richard Liesen
    9120              :         //       DATE WRITTEN   Feb 2001
    9121              : 
    9122              :         // PURPOSE OF THIS SUBROUTINE:
    9123              :         // This subroutine updates the report variable for the coils.
    9124              : 
    9125              :         // METHODOLOGY EMPLOYED:
    9126              :         // Update fan part-load ratio based on mass flow rate ratio.
    9127              :         // Update global variables used by AirflowNetwork module.
    9128              : 
    9129              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    9130              :         Real64 ratio;
    9131              :         Real64 OnOffRatio;
    9132      6219025 :         auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    9133              : 
    9134              :         // Report the Furnace Fan Part Load Ratio
    9135      6219025 :         if (thisFurnace.NumOfSpeedCooling < 1) {
    9136      4711401 :             if (thisFurnace.DesignMassFlowRate > 0.0) {
    9137      4711401 :                 thisFurnace.FanPartLoadRatio = thisFurnace.MdotFurnace / thisFurnace.DesignMassFlowRate;
    9138              :             } else {
    9139            0 :                 thisFurnace.FanPartLoadRatio = 0.0;
    9140              :             }
    9141              :         }
    9142              : 
    9143              :         // Set mass flow rates during on and off cycle using an OnOff fan
    9144      6219025 :         if (state.afn->distribution_simulated) {
    9145       214495 :             state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopSystemOnMassFlowrate = state.dataFurnaces->CompOnMassFlow;
    9146       214495 :             state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopSystemOffMassFlowrate = state.dataFurnaces->CompOffMassFlow;
    9147       214495 :             state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopFanOperationMode = thisFurnace.fanOp;
    9148       214495 :             state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopOnOffFanPartLoadRatio = thisFurnace.FanPartLoadRatio;
    9149       214495 :             OnOffRatio = state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopOnOffFanPartLoadRatio;
    9150       214495 :             if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_AirToAir) {
    9151       150922 :                 state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopOnOffFanPartLoadRatio =
    9152       150922 :                     max(thisFurnace.FanPartLoadRatio, thisFurnace.HeatPartLoadRatio, thisFurnace.CoolPartLoadRatio);
    9153       150922 :                 state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopOnOffFanPartLoadRatio =
    9154       150922 :                     min(1.0, state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopOnOffFanPartLoadRatio);
    9155              :             }
    9156       214495 :             if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatCool) {
    9157        24774 :                 if (thisFurnace.HeatPartLoadRatio == 0.0 && thisFurnace.CoolPartLoadRatio == 0.0 && thisFurnace.FanPartLoadRatio > 0.0) {
    9158         7424 :                     if (state.dataFurnaces->CompOnMassFlow < max(thisFurnace.MaxCoolAirMassFlow, thisFurnace.MaxHeatAirMassFlow) &&
    9159            0 :                         state.dataFurnaces->CompOnMassFlow > 0.0) {
    9160            0 :                         ratio = max(thisFurnace.MaxCoolAirMassFlow, thisFurnace.MaxHeatAirMassFlow) / state.dataFurnaces->CompOnMassFlow;
    9161            0 :                         state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopOnOffFanPartLoadRatio =
    9162            0 :                             state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopOnOffFanPartLoadRatio * ratio;
    9163              :                     }
    9164              :                 }
    9165              :             }
    9166              :         }
    9167      6219025 :         if (thisFurnace.FirstPass) {
    9168          359 :             if (!state.dataGlobal->SysSizingCalc) {
    9169          359 :                 DataSizing::resetHVACSizingGlobals(state, 0, state.dataSize->CurSysNum, thisFurnace.FirstPass);
    9170              :             }
    9171              :         }
    9172      6219025 :         state.dataHVACGlobal->OnOffFanPartLoadFraction =
    9173              :             1.0; // reset to 1 in case blow through fan configuration (fan resets to 1, but for blow thru fans coil sets back down < 1)
    9174      6219025 :     }
    9175              : 
    9176     67490593 :     void CalcNonDXHeatingCoils(EnergyPlusData &state,
    9177              :                                int const FurnaceNum,           // Furnace Index
    9178              :                                bool const SuppHeatingCoilFlag, // .TRUE. if supplemental heating coil
    9179              :                                bool const FirstHVACIteration,  // flag for first HVAC iteration in the time step
    9180              :                                Real64 const QCoilLoad,         // load met by unit (watts)
    9181              :                                HVAC::FanOp const fanOp,        // fan operation mode
    9182              :                                Real64 &HeatCoilLoadmet         // Heating Load Met
    9183              :     )
    9184              :     {
    9185              :         // SUBROUTINE INFORMATION:
    9186              :         //       AUTHOR         Bereket Nigusse, FSEC/UCF
    9187              :         //       DATE WRITTEN   January 2012
    9188              : 
    9189              :         // PURPOSE OF THIS SUBROUTINE:
    9190              :         // This subroutine simulates the four non dx heating coil types: Gas, Electric, hot water and steam.
    9191              : 
    9192              :         // METHODOLOGY EMPLOYED:
    9193              :         // Simply calls the different heating coil component.  The hot water flow rate matching the coil load
    9194              :         // is calculated iteratively.
    9195              : 
    9196              :         // SUBROUTINE PARAMETER DEFINITIONS:
    9197     67490593 :         Real64 constexpr ErrTolerance(0.001); // convergence limit for hotwater coil
    9198     67490593 :         int constexpr SolveMaxIter(50);
    9199              : 
    9200              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    9201              :         Real64 mdot;              // heating coil steam or hot water mass flow rate
    9202              :         Real64 MinWaterFlow;      // coil minimum hot water mass flow rate, kg/s
    9203              :         Real64 MaxHotWaterFlow;   // coil maximum hot water mass flow rate, kg/s
    9204              :         Real64 HotWaterMdot;      // actual hot water mass flow rate
    9205     67490593 :         int CoilTypeNum(0);       // heating coil type number
    9206     67490593 :         int HeatingCoilIndex(0);  // heating coil index
    9207     67490593 :         int CoilControlNode(0);   // control node for hot water and steam heating coils
    9208     67490593 :         int CoilOutletNode(0);    // air outlet node of the heating coils
    9209     67490593 :         PlantLocation plantLoc{}; // plant loop location
    9210              : 
    9211     67490593 :         Real64 QActual = 0.0;                                               // actual heating load
    9212     67490593 :         std::string &HeatingCoilName = state.dataFurnaces->HeatingCoilName; // name of heating coil
    9213     67490593 :         auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    9214              : 
    9215     67490593 :         if (SuppHeatingCoilFlag) {
    9216     19152541 :             HeatingCoilName = thisFurnace.SuppHeatCoilName;
    9217     19152541 :             HeatingCoilIndex = thisFurnace.SuppHeatCoilIndex;
    9218     19152541 :             CoilControlNode = thisFurnace.SuppCoilControlNode;
    9219     19152541 :             CoilOutletNode = thisFurnace.SuppCoilOutletNode;
    9220     19152541 :             CoilTypeNum = thisFurnace.SuppHeatCoilType_Num;
    9221     19152541 :             plantLoc = thisFurnace.SuppPlantLoc;
    9222     19152541 :             MaxHotWaterFlow = thisFurnace.MaxSuppCoilFluidFlow;
    9223              :         } else {
    9224     48338052 :             HeatingCoilName = thisFurnace.HeatingCoilName;
    9225     48338052 :             HeatingCoilIndex = thisFurnace.HeatingCoilIndex;
    9226     48338052 :             CoilControlNode = thisFurnace.CoilControlNode;
    9227     48338052 :             CoilOutletNode = thisFurnace.CoilOutletNode;
    9228     48338052 :             CoilTypeNum = thisFurnace.HeatingCoilType_Num;
    9229     48338052 :             plantLoc = thisFurnace.plantLoc;
    9230     48338052 :             MaxHotWaterFlow = thisFurnace.MaxHeatCoilFluidFlow;
    9231              :         }
    9232              : 
    9233     67490593 :         switch (CoilTypeNum) {
    9234     67399865 :         case HVAC::Coil_HeatingGasOrOtherFuel:
    9235              :         case HVAC::Coil_HeatingElectric:
    9236              :         case HVAC::Coil_HeatingDesuperheater: {
    9237     67399865 :             HeatingCoils::SimulateHeatingCoilComponents(
    9238              :                 state, HeatingCoilName, FirstHVACIteration, QCoilLoad, HeatingCoilIndex, QActual, SuppHeatingCoilFlag, fanOp);
    9239     67399865 :         } break;
    9240        90728 :         case HVAC::Coil_HeatingWater: {
    9241        90728 :             if (QCoilLoad > HVAC::SmallLoad) {
    9242         1590 :                 PlantUtilities::SetComponentFlowRate(state, MaxHotWaterFlow, CoilControlNode, CoilOutletNode, plantLoc);
    9243         1590 :                 WaterCoils::SimulateWaterCoilComponents(state, HeatingCoilName, FirstHVACIteration, HeatingCoilIndex, QActual, fanOp);
    9244              : 
    9245         1590 :                 if (QActual > (QCoilLoad + HVAC::SmallLoad)) {
    9246              :                     // control water flow to obtain output matching QCoilLoad
    9247         1468 :                     MinWaterFlow = 0.0;
    9248        22516 :                     auto f = [&state, FurnaceNum, FirstHVACIteration, QCoilLoad, SuppHeatingCoilFlag](Real64 const HWFlow) {
    9249        22516 :                         Real64 QCoilRequested = QCoilLoad;
    9250              : 
    9251              :                         // FUNCTION LOCAL VARIABLE DECLARATIONS:
    9252              :                         Real64 QCoilActual;   // delivered coil load, W
    9253        22516 :                         Real64 mdot = HWFlow; // to get non-const argument
    9254        22516 :                         QCoilActual = QCoilRequested;
    9255        22516 :                         if (!SuppHeatingCoilFlag) {
    9256            0 :                             PlantUtilities::SetComponentFlowRate(state,
    9257              :                                                                  mdot,
    9258            0 :                                                                  state.dataFurnaces->Furnace(FurnaceNum).CoilControlNode,
    9259            0 :                                                                  state.dataFurnaces->Furnace(FurnaceNum).CoilOutletNode,
    9260            0 :                                                                  state.dataFurnaces->Furnace(FurnaceNum).plantLoc);
    9261            0 :                             WaterCoils::SimulateWaterCoilComponents(state,
    9262            0 :                                                                     state.dataFurnaces->Furnace(FurnaceNum).HeatingCoilName,
    9263              :                                                                     FirstHVACIteration,
    9264            0 :                                                                     state.dataFurnaces->Furnace(FurnaceNum).HeatingCoilIndex,
    9265              :                                                                     QCoilActual,
    9266            0 :                                                                     state.dataFurnaces->Furnace(FurnaceNum).fanOp);
    9267              :                         } else {
    9268              :                             // supplemental coil
    9269        45032 :                             PlantUtilities::SetComponentFlowRate(state,
    9270              :                                                                  mdot,
    9271        22516 :                                                                  state.dataFurnaces->Furnace(FurnaceNum).SuppCoilControlNode,
    9272        22516 :                                                                  state.dataFurnaces->Furnace(FurnaceNum).SuppCoilOutletNode,
    9273        22516 :                                                                  state.dataFurnaces->Furnace(FurnaceNum).SuppPlantLoc);
    9274              :                             // simulate the hot water supplemental heating coil
    9275        67548 :                             WaterCoils::SimulateWaterCoilComponents(state,
    9276        22516 :                                                                     state.dataFurnaces->Furnace(FurnaceNum).SuppHeatCoilName,
    9277              :                                                                     FirstHVACIteration,
    9278        22516 :                                                                     state.dataFurnaces->Furnace(FurnaceNum).SuppHeatCoilIndex,
    9279              :                                                                     QCoilActual,
    9280        22516 :                                                                     state.dataFurnaces->Furnace(FurnaceNum).fanOp);
    9281              :                         }
    9282        45032 :                         return QCoilRequested != 0.0 ? (QCoilActual - QCoilRequested) / QCoilRequested : 0.0;
    9283         1468 :                     };
    9284         1468 :                     int SolFlag = 0;
    9285         1468 :                     General::SolveRoot(state, ErrTolerance, SolveMaxIter, SolFlag, HotWaterMdot, f, MinWaterFlow, MaxHotWaterFlow);
    9286         1468 :                     if (SolFlag == -1) {
    9287            0 :                         if (thisFurnace.HotWaterCoilMaxIterIndex == 0) {
    9288            0 :                             ShowWarningMessage(state,
    9289            0 :                                                format("CalcNonDXHeatingCoils: Hot water coil control failed for {}=\"{}\"",
    9290            0 :                                                       HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    9291            0 :                                                       thisFurnace.Name));
    9292            0 :                             ShowContinueErrorTimeStamp(state, "");
    9293            0 :                             ShowContinueError(state, format("  Iteration limit [{}] exceeded in calculating hot water mass flow rate", SolveMaxIter));
    9294              :                         }
    9295            0 :                         ShowRecurringWarningErrorAtEnd(
    9296              :                             state,
    9297            0 :                             format("CalcNonDXHeatingCoils: Hot water coil control failed (iteration limit [{}]) for {}=\"{}",
    9298              :                                    SolveMaxIter,
    9299            0 :                                    HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    9300            0 :                                    thisFurnace.Name),
    9301            0 :                             thisFurnace.HotWaterCoilMaxIterIndex);
    9302         1468 :                     } else if (SolFlag == -2) {
    9303            0 :                         if (thisFurnace.HotWaterCoilMaxIterIndex2 == 0) {
    9304            0 :                             ShowWarningMessage(state,
    9305            0 :                                                format("CalcNonDXHeatingCoils: Hot water coil control failed (maximum flow limits) for {}=\"{}\"",
    9306            0 :                                                       HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    9307            0 :                                                       thisFurnace.Name));
    9308            0 :                             ShowContinueErrorTimeStamp(state, "");
    9309            0 :                             ShowContinueError(state, "...Bad hot water maximum flow rate limits");
    9310            0 :                             ShowContinueError(state, format("...Given minimum water flow rate={:.3R} kg/s", MinWaterFlow));
    9311            0 :                             ShowContinueError(state, format("...Given maximum water flow rate={:.3R} kg/s", MaxHotWaterFlow));
    9312              :                         }
    9313            0 :                         ShowRecurringWarningErrorAtEnd(state,
    9314            0 :                                                        format("CalcNonDXHeatingCoils: Hot water coil control failed (flow limits) for {}=\"{}\"",
    9315            0 :                                                               HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    9316            0 :                                                               thisFurnace.Name),
    9317            0 :                                                        thisFurnace.HotWaterCoilMaxIterIndex2,
    9318              :                                                        MaxHotWaterFlow,
    9319              :                                                        MinWaterFlow,
    9320              :                                                        _,
    9321              :                                                        "[kg/s]",
    9322              :                                                        "[kg/s]");
    9323              :                     }
    9324              :                 }
    9325              :             } else {
    9326        89138 :                 mdot = 0.0;
    9327        89138 :                 PlantUtilities::SetComponentFlowRate(state, mdot, CoilControlNode, CoilOutletNode, plantLoc);
    9328              :             }
    9329              :             // simulate the hot water heating coil
    9330        90728 :             WaterCoils::SimulateWaterCoilComponents(state, HeatingCoilName, FirstHVACIteration, HeatingCoilIndex, QActual, fanOp);
    9331        90728 :         } break;
    9332            0 :         case HVAC::Coil_HeatingSteam: {
    9333            0 :             if (QCoilLoad > HVAC::SmallLoad) {
    9334            0 :                 PlantUtilities::SetComponentFlowRate(state, MaxHotWaterFlow, CoilControlNode, CoilOutletNode, plantLoc);
    9335              :                 // simulate the steam heating coil
    9336            0 :                 SteamCoils::SimulateSteamCoilComponents(state, HeatingCoilName, FirstHVACIteration, HeatingCoilIndex, QCoilLoad, QActual, fanOp);
    9337              :             } else {
    9338            0 :                 mdot = 0.0;
    9339            0 :                 PlantUtilities::SetComponentFlowRate(state, mdot, CoilControlNode, CoilOutletNode, plantLoc);
    9340              :                 // simulate the steam heating coil
    9341            0 :                 SteamCoils::SimulateSteamCoilComponents(state, HeatingCoilName, FirstHVACIteration, HeatingCoilIndex, QCoilLoad, QActual, fanOp);
    9342              :             }
    9343            0 :         } break;
    9344            0 :         default:
    9345            0 :             break;
    9346              :         }
    9347              : 
    9348     67490593 :         HeatCoilLoadmet = QActual;
    9349     67490593 :     }
    9350              : 
    9351              :     //        End of Reporting subroutines for the Furnace Module
    9352              : 
    9353              :     //******************************************************************************
    9354              : 
    9355      1507624 :     void SimVariableSpeedHP(EnergyPlusData &state,
    9356              :                             int const FurnaceNum,          // number of the current engine driven Heat Pump being simulated
    9357              :                             bool const FirstHVACIteration, // TRUE if 1st HVAC simulation of system timestep
    9358              :                             int const AirLoopNum,          // index to air loop
    9359              :                             Real64 const QZnReq,           // required zone load
    9360              :                             Real64 const QLatReq,          // required latent load
    9361              :                             Real64 &OnOffAirFlowRatio      // ratio of compressor ON airflow to AVERAGE airflow over timestep
    9362              :     )
    9363              :     {
    9364              : 
    9365              :         // SUBROUTINE INFORMATION:
    9366              :         //       AUTHOR         Bo Shen, based on HVACMultiSpeedHeatPump:CalcMSHeatPump
    9367              :         //       DATE WRITTEN   March, 2012
    9368              : 
    9369              :         // PURPOSE OF THIS SUBROUTINE:
    9370              :         // Simulate a multispeed heat pump; adjust its output to match the
    9371              :         // required system load.
    9372              : 
    9373              :         // METHODOLOGY EMPLOYED:
    9374              :         // Calls ControlMSHPOutput to obtain the desired unit output
    9375              : 
    9376              :         Real64 PartLoadFrac; // compressor part load fraction
    9377              :         Real64 SpeedRatio;   // compressor speed ratio
    9378              :         Real64 QTotUnitOut;  // capacity output
    9379      1507624 :         auto &SpeedNum = state.dataFurnaces->SpeedNum;
    9380      1507624 :         auto &SupHeaterLoad = state.dataFurnaces->SupHeaterLoad;
    9381              :         HVAC::CompressorOp compressorOp; // compressor operation; 1=on, 0=off
    9382              :         Real64 QSensUnitOut;             // sensible capacity output
    9383              :         Real64 QLatUnitOut;              // latent capacity output
    9384              :         Real64 ActualSensibleOutput;     // Actual furnace sensible capacity
    9385              :         Real64 QToHeatSetPt;             // Load required to meet heating setpoint temp (>0 is a heating load)
    9386              :         Real64 NoCompOutput;             // output when no active compressor [W]
    9387              :         bool EconoActive;                // TRUE if Economizer is active
    9388              : 
    9389              :         // zero DX coils, and supplemental electric heater electricity consumption
    9390      1507624 :         state.dataHVACGlobal->DXElecHeatingPower = 0.0;
    9391      1507624 :         state.dataHVACGlobal->DXElecCoolingPower = 0.0;
    9392      1507624 :         state.dataFurnaces->SaveCompressorPLR = 0.0;
    9393      1507624 :         state.dataHVACGlobal->ElecHeatingCoilPower = 0.0;
    9394      1507624 :         state.dataHVACGlobal->SuppHeatingCoilPower = 0.0;
    9395      1507624 :         state.dataHVACGlobal->DefrostElecPower = 0.0;
    9396              : 
    9397      1507624 :         Real64 SystemSensibleLoad = QZnReq; // Positive value means heating required
    9398      1507624 :         Real64 TotalZoneSensibleLoad = QZnReq;
    9399      1507624 :         Real64 TotalZoneLatentLoad = QLatReq;
    9400      1507624 :         auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    9401              :         // initialize local variables
    9402      1507624 :         bool UnitOn = true;
    9403      1507624 :         int OutletNode = thisFurnace.FurnaceOutletNodeNum;
    9404      1507624 :         int InletNode = thisFurnace.FurnaceInletNodeNum;
    9405      1507624 :         Real64 AirMassFlow = thisFurnace.DesignMassFlowRate;
    9406      1507624 :         HVAC::FanOp fanOp = thisFurnace.fanOp; // fan operating mode
    9407      1507624 :         int ZoneNum = thisFurnace.ControlZoneNum;
    9408              : 
    9409              :         // Set latent load for heating
    9410      1507624 :         if (state.dataFurnaces->HeatingLoad) {
    9411       105434 :             thisFurnace.HeatCoolMode = Furnaces::ModeOfOperation::HeatingMode;
    9412              :             // Set latent load for cooling and no sensible load condition
    9413      1402190 :         } else if (state.dataFurnaces->CoolingLoad) {
    9414      1302969 :             thisFurnace.HeatCoolMode = Furnaces::ModeOfOperation::CoolingMode;
    9415              :         } else {
    9416        99221 :             thisFurnace.HeatCoolMode = Furnaces::ModeOfOperation::NoCoolHeat;
    9417              :         }
    9418              : 
    9419              :         // set the on/off flags
    9420      1507624 :         if (thisFurnace.fanOp == HVAC::FanOp::Cycling) {
    9421              :             // cycling unit only runs if there is a cooling or heating load.
    9422        55903 :             if (std::abs(QZnReq) < HVAC::SmallLoad || AirMassFlow < HVAC::SmallMassFlow ||
    9423        25641 :                 state.dataZoneEnergyDemand->CurDeadBandOrSetback(ZoneNum)) {
    9424         4624 :                 UnitOn = false;
    9425              :             }
    9426      1477362 :         } else if (thisFurnace.fanOp == HVAC::FanOp::Continuous) {
    9427              :             // continuous unit: fan runs if scheduled on; coil runs only if there is a cooling or heating load
    9428      1477362 :             if (AirMassFlow < HVAC::SmallMassFlow) {
    9429            0 :                 UnitOn = false;
    9430              :             }
    9431              :         }
    9432              : 
    9433      1507624 :         state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
    9434      1507624 :         EconoActive = (AirLoopNum != 0) ? state.dataAirLoop->AirLoopControlInfo(AirLoopNum).EconoActive : false;
    9435              : 
    9436      1507624 :         Real64 SaveMassFlowRate = state.dataLoopNodes->Node(InletNode).MassFlowRate;
    9437              :         // decide current working mode for IHP
    9438      1507624 :         if ((FirstHVACIteration) && (thisFurnace.bIsIHP)) {
    9439         5024 :             IntegratedHeatPump::DecideWorkMode(state, thisFurnace.CoolingCoilIndex, TotalZoneSensibleLoad, TotalZoneLatentLoad);
    9440              :         }
    9441              : 
    9442      1507624 :         if (!FirstHVACIteration && thisFurnace.fanOp == HVAC::FanOp::Cycling &&
    9443        15160 :             (QZnReq < (-1.0 * HVAC::SmallLoad) || TotalZoneLatentLoad < (-HVAC::SmallLoad)) && EconoActive) {
    9444              :             // for cycling fan, cooling load, check whether furnace can meet load with compressor off
    9445            0 :             compressorOp = HVAC::CompressorOp::Off;
    9446            0 :             ControlVSHPOutput(state,
    9447              :                               FurnaceNum,
    9448              :                               FirstHVACIteration,
    9449              :                               compressorOp,
    9450              :                               fanOp,
    9451              :                               TotalZoneSensibleLoad,
    9452              :                               TotalZoneLatentLoad,
    9453              :                               SpeedNum,
    9454              :                               SpeedRatio,
    9455              :                               PartLoadFrac,
    9456              :                               OnOffAirFlowRatio,
    9457              :                               SupHeaterLoad);
    9458              : 
    9459            0 :             TotalZoneSensibleLoad = QZnReq;
    9460            0 :             TotalZoneLatentLoad = QLatReq;
    9461              : 
    9462            0 :             if (SpeedNum == thisFurnace.NumOfSpeedCooling && SpeedRatio == 1.0) {
    9463              :                 // compressor on (reset inlet air mass flow rate to starting value)
    9464            0 :                 state.dataLoopNodes->Node(InletNode).MassFlowRate = SaveMassFlowRate;
    9465            0 :                 compressorOp = HVAC::CompressorOp::On;
    9466            0 :                 ControlVSHPOutput(state,
    9467              :                                   FurnaceNum,
    9468              :                                   FirstHVACIteration,
    9469              :                                   compressorOp,
    9470              :                                   fanOp,
    9471              :                                   TotalZoneSensibleLoad,
    9472              :                                   TotalZoneLatentLoad,
    9473              :                                   SpeedNum,
    9474              :                                   SpeedRatio,
    9475              :                                   PartLoadFrac,
    9476              :                                   OnOffAirFlowRatio,
    9477              :                                   SupHeaterLoad);
    9478              :             }
    9479              :         } else {
    9480              :             // compressor on
    9481      1507624 :             compressorOp = HVAC::CompressorOp::On;
    9482              : 
    9483      1507624 :             ControlVSHPOutput(state,
    9484              :                               FurnaceNum,
    9485              :                               FirstHVACIteration,
    9486              :                               compressorOp,
    9487              :                               fanOp,
    9488              :                               TotalZoneSensibleLoad,
    9489              :                               TotalZoneLatentLoad,
    9490              :                               SpeedNum,
    9491              :                               SpeedRatio,
    9492              :                               PartLoadFrac,
    9493              :                               OnOffAirFlowRatio,
    9494              :                               SupHeaterLoad);
    9495              :         }
    9496              : 
    9497      1507624 :         if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatCool) {
    9498      1247320 :             state.dataFurnaces->SaveCompressorPLR = PartLoadFrac;
    9499              :         } else {
    9500       260304 :             if (SpeedNum > 1) {
    9501       110053 :                 state.dataFurnaces->SaveCompressorPLR = 1.0;
    9502              :             }
    9503              : 
    9504       260304 :             if (PartLoadFrac == 1.0 && state.dataFurnaces->SaveCompressorPLR < 1.0) {
    9505           10 :                 PartLoadFrac = state.dataFurnaces->SaveCompressorPLR;
    9506              :             }
    9507              :         }
    9508              : 
    9509      1507624 :         Real64 ReheatCoilLoad = 0.0;
    9510      1507624 :         TotalZoneSensibleLoad = QZnReq;
    9511      1507624 :         TotalZoneLatentLoad = QLatReq;
    9512              :         //     Calculate the reheat coil output
    9513      3003668 :         if ((thisFurnace.availSched->getCurrentVal() > 0.0) &&
    9514      1496044 :             (thisFurnace.Humidistat && thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat &&
    9515              :              (QLatReq < 0.0))) { // if a Humidistat is installed and dehumidification control type is CoolReheat
    9516        74584 :             CalcVarSpeedHeatPump(state,
    9517              :                                  FurnaceNum,
    9518              :                                  FirstHVACIteration,
    9519              :                                  compressorOp,
    9520              :                                  SpeedNum,
    9521              :                                  SpeedRatio,
    9522              :                                  PartLoadFrac,
    9523              :                                  ActualSensibleOutput,
    9524              :                                  QLatUnitOut,
    9525              :                                  TotalZoneSensibleLoad,
    9526              :                                  TotalZoneLatentLoad,
    9527              :                                  OnOffAirFlowRatio,
    9528              :                                  ReheatCoilLoad);
    9529        74584 :             if (thisFurnace.ZoneSequenceHeatingNum > 0) {
    9530        74584 :                 QToHeatSetPt = (state.dataZoneEnergyDemand->ZoneSysEnergyDemand(thisFurnace.ControlZoneNum)
    9531        74584 :                                     .SequencedOutputRequiredToHeatingSP(thisFurnace.ZoneSequenceHeatingNum) /
    9532        74584 :                                 thisFurnace.ControlZoneMassFlowFrac);
    9533              :             } else {
    9534            0 :                 QToHeatSetPt = (state.dataZoneEnergyDemand->ZoneSysEnergyDemand(thisFurnace.ControlZoneNum).OutputRequiredToHeatingSP /
    9535            0 :                                 thisFurnace.ControlZoneMassFlowFrac);
    9536              :             }
    9537              :             //       Cooling mode or floating condition and dehumidification is required
    9538        74584 :             if (QToHeatSetPt < 0.0) {
    9539              :                 //         Calculate the reheat coil load wrt the heating setpoint temperature. Reheat coil picks up
    9540              :                 //         the entire excess sensible cooling (DX cooling coil and impact of outdoor air).
    9541        52682 :                 ReheatCoilLoad = max(0.0, (QToHeatSetPt - ActualSensibleOutput));
    9542        52682 :                 thisFurnace.DehumidInducedHeatingDemandRate = ReheatCoilLoad;
    9543              :                 //       Heating mode and dehumidification is required
    9544              :             } else {
    9545        21902 :                 ReheatCoilLoad = max(QToHeatSetPt, QToHeatSetPt - ActualSensibleOutput);
    9546        21902 :                 thisFurnace.DehumidInducedHeatingDemandRate = max(0.0, ActualSensibleOutput * (-1.0));
    9547              :             }
    9548              : 
    9549        74584 :             SupHeaterLoad = 0.0;
    9550        74584 :             CalcVarSpeedHeatPump(state,
    9551              :                                  FurnaceNum,
    9552              :                                  FirstHVACIteration,
    9553              :                                  compressorOp,
    9554              :                                  1,
    9555              :                                  0.0,
    9556              :                                  0.0,
    9557              :                                  NoCompOutput,
    9558              :                                  QLatUnitOut,
    9559              :                                  0.0,
    9560              :                                  0.0,
    9561              :                                  OnOffAirFlowRatio,
    9562              :                                  SupHeaterLoad);
    9563              : 
    9564        74584 :             if (NoCompOutput > SystemSensibleLoad && SystemSensibleLoad > 0.0 && ReheatCoilLoad > 0.0) {
    9565              :                 // Reduce reheat coil load if you are controlling high humidity but outside air
    9566              :                 // and/or the supply air fan is providing enough heat to meet the system sensible load.
    9567              :                 // This will bring the zone temp closer to the heating setpoint temp.
    9568         4561 :                 ReheatCoilLoad = max(0.0, ReheatCoilLoad - (NoCompOutput - SystemSensibleLoad));
    9569              :             }
    9570              :         } else {
    9571              :             //       No humidistat installed
    9572      1433040 :             ReheatCoilLoad = 0.0;
    9573              :         }
    9574              : 
    9575      1507624 :         TotalZoneSensibleLoad = QZnReq;
    9576      1507624 :         TotalZoneLatentLoad = QLatReq;
    9577      1507624 :         if (ReheatCoilLoad > 0.0) {
    9578        65311 :             CalcVarSpeedHeatPump(state,
    9579              :                                  FurnaceNum,
    9580              :                                  FirstHVACIteration,
    9581              :                                  compressorOp,
    9582              :                                  SpeedNum,
    9583              :                                  SpeedRatio,
    9584              :                                  PartLoadFrac,
    9585              :                                  QSensUnitOut,
    9586              :                                  QLatUnitOut,
    9587              :                                  TotalZoneSensibleLoad,
    9588              :                                  TotalZoneLatentLoad,
    9589              :                                  OnOffAirFlowRatio,
    9590              :                                  ReheatCoilLoad);
    9591              :         } else {
    9592      1442313 :             CalcVarSpeedHeatPump(state,
    9593              :                                  FurnaceNum,
    9594              :                                  FirstHVACIteration,
    9595              :                                  compressorOp,
    9596              :                                  SpeedNum,
    9597              :                                  SpeedRatio,
    9598              :                                  PartLoadFrac,
    9599              :                                  QSensUnitOut,
    9600              :                                  QLatUnitOut,
    9601              :                                  TotalZoneSensibleLoad,
    9602              :                                  TotalZoneLatentLoad,
    9603              :                                  OnOffAirFlowRatio,
    9604              :                                  SupHeaterLoad);
    9605              :         }
    9606              : 
    9607              :         // calculate delivered capacity
    9608      1507624 :         AirMassFlow = state.dataLoopNodes->Node(InletNode).MassFlowRate;
    9609              : 
    9610      1507624 :         thisFurnace.MdotFurnace = AirMassFlow;
    9611              : 
    9612      1507624 :         QTotUnitOut =
    9613      1507624 :             AirMassFlow * (state.dataLoopNodes->Node(OutletNode).Enthalpy - state.dataLoopNodes->Node(thisFurnace.NodeNumOfControlledZone).Enthalpy);
    9614              : 
    9615      1507624 :         state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail = AirMassFlow;
    9616      1507624 :         state.dataLoopNodes->Node(OutletNode).MassFlowRateMaxAvail = AirMassFlow;
    9617              : 
    9618      1507624 :         if (!FirstHVACIteration && AirMassFlow > 0.0 && AirLoopNum > 0) {
    9619      1408368 :             int TotBranchNum = state.dataAirSystemsData->PrimaryAirSystems(AirLoopNum).NumOutletBranches;
    9620      1408368 :             if (TotBranchNum == 1) {
    9621      1408368 :                 int ZoneSideNodeNum = state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).ZoneEquipSupplyNodeNum(1);
    9622              :                 // THE MASS FLOW PRECISION of the system solver is not enough for some small air flow rate iterations , BY DEBUGGING
    9623              :                 // it may cause mass flow rate oscillations between airloop and zoneequip
    9624              :                 // specify the air flow rate directly for one-to-one system, when the iteration deviation is closing the solver precision level
    9625              :                 // 0.02 is 2 * HVACFlowRateToler, in order to accommodate the system solver precision level
    9626      1408368 :                 if (std::abs(AirMassFlow - state.dataLoopNodes->Node(ZoneSideNodeNum).MassFlowRate) < 0.02) {
    9627       797935 :                     state.dataLoopNodes->Node(ZoneSideNodeNum).MassFlowRateMaxAvail = AirMassFlow;
    9628              :                 }
    9629      1408368 :                 state.dataLoopNodes->Node(ZoneSideNodeNum).MassFlowRate = AirMassFlow;
    9630              :             }
    9631              : 
    9632              :             // the below might be useful if more divergences occur
    9633              :             // Node(PrimaryAirSystem(AirLoopNumber)%Branch(1)%NodeNumIn)%MassFlowRateMaxAvail = AirMassFlow
    9634              :             // Node(PrimaryAirSystem(AirLoopNumber)%Branch(1)%NodeNumIn)%MassFlowRate = AirMassFlow
    9635              :         }
    9636              : 
    9637              :         // report variables
    9638      1507624 :         thisFurnace.DehumidInducedHeatingDemandRate = ReheatCoilLoad;
    9639      1507624 :         if (QZnReq > HVAC::SmallLoad) { // HEATING LOAD
    9640       123543 :             thisFurnace.CoolingCoilSensDemand = 0.0;
    9641       123543 :             thisFurnace.HeatingCoilSensDemand = QZnReq;
    9642              :         } else {
    9643      1384081 :             thisFurnace.CoolingCoilSensDemand = std::abs(QZnReq);
    9644      1384081 :             thisFurnace.HeatingCoilSensDemand = 0.0;
    9645              :         }
    9646              : 
    9647      1507624 :         thisFurnace.CompPartLoadRatio = state.dataFurnaces->SaveCompressorPLR;
    9648      1507624 :         if (thisFurnace.fanOp == HVAC::FanOp::Cycling) {
    9649        30262 :             if (SupHeaterLoad > 0.0) {
    9650        13986 :                 thisFurnace.FanPartLoadRatio = 1.0;
    9651              :             } else {
    9652        16276 :                 if (SpeedNum < 2) {
    9653         8962 :                     thisFurnace.FanPartLoadRatio = PartLoadFrac;
    9654              :                 } else {
    9655         7314 :                     thisFurnace.FanPartLoadRatio = 1.0;
    9656              :                 }
    9657              :             }
    9658              :         } else {
    9659      1477362 :             if (UnitOn) {
    9660      1477362 :                 thisFurnace.FanPartLoadRatio = 1.0;
    9661              :             } else {
    9662            0 :                 if (SpeedNum < 2) {
    9663            0 :                     thisFurnace.FanPartLoadRatio = PartLoadFrac;
    9664              :                 } else {
    9665            0 :                     thisFurnace.FanPartLoadRatio = 1.0;
    9666              :                 }
    9667              :             }
    9668              :         }
    9669      1507624 :     }
    9670              : 
    9671              :     //******************************************************************************
    9672              : 
    9673      1507624 :     void ControlVSHPOutput(EnergyPlusData &state,
    9674              :                            int const FurnaceNum,                  // Unit index of engine driven heat pump
    9675              :                            bool const FirstHVACIteration,         // flag for 1st HVAC iteration in the time step
    9676              :                            HVAC::CompressorOp const compressorOp, // compressor operation; 1=on, 0=off
    9677              :                            HVAC::FanOp const fanOp,               // operating mode: FanOp::Cycling | FanOp::Continuous
    9678              :                            Real64 &QZnReq,                        // cooling or heating output needed by zone [W]
    9679              :                            Real64 QLatReq,                        // latent cooling output needed by zone [W]
    9680              :                            int &SpeedNum,                         // Speed number
    9681              :                            Real64 &SpeedRatio,                    // unit speed ratio for DX coils
    9682              :                            Real64 &PartLoadFrac,                  // unit part load fraction
    9683              :                            Real64 &OnOffAirFlowRatio,             // ratio of compressor ON airflow to AVERAGE airflow over timestep
    9684              :                            Real64 &SupHeaterLoad                  // Supplemental heater load [W]
    9685              :     )
    9686              :     {
    9687              : 
    9688              :         // SUBROUTINE INFORMATION:
    9689              :         //       AUTHOR         Bo Shen, based on HVACMultiSpeedHeatPump:ControlMSHPOutput
    9690              :         //       DATE WRITTEN   March,  2012
    9691              : 
    9692              :         // PURPOSE OF THIS SUBROUTINE:
    9693              :         // Determine the part load fraction at low speed, and speed ratio at high speed for this time step.
    9694              : 
    9695              :         // METHODOLOGY EMPLOYED:
    9696              :         // Use RegulaFalsi technique to iterate on part-load ratio until convergence is achieved.
    9697              : 
    9698              :         // SUBROUTINE PARAMETER DEFINITIONS:
    9699      1507624 :         int constexpr MaxIte(500); // maximum number of iterations
    9700              : 
    9701              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    9702              :         Real64 FullOutput;   // unit full output when compressor is operating [W]
    9703              :         Real64 LowOutput;    // unit full output at low speed [W]
    9704              :         Real64 TempOutput;   // unit output when iteration limit exceeded [W]
    9705              :         Real64 NoCompOutput; // output when no active compressor [W]
    9706              :         int SolFla;          // Flag of RegulaFalsi solver
    9707              :         Real64 QCoilActual;  // coil load actually delivered returned to calling component
    9708              :         int i;               // Speed index
    9709      1507624 :         IntegratedHeatPump::IHPOperationMode IHPMode(IntegratedHeatPump::IHPOperationMode::Idle);
    9710              : 
    9711      1507624 :         SupHeaterLoad = 0.0;
    9712      1507624 :         PartLoadFrac = 0.0;
    9713      1507624 :         SpeedRatio = 0.0;
    9714      1507624 :         SpeedNum = 1;
    9715      1507624 :         Real64 LatOutput = 0.0;
    9716      1507624 :         Real64 noLatOutput = 0.0;
    9717      1507624 :         Real64 ErrorToler = 0.001; // Error tolerance for convergence from input deck
    9718              : 
    9719      1507624 :         auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    9720      1507624 :         if (thisFurnace.availSched->getCurrentVal() == 0.0) {
    9721        48514 :             return;
    9722              :         }
    9723              : 
    9724              :         // Get result when DX coil is off
    9725      1496044 :         SupHeaterLoad = 0.0;
    9726      1496044 :         CalcVarSpeedHeatPump(state,
    9727              :                              FurnaceNum,
    9728              :                              FirstHVACIteration,
    9729              :                              compressorOp,
    9730              :                              SpeedNum,
    9731              :                              SpeedRatio,
    9732              :                              PartLoadFrac,
    9733              :                              NoCompOutput,
    9734              :                              noLatOutput,
    9735              :                              0.0,
    9736              :                              0.0,
    9737              :                              OnOffAirFlowRatio,
    9738              :                              SupHeaterLoad);
    9739              : 
    9740      1496044 :         if (thisFurnace.bIsIHP) {
    9741        10094 :             IHPMode = IntegratedHeatPump::GetCurWorkMode(state, thisFurnace.CoolingCoilIndex);
    9742        10094 :             if ((IntegratedHeatPump::IHPOperationMode::DedicatedWaterHtg == IHPMode) ||
    9743              :                 (IntegratedHeatPump::IHPOperationMode::SCWHMatchWH == IHPMode)) { // cooling capacity is a resultant
    9744          280 :                 return;
    9745              :             }
    9746              :         }
    9747              : 
    9748              :         // If cooling and NoCompOutput < QZnReq, the coil needs to be off
    9749              :         // If heating and NoCompOutput > QZnReq, the coil needs to be off
    9750              :         // If no cooling or heating and no latent load, the coil needs to be off
    9751      1495764 :         if (QZnReq < -HVAC::SmallLoad) {
    9752      1285333 :             if (NoCompOutput < QZnReq && QLatReq >= -HVAC::SmallLoad) {
    9753          382 :                 return;
    9754              :             }
    9755       210431 :         } else if (QZnReq > HVAC::SmallLoad) {
    9756       123543 :             if (NoCompOutput > QZnReq && QLatReq >= -HVAC::SmallLoad) {
    9757         1369 :                 return;
    9758              :             }
    9759       122174 :             if (QLatReq <= -HVAC::SmallLoad) {
    9760        17008 :                 QZnReq = 0.0; // Zero heating load to allow dehumidification
    9761              :             }
    9762              :         } else {
    9763        86888 :             if (QLatReq >= -HVAC::SmallLoad) {
    9764        32412 :                 return;
    9765              :             }
    9766              :         }
    9767              : 
    9768              :         // Get full load result
    9769      1461601 :         PartLoadFrac = 1.0;
    9770      1461601 :         SpeedRatio = 1.0;
    9771      1461601 :         if (thisFurnace.HeatCoolMode == Furnaces::ModeOfOperation::HeatingMode) {
    9772       105096 :             SpeedNum = thisFurnace.NumOfSpeedHeating;
    9773      1356505 :         } else if (thisFurnace.HeatCoolMode == Furnaces::ModeOfOperation::CoolingMode) {
    9774      1301628 :             SpeedNum = thisFurnace.NumOfSpeedCooling;
    9775        54877 :         } else if (QLatReq < -HVAC::SmallLoad) {
    9776        54476 :             SpeedNum = thisFurnace.NumOfSpeedCooling;
    9777              :         } else {
    9778          401 :             SpeedNum = 1;
    9779          401 :             PartLoadFrac = 0.0;
    9780              :         }
    9781              : 
    9782      1461601 :         if (thisFurnace.bIsIHP) {
    9783         8503 :             SpeedNum = IntegratedHeatPump::GetMaxSpeedNumIHP(state, thisFurnace.CoolingCoilIndex);
    9784              :         }
    9785              : 
    9786      1461601 :         CalcVarSpeedHeatPump(state,
    9787              :                              FurnaceNum,
    9788              :                              FirstHVACIteration,
    9789              :                              compressorOp,
    9790              :                              SpeedNum,
    9791              :                              SpeedRatio,
    9792              :                              PartLoadFrac,
    9793              :                              FullOutput,
    9794              :                              LatOutput,
    9795              :                              QZnReq,
    9796              :                              QLatReq,
    9797              :                              OnOffAirFlowRatio,
    9798              :                              SupHeaterLoad);
    9799              : 
    9800      1461601 :         if (QLatReq < (-1.0 * HVAC::SmallLoad)) { // dehumidification mode
    9801        74584 :             if (QLatReq <= LatOutput || (QZnReq < -HVAC::SmallLoad && QZnReq <= FullOutput) || (QZnReq > HVAC::SmallLoad && QZnReq >= FullOutput)) {
    9802          138 :                 PartLoadFrac = 1.0;
    9803          138 :                 SpeedRatio = 1.0;
    9804          138 :                 thisFurnace.CompPartLoadRatio = PartLoadFrac;
    9805          138 :                 thisFurnace.CompSpeedRatio = SpeedRatio;
    9806          138 :                 thisFurnace.CompSpeedNum = SpeedNum;
    9807          138 :                 return;
    9808              :             }
    9809      1387017 :         } else if (QZnReq < -HVAC::SmallLoad) {
    9810      1281851 :             if (QZnReq <= FullOutput) {
    9811         2353 :                 PartLoadFrac = 1.0;
    9812         2353 :                 SpeedRatio = 1.0;
    9813         2353 :                 thisFurnace.CompPartLoadRatio = PartLoadFrac;
    9814         2353 :                 thisFurnace.CompSpeedRatio = SpeedRatio;
    9815         2353 :                 thisFurnace.CompSpeedNum = SpeedNum;
    9816         2353 :                 return;
    9817              :             }
    9818              :         } else {
    9819       105166 :             if (QZnReq >= FullOutput) {
    9820        46302 :                 PartLoadFrac = 1.0;
    9821        46302 :                 SpeedRatio = 1.0;
    9822              :                 // may need supplemental heating so don't return in heating mode
    9823              :             }
    9824              :         }
    9825              : 
    9826      1459110 :         if ((QZnReq < -HVAC::SmallLoad && NoCompOutput - QZnReq > HVAC::SmallLoad) ||
    9827       176512 :             (QZnReq > HVAC::SmallLoad && QZnReq - NoCompOutput > HVAC::SmallLoad)) {
    9828      1387744 :             if ((QZnReq > HVAC::SmallLoad && QZnReq < FullOutput) || (QZnReq < (-1.0 * HVAC::SmallLoad) && QZnReq > FullOutput)) {
    9829              :                 // Check whether the low speed coil can meet the load or not
    9830      1341462 :                 CalcVarSpeedHeatPump(state,
    9831              :                                      FurnaceNum,
    9832              :                                      FirstHVACIteration,
    9833              :                                      compressorOp,
    9834              :                                      1,
    9835              :                                      0.0,
    9836              :                                      1.0,
    9837              :                                      LowOutput,
    9838              :                                      LatOutput,
    9839              :                                      QZnReq,
    9840              :                                      QLatReq,
    9841              :                                      OnOffAirFlowRatio,
    9842              :                                      SupHeaterLoad);
    9843      1341462 :                 if ((QZnReq > HVAC::SmallLoad && QZnReq <= LowOutput) || (QZnReq < (-HVAC::SmallLoad) && QZnReq >= LowOutput)) {
    9844              :                     // Calculate the part load fraction
    9845       335879 :                     SpeedRatio = 0.0;
    9846       335879 :                     SpeedNum = 1;
    9847              :                     auto f = // (AUTO_OK_LAMBDA)
    9848      2031213 :                         [&state, FurnaceNum, FirstHVACIteration, QZnReq, OnOffAirFlowRatio, SupHeaterLoad, compressorOp](Real64 const PartLoadFrac) {
    9849      1695334 :                             return VSHPCyclingResidual(
    9850      1695334 :                                 state, PartLoadFrac, FurnaceNum, FirstHVACIteration, QZnReq, OnOffAirFlowRatio, SupHeaterLoad, compressorOp, 1.0);
    9851       335879 :                         };
    9852       335879 :                     General::SolveRoot(state, ErrorToler, MaxIte, SolFla, PartLoadFrac, f, 0.0, 1.0);
    9853       335879 :                     if (SolFla == -1) {
    9854            0 :                         if (!state.dataGlobal->WarmupFlag) {
    9855            0 :                             if (thisFurnace.ErrCountCyc == 0) {
    9856            0 :                                 ++thisFurnace.ErrCountCyc;
    9857            0 :                                 ShowWarningError(
    9858            0 :                                     state, format("Iteration limit exceeded calculating VS WSHP unit cycling ratio, for unit={}", thisFurnace.Name));
    9859            0 :                                 ShowContinueErrorTimeStamp(state, format("Cycling ratio returned={:.2R}", PartLoadFrac));
    9860              :                             } else {
    9861            0 :                                 ShowRecurringWarningErrorAtEnd(
    9862              :                                     state,
    9863            0 :                                     thisFurnace.Name + "\": Iteration limit warning exceeding calculating DX unit cycling ratio  continues...",
    9864            0 :                                     thisFurnace.ErrIndexCyc,
    9865              :                                     PartLoadFrac,
    9866              :                                     PartLoadFrac);
    9867              :                             }
    9868              :                         }
    9869       335879 :                     } else if (SolFla == -2) {
    9870            0 :                         ShowFatalError(
    9871            0 :                             state, format("VS WSHP unit cycling ratio calculation failed: cycling limits exceeded, for unit={}", thisFurnace.Name));
    9872              :                     }
    9873       335879 :                 } else {
    9874              :                     // Check to see which speed to meet the load
    9875      1005583 :                     PartLoadFrac = 1.0;
    9876      1005583 :                     SpeedRatio = 1.0;
    9877      1005583 :                     if (QZnReq < -HVAC::SmallLoad) { // Cooling
    9878      4429293 :                         for (i = 2; i <= thisFurnace.NumOfSpeedCooling; ++i) {
    9879      4429293 :                             CalcVarSpeedHeatPump(state,
    9880              :                                                  FurnaceNum,
    9881              :                                                  FirstHVACIteration,
    9882              :                                                  compressorOp,
    9883              :                                                  i,
    9884              :                                                  SpeedRatio,
    9885              :                                                  PartLoadFrac,
    9886              :                                                  TempOutput,
    9887              :                                                  LatOutput,
    9888              :                                                  QZnReq,
    9889              :                                                  QLatReq,
    9890              :                                                  OnOffAirFlowRatio,
    9891              :                                                  SupHeaterLoad);
    9892              : 
    9893      4429293 :                             if (QZnReq >= TempOutput) {
    9894       965495 :                                 SpeedNum = i;
    9895       965495 :                                 break;
    9896              :                             }
    9897              :                         }
    9898              :                     } else {
    9899       190721 :                         for (i = 2; i <= thisFurnace.NumOfSpeedHeating; ++i) {
    9900       190721 :                             CalcVarSpeedHeatPump(state,
    9901              :                                                  FurnaceNum,
    9902              :                                                  FirstHVACIteration,
    9903              :                                                  compressorOp,
    9904              :                                                  i,
    9905              :                                                  SpeedRatio,
    9906              :                                                  PartLoadFrac,
    9907              :                                                  TempOutput,
    9908              :                                                  LatOutput,
    9909              :                                                  QZnReq,
    9910              :                                                  QLatReq,
    9911              :                                                  OnOffAirFlowRatio,
    9912              :                                                  SupHeaterLoad);
    9913       190721 :                             if (QZnReq <= TempOutput) {
    9914        40088 :                                 SpeedNum = i;
    9915        40088 :                                 break;
    9916              :                             }
    9917              :                         }
    9918              :                     }
    9919      4433648 :                     auto f = [&state, FurnaceNum, FirstHVACIteration, QZnReq, OnOffAirFlowRatio, SupHeaterLoad, SpeedNum, compressorOp](
    9920              :                                  Real64 const SpeedRatio) {
    9921      3428065 :                         return VSHPSpeedResidual(
    9922      3428065 :                             state, SpeedRatio, FurnaceNum, FirstHVACIteration, QZnReq, OnOffAirFlowRatio, SupHeaterLoad, SpeedNum, compressorOp, 1.0);
    9923      1005583 :                     };
    9924      1005583 :                     General::SolveRoot(state, ErrorToler, MaxIte, SolFla, SpeedRatio, f, 1.0e-10, 1.0);
    9925      1005583 :                     if (SolFla == -1) {
    9926            0 :                         if (!state.dataGlobal->WarmupFlag) {
    9927            0 :                             if (thisFurnace.ErrCountVar == 0) {
    9928            0 :                                 ++thisFurnace.ErrCountVar;
    9929            0 :                                 ShowWarningError(
    9930            0 :                                     state, format("Iteration limit exceeded calculating VS WSHP unit speed ratio, for unit={}", thisFurnace.Name));
    9931            0 :                                 ShowContinueErrorTimeStamp(state, format("Speed ratio returned=[{:.2R}], Speed number ={}", SpeedRatio, SpeedNum));
    9932              :                             } else {
    9933            0 :                                 ShowRecurringWarningErrorAtEnd(
    9934              :                                     state,
    9935            0 :                                     thisFurnace.Name + "\": Iteration limit warning exceeding calculating DX unit speed ratio continues...",
    9936            0 :                                     thisFurnace.ErrIndexVar,
    9937              :                                     SpeedRatio,
    9938              :                                     SpeedRatio);
    9939              :                             }
    9940              :                         }
    9941      1005583 :                     } else if (SolFla == -2) {
    9942            0 :                         ShowFatalError(
    9943            0 :                             state, format("VS WSHP unit compressor speed calculation failed: speed limits exceeded, for unit={}", thisFurnace.Name));
    9944              :                     }
    9945              :                 }
    9946      1341462 :             } else {
    9947        46282 :                 LatOutput = noLatOutput; // reset full output if not needed for sensible load
    9948        46282 :                 SpeedNum = 1;            // reset speed from full output test
    9949              :             }
    9950      1387744 :         } else {
    9951        71366 :             LatOutput = noLatOutput; // reset full output if not needed for sensible load
    9952        71366 :             SpeedNum = 1;            // reset speed from full output test
    9953              :         }
    9954              :         // meet the latent load
    9955      1459110 :         if (QLatReq < -HVAC::SmallLoad && QLatReq < LatOutput) {
    9956        71282 :             PartLoadFrac = 1.0;
    9957        71282 :             SpeedRatio = 1.0;
    9958       113772 :             for (i = SpeedNum; i <= thisFurnace.NumOfSpeedCooling; ++i) {
    9959       113772 :                 CalcVarSpeedHeatPump(state,
    9960              :                                      FurnaceNum,
    9961              :                                      FirstHVACIteration,
    9962              :                                      compressorOp,
    9963              :                                      i,
    9964              :                                      SpeedRatio,
    9965              :                                      PartLoadFrac,
    9966              :                                      TempOutput,
    9967              :                                      LatOutput,
    9968              :                                      QZnReq,
    9969              :                                      QLatReq,
    9970              :                                      OnOffAirFlowRatio,
    9971              :                                      SupHeaterLoad);
    9972              : 
    9973       113772 :                 if (QLatReq > LatOutput) {
    9974        71282 :                     SpeedNum = i;
    9975        71282 :                     break;
    9976              :                 }
    9977              :             }
    9978        71282 :             if (QLatReq - LatOutput > HVAC::SmallLoad) {
    9979        71227 :                 if (SpeedNum < 2) {
    9980              :                     auto f = // (AUTO_OK_LAMBDA)
    9981       316336 :                         [&state, FurnaceNum, FirstHVACIteration, QLatReq, OnOffAirFlowRatio, SupHeaterLoad, compressorOp](Real64 const PartLoadFrac) {
    9982       269407 :                             return VSHPCyclingResidual(
    9983       269407 :                                 state, PartLoadFrac, FurnaceNum, FirstHVACIteration, QLatReq, OnOffAirFlowRatio, SupHeaterLoad, compressorOp, 0.0);
    9984        46929 :                         };
    9985        46929 :                     General::SolveRoot(state, ErrorToler, MaxIte, SolFla, PartLoadFrac, f, 0.0, 1.0);
    9986              :                 } else {
    9987       130582 :                     auto f = [&state, FurnaceNum, FirstHVACIteration, QLatReq, OnOffAirFlowRatio, SupHeaterLoad, SpeedNum, compressorOp](
    9988              :                                  Real64 const SpeedRatio) {
    9989       106284 :                         return VSHPSpeedResidual(state,
    9990              :                                                  SpeedRatio,
    9991              :                                                  FurnaceNum,
    9992              :                                                  FirstHVACIteration,
    9993              :                                                  QLatReq,
    9994              :                                                  OnOffAirFlowRatio,
    9995              :                                                  SupHeaterLoad,
    9996              :                                                  SpeedNum,
    9997              :                                                  compressorOp,
    9998       106284 :                                                  0.0);
    9999        24298 :                     };
   10000        24298 :                     General::SolveRoot(state, ErrorToler, MaxIte, SolFla, SpeedRatio, f, 1.0e-10, 1.0);
   10001              :                 }
   10002        71227 :                 if (SolFla == -1) {
   10003            0 :                     if (!state.dataGlobal->WarmupFlag) {
   10004            0 :                         if (thisFurnace.ErrCountVar2 == 0) {
   10005            0 :                             ++thisFurnace.ErrCountVar2;
   10006            0 :                             ShowWarningError(state,
   10007            0 :                                              format("Iteration limit exceeded calculating VS WSHP unit speed ratio, for unit={}", thisFurnace.Name));
   10008            0 :                             ShowContinueErrorTimeStamp(state, format("Speed ratio returned=[{:.2R}], Speed number ={}", SpeedRatio, SpeedNum));
   10009              :                         } else {
   10010            0 :                             ShowRecurringWarningErrorAtEnd(state,
   10011            0 :                                                            thisFurnace.Name +
   10012              :                                                                "\": Iteration limit warning exceeding calculating DX unit speed ratio continues...",
   10013            0 :                                                            thisFurnace.ErrIndexVar,
   10014              :                                                            SpeedRatio,
   10015              :                                                            SpeedRatio);
   10016              :                         }
   10017              :                     }
   10018        71227 :                 } else if (SolFla == -2) {
   10019            0 :                     ShowFatalError(state,
   10020            0 :                                    format("VS WSHP unit compressor speed calculation failed: speed limits exceeded, for unit={}", thisFurnace.Name));
   10021              :                 }
   10022              :             }
   10023              :         }
   10024              :         // end meet the latent load
   10025              : 
   10026              :         // if the heating coil cannot meet the load, trim with supplemental heater
   10027              :         // occurs with constant fan mode when compressor is on or off
   10028              :         // occurs with cycling fan mode when compressor PLR is equal to 1
   10029      1459110 :         if ((QZnReq > HVAC::SmallLoad && QZnReq > FullOutput) && (thisFurnace.SuppHeatCoilIndex != 0)) {
   10030        25968 :             PartLoadFrac = 1.0;
   10031        25968 :             SpeedRatio = 1.0;
   10032        25968 :             if (thisFurnace.NumOfSpeedHeating > 0) {
   10033        25968 :                 SpeedNum = thisFurnace.NumOfSpeedHeating; // maximum heating speed, avoid zero for cooling only mode
   10034              :             }
   10035              : 
   10036        25968 :             if (state.dataEnvrn->OutDryBulbTemp <= thisFurnace.MaxOATSuppHeat) {
   10037        25968 :                 SupHeaterLoad = QZnReq - FullOutput;
   10038              :             } else {
   10039            0 :                 SupHeaterLoad = 0.0;
   10040              :             }
   10041        25968 :             CalcVarSpeedHeatPump(state,
   10042              :                                  FurnaceNum,
   10043              :                                  FirstHVACIteration,
   10044              :                                  compressorOp,
   10045              :                                  SpeedNum,
   10046              :                                  SpeedRatio,
   10047              :                                  PartLoadFrac,
   10048              :                                  TempOutput,
   10049              :                                  LatOutput,
   10050              :                                  QZnReq,
   10051              :                                  QLatReq,
   10052              :                                  OnOffAirFlowRatio,
   10053              :                                  SupHeaterLoad);
   10054              :         }
   10055              : 
   10056              :         // check the outlet of the supplemental heater to be lower than the maximum supplemental heater supply air temperature
   10057      1459110 :         if (state.dataLoopNodes->Node(thisFurnace.FurnaceOutletNodeNum).Temp > thisFurnace.DesignMaxOutletTemp && SupHeaterLoad > 0.0) {
   10058              : 
   10059              :             //   If the supply air temperature is to high, turn off the supplemental heater to recalculate the outlet temperature
   10060           96 :             CalcNonDXHeatingCoils(state, FurnaceNum, true, FirstHVACIteration, 0.0, fanOp, QCoilActual);
   10061              :             //   If the outlet temperature is below the maximum supplemental heater supply air temperature, reduce the load passed to
   10062              :             //   the supplemental heater, otherwise leave the supplemental heater off. If the supplemental heater is to be turned on,
   10063              :             //   use the outlet conditions when the supplemental heater was off (CALL above) as the inlet conditions for the calculation
   10064              :             //   of supplemental heater load to just meet the maximum supply air temperature from the supplemental heater.
   10065           96 :             if (state.dataLoopNodes->Node(thisFurnace.FurnaceOutletNodeNum).Temp < thisFurnace.DesignMaxOutletTemp) {
   10066           96 :                 Real64 CpAir = Psychrometrics::PsyCpAirFnW(state.dataLoopNodes->Node(thisFurnace.FurnaceOutletNodeNum).HumRat);
   10067           96 :                 SupHeaterLoad = state.dataLoopNodes->Node(thisFurnace.FurnaceInletNodeNum).MassFlowRate * CpAir *
   10068           96 :                                 (thisFurnace.DesignMaxOutletTemp - state.dataLoopNodes->Node(thisFurnace.FurnaceOutletNodeNum).Temp);
   10069              : 
   10070              :             } else {
   10071            0 :                 SupHeaterLoad = 0.0;
   10072              :             }
   10073              :         }
   10074              : 
   10075              :         // prepare module level output
   10076      1459110 :         thisFurnace.CompPartLoadRatio = PartLoadFrac;
   10077      1459110 :         thisFurnace.CompSpeedRatio = SpeedRatio;
   10078      1459110 :         thisFurnace.CompSpeedNum = SpeedNum;
   10079      1459110 :         thisFurnace.CoolingCoilLatentDemand = std::abs(QLatReq);
   10080              : 
   10081      1459110 :         if (thisFurnace.fanOp == HVAC::FanOp::Continuous) {
   10082      1433624 :             thisFurnace.FanPartLoadRatio = 1.0;
   10083              :         } else {
   10084        25486 :             thisFurnace.FanPartLoadRatio = PartLoadFrac;
   10085              :         }
   10086              :     }
   10087              : 
   10088              :     //******************************************************************************
   10089              : 
   10090     17687782 :     void CalcVarSpeedHeatPump(EnergyPlusData &state,
   10091              :                               int const FurnaceNum,                  // Variable speed heat pump number
   10092              :                               bool const FirstHVACIteration,         // Flag for 1st HVAC iteration
   10093              :                               HVAC::CompressorOp const compressorOp, // Compressor on/off; 1=on, 0=off
   10094              :                               int const SpeedNum,                    // Speed number
   10095              :                               Real64 const SpeedRatio,               // Compressor speed ratio
   10096              :                               Real64 const PartLoadFrac,             // Compressor part load fraction
   10097              :                               Real64 &SensibleLoadMet,               // Sensible cooling load met (furnace outlet with respect to control zone temp)
   10098              :                               Real64 &LatentLoadMet,     // Latent cooling load met (furnace outlet with respect to control zone humidity ratio)
   10099              :                               Real64 const QZnReq,       // Zone load (W)
   10100              :                               Real64 const QLatReq,      // Zone latent load []
   10101              :                               Real64 &OnOffAirFlowRatio, // Ratio of compressor ON airflow to AVERAGE airflow over timestep
   10102              :                               Real64 const SupHeaterLoad // supplemental heater load (W)
   10103              :     )
   10104              :     {
   10105              :         // SUBROUTINE INFORMATION:
   10106              :         //       AUTHOR:          Bo Shen, based on HVACMultiSpeedHeatPump:CalcMSHeatPump
   10107              :         //       DATE WRITTEN:    March 2012
   10108              : 
   10109              :         // PURPOSE OF THIS SUBROUTINE:
   10110              :         //  This routine will calculates MSHP performance based on given system load
   10111              : 
   10112     17687782 :         Real64 SavePartloadRatio = 0.0; // part-load ratio
   10113     17687782 :         Real64 SaveSpeedRatio = 0.0;    // speed ratio
   10114     17687782 :         Real64 QCoilActual = 0.0;       // coil load actually delivered returned to calling component
   10115     17687782 :         Real64 HeatCoilLoad = 0.0;      // required heating coil load
   10116              : 
   10117     17687782 :         state.dataFurnaces->SaveCompressorPLR = 0.0;
   10118              : 
   10119              :         // Set inlet air mass flow rate based on PLR and compressor on/off air flow rates
   10120     17687782 :         SetVSHPAirFlow(state, FurnaceNum, PartLoadFrac, OnOffAirFlowRatio, SpeedNum, SpeedRatio);
   10121              : 
   10122     17687782 :         auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
   10123              : 
   10124     17687782 :         if ((SupHeaterLoad > 1.0e-10) && (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatCool) && (thisFurnace.SuppHeatCoilIndex == 0)) {
   10125              :             // ONLY HEATING COIL, NO SUPPLEMENTAL COIL, USED FOR REHEAT DURING DUHMI
   10126            0 :             HeatCoilLoad = thisFurnace.DesignHeatingCapacity * PartLoadFrac; // REHEAT IN FAN ON TIME
   10127              : 
   10128            0 :             if (HeatCoilLoad > SupHeaterLoad) {
   10129            0 :                 HeatCoilLoad = SupHeaterLoad; // HEATING COIL RUN TIME < FAN ON TIME
   10130              :             }
   10131              : 
   10132     17687782 :         } else if ((QZnReq > HVAC::SmallLoad) && (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatCool)) {
   10133        63320 :             HeatCoilLoad = thisFurnace.DesignHeatingCapacity * PartLoadFrac;
   10134              :         } else {
   10135     17624462 :             HeatCoilLoad = 0.0;
   10136              :         }
   10137              : 
   10138     17687782 :         Real64 AirMassFlow = state.dataLoopNodes->Node(thisFurnace.FurnaceInletNodeNum).MassFlowRate;
   10139              :         // if blow through, simulate fan then coils
   10140     17687782 :         if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
   10141     17687782 :             state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
   10142              : 
   10143     17687782 :             if ((!thisFurnace.CoolingCoilUpstream) && (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatCool)) {
   10144              :                 // simulate thisFurnace heating coil
   10145            0 :                 bool SuppHeatingCoilFlag = false; // if true simulates supplemental heating coil
   10146            0 :                 CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, thisFurnace.fanOp, QCoilActual);
   10147              :             }
   10148              : 
   10149     31623779 :             if ((QZnReq < -HVAC::SmallLoad || (QLatReq < -HVAC::SmallLoad)) &&
   10150     13935997 :                 (state.dataEnvrn->OutDryBulbTemp >= thisFurnace.MinOATCompressorCooling)) { // COOLING MODE or dehumidification mode
   10151              : 
   10152     13935997 :                 if (thisFurnace.bIsIHP) {
   10153        73294 :                     IntegratedHeatPump::SimIHP(state,
   10154              :                                                BlankString,
   10155        36647 :                                                thisFurnace.CoolingCoilIndex,
   10156              :                                                thisFurnace.fanOp,
   10157              :                                                compressorOp,
   10158              :                                                PartLoadFrac,
   10159              :                                                SpeedNum,
   10160              :                                                SpeedRatio,
   10161              :                                                QZnReq,
   10162              :                                                QLatReq,
   10163              :                                                false,
   10164              :                                                false,
   10165              :                                                OnOffAirFlowRatio);
   10166              :                 } else {
   10167     13899350 :                     VariableSpeedCoils::SimVariableSpeedCoils(state,
   10168              :                                                               BlankString,
   10169     13899350 :                                                               thisFurnace.CoolingCoilIndex,
   10170              :                                                               thisFurnace.fanOp,
   10171              :                                                               compressorOp,
   10172              :                                                               PartLoadFrac,
   10173              :                                                               SpeedNum,
   10174              :                                                               SpeedRatio,
   10175              :                                                               QZnReq,
   10176              :                                                               QLatReq,
   10177              :                                                               OnOffAirFlowRatio);
   10178              :                 }
   10179              : 
   10180     13935997 :                 SavePartloadRatio = PartLoadFrac;
   10181     13935997 :                 SaveSpeedRatio = SpeedRatio;
   10182              : 
   10183     13935997 :                 state.dataFurnaces->SaveCompressorPLR = state.dataVariableSpeedCoils->VarSpeedCoil(thisFurnace.CoolingCoilIndex).PartLoadRatio;
   10184              :             } else {
   10185      3751785 :                 if (thisFurnace.bIsIHP) {
   10186        51358 :                     IntegratedHeatPump::SimIHP(state,
   10187              :                                                BlankString,
   10188        25679 :                                                thisFurnace.CoolingCoilIndex,
   10189              :                                                thisFurnace.fanOp,
   10190              :                                                compressorOp,
   10191              :                                                PartLoadFrac,
   10192              :                                                SpeedNum,
   10193              :                                                SpeedRatio,
   10194              :                                                QZnReq,
   10195              :                                                QLatReq,
   10196              :                                                false,
   10197              :                                                false,
   10198              :                                                OnOffAirFlowRatio);
   10199              :                 } else {
   10200      3726106 :                     VariableSpeedCoils::SimVariableSpeedCoils(
   10201      3726106 :                         state, BlankString, thisFurnace.CoolingCoilIndex, thisFurnace.fanOp, compressorOp, 0.0, 1, 0.0, 0.0, 0.0, OnOffAirFlowRatio);
   10202              :                 }
   10203              :             }
   10204              : 
   10205     17687782 :             if (thisFurnace.type != HVAC::UnitarySysType::Unitary_HeatCool) {
   10206      2335958 :                 if ((QZnReq > HVAC::SmallLoad) && state.dataFurnaces->HeatingLoad) {
   10207       598955 :                     if (thisFurnace.bIsIHP) {
   10208        27964 :                         IntegratedHeatPump::SimIHP(state,
   10209              :                                                    BlankString,
   10210        13982 :                                                    thisFurnace.HeatingCoilIndex,
   10211              :                                                    thisFurnace.fanOp,
   10212              :                                                    compressorOp,
   10213              :                                                    PartLoadFrac,
   10214              :                                                    SpeedNum,
   10215              :                                                    SpeedRatio,
   10216              :                                                    QZnReq,
   10217              :                                                    QLatReq,
   10218              :                                                    false,
   10219              :                                                    false,
   10220              :                                                    OnOffAirFlowRatio);
   10221              :                     } else {
   10222       584973 :                         VariableSpeedCoils::SimVariableSpeedCoils(state,
   10223              :                                                                   BlankString,
   10224       584973 :                                                                   thisFurnace.HeatingCoilIndex,
   10225              :                                                                   thisFurnace.fanOp,
   10226              :                                                                   compressorOp,
   10227              :                                                                   PartLoadFrac,
   10228              :                                                                   SpeedNum,
   10229              :                                                                   SpeedRatio,
   10230              :                                                                   QZnReq,
   10231              :                                                                   QLatReq,
   10232              :                                                                   OnOffAirFlowRatio);
   10233              :                     }
   10234              : 
   10235       598955 :                     SavePartloadRatio = PartLoadFrac;
   10236       598955 :                     SaveSpeedRatio = SpeedRatio;
   10237              : 
   10238       598955 :                     state.dataFurnaces->SaveCompressorPLR = state.dataVariableSpeedCoils->VarSpeedCoil(thisFurnace.HeatingCoilIndex).PartLoadRatio;
   10239              :                 } else {
   10240      1737003 :                     if (thisFurnace.bIsIHP) {
   10241        96688 :                         IntegratedHeatPump::SimIHP(state,
   10242              :                                                    BlankString,
   10243        48344 :                                                    thisFurnace.CoolingCoilIndex,
   10244              :                                                    thisFurnace.fanOp,
   10245              :                                                    compressorOp,
   10246              :                                                    PartLoadFrac,
   10247              :                                                    SpeedNum,
   10248              :                                                    SpeedRatio,
   10249              :                                                    QZnReq,
   10250              :                                                    QLatReq,
   10251              :                                                    false,
   10252              :                                                    false,
   10253              :                                                    OnOffAirFlowRatio);
   10254              :                     } else {
   10255      1688659 :                         VariableSpeedCoils::SimVariableSpeedCoils(state,
   10256              :                                                                   BlankString,
   10257      1688659 :                                                                   thisFurnace.HeatingCoilIndex,
   10258              :                                                                   thisFurnace.fanOp,
   10259              :                                                                   compressorOp,
   10260              :                                                                   0.0,
   10261              :                                                                   1,
   10262              :                                                                   0.0,
   10263              :                                                                   0.0,
   10264              :                                                                   0.0,
   10265              :                                                                   OnOffAirFlowRatio);
   10266              :                     }
   10267              :                 }
   10268     15351824 :             } else if (thisFurnace.CoolingCoilUpstream && (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatCool)) {
   10269              :                 // simulate thisFurnace heating coil
   10270     15351824 :                 bool SuppHeatingCoilFlag = false; // if true simulates supplemental heating coil
   10271     15351824 :                 CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, thisFurnace.fanOp, QCoilActual);
   10272              :             }
   10273              : 
   10274              :             // Call twice to ensure the fan outlet conditions are updated
   10275     17687782 :             state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
   10276              : 
   10277     17687782 :             if ((!thisFurnace.CoolingCoilUpstream) && (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatCool)) {
   10278              :                 // simulate thisFurnace heating coil
   10279            0 :                 bool SuppHeatingCoilFlag = false; // if true simulates supplemental heating coil
   10280            0 :                 CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, thisFurnace.fanOp, QCoilActual);
   10281              :             }
   10282              : 
   10283     31623779 :             if ((QZnReq < -HVAC::SmallLoad || (QLatReq < -HVAC::SmallLoad)) &&
   10284     13935997 :                 (state.dataEnvrn->OutDryBulbTemp >= thisFurnace.MinOATCompressorCooling)) {
   10285              : 
   10286     13935997 :                 if (thisFurnace.bIsIHP) {
   10287        73294 :                     IntegratedHeatPump::SimIHP(state,
   10288              :                                                BlankString,
   10289        36647 :                                                thisFurnace.CoolingCoilIndex,
   10290              :                                                thisFurnace.fanOp,
   10291              :                                                compressorOp,
   10292              :                                                PartLoadFrac,
   10293              :                                                SpeedNum,
   10294              :                                                SpeedRatio,
   10295              :                                                QZnReq,
   10296              :                                                QLatReq,
   10297              :                                                false,
   10298              :                                                false,
   10299              :                                                OnOffAirFlowRatio);
   10300              :                 } else {
   10301     13899350 :                     VariableSpeedCoils::SimVariableSpeedCoils(state,
   10302              :                                                               BlankString,
   10303     13899350 :                                                               thisFurnace.CoolingCoilIndex,
   10304              :                                                               thisFurnace.fanOp,
   10305              :                                                               compressorOp,
   10306              :                                                               PartLoadFrac,
   10307              :                                                               SpeedNum,
   10308              :                                                               SpeedRatio,
   10309              :                                                               QZnReq,
   10310              :                                                               QLatReq,
   10311              :                                                               OnOffAirFlowRatio);
   10312              :                 }
   10313              : 
   10314     13935997 :                 SavePartloadRatio = PartLoadFrac;
   10315     13935997 :                 SaveSpeedRatio = SpeedRatio;
   10316     13935997 :                 state.dataFurnaces->SaveCompressorPLR = state.dataVariableSpeedCoils->VarSpeedCoil(thisFurnace.CoolingCoilIndex).PartLoadRatio;
   10317              :             } else {
   10318              : 
   10319      3751785 :                 if (thisFurnace.bIsIHP) {
   10320        51358 :                     IntegratedHeatPump::SimIHP(state,
   10321              :                                                BlankString,
   10322        25679 :                                                thisFurnace.CoolingCoilIndex,
   10323              :                                                thisFurnace.fanOp,
   10324              :                                                compressorOp,
   10325              :                                                PartLoadFrac,
   10326              :                                                SpeedNum,
   10327              :                                                SpeedRatio,
   10328              :                                                QZnReq,
   10329              :                                                QLatReq,
   10330              :                                                false,
   10331              :                                                false,
   10332              :                                                OnOffAirFlowRatio);
   10333              :                 } else {
   10334      3726106 :                     VariableSpeedCoils::SimVariableSpeedCoils(
   10335      3726106 :                         state, BlankString, thisFurnace.CoolingCoilIndex, thisFurnace.fanOp, compressorOp, 0.0, 1, 0.0, 0.0, 0.0, OnOffAirFlowRatio);
   10336              :                 }
   10337              :             }
   10338              : 
   10339     17687782 :             if (thisFurnace.type != HVAC::UnitarySysType::Unitary_HeatCool) {
   10340      2335958 :                 if ((QZnReq > HVAC::SmallLoad) && state.dataFurnaces->HeatingLoad) {
   10341       598955 :                     if (thisFurnace.bIsIHP) {
   10342        27964 :                         IntegratedHeatPump::SimIHP(state,
   10343              :                                                    BlankString,
   10344        13982 :                                                    thisFurnace.HeatingCoilIndex,
   10345              :                                                    thisFurnace.fanOp,
   10346              :                                                    compressorOp,
   10347              :                                                    PartLoadFrac,
   10348              :                                                    SpeedNum,
   10349              :                                                    SpeedRatio,
   10350              :                                                    QZnReq,
   10351              :                                                    QLatReq,
   10352              :                                                    false,
   10353              :                                                    false,
   10354              :                                                    OnOffAirFlowRatio);
   10355              :                     } else {
   10356       584973 :                         VariableSpeedCoils::SimVariableSpeedCoils(state,
   10357              :                                                                   BlankString,
   10358       584973 :                                                                   thisFurnace.HeatingCoilIndex,
   10359              :                                                                   thisFurnace.fanOp,
   10360              :                                                                   compressorOp,
   10361              :                                                                   PartLoadFrac,
   10362              :                                                                   SpeedNum,
   10363              :                                                                   SpeedRatio,
   10364              :                                                                   QZnReq,
   10365              :                                                                   QLatReq,
   10366              :                                                                   OnOffAirFlowRatio);
   10367              :                     }
   10368              : 
   10369       598955 :                     SavePartloadRatio = PartLoadFrac;
   10370       598955 :                     SaveSpeedRatio = SpeedRatio;
   10371       598955 :                     state.dataFurnaces->SaveCompressorPLR = state.dataVariableSpeedCoils->VarSpeedCoil(thisFurnace.HeatingCoilIndex).PartLoadRatio;
   10372              :                 } else {
   10373      1737003 :                     if (thisFurnace.bIsIHP) {
   10374        96688 :                         IntegratedHeatPump::SimIHP(state,
   10375              :                                                    BlankString,
   10376        48344 :                                                    thisFurnace.CoolingCoilIndex,
   10377              :                                                    thisFurnace.fanOp,
   10378              :                                                    compressorOp,
   10379              :                                                    PartLoadFrac,
   10380              :                                                    SpeedNum,
   10381              :                                                    SpeedRatio,
   10382              :                                                    QZnReq,
   10383              :                                                    QLatReq,
   10384              :                                                    false,
   10385              :                                                    false,
   10386              :                                                    OnOffAirFlowRatio);
   10387              :                     } else {
   10388      1688659 :                         VariableSpeedCoils::SimVariableSpeedCoils(state,
   10389              :                                                                   BlankString,
   10390      1688659 :                                                                   thisFurnace.HeatingCoilIndex,
   10391              :                                                                   thisFurnace.fanOp,
   10392              :                                                                   compressorOp,
   10393              :                                                                   0.0,
   10394              :                                                                   1,
   10395              :                                                                   0.0,
   10396              :                                                                   0.0,
   10397              :                                                                   0.0,
   10398              :                                                                   OnOffAirFlowRatio);
   10399              :                     }
   10400              :                 }
   10401     15351824 :             } else if (thisFurnace.CoolingCoilUpstream && (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatCool)) {
   10402              :                 // simulate thisFurnace heating coil
   10403     15351824 :                 bool SuppHeatingCoilFlag = false; // if true simulates supplemental heating coil
   10404     15351824 :                 CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, thisFurnace.fanOp, QCoilActual);
   10405              :             }
   10406              : 
   10407              :             //  Simulate supplemental heating coil for blow through fan
   10408     17687782 :             if (thisFurnace.SuppHeatCoilIndex > 0) {
   10409      2335958 :                 bool SuppHeatingCoilFlag = true; // if true simulates supplemental heating coil
   10410      2335958 :                 CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, SupHeaterLoad, thisFurnace.fanOp, QCoilActual);
   10411              :             }
   10412              :         } else { // otherwise simulate DX coils then fan then supplemental heater
   10413              : 
   10414            0 :             if ((!thisFurnace.CoolingCoilUpstream) && (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatCool)) {
   10415              :                 // simulate thisFurnace heating coil
   10416            0 :                 bool SuppHeatingCoilFlag = false; // if true simulates supplemental heating coil
   10417            0 :                 CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, thisFurnace.fanOp, QCoilActual);
   10418              :             }
   10419              : 
   10420            0 :             if ((QZnReq < -HVAC::SmallLoad || (QLatReq < -HVAC::SmallLoad)) &&
   10421            0 :                 (state.dataEnvrn->OutDryBulbTemp >= thisFurnace.MinOATCompressorCooling)) {
   10422              : 
   10423            0 :                 if (thisFurnace.bIsIHP) {
   10424            0 :                     IntegratedHeatPump::SimIHP(state,
   10425              :                                                BlankString,
   10426            0 :                                                thisFurnace.CoolingCoilIndex,
   10427              :                                                thisFurnace.fanOp,
   10428              :                                                compressorOp,
   10429              :                                                PartLoadFrac,
   10430              :                                                SpeedNum,
   10431              :                                                SpeedRatio,
   10432              :                                                QZnReq,
   10433              :                                                QLatReq,
   10434              :                                                false,
   10435              :                                                false,
   10436              :                                                OnOffAirFlowRatio);
   10437              :                 } else {
   10438            0 :                     VariableSpeedCoils::SimVariableSpeedCoils(state,
   10439              :                                                               BlankString,
   10440            0 :                                                               thisFurnace.CoolingCoilIndex,
   10441              :                                                               thisFurnace.fanOp,
   10442              :                                                               compressorOp,
   10443              :                                                               PartLoadFrac,
   10444              :                                                               SpeedNum,
   10445              :                                                               SpeedRatio,
   10446              :                                                               QZnReq,
   10447              :                                                               QLatReq,
   10448              :                                                               OnOffAirFlowRatio);
   10449              :                 }
   10450              : 
   10451            0 :                 SavePartloadRatio = PartLoadFrac;
   10452            0 :                 SaveSpeedRatio = SpeedRatio;
   10453              : 
   10454            0 :                 state.dataFurnaces->SaveCompressorPLR = state.dataVariableSpeedCoils->VarSpeedCoil(thisFurnace.CoolingCoilIndex).PartLoadRatio;
   10455              :             } else {
   10456            0 :                 if (thisFurnace.bIsIHP) {
   10457            0 :                     IntegratedHeatPump::SimIHP(state,
   10458              :                                                BlankString,
   10459            0 :                                                thisFurnace.CoolingCoilIndex,
   10460              :                                                thisFurnace.fanOp,
   10461              :                                                compressorOp,
   10462              :                                                PartLoadFrac,
   10463              :                                                SpeedNum,
   10464              :                                                SpeedRatio,
   10465              :                                                QZnReq,
   10466              :                                                QLatReq,
   10467              :                                                false,
   10468              :                                                false,
   10469              :                                                OnOffAirFlowRatio);
   10470              :                 } else {
   10471            0 :                     VariableSpeedCoils::SimVariableSpeedCoils(
   10472            0 :                         state, BlankString, thisFurnace.CoolingCoilIndex, thisFurnace.fanOp, compressorOp, 0.0, 1, 0.0, 0.0, 0.0, OnOffAirFlowRatio);
   10473              :                 }
   10474              :             }
   10475              : 
   10476            0 :             if (thisFurnace.type != HVAC::UnitarySysType::Unitary_HeatCool) {
   10477            0 :                 if (QZnReq > HVAC::SmallLoad && (state.dataEnvrn->OutDryBulbTemp >= thisFurnace.MinOATCompressorCooling)) {
   10478              : 
   10479            0 :                     if (thisFurnace.bIsIHP) {
   10480            0 :                         IntegratedHeatPump::SimIHP(state,
   10481              :                                                    BlankString,
   10482            0 :                                                    thisFurnace.HeatingCoilIndex,
   10483              :                                                    thisFurnace.fanOp,
   10484              :                                                    compressorOp,
   10485              :                                                    PartLoadFrac,
   10486              :                                                    SpeedNum,
   10487              :                                                    SpeedRatio,
   10488              :                                                    QZnReq,
   10489              :                                                    QLatReq,
   10490              :                                                    false,
   10491              :                                                    false,
   10492              :                                                    OnOffAirFlowRatio);
   10493              :                     } else {
   10494            0 :                         VariableSpeedCoils::SimVariableSpeedCoils(state,
   10495              :                                                                   BlankString,
   10496            0 :                                                                   thisFurnace.HeatingCoilIndex,
   10497              :                                                                   thisFurnace.fanOp,
   10498              :                                                                   compressorOp,
   10499              :                                                                   PartLoadFrac,
   10500              :                                                                   SpeedNum,
   10501              :                                                                   SpeedRatio,
   10502              :                                                                   QZnReq,
   10503              :                                                                   QLatReq,
   10504              :                                                                   OnOffAirFlowRatio);
   10505              :                     }
   10506              : 
   10507            0 :                     SavePartloadRatio = PartLoadFrac;
   10508            0 :                     SaveSpeedRatio = SpeedRatio;
   10509            0 :                     state.dataFurnaces->SaveCompressorPLR = state.dataVariableSpeedCoils->VarSpeedCoil(thisFurnace.HeatingCoilIndex).PartLoadRatio;
   10510              :                 } else {
   10511            0 :                     if (thisFurnace.bIsIHP) {
   10512            0 :                         IntegratedHeatPump::SimIHP(state,
   10513              :                                                    BlankString,
   10514            0 :                                                    thisFurnace.CoolingCoilIndex,
   10515              :                                                    thisFurnace.fanOp,
   10516              :                                                    compressorOp,
   10517              :                                                    PartLoadFrac,
   10518              :                                                    SpeedNum,
   10519              :                                                    SpeedRatio,
   10520              :                                                    QZnReq,
   10521              :                                                    QLatReq,
   10522              :                                                    false,
   10523              :                                                    false,
   10524              :                                                    OnOffAirFlowRatio);
   10525              :                     } else {
   10526            0 :                         VariableSpeedCoils::SimVariableSpeedCoils(state,
   10527              :                                                                   BlankString,
   10528            0 :                                                                   thisFurnace.HeatingCoilIndex,
   10529              :                                                                   thisFurnace.fanOp,
   10530              :                                                                   compressorOp,
   10531              :                                                                   0.0,
   10532              :                                                                   1,
   10533              :                                                                   0.0,
   10534              :                                                                   0.0,
   10535              :                                                                   0.0,
   10536              :                                                                   OnOffAirFlowRatio);
   10537              :                     }
   10538              :                 }
   10539            0 :             } else if (thisFurnace.CoolingCoilUpstream && (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatCool)) {
   10540              :                 // simulate thisFurnace heating coil
   10541            0 :                 bool SuppHeatingCoilFlag = false; // if true simulates supplemental heating coil
   10542            0 :                 CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, thisFurnace.fanOp, QCoilActual);
   10543              :             }
   10544              : 
   10545            0 :             state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
   10546              :             //  Simulate supplemental heating coil for draw through fan
   10547            0 :             if (thisFurnace.SuppHeatCoilIndex > 0) {
   10548            0 :                 bool SuppHeatingCoilFlag = true; // if true simulates supplemental heating coil
   10549            0 :                 CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, SupHeaterLoad, thisFurnace.fanOp, QCoilActual);
   10550              :             }
   10551              :         }
   10552              : 
   10553              :         // If the fan runs continually do not allow coils to set OnOffFanPartLoadRatio.
   10554     17687782 :         if (thisFurnace.fanOp == HVAC::FanOp::Continuous) {
   10555     17499846 :             state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
   10556              :         }
   10557              : 
   10558     17687782 :         auto &outNode = state.dataLoopNodes->Node(thisFurnace.FurnaceOutletNodeNum);
   10559     17687782 :         auto &zoneNode = state.dataLoopNodes->Node(thisFurnace.NodeNumOfControlledZone);
   10560     17687782 :         Real64 zoneEnthalpy = Psychrometrics::PsyHFnTdbW(zoneNode.Temp, zoneNode.HumRat);
   10561     17687782 :         Real64 outletEnthalpy = Psychrometrics::PsyHFnTdbW(outNode.Temp, outNode.HumRat);
   10562     17687782 :         Real64 totalLoadMet = AirMassFlow * (outletEnthalpy - zoneEnthalpy);
   10563     17687782 :         SensibleLoadMet =
   10564     17687782 :             AirMassFlow * Psychrometrics::PsyDeltaHSenFnTdb2W2Tdb1W1(outNode.Temp, outNode.HumRat, zoneNode.Temp, zoneNode.HumRat); // sensible {W};
   10565     17687782 :         LatentLoadMet = totalLoadMet - SensibleLoadMet;
   10566     17687782 :         thisFurnace.LatentLoadMet = LatentLoadMet;
   10567     17687782 :     }
   10568              : 
   10569              :     //******************************************************************************
   10570              : 
   10571      1964741 :     Real64 VSHPCyclingResidual(EnergyPlusData &state,
   10572              :                                Real64 const PartLoadFrac, // compressor cycling ratio (1.0 is continuous, 0.0 is off)
   10573              :                                int FurnaceNum,
   10574              :                                // int ZoneNum,
   10575              :                                bool FirstHVACIteration,
   10576              :                                // int fanOp,
   10577              :                                Real64 LoadToBeMet,
   10578              :                                Real64 OnOffAirFlowRatio,
   10579              :                                Real64 SupHeaterLoad,
   10580              :                                HVAC::CompressorOp compressorOp,
   10581              :                                Real64 par9_SensLatFlag)
   10582              :     {
   10583              :         // FUNCTION INFORMATION:
   10584              :         //       AUTHOR         Bo Shen, based on HVACMultiSpeedHeatPump:MSHPCyclingResidual
   10585              :         //       DATE WRITTEN   March, 2012
   10586              : 
   10587              :         // PURPOSE OF THIS FUNCTION:
   10588              :         //  Calculates residual function ((ActualOutput - QZnReq)/QZnReq)
   10589              :         //  MSHP output depends on the part load ratio which is being varied to zero the residual.
   10590              : 
   10591              :         // METHODOLOGY EMPLOYED:
   10592              :         //  Calls CalcMSHeatPump to get ActualOutput at the given part load ratio
   10593              :         //  and calculates the residual as defined above
   10594              : 
   10595              :         // int FurnaceNum = int(Par[0]);
   10596              :         // int ZoneNum = int(Par[1]);
   10597              :         // bool FirstHVACIteration = (Par[2] == 1.0);
   10598              :         // int fanOp = int(Par[3]);
   10599              :         // Real64 LoadToBeMet = Par[4];
   10600              :         // Real64 OnOffAirFlowRatio = Par[5];
   10601              :         // Real64 SupHeaterLoad = Par[6];
   10602              :         // CompressorOperation CompressorOp = static_cast<CompressorOperation>(Par[8]);
   10603              :         // Real64 par9_SensLatFlag = Par[9];
   10604              : 
   10605              :         // FUNCTION LOCAL VARIABLE DECLARATIONS:
   10606              :         Real64 ZoneSensLoadMet; // delivered sensible capacity of MSHP
   10607              :         Real64 ZoneLatLoadMet;  // delivered latent capacity of MSHP
   10608              : 
   10609      1964741 :         Real64 QZnReq = 0.0;
   10610      1964741 :         Real64 QZnLat = 0.0;
   10611      1964741 :         if (par9_SensLatFlag == 1.0) {
   10612      1695334 :             QZnReq = LoadToBeMet;
   10613              :         } else {
   10614       269407 :             QZnLat = LoadToBeMet;
   10615              :         }
   10616              : 
   10617      1964741 :         CalcVarSpeedHeatPump(state,
   10618              :                              FurnaceNum,
   10619              :                              FirstHVACIteration,
   10620              :                              compressorOp,
   10621              :                              1,
   10622              :                              0.0,
   10623              :                              PartLoadFrac,
   10624              :                              ZoneSensLoadMet,
   10625              :                              ZoneLatLoadMet,
   10626              :                              QZnReq,
   10627              :                              QZnLat,
   10628              :                              OnOffAirFlowRatio,
   10629              :                              SupHeaterLoad);
   10630              : 
   10631      1964741 :         Real64 ResScale = std::abs(LoadToBeMet);
   10632      1964741 :         if (ResScale < 100.0) {
   10633         7954 :             ResScale = 100.0;
   10634              :         } else {
   10635      1956787 :             ResScale = LoadToBeMet;
   10636              :         }
   10637              : 
   10638              :         // Calculate residual based on output calculation flag
   10639      1964741 :         if (par9_SensLatFlag == 1.0) {
   10640      1695334 :             return (ZoneSensLoadMet - LoadToBeMet) / ResScale;
   10641              :         } else {
   10642       269407 :             return (ZoneLatLoadMet - LoadToBeMet) / ResScale;
   10643              :         }
   10644              :     }
   10645              : 
   10646              :     //******************************************************************************
   10647              : 
   10648      3534349 :     Real64 VSHPSpeedResidual(EnergyPlusData &state,
   10649              :                              Real64 const SpeedRatio, // compressor cycling ratio (1.0 is continuous, 0.0 is off)
   10650              :                              int FurnaceNum,
   10651              :                              // int ZoneNum,
   10652              :                              bool FirstHVACIteration,
   10653              :                              // int fanOp
   10654              :                              Real64 LoadToBeMet,
   10655              :                              Real64 OnOffAirFlowRatio,
   10656              :                              Real64 SupHeaterLoad,
   10657              :                              int SpeedNum,
   10658              :                              HVAC::CompressorOp compressorOp,
   10659              :                              Real64 par9_SensLatFlag)
   10660              :     {
   10661              :         // FUNCTION INFORMATION:
   10662              :         //       AUTHOR         Bo Shen, , based on HVACMultiSpeedHeatPump:MSHPVarSpeedgResidual
   10663              :         //       DATE WRITTEN   March, 2012
   10664              : 
   10665              :         // PURPOSE OF THIS FUNCTION:
   10666              :         //  Calculates residual function ((ActualOutput - QZnReq)/QZnReq)
   10667              :         //  MSHP output depends on the part load ratio which is being varied to zero the residual.
   10668              : 
   10669              :         // METHODOLOGY EMPLOYED:
   10670              :         //  Calls CalcMSHeatPump to get ActualOutput at the given speed ratio (partload ratio for high speed)
   10671              :         //  and calculates the residual as defined above
   10672              : 
   10673      3534349 :         Real64 QZnReq = 0.0;
   10674      3534349 :         Real64 QZnLat = 0.0;
   10675      3534349 :         if (par9_SensLatFlag == 1.0) {
   10676      3428065 :             QZnReq = LoadToBeMet;
   10677              :         } else {
   10678       106284 :             QZnLat = LoadToBeMet;
   10679              :         }
   10680              : 
   10681              :         Real64 ZoneSensLoadMet; // delivered sensible capacity of MSHP
   10682              :         Real64 ZoneLatLoadMet;  // delivered latent capacity of MSHP
   10683      3534349 :         CalcVarSpeedHeatPump(state,
   10684              :                              FurnaceNum,
   10685              :                              FirstHVACIteration,
   10686              :                              compressorOp,
   10687              :                              SpeedNum,
   10688              :                              SpeedRatio,
   10689              :                              1.0,
   10690              :                              ZoneSensLoadMet,
   10691              :                              ZoneLatLoadMet,
   10692              :                              QZnReq,
   10693              :                              QZnLat,
   10694              :                              OnOffAirFlowRatio,
   10695              :                              SupHeaterLoad);
   10696              : 
   10697      3534349 :         Real64 ResScale = std::abs(LoadToBeMet);
   10698      3534349 :         if (ResScale < 100.0) {
   10699            0 :             ResScale = 100.0;
   10700              :         } else {
   10701      3534349 :             ResScale = LoadToBeMet;
   10702              :         }
   10703              : 
   10704              :         // Calculate residual based on output calculation flag
   10705      3534349 :         if (par9_SensLatFlag == 1.0) {
   10706      3428065 :             return (ZoneSensLoadMet - LoadToBeMet) / ResScale;
   10707              :         } else {
   10708       106284 :             return (ZoneLatLoadMet - LoadToBeMet) / ResScale;
   10709              :         }
   10710              :     }
   10711              : 
   10712     17687782 :     void SetVSHPAirFlow(EnergyPlusData &state,
   10713              :                         int const FurnaceNum,                        // Unit index
   10714              :                         Real64 const PartLoadRatio,                  // unit part load ratio
   10715              :                         Real64 &OnOffAirFlowRatio,                   // ratio of compressor ON airflow to average airflow over timestep
   10716              :                         ObjexxFCL::Optional_int_const SpeedNum,      // Speed number
   10717              :                         ObjexxFCL::Optional<Real64 const> SpeedRatio // Speed ratio
   10718              :     )
   10719              :     {
   10720              : 
   10721              :         // SUBROUTINE INFORMATION:
   10722              :         //       AUTHOR         Bo Shen, based on HVACMultiSpeedHeatPump:SetAverageAirFlow
   10723              :         //       DATE WRITTEN   March, 2012
   10724              : 
   10725              :         // PURPOSE OF THIS SUBROUTINE:
   10726              :         // Set the average air mass flow rates using the part load fraction of the heat pump for this time step
   10727              :         // Set OnOffAirFlowRatio to be used by DX coils
   10728              : 
   10729              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
   10730              :         Real64 AverageUnitMassFlow; // average supply air mass flow rate over time step
   10731              : 
   10732     17687782 :         auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
   10733              : 
   10734     17687782 :         state.dataHVACGlobal->MSHPMassFlowRateLow = 0.0;  // Mass flow rate at low speed
   10735     17687782 :         state.dataHVACGlobal->MSHPMassFlowRateHigh = 0.0; // Mass flow rate at high speed
   10736              : 
   10737     17687782 :         if (thisFurnace.fanOp == HVAC::FanOp::Continuous) {
   10738     17499846 :             state.dataFurnaces->CompOffMassFlow = thisFurnace.IdleMassFlowRate;
   10739     17499846 :             state.dataFurnaces->CompOffFlowRatio = thisFurnace.IdleSpeedRatio;
   10740              :         } else {
   10741       187936 :             state.dataFurnaces->CompOffMassFlow = 0.0;
   10742       187936 :             state.dataFurnaces->CompOffFlowRatio = 0.0;
   10743              :         }
   10744              : 
   10745     17687782 :         if (state.dataFurnaces->CoolingLoad && (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatCool)) {
   10746     15238427 :             if (thisFurnace.NumOfSpeedCooling > 0) {
   10747     15238427 :                 state.dataFurnaces->CompOnMassFlow = thisFurnace.CoolMassFlowRate(thisFurnace.NumOfSpeedCooling);
   10748     15238427 :                 state.dataFurnaces->CompOnFlowRatio = thisFurnace.MSCoolingSpeedRatio(thisFurnace.NumOfSpeedCooling);
   10749     15238427 :                 state.dataHVACGlobal->MSHPMassFlowRateLow = thisFurnace.CoolMassFlowRate(thisFurnace.NumOfSpeedCooling);
   10750     15238427 :                 state.dataHVACGlobal->MSHPMassFlowRateHigh = thisFurnace.CoolMassFlowRate(thisFurnace.NumOfSpeedCooling);
   10751              :             } else {
   10752            0 :                 state.dataFurnaces->CompOnMassFlow = thisFurnace.MaxCoolAirMassFlow;
   10753            0 :                 state.dataFurnaces->CompOnFlowRatio = thisFurnace.CoolingSpeedRatio;
   10754              :             }
   10755     15238427 :             AverageUnitMassFlow = (PartLoadRatio * state.dataFurnaces->CompOnMassFlow) + ((1 - PartLoadRatio) * state.dataFurnaces->CompOffMassFlow);
   10756     15238427 :             if (state.dataFurnaces->CompOffFlowRatio > 0.0) {
   10757     15238427 :                 state.dataFurnaces->FanSpeedRatio =
   10758     15238427 :                     (PartLoadRatio * state.dataFurnaces->CompOnFlowRatio) + ((1 - PartLoadRatio) * state.dataFurnaces->CompOffFlowRatio);
   10759              :             } else {
   10760            0 :                 state.dataFurnaces->FanSpeedRatio = state.dataFurnaces->CompOnFlowRatio;
   10761              :             }
   10762      2449355 :         } else if (state.dataFurnaces->HeatingLoad && (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatCool)) {
   10763       111753 :             if (thisFurnace.NumOfSpeedHeating > 0) {
   10764            0 :                 state.dataFurnaces->CompOnMassFlow = thisFurnace.HeatMassFlowRate(thisFurnace.NumOfSpeedHeating);
   10765            0 :                 state.dataFurnaces->CompOnFlowRatio = thisFurnace.MSHeatingSpeedRatio(thisFurnace.NumOfSpeedHeating);
   10766            0 :                 state.dataHVACGlobal->MSHPMassFlowRateLow = thisFurnace.HeatMassFlowRate(thisFurnace.NumOfSpeedHeating);
   10767            0 :                 state.dataHVACGlobal->MSHPMassFlowRateHigh = thisFurnace.HeatMassFlowRate(thisFurnace.NumOfSpeedHeating);
   10768              :             } else {
   10769       111753 :                 state.dataFurnaces->CompOnMassFlow = thisFurnace.MaxHeatAirMassFlow;
   10770       111753 :                 state.dataFurnaces->CompOnFlowRatio = thisFurnace.HeatingSpeedRatio;
   10771              :             }
   10772       111753 :             AverageUnitMassFlow = (PartLoadRatio * state.dataFurnaces->CompOnMassFlow) + ((1 - PartLoadRatio) * state.dataFurnaces->CompOffMassFlow);
   10773       111753 :             if (state.dataFurnaces->CompOffFlowRatio > 0.0) {
   10774       111753 :                 state.dataFurnaces->FanSpeedRatio =
   10775       111753 :                     (PartLoadRatio * state.dataFurnaces->CompOnFlowRatio) + ((1 - PartLoadRatio) * state.dataFurnaces->CompOffFlowRatio);
   10776              :             } else {
   10777            0 :                 state.dataFurnaces->FanSpeedRatio = state.dataFurnaces->CompOnFlowRatio;
   10778              :             }
   10779      2337602 :         } else if (thisFurnace.bIsIHP) {
   10780        62326 :             if (!state.dataZoneEnergyDemand->CurDeadBandOrSetback(thisFurnace.ControlZoneNum) && present(SpeedNum)) {
   10781              :                 // if(present(SpeedNum)) {
   10782       118274 :                 state.dataFurnaces->CompOnMassFlow =
   10783        59137 :                     IntegratedHeatPump::GetAirMassFlowRateIHP(state, thisFurnace.CoolingCoilIndex, SpeedNum, SpeedRatio, false);
   10784       118274 :                 state.dataFurnaces->CompOnFlowRatio =
   10785        59137 :                     state.dataFurnaces->CompOnMassFlow /
   10786        59137 :                     IntegratedHeatPump::GetAirMassFlowRateIHP(
   10787              :                         state, thisFurnace.CoolingCoilIndex, IntegratedHeatPump::GetMaxSpeedNumIHP(state, thisFurnace.CoolingCoilIndex), 1.0, false);
   10788       118274 :                 state.dataHVACGlobal->MSHPMassFlowRateLow =
   10789        59137 :                     IntegratedHeatPump::GetAirMassFlowRateIHP(state, thisFurnace.CoolingCoilIndex, SpeedNum, 0.0, false);
   10790        59137 :                 state.dataHVACGlobal->MSHPMassFlowRateHigh =
   10791        59137 :                     IntegratedHeatPump::GetAirMassFlowRateIHP(state, thisFurnace.CoolingCoilIndex, SpeedNum, 1.0, false);
   10792              :             }
   10793              : 
   10794              :             // Set up fan flow rate during compressor off time
   10795        62326 :             if (thisFurnace.fanOp == HVAC::FanOp::Continuous && present(SpeedNum)) {
   10796            0 :                 if (thisFurnace.AirFlowControl == AirFlowControlConstFan::UseCompressorOnFlow && state.dataFurnaces->CompOnMassFlow > 0.0) {
   10797            0 :                     state.dataFurnaces->CompOffMassFlow =
   10798            0 :                         IntegratedHeatPump::GetAirMassFlowRateIHP(state, thisFurnace.CoolingCoilIndex, SpeedNum, 1.0, false);
   10799            0 :                     state.dataFurnaces->CompOffFlowRatio =
   10800            0 :                         state.dataFurnaces->CompOffMassFlow /
   10801            0 :                         IntegratedHeatPump::GetAirMassFlowRateIHP(state,
   10802              :                                                                   thisFurnace.CoolingCoilIndex,
   10803              :                                                                   IntegratedHeatPump::GetMaxSpeedNumIHP(state, thisFurnace.CoolingCoilIndex),
   10804              :                                                                   1.0,
   10805              :                                                                   false);
   10806              :                 }
   10807              :             }
   10808              : 
   10809        62326 :             if (present(SpeedNum)) {
   10810        62326 :                 if (SpeedNum > 1) {
   10811        39843 :                     AverageUnitMassFlow = state.dataFurnaces->CompOnMassFlow;
   10812        39843 :                     state.dataFurnaces->FanSpeedRatio = state.dataFurnaces->CompOnFlowRatio;
   10813              :                 } else {
   10814        22483 :                     AverageUnitMassFlow =
   10815        22483 :                         (PartLoadRatio * state.dataFurnaces->CompOnMassFlow) + ((1 - PartLoadRatio) * state.dataFurnaces->CompOffMassFlow);
   10816        22483 :                     if (state.dataFurnaces->CompOffFlowRatio > 0.0) {
   10817            0 :                         state.dataFurnaces->FanSpeedRatio =
   10818            0 :                             (PartLoadRatio * state.dataFurnaces->CompOnFlowRatio) + ((1 - PartLoadRatio) * state.dataFurnaces->CompOffFlowRatio);
   10819              :                     } else {
   10820        22483 :                         state.dataFurnaces->FanSpeedRatio = state.dataFurnaces->CompOnFlowRatio;
   10821              :                     }
   10822              :                 }
   10823              :             } else {
   10824            0 :                 AverageUnitMassFlow =
   10825            0 :                     (PartLoadRatio * state.dataFurnaces->CompOnMassFlow) + ((1 - PartLoadRatio) * state.dataFurnaces->CompOffMassFlow);
   10826            0 :                 if (state.dataFurnaces->CompOffFlowRatio > 0.0) {
   10827            0 :                     state.dataFurnaces->FanSpeedRatio =
   10828            0 :                         (PartLoadRatio * state.dataFurnaces->CompOnFlowRatio) + ((1 - PartLoadRatio) * state.dataFurnaces->CompOffFlowRatio);
   10829              :                 } else {
   10830            0 :                     state.dataFurnaces->FanSpeedRatio = state.dataFurnaces->CompOnFlowRatio;
   10831              :                 }
   10832              :             }
   10833              : 
   10834        62326 :             if (IntegratedHeatPump::IHPOperationMode::SCWHMatchWH ==
   10835        62326 :                 state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).CurMode) {
   10836          672 :                 state.dataFurnaces->CompOnMassFlow =
   10837          336 :                     IntegratedHeatPump::GetAirMassFlowRateIHP(state, thisFurnace.CoolingCoilIndex, SpeedNum, SpeedRatio, false);
   10838          336 :                 AverageUnitMassFlow = state.dataFurnaces->CompOnMassFlow;
   10839              :             }
   10840              :         } else {
   10841      2275276 :             if (!state.dataZoneEnergyDemand->CurDeadBandOrSetback(thisFurnace.ControlZoneNum) && present(SpeedNum)) {
   10842      1503373 :                 if (thisFurnace.HeatCoolMode == Furnaces::ModeOfOperation::HeatingMode) {
   10843       728218 :                     if (SpeedNum == 1) {
   10844       258337 :                         state.dataFurnaces->CompOnMassFlow = thisFurnace.HeatMassFlowRate(SpeedNum);
   10845       258337 :                         state.dataFurnaces->CompOnFlowRatio = thisFurnace.MSHeatingSpeedRatio(SpeedNum);
   10846       258337 :                         state.dataHVACGlobal->MSHPMassFlowRateLow = thisFurnace.HeatMassFlowRate(1);
   10847       258337 :                         state.dataHVACGlobal->MSHPMassFlowRateHigh = thisFurnace.HeatMassFlowRate(1);
   10848       469881 :                     } else if (SpeedNum > 1) {
   10849       939762 :                         state.dataFurnaces->CompOnMassFlow =
   10850       469881 :                             SpeedRatio * thisFurnace.HeatMassFlowRate(SpeedNum) + (1.0 - SpeedRatio) * thisFurnace.HeatMassFlowRate(SpeedNum - 1);
   10851       469881 :                         state.dataFurnaces->CompOnFlowRatio = SpeedRatio * thisFurnace.MSHeatingSpeedRatio(SpeedNum) +
   10852       469881 :                                                               (1.0 - SpeedRatio) * thisFurnace.MSHeatingSpeedRatio(SpeedNum - 1);
   10853       469881 :                         state.dataHVACGlobal->MSHPMassFlowRateLow = thisFurnace.HeatMassFlowRate(SpeedNum - 1);
   10854       469881 :                         state.dataHVACGlobal->MSHPMassFlowRateHigh = thisFurnace.HeatMassFlowRate(SpeedNum);
   10855              :                     }
   10856       775155 :                 } else if (thisFurnace.HeatCoolMode == Furnaces::ModeOfOperation::CoolingMode) {
   10857       629651 :                     if (SpeedNum == 1) {
   10858       445955 :                         state.dataFurnaces->CompOnMassFlow = thisFurnace.CoolMassFlowRate(SpeedNum);
   10859       445955 :                         state.dataFurnaces->CompOnFlowRatio = thisFurnace.MSCoolingSpeedRatio(SpeedNum);
   10860       445955 :                         state.dataHVACGlobal->MSHPMassFlowRateLow = thisFurnace.CoolMassFlowRate(1);
   10861       445955 :                         state.dataHVACGlobal->MSHPMassFlowRateHigh = thisFurnace.CoolMassFlowRate(1);
   10862       183696 :                     } else if (SpeedNum > 1) {
   10863       367392 :                         state.dataFurnaces->CompOnMassFlow =
   10864       183696 :                             SpeedRatio * thisFurnace.CoolMassFlowRate(SpeedNum) + (1.0 - SpeedRatio) * thisFurnace.CoolMassFlowRate(SpeedNum - 1);
   10865       183696 :                         state.dataFurnaces->CompOnFlowRatio = SpeedRatio * thisFurnace.MSCoolingSpeedRatio(SpeedNum) +
   10866       183696 :                                                               (1.0 - SpeedRatio) * thisFurnace.MSCoolingSpeedRatio(SpeedNum - 1);
   10867       183696 :                         state.dataHVACGlobal->MSHPMassFlowRateLow = thisFurnace.CoolMassFlowRate(SpeedNum - 1);
   10868       183696 :                         state.dataHVACGlobal->MSHPMassFlowRateHigh = thisFurnace.CoolMassFlowRate(SpeedNum);
   10869              :                     }
   10870              :                 }
   10871              :             }
   10872              : 
   10873              :             // Set up fan flow rate during compressor off time
   10874      2275276 :             if (thisFurnace.fanOp == HVAC::FanOp::Continuous && present(SpeedNum)) {
   10875      2149666 :                 if (thisFurnace.AirFlowControl == AirFlowControlConstFan::UseCompressorOnFlow && state.dataFurnaces->CompOnMassFlow > 0.0) {
   10876      2148022 :                     if (SpeedNum == 1) { // LOWEST SPEED USE IDLE FLOW
   10877      1318263 :                         state.dataFurnaces->CompOffMassFlow = thisFurnace.IdleMassFlowRate;
   10878      1318263 :                         state.dataFurnaces->CompOffFlowRatio = thisFurnace.IdleSpeedRatio;
   10879       829759 :                     } else if (thisFurnace.LastMode == Furnaces::ModeOfOperation::HeatingMode) {
   10880       441861 :                         state.dataFurnaces->CompOffMassFlow = thisFurnace.HeatMassFlowRate(SpeedNum);
   10881       441861 :                         state.dataFurnaces->CompOffFlowRatio = thisFurnace.MSHeatingSpeedRatio(SpeedNum);
   10882              :                     } else {
   10883       387898 :                         state.dataFurnaces->CompOffMassFlow = thisFurnace.CoolMassFlowRate(SpeedNum);
   10884       387898 :                         state.dataFurnaces->CompOffFlowRatio = thisFurnace.MSCoolingSpeedRatio(SpeedNum);
   10885              :                     }
   10886              :                 }
   10887              :             }
   10888              : 
   10889      2275276 :             if (present(SpeedNum)) {
   10890      2275276 :                 if (SpeedNum > 1) {
   10891       910227 :                     AverageUnitMassFlow = state.dataFurnaces->CompOnMassFlow;
   10892       910227 :                     state.dataFurnaces->FanSpeedRatio = state.dataFurnaces->CompOnFlowRatio;
   10893              :                 } else {
   10894      1365049 :                     AverageUnitMassFlow =
   10895      1365049 :                         (PartLoadRatio * state.dataFurnaces->CompOnMassFlow) + ((1 - PartLoadRatio) * state.dataFurnaces->CompOffMassFlow);
   10896      1365049 :                     if (state.dataFurnaces->CompOffFlowRatio > 0.0) {
   10897      1319907 :                         state.dataFurnaces->FanSpeedRatio =
   10898      1319907 :                             (PartLoadRatio * state.dataFurnaces->CompOnFlowRatio) + ((1 - PartLoadRatio) * state.dataFurnaces->CompOffFlowRatio);
   10899              :                     } else {
   10900        45142 :                         state.dataFurnaces->FanSpeedRatio = state.dataFurnaces->CompOnFlowRatio;
   10901              :                     }
   10902              :                 }
   10903              :             } else {
   10904            0 :                 AverageUnitMassFlow =
   10905            0 :                     (PartLoadRatio * state.dataFurnaces->CompOnMassFlow) + ((1 - PartLoadRatio) * state.dataFurnaces->CompOffMassFlow);
   10906            0 :                 if (state.dataFurnaces->CompOffFlowRatio > 0.0) {
   10907            0 :                     state.dataFurnaces->FanSpeedRatio =
   10908            0 :                         (PartLoadRatio * state.dataFurnaces->CompOnFlowRatio) + ((1 - PartLoadRatio) * state.dataFurnaces->CompOffFlowRatio);
   10909              :                 } else {
   10910            0 :                     state.dataFurnaces->FanSpeedRatio = state.dataFurnaces->CompOnFlowRatio;
   10911              :                 }
   10912              :             }
   10913              :         }
   10914              : 
   10915     35363984 :         if ((thisFurnace.availSched->getCurrentVal() == 0.0) || state.dataHVACGlobal->TurnFansOff ||
   10916     17676202 :             (thisFurnace.fanAvailSched->getCurrentVal() == 0.0 && !state.dataHVACGlobal->TurnFansOn)) {
   10917        11580 :             state.dataLoopNodes->Node(thisFurnace.FurnaceInletNodeNum).MassFlowRate = 0.0;
   10918        11580 :             OnOffAirFlowRatio = 0.0;
   10919              :         } else {
   10920     17676202 :             state.dataLoopNodes->Node(thisFurnace.FurnaceInletNodeNum).MassFlowRate = AverageUnitMassFlow;
   10921     17676202 :             state.dataLoopNodes->Node(thisFurnace.FurnaceInletNodeNum).MassFlowRateMaxAvail = AverageUnitMassFlow;
   10922     17676202 :             if (AverageUnitMassFlow > 0.0) {
   10923     17637342 :                 OnOffAirFlowRatio = state.dataFurnaces->CompOnMassFlow / AverageUnitMassFlow;
   10924              :             } else {
   10925        38860 :                 OnOffAirFlowRatio = 0.0;
   10926              :             }
   10927              :         }
   10928              : 
   10929     17687782 :         state.dataLoopNodes->Node(thisFurnace.FurnaceOutletNodeNum).MassFlowRate =
   10930     17687782 :             state.dataLoopNodes->Node(thisFurnace.FurnaceInletNodeNum).MassFlowRate;
   10931     17687782 :     }
   10932              : 
   10933          359 :     void SetMinOATCompressor(EnergyPlusData &state,
   10934              :                              int const FurnaceNum,                    // index to furnace
   10935              :                              std::string const &cCurrentModuleObject, // type of furnace
   10936              :                              bool &ErrorsFound                        // GetInput logical that errors were found
   10937              :     )
   10938              :     {
   10939          359 :         bool errFlag = false;
   10940          359 :         auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
   10941              : 
   10942              :         // Set minimum OAT for heat pump compressor operation in heating mode
   10943          359 :         if (thisFurnace.CoolingCoilType_Num == HVAC::CoilDX_CoolingSingleSpeed) {
   10944          206 :             thisFurnace.MinOATCompressorCooling = DXCoils::GetMinOATCompressor(state, thisFurnace.CoolingCoilIndex, errFlag);
   10945          153 :         } else if (thisFurnace.CoolingCoilType_Num == HVAC::CoilDX_CoolingHXAssisted) {
   10946            3 :             std::string ChildCoolingCoilType = state.dataHVACAssistedCC->HXAssistedCoil(thisFurnace.CoolingCoilIndex).CoolingCoilType;
   10947            3 :             std::string ChildCoolingCoilName = state.dataHVACAssistedCC->HXAssistedCoil(thisFurnace.CoolingCoilIndex).CoolingCoilName;
   10948              : 
   10949            3 :             if (Util::SameString(ChildCoolingCoilType, "COIL:COOLING:DX")) {
   10950            1 :                 int childCCIndex_DX = CoilCoolingDX::factory(state, ChildCoolingCoilName);
   10951            1 :                 if (childCCIndex_DX < 0) {
   10952            0 :                     ShowContinueError(state, format("Occurs in {} = {}", cCurrentModuleObject, thisFurnace.Name));
   10953            0 :                     errFlag = true;
   10954            0 :                     ErrorsFound = true;
   10955              :                 }
   10956            1 :                 auto const &newCoil = state.dataCoilCoolingDX->coilCoolingDXs[childCCIndex_DX];
   10957            1 :                 thisFurnace.MinOATCompressorCooling = newCoil.performance.minOutdoorDrybulb;
   10958            2 :             } else if (Util::SameString(ChildCoolingCoilType, "Coil:Cooling:DX:VariableSpeed")) {
   10959            0 :                 int childCCIndex_VS = state.dataHVACAssistedCC->HXAssistedCoil(thisFurnace.CoolingCoilIndex).CoolingCoilIndex;
   10960            0 :                 thisFurnace.MinOATCompressorCooling = VariableSpeedCoils::GetVSCoilMinOATCompressor(state, childCCIndex_VS, errFlag);
   10961              :             } else { // Single speed
   10962            2 :                 int childCCIndex_SP = state.dataHVACAssistedCC->HXAssistedCoil(thisFurnace.CoolingCoilIndex).CoolingCoilIndex;
   10963            2 :                 thisFurnace.MinOATCompressorCooling = DXCoils::GetMinOATCompressor(state, childCCIndex_SP, errFlag);
   10964              :             }
   10965          153 :         } else if (thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingAirToAirVariableSpeed) {
   10966            7 :             thisFurnace.MinOATCompressorCooling = VariableSpeedCoils::GetVSCoilMinOATCompressor(state, thisFurnace.CoolingCoilIndex, errFlag);
   10967              :         } else {
   10968          143 :             thisFurnace.MinOATCompressorCooling = -1000.0;
   10969              :         }
   10970          359 :         if (errFlag) {
   10971            0 :             ShowContinueError(state, format("...occurs in {} = {}", cCurrentModuleObject, thisFurnace.Name));
   10972            0 :             ErrorsFound = true;
   10973              :         }
   10974              : 
   10975              :         // Set minimum OAT for heat pump compressor operation in heating mode
   10976          359 :         errFlag = false;
   10977          359 :         if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingAirToAirVariableSpeed) {
   10978            3 :             thisFurnace.MinOATCompressorHeating = VariableSpeedCoils::GetVSCoilMinOATCompressor(state, thisFurnace.HeatingCoilIndex, errFlag);
   10979          356 :         } else if (thisFurnace.HeatingCoilType_Num == HVAC::CoilDX_HeatingEmpirical) {
   10980           32 :             thisFurnace.MinOATCompressorHeating = DXCoils::GetMinOATCompressor(state, thisFurnace.HeatingCoilIndex, errFlag);
   10981              :         } else {
   10982          324 :             thisFurnace.MinOATCompressorHeating = -1000.0;
   10983              :         }
   10984          359 :         if (errFlag) {
   10985            0 :             ShowContinueError(state, format("...occurs in {} = {}", cCurrentModuleObject, thisFurnace.Name));
   10986            0 :             ErrorsFound = true;
   10987              :         }
   10988          359 :     }
   10989              : 
   10990              : } // namespace Furnaces
   10991              : 
   10992              : } // namespace EnergyPlus
        

Generated by: LCOV version 2.0-1