LCOV - code coverage report
Current view: top level - EnergyPlus - Furnaces.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 3307 5313 62.2 %
Date: 2024-08-24 18:31:18 Functions: 33 34 97.1 %

          Line data    Source code
       1             : // EnergyPlus, Copyright (c) 1996-2024, The Board of Trustees of the University of Illinois,
       2             : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
       3             : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
       4             : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
       5             : // contributors. All rights reserved.
       6             : //
       7             : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
       8             : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
       9             : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
      10             : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
      11             : // derivative works, and perform publicly and display publicly, and to permit others to do so.
      12             : //
      13             : // Redistribution and use in source and binary forms, with or without modification, are permitted
      14             : // provided that the following conditions are met:
      15             : //
      16             : // (1) Redistributions of source code must retain the above copyright notice, this list of
      17             : //     conditions and the following disclaimer.
      18             : //
      19             : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
      20             : //     conditions and the following disclaimer in the documentation and/or other materials
      21             : //     provided with the distribution.
      22             : //
      23             : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
      24             : //     the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
      25             : //     used to endorse or promote products derived from this software without specific prior
      26             : //     written permission.
      27             : //
      28             : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
      29             : //     without changes from the version obtained under this License, or (ii) Licensee makes a
      30             : //     reference solely to the software portion of its product, Licensee must refer to the
      31             : //     software as "EnergyPlus version X" software, where "X" is the version number Licensee
      32             : //     obtained under this License and may not use a different name for the software. Except as
      33             : //     specifically required in this Section (4), Licensee shall not use in a company name, a
      34             : //     product name, in advertising, publicity, or other promotional activities any name, trade
      35             : //     name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
      36             : //     similar designation, without the U.S. Department of Energy's prior written consent.
      37             : //
      38             : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
      39             : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
      40             : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
      41             : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      42             : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      43             : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      44             : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      45             : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      46             : // POSSIBILITY OF SUCH DAMAGE.
      47             : 
      48             : // C++ Headers
      49             : #include <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 dehumidificaiton 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 dehumidificaiton 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             :     // Dehumidificaiton 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             :     constexpr std::string_view fluidNameSteam("STEAM");
     169             : 
     170             :     // Functions
     171             : 
     172     6243009 :     void SimFurnace(EnergyPlusData &state,
     173             :                     std::string_view FurnaceName,
     174             :                     bool const FirstHVACIteration,
     175             :                     int const AirLoopNum, // Primary air loop number
     176             :                     int &CompIndex        // Pointer to which furnace
     177             :     )
     178             :     {
     179             : 
     180             :         // SUBROUTINE INFORMATION:
     181             :         //       AUTHOR         Dan Fisher
     182             :         //       DATE WRITTEN   Jan 2001
     183             :         //       MODIFIED       Richard Liesen, Oct 2001 - Richard Raustad; Bo Shen, March 2012, for VS WSHP
     184             :         //       RE-ENGINEERED  Feb 2001
     185             : 
     186             :         // PURPOSE OF THIS SUBROUTINE:
     187             :         // This subroutine manages Furnace component simulation.
     188             : 
     189             :         // METHODOLOGY EMPLOYED:
     190             :         // Call the calc routine to determine an operating PLR. Resimulate child components at this PLR.
     191             :         // A supplemental heater augments the heating capacity for both air-to-air and water-to-air heat pump systems.
     192             :         // A reheat coil is used for the HeatCool furnace/unitarysystem to offset the sensible cooling when the
     193             :         // dehumidification control type is COOLREHEAT. Both the supplemental and reheat heating coil load is calculated
     194             :         // in the Calc routines and returned here through subroutine arguments. The actual simulation of these coils is
     195             :         // performed here (i.e. the supplemental and reheat coil loads are passed as 0 to CalcFurnaceOutput).
     196             : 
     197             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     198             :         int FurnaceNum;           // Furnace number
     199     6243009 :         Real64 HeatCoilLoad(0.0); // Zone heating coil load
     200             :         Real64 ReheatCoilLoad;    // Load to be met by the reheat coil (if high humidity control)
     201             :         Real64 MoistureLoad;      // Control zone latent load
     202     6243009 :         Real64 Dummy(0.0);
     203     6243009 :         HVAC::FanOp fanOp = HVAC::FanOp::Invalid; // Fan operating mode (1=FanOp::Cycling, 2=FanOp::Continuous)
     204             : 
     205             :         Real64 QActual;           // actual heating coil output (W)
     206             :         bool SuppHeatingCoilFlag; // true if supplemental heating coil
     207             : 
     208             :         // Obtains and Allocates Furnace related parameters from input file
     209     6243009 :         if (state.dataFurnaces->GetFurnaceInputFlag) { // First time subroutine has been entered
     210             :             // Get the furnace input
     211          97 :             GetFurnaceInput(state);
     212          97 :             state.dataFurnaces->GetFurnaceInputFlag = false;
     213             :         }
     214             : 
     215             :         // Find the correct Furnace
     216     6243009 :         if (CompIndex == 0) {
     217         359 :             FurnaceNum = Util::FindItemInList(FurnaceName, state.dataFurnaces->Furnace);
     218         359 :             if (FurnaceNum == 0) {
     219           0 :                 ShowFatalError(state, format("SimFurnace: Unit not found={}", FurnaceName));
     220             :             }
     221         359 :             CompIndex = FurnaceNum;
     222             :         } else {
     223     6242650 :             FurnaceNum = CompIndex;
     224     6242650 :             if (FurnaceNum > state.dataFurnaces->NumFurnaces || FurnaceNum < 1) {
     225           0 :                 ShowFatalError(state,
     226           0 :                                format("SimFurnace:  Invalid CompIndex passed={}, Number of Units={}, Entered Unit name={}",
     227             :                                       FurnaceNum,
     228           0 :                                       state.dataFurnaces->NumFurnaces,
     229             :                                       FurnaceName));
     230             :             }
     231     6242650 :             if (state.dataFurnaces->CheckEquipName(FurnaceNum)) {
     232         359 :                 if (FurnaceName != state.dataFurnaces->Furnace(FurnaceNum).Name) {
     233           0 :                     ShowFatalError(state,
     234           0 :                                    format("SimFurnace: Invalid CompIndex passed={}, Unit name={}, stored Unit Name for that index={}",
     235             :                                           FurnaceNum,
     236             :                                           FurnaceName,
     237           0 :                                           state.dataFurnaces->Furnace(FurnaceNum).Name));
     238             :                 }
     239         359 :                 state.dataFurnaces->CheckEquipName(FurnaceNum) = false;
     240             :             }
     241             :         }
     242             : 
     243     6243009 :         bool HXUnitOn = false;          // flag to control HX assisted cooling coil
     244     6243009 :         Real64 OnOffAirFlowRatio = 0.0; // Ratio of compressor ON air flow to AVERAGE air flow over time step
     245             :         // here we need to deal with sequenced zone equip sensible load in control zone
     246     6243009 :         Real64 ZoneLoad = 0.0;
     247             : 
     248     6243009 :         auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
     249     6243009 :         auto &zoneSysEnergyDemand = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(thisFurnace.ControlZoneNum);
     250     6243009 :         if (thisFurnace.ZoneSequenceCoolingNum > 0 && thisFurnace.ZoneSequenceHeatingNum > 0) {
     251     6242650 :             Real64 ZoneLoadToCoolSPSequenced = zoneSysEnergyDemand.SequencedOutputRequiredToCoolingSP(thisFurnace.ZoneSequenceCoolingNum);
     252     6242650 :             Real64 ZoneLoadToHeatSPSequenced = zoneSysEnergyDemand.SequencedOutputRequiredToHeatingSP(thisFurnace.ZoneSequenceHeatingNum);
     253     6242650 :             auto const &tempControlType = state.dataHeatBalFanSys->TempControlType(thisFurnace.ControlZoneNum);
     254     6242650 :             if (ZoneLoadToHeatSPSequenced > 0.0 && ZoneLoadToCoolSPSequenced > 0.0 && tempControlType != HVAC::ThermostatType::SingleCooling) {
     255     2027000 :                 ZoneLoad = ZoneLoadToHeatSPSequenced;
     256     4215650 :             } else if (ZoneLoadToHeatSPSequenced > 0.0 && ZoneLoadToCoolSPSequenced > 0.0 && tempControlType == HVAC::ThermostatType::SingleCooling) {
     257       66828 :                 ZoneLoad = 0.0;
     258     4148822 :             } else if (ZoneLoadToHeatSPSequenced < 0.0 && ZoneLoadToCoolSPSequenced < 0.0 && tempControlType != HVAC::ThermostatType::SingleHeating) {
     259     3045034 :                 ZoneLoad = ZoneLoadToCoolSPSequenced;
     260     1103788 :             } else if (ZoneLoadToHeatSPSequenced < 0.0 && ZoneLoadToCoolSPSequenced < 0.0 && tempControlType == HVAC::ThermostatType::SingleHeating) {
     261       25175 :                 ZoneLoad = 0.0;
     262     1078613 :             } else if (ZoneLoadToHeatSPSequenced <= 0.0 && ZoneLoadToCoolSPSequenced >= 0.0) {
     263     1078613 :                 ZoneLoad = 0.0;
     264             :             }
     265     6242650 :             MoistureLoad = state.dataZoneEnergyDemand->ZoneSysMoistureDemand(thisFurnace.ControlZoneNum)
     266     6242650 :                                .SequencedOutputRequiredToDehumidSP(thisFurnace.ZoneSequenceCoolingNum);
     267     6242650 :         } else {
     268         359 :             ZoneLoad = zoneSysEnergyDemand.RemainingOutputRequired;
     269         359 :             MoistureLoad = state.dataZoneEnergyDemand->ZoneSysMoistureDemand(thisFurnace.ControlZoneNum).OutputRequiredToDehumidifyingSP;
     270             :         }
     271             : 
     272             :         // H2OHtOfVap
     273     6243009 :         MoistureLoad *= Psychrometrics::PsyHfgAirFnWTdb(state.dataLoopNodes->Node(thisFurnace.NodeNumOfControlledZone).HumRat,
     274     6243009 :                                                         state.dataLoopNodes->Node(thisFurnace.NodeNumOfControlledZone).Temp);
     275             : 
     276             :         // Initialize Furnace Flows
     277     6243009 :         InitFurnace(state, FurnaceNum, AirLoopNum, OnOffAirFlowRatio, fanOp, ZoneLoad, MoistureLoad, FirstHVACIteration);
     278             : 
     279     6243009 :         int FurnaceInletNode = thisFurnace.FurnaceInletNodeNum;
     280             : 
     281             :         // MassFlowRateMaxAvail issues are impeding non-VAV air loop equipment by limiting air flow
     282             :         // temporarily open up flow limits while simulating, and then set this same value at the INLET after this parent has simulated
     283     6243009 :         Real64 TempMassFlowRateMaxAvail = state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRateMaxAvail;
     284     6243009 :         state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRateMaxAvail = thisFurnace.DesignMassFlowRate;
     285             : 
     286     6243009 :         Real64 FurnaceSavMdot = state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate;
     287     6243009 :         HVAC::CompressorOp compressorOp = HVAC::CompressorOp::On;
     288     6243009 :         state.dataFurnaces->CoolHeatPLRRat = 1.0;
     289             : 
     290             :         // Simulate correct system type (1 of 4 choices)
     291     6243009 :         switch (thisFurnace.type) {
     292             :             // Simulate HeatOnly systems:
     293       24444 :         case HVAC::UnitarySysType::Furnace_HeatOnly:
     294             :         case HVAC::UnitarySysType::Unitary_HeatOnly: {
     295             :             // Update the furnace flow rates
     296       24444 :             CalcNewZoneHeatOnlyFlowRates(state, FurnaceNum, FirstHVACIteration, ZoneLoad, HeatCoilLoad, OnOffAirFlowRatio);
     297             : 
     298       24444 :             if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
     299             :                 // simulate fan
     300       24444 :                 state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
     301             :             }
     302             : 
     303             :             // simulate furnace heating coil
     304       24444 :             SuppHeatingCoilFlag = false; // if true simulates supplemental heating coil
     305       24444 :             CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, fanOp, QActual);
     306             : 
     307       24444 :             if (thisFurnace.fanPlace == HVAC::FanPlace::DrawThru) {
     308             :                 // simulate fan
     309           0 :                 state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
     310             :             }
     311       24444 :         } break;
     312             :             // Simulate HeatCool sytems:
     313     3738201 :         case HVAC::UnitarySysType::Furnace_HeatCool:
     314             :         case HVAC::UnitarySysType::Unitary_HeatCool: {
     315     3738201 :             if (thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingAirToAirVariableSpeed) {
     316             :                 // variable speed cooling coil
     317     1247320 :                 HeatCoilLoad = 0.0;
     318     1247320 :                 if (thisFurnace.bIsIHP)
     319           0 :                     state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).ControlledZoneTemp =
     320           0 :                         state.dataLoopNodes->Node(thisFurnace.NodeNumOfControlledZone).Temp;
     321     1247320 :                 SimVariableSpeedHP(state, FurnaceNum, FirstHVACIteration, AirLoopNum, ZoneLoad, MoistureLoad, OnOffAirFlowRatio);
     322             :             } else {
     323             :                 // calculate the system flow rate
     324     2743943 :                 if (!FirstHVACIteration && thisFurnace.fanOp == HVAC::FanOp::Cycling && state.dataFurnaces->CoolingLoad &&
     325      253062 :                     state.dataAirLoop->AirLoopControlInfo(AirLoopNum).EconoActive) {
     326             :                     // for cycling fan, cooling load, check whether furnace can meet load with compressor off
     327        5692 :                     compressorOp = HVAC::CompressorOp::Off;
     328        5692 :                     CalcNewZoneHeatCoolFlowRates(state,
     329             :                                                  FurnaceNum,
     330             :                                                  FirstHVACIteration,
     331             :                                                  compressorOp,
     332             :                                                  ZoneLoad,
     333             :                                                  MoistureLoad,
     334             :                                                  HeatCoilLoad,
     335             :                                                  ReheatCoilLoad,
     336             :                                                  OnOffAirFlowRatio,
     337             :                                                  HXUnitOn);
     338        5692 :                     if (thisFurnace.CoolPartLoadRatio >= 1.0 || thisFurnace.HeatPartLoadRatio >= 1.0 ||
     339        2160 :                         (thisFurnace.CoolPartLoadRatio <= 0.0 && thisFurnace.HeatPartLoadRatio <= 0.0)) {
     340             :                         // compressor on (reset inlet air mass flow rate to starting value)
     341        5672 :                         state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = FurnaceSavMdot;
     342        5672 :                         compressorOp = HVAC::CompressorOp::On;
     343        5672 :                         CalcNewZoneHeatCoolFlowRates(state,
     344             :                                                      FurnaceNum,
     345             :                                                      FirstHVACIteration,
     346             :                                                      compressorOp,
     347             :                                                      ZoneLoad,
     348             :                                                      MoistureLoad,
     349             :                                                      HeatCoilLoad,
     350             :                                                      ReheatCoilLoad,
     351             :                                                      OnOffAirFlowRatio,
     352             :                                                      HXUnitOn);
     353             :                     }
     354             :                 } else {
     355             :                     // compressor on
     356     2485189 :                     CalcNewZoneHeatCoolFlowRates(state,
     357             :                                                  FurnaceNum,
     358             :                                                  FirstHVACIteration,
     359             :                                                  compressorOp,
     360             :                                                  ZoneLoad,
     361             :                                                  MoistureLoad,
     362             :                                                  HeatCoilLoad,
     363             :                                                  ReheatCoilLoad,
     364             :                                                  OnOffAirFlowRatio,
     365             :                                                  HXUnitOn);
     366             :                 }
     367             : 
     368     2490881 :                 if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
     369             :                     // simulate fan
     370     2451427 :                     state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
     371             :                 }
     372             : 
     373     2490881 :                 if (!thisFurnace.CoolingCoilUpstream) {
     374             :                     // simulate furnace heating coil
     375     1128522 :                     SuppHeatingCoilFlag = false; // if true simulates supplemental heating coil
     376     1128522 :                     CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, fanOp, QActual);
     377             :                 }
     378             : 
     379             :                 // simulate furnace DX cooling coil
     380     2490881 :                 if (thisFurnace.CoolingCoilType_Num == HVAC::CoilDX_CoolingHXAssisted) {
     381      151317 :                     HVACHXAssistedCoolingCoil::SimHXAssistedCoolingCoil(state,
     382             :                                                                         BlankString,
     383             :                                                                         FirstHVACIteration,
     384             :                                                                         compressorOp,
     385             :                                                                         thisFurnace.CoolPartLoadRatio,
     386       50439 :                                                                         thisFurnace.CoolingCoilIndex,
     387             :                                                                         fanOp,
     388             :                                                                         HXUnitOn,
     389             :                                                                         OnOffAirFlowRatio,
     390       50439 :                                                                         state.dataFurnaces->EconomizerFlag);
     391             :                 } else {
     392     7321326 :                     DXCoils::SimDXCoil(state,
     393             :                                        BlankString,
     394             :                                        compressorOp,
     395             :                                        FirstHVACIteration,
     396     2440442 :                                        thisFurnace.CoolingCoilIndex,
     397             :                                        fanOp,
     398     2440442 :                                        thisFurnace.CoolPartLoadRatio,
     399             :                                        OnOffAirFlowRatio,
     400     2440442 :                                        state.dataFurnaces->CoolHeatPLRRat);
     401             :                 }
     402             : 
     403     2490881 :                 if (thisFurnace.CoolingCoilUpstream) {
     404             :                     // simulate furnace heating coil
     405     1362359 :                     SuppHeatingCoilFlag = false; // if true simulates supplemental heating coil
     406     1362359 :                     CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, fanOp, QActual);
     407             :                 }
     408             : 
     409     2490881 :                 if (thisFurnace.fanPlace == HVAC::FanPlace::DrawThru) {
     410             :                     // simulate fan
     411       39454 :                     state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
     412             :                 }
     413             : 
     414             :                 // Simulate furnace reheat coil if a humidistat is used or if the reheat coil is present
     415     2490881 :                 if (thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat || thisFurnace.SuppHeatCoilIndex > 0) {
     416      837862 :                     SuppHeatingCoilFlag = true; // if truee simulates supplemental heating coil
     417      837862 :                     CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, ReheatCoilLoad, fanOp, QActual);
     418             :                 }
     419             :             }
     420     3738201 :         } break;
     421             :             // Simulate air-to-air heat pumps:
     422      421792 :         case HVAC::UnitarySysType::Unitary_HeatPump_AirToAir: {
     423      421792 :             if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingAirToAirVariableSpeed) {
     424             :                 // variable speed heat pump
     425       30262 :                 HeatCoilLoad = 0.0;
     426       30262 :                 if (thisFurnace.bIsIHP) {
     427       10106 :                     auto &integratedHP = state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex);
     428       10106 :                     integratedHP.ControlledZoneTemp = state.dataLoopNodes->Node(thisFurnace.NodeNumOfControlledZone).Temp;
     429       10106 :                     integratedHP.IDFanID = thisFurnace.FanIndex; // why do this every time?
     430       10106 :                     integratedHP.IDFanName = BlankString;
     431       10106 :                     integratedHP.fanPlace = thisFurnace.fanPlace;
     432             :                 }
     433             : 
     434       30262 :                 SimVariableSpeedHP(state, FurnaceNum, FirstHVACIteration, AirLoopNum, ZoneLoad, MoistureLoad, OnOffAirFlowRatio);
     435             :             } else {
     436             :                 // Update the furnace flow rates
     437      496877 :                 if (!FirstHVACIteration && thisFurnace.fanOp == HVAC::FanOp::Cycling && state.dataFurnaces->CoolingLoad &&
     438      105347 :                     state.dataAirLoop->AirLoopControlInfo(AirLoopNum).EconoActive) {
     439             :                     // for cycling fan, cooling load, check whether furnace can meet load with compressor off
     440         538 :                     compressorOp = HVAC::CompressorOp::Off;
     441         538 :                     CalcNewZoneHeatCoolFlowRates(state,
     442             :                                                  FurnaceNum,
     443             :                                                  FirstHVACIteration,
     444             :                                                  compressorOp,
     445             :                                                  ZoneLoad,
     446             :                                                  MoistureLoad,
     447             :                                                  HeatCoilLoad,
     448             :                                                  ReheatCoilLoad,
     449             :                                                  OnOffAirFlowRatio,
     450             :                                                  HXUnitOn);
     451         538 :                     if (thisFurnace.CoolPartLoadRatio >= 1.0 || thisFurnace.HeatPartLoadRatio >= 1.0 ||
     452         406 :                         (thisFurnace.CoolPartLoadRatio <= 0.0 && thisFurnace.HeatPartLoadRatio <= 0.0)) {
     453             :                         // compressor on (reset inlet air mass flow rate to starting value)
     454         132 :                         compressorOp = HVAC::CompressorOp::On;
     455         132 :                         state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = FurnaceSavMdot;
     456         132 :                         CalcNewZoneHeatCoolFlowRates(state,
     457             :                                                      FurnaceNum,
     458             :                                                      FirstHVACIteration,
     459             :                                                      compressorOp,
     460             :                                                      ZoneLoad,
     461             :                                                      MoistureLoad,
     462             :                                                      HeatCoilLoad,
     463             :                                                      ReheatCoilLoad,
     464             :                                                      OnOffAirFlowRatio,
     465             :                                                      HXUnitOn);
     466             :                     }
     467             :                 } else {
     468             :                     // compressor on
     469      390992 :                     CalcNewZoneHeatCoolFlowRates(state,
     470             :                                                  FurnaceNum,
     471             :                                                  FirstHVACIteration,
     472             :                                                  compressorOp,
     473             :                                                  ZoneLoad,
     474             :                                                  MoistureLoad,
     475             :                                                  HeatCoilLoad,
     476             :                                                  ReheatCoilLoad,
     477             :                                                  OnOffAirFlowRatio,
     478             :                                                  HXUnitOn);
     479             :                 }
     480             : 
     481      391530 :                 if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
     482      391530 :                     state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
     483             :                 }
     484             : 
     485      391530 :                 if (thisFurnace.CoolingCoilType_Num == HVAC::CoilDX_CoolingHXAssisted) {
     486           0 :                     HVACHXAssistedCoolingCoil::SimHXAssistedCoolingCoil(state,
     487             :                                                                         BlankString,
     488             :                                                                         FirstHVACIteration,
     489             :                                                                         compressorOp,
     490             :                                                                         thisFurnace.CoolPartLoadRatio,
     491           0 :                                                                         thisFurnace.CoolingCoilIndex,
     492             :                                                                         fanOp,
     493             :                                                                         HXUnitOn,
     494             :                                                                         OnOffAirFlowRatio,
     495           0 :                                                                         state.dataFurnaces->EconomizerFlag);
     496             :                 } else {
     497      783060 :                     DXCoils::SimDXCoil(state,
     498             :                                        BlankString,
     499             :                                        compressorOp,
     500             :                                        FirstHVACIteration,
     501      391530 :                                        thisFurnace.CoolingCoilIndex,
     502             :                                        fanOp,
     503      391530 :                                        thisFurnace.CoolPartLoadRatio,
     504             :                                        OnOffAirFlowRatio);
     505             :                 }
     506      783060 :                 DXCoils::SimDXCoil(state,
     507             :                                    BlankString,
     508             :                                    compressorOp,
     509             :                                    FirstHVACIteration,
     510      391530 :                                    thisFurnace.HeatingCoilIndex,
     511             :                                    fanOp,
     512      391530 :                                    thisFurnace.HeatPartLoadRatio,
     513             :                                    OnOffAirFlowRatio);
     514      391530 :                 if (thisFurnace.fanPlace == HVAC::FanPlace::DrawThru) {
     515           0 :                     state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
     516             :                 }
     517             : 
     518             :                 // Simulate furnace reheat coil if a humidistat is present, the dehumidification type of coolreheat and
     519             :                 // reheat coil load exists
     520      391530 :                 if (thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat && ReheatCoilLoad > 0.0) {
     521        6194 :                     SuppHeatingCoilFlag = true; // if truee simulates supplemental heating coil
     522        6194 :                     CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, ReheatCoilLoad, fanOp, QActual);
     523             :                 } else {
     524      385336 :                     SuppHeatingCoilFlag = true; // if true simulates supplemental heating coil
     525      385336 :                     CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, fanOp, QActual);
     526             :                 }
     527             :             }
     528      421792 :         } break;
     529             :         // Simulate water-to-air systems:
     530     2058572 :         case HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir: {
     531     2058572 :             if (thisFurnace.WatertoAirHPType == WAHPCoilType::Simple) {
     532             :                 // Update the furnace flow rates
     533             :                 //   When CompressorOp logic is added to the child cooling coil (COIL:WaterToAirHP:EquationFit:Cooling), then this logic
     534             :                 //   needs to be reinstated... to align with Unitary/Furnace HeatCool and Unitary Air-to-Air Heat Pump (see above).
     535     2138290 :                 if (!FirstHVACIteration && thisFurnace.fanOp == HVAC::FanOp::Cycling && state.dataFurnaces->CoolingLoad &&
     536      429030 :                     state.dataAirLoop->AirLoopControlInfo(AirLoopNum).EconoActive) {
     537             :                     // for cycling fan, cooling load, check whether furnace can meet load with compressor off
     538           0 :                     compressorOp = HVAC::CompressorOp::Off;
     539           0 :                     CalcNewZoneHeatCoolFlowRates(state,
     540             :                                                  FurnaceNum,
     541             :                                                  FirstHVACIteration,
     542             :                                                  compressorOp,
     543             :                                                  ZoneLoad,
     544             :                                                  MoistureLoad,
     545             :                                                  HeatCoilLoad,
     546             :                                                  ReheatCoilLoad,
     547             :                                                  OnOffAirFlowRatio,
     548             :                                                  HXUnitOn);
     549           0 :                     if (thisFurnace.CoolPartLoadRatio >= 1.0 || thisFurnace.HeatPartLoadRatio >= 1.0 ||
     550           0 :                         (thisFurnace.CoolPartLoadRatio <= 0.0 && thisFurnace.HeatPartLoadRatio <= 0.0)) {
     551             :                         // compressor on (reset inlet air mass flow rate to starting value)
     552           0 :                         compressorOp = HVAC::CompressorOp::On;
     553           0 :                         state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = FurnaceSavMdot;
     554           0 :                         CalcNewZoneHeatCoolFlowRates(state,
     555             :                                                      FurnaceNum,
     556             :                                                      FirstHVACIteration,
     557             :                                                      compressorOp,
     558             :                                                      ZoneLoad,
     559             :                                                      MoistureLoad,
     560             :                                                      HeatCoilLoad,
     561             :                                                      ReheatCoilLoad,
     562             :                                                      OnOffAirFlowRatio,
     563             :                                                      HXUnitOn);
     564             :                     }
     565             :                 } else {
     566             :                     // compressor on
     567     1709260 :                     CalcNewZoneHeatCoolFlowRates(state,
     568             :                                                  FurnaceNum,
     569             :                                                  FirstHVACIteration,
     570             :                                                  compressorOp,
     571             :                                                  ZoneLoad,
     572             :                                                  MoistureLoad,
     573             :                                                  HeatCoilLoad,
     574             :                                                  ReheatCoilLoad,
     575             :                                                  OnOffAirFlowRatio,
     576             :                                                  HXUnitOn);
     577             :                 }
     578     1709260 :                 if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
     579     1709260 :                     state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
     580             :                 }
     581             : 
     582     1709260 :                 WaterToAirHeatPumpSimple::SimWatertoAirHPSimple(state,
     583             :                                                                 BlankString,
     584     1709260 :                                                                 thisFurnace.CoolingCoilIndex,
     585             :                                                                 thisFurnace.CoolingCoilSensDemand,
     586             :                                                                 thisFurnace.CoolingCoilLatentDemand,
     587             :                                                                 thisFurnace.fanOp,
     588             :                                                                 compressorOp,
     589             :                                                                 thisFurnace.CoolPartLoadRatio,
     590             :                                                                 FirstHVACIteration);
     591     1709260 :                 WaterToAirHeatPumpSimple::SimWatertoAirHPSimple(state,
     592             :                                                                 BlankString,
     593     1709260 :                                                                 thisFurnace.HeatingCoilIndex,
     594             :                                                                 thisFurnace.HeatingCoilSensDemand,
     595             :                                                                 Dummy,
     596             :                                                                 thisFurnace.fanOp,
     597             :                                                                 compressorOp,
     598             :                                                                 thisFurnace.HeatPartLoadRatio,
     599             :                                                                 FirstHVACIteration);
     600             : 
     601     1709260 :                 if (thisFurnace.fanPlace == HVAC::FanPlace::DrawThru) {
     602           0 :                     state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
     603             :                 }
     604     1709260 :                 if (thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat && ReheatCoilLoad > 0.0) {
     605       15850 :                     SuppHeatingCoilFlag = true; // if true simulates supplemental heating coil
     606       15850 :                     CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, ReheatCoilLoad, fanOp, QActual);
     607             :                 } else {
     608     1693410 :                     SuppHeatingCoilFlag = true; // if true simulates supplemental heating coil
     609     1693410 :                     CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, fanOp, QActual);
     610             :                 }
     611      349312 :             } else if (thisFurnace.WatertoAirHPType == WAHPCoilType::ParEst) {
     612             : 
     613             :                 // simulate the heat pump
     614      119270 :                 HeatCoilLoad = 0.0;
     615      119270 :                 CalcWaterToAirHeatPump(state, FurnaceNum, FirstHVACIteration, compressorOp, ZoneLoad, MoistureLoad);
     616      230042 :             } else if (thisFurnace.WatertoAirHPType == WAHPCoilType::VarSpeedEquationFit) {
     617             :                 // simulate the heat pump
     618      230042 :                 HeatCoilLoad = 0.0;
     619      230042 :                 if (thisFurnace.bIsIHP)
     620           0 :                     state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).ControlledZoneTemp =
     621           0 :                         state.dataLoopNodes->Node(thisFurnace.NodeNumOfControlledZone).Temp;
     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     2058572 :         } 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     6243009 :         auto &airLoopControlInfo = state.dataAirLoop->AirLoopControlInfo(AirLoopNum);
     638     6243009 :         if (thisFurnace.CompPartLoadRatio > 0.0 && airLoopControlInfo.CanLockoutEconoWithCompressor) {
     639      278181 :             airLoopControlInfo.ReqstEconoLockoutWithCompressor = true;
     640             :         } else {
     641     5964828 :             airLoopControlInfo.ReqstEconoLockoutWithCompressor = false;
     642             :         }
     643             : 
     644     6243009 :         if ((HeatCoilLoad > 0.0 || thisFurnace.HeatPartLoadRatio > 0.0) &&
     645     1744246 :             (airLoopControlInfo.CanLockoutEconoWithCompressor || airLoopControlInfo.CanLockoutEconoWithHeating)) {
     646      905744 :             airLoopControlInfo.ReqstEconoLockoutWithHeating = true;
     647             :         } else {
     648     5337265 :             airLoopControlInfo.ReqstEconoLockoutWithHeating = false;
     649             :         }
     650             : 
     651     6243009 :         if (thisFurnace.fanOp == HVAC::FanOp::Cycling) {
     652     2858974 :             state.dataAirLoop->AirLoopFlow(AirLoopNum).FanPLR = thisFurnace.FanPartLoadRatio;
     653             :         } else {
     654     3384035 :             state.dataAirLoop->AirLoopFlow(AirLoopNum).FanPLR = 1.0; // 1 means constant fan does not cycle.
     655             :         }
     656             : 
     657             :         // Report the current Furnace output
     658     6243009 :         ReportFurnace(state, FurnaceNum, AirLoopNum);
     659             : 
     660             :         // Reset OnOffFanPartLoadFraction to 1 in case another on/off fan is called without a part-load curve
     661     6243009 :         state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
     662             : 
     663     6243009 :         state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRateMaxAvail = TempMassFlowRateMaxAvail;
     664     6243009 :     }
     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             :         int SteamIndex;                // steam coil index
     737             :         Real64 SteamDensity;           // density of steam at 100C
     738             :         int DXCoilIndex;               // Index to DX coil in HXAssited object
     739          97 :         std::string IHPCoilName;       // IHP cooling coil name
     740          97 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
     741             :         DataLoopNode::ConnectionObjectType currentModuleObjectType;
     742             : 
     743          97 :         state.dataFurnaces->GetFurnaceInputFlag = false;
     744          97 :         int MaxNumbers = 0;
     745          97 :         int MaxAlphas = 0;
     746             : 
     747          97 :         std::string_view CurrentModuleObject = "AirLoopHVAC:Unitary:Furnace:HeatOnly";
     748          97 :         int NumHeatOnly = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
     749          97 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NumFields, NumAlphas, NumNumbers);
     750          97 :         MaxNumbers = max(MaxNumbers, NumNumbers);
     751          97 :         MaxAlphas = max(MaxAlphas, NumAlphas);
     752             : 
     753          97 :         CurrentModuleObject = "AirLoopHVAC:Unitary:Furnace:HeatCool";
     754          97 :         int NumHeatCool = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
     755          97 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NumFields, NumAlphas, NumNumbers);
     756          97 :         MaxNumbers = max(MaxNumbers, NumNumbers);
     757          97 :         MaxAlphas = max(MaxAlphas, NumAlphas);
     758             : 
     759          97 :         CurrentModuleObject = "AirLoopHVAC:UnitaryHeatOnly";
     760          97 :         int NumUnitaryHeatOnly = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
     761          97 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NumFields, NumAlphas, NumNumbers);
     762          97 :         MaxNumbers = max(MaxNumbers, NumNumbers);
     763          97 :         MaxAlphas = max(MaxAlphas, NumAlphas);
     764             : 
     765          97 :         CurrentModuleObject = "AirLoopHVAC:UnitaryHeatCool";
     766          97 :         int NumUnitaryHeatCool = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
     767          97 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NumFields, NumAlphas, NumNumbers);
     768          97 :         MaxNumbers = max(MaxNumbers, NumNumbers);
     769          97 :         MaxAlphas = max(MaxAlphas, NumAlphas);
     770             : 
     771          97 :         CurrentModuleObject = "AirLoopHVAC:UnitaryHeatPump:AirToAir";
     772          97 :         int NumHeatPump = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
     773          97 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NumFields, NumAlphas, NumNumbers);
     774          97 :         MaxNumbers = max(MaxNumbers, NumNumbers);
     775          97 :         MaxAlphas = max(MaxAlphas, NumAlphas);
     776             : 
     777          97 :         CurrentModuleObject = "AirLoopHVAC:UnitaryHeatPump:WaterToAir";
     778          97 :         int NumWaterToAirHeatPump = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
     779          97 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NumFields, NumAlphas, NumNumbers);
     780          97 :         MaxNumbers = max(MaxNumbers, NumNumbers);
     781          97 :         MaxAlphas = max(MaxAlphas, NumAlphas);
     782             : 
     783          97 :         Alphas.allocate(MaxAlphas);
     784          97 :         Numbers.dimension(MaxNumbers, 0.0);
     785          97 :         cAlphaFields.allocate(MaxAlphas);
     786          97 :         cNumericFields.allocate(MaxNumbers);
     787          97 :         lAlphaBlanks.dimension(MaxAlphas, true);
     788          97 :         lNumericBlanks.dimension(MaxNumbers, true);
     789             : 
     790          97 :         state.dataFurnaces->NumFurnaces = NumHeatOnly + NumHeatCool + NumUnitaryHeatOnly + NumUnitaryHeatCool + NumHeatPump + NumWaterToAirHeatPump;
     791             : 
     792          97 :         if (state.dataFurnaces->NumFurnaces > 0) {
     793          97 :             state.dataFurnaces->Furnace.allocate(state.dataFurnaces->NumFurnaces);
     794          97 :             state.dataFurnaces->UniqueFurnaceNames.reserve(state.dataFurnaces->NumFurnaces);
     795             :         }
     796          97 :         state.dataFurnaces->CheckEquipName.dimension(state.dataFurnaces->NumFurnaces, true);
     797             : 
     798          97 :         int IHPCoilIndex = 0;
     799             : 
     800             :         // Get the data for the HeatOnly Furnace
     801         101 :         for (int HeatOnlyNum = 1; HeatOnlyNum <= NumHeatOnly + NumUnitaryHeatOnly; ++HeatOnlyNum) {
     802             : 
     803           4 :             FanInletNode = 0;
     804           4 :             FanOutletNode = 0;
     805           4 :             HeatingCoilInletNode = 0;
     806           4 :             HeatingCoilOutletNode = 0;
     807           4 :             CoolingCoilType = ' ';
     808           4 :             CoolingCoilName = ' ';
     809           4 :             HeatingCoilType = ' ';
     810           4 :             HeatingCoilName = ' ';
     811             : 
     812           4 :             FurnaceNum = HeatOnlyNum;
     813           4 :             auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
     814             : 
     815             :             //       Furnace and UnitarySystem objects are both read in here.
     816             :             //       Will still have 2 differently named objects for the user, but read in with 1 DO loop.
     817           4 :             if (HeatOnlyNum <= NumHeatOnly) {
     818           3 :                 CurrentModuleObject = "AirLoopHVAC:Unitary:Furnace:HeatOnly";
     819           3 :                 currentModuleObjectType = DataLoopNode::ConnectionObjectType::AirLoopHVACUnitaryFurnaceHeatOnly;
     820           3 :                 thisFurnace.type = HVAC::UnitarySysType::Furnace_HeatOnly;
     821           3 :                 GetObjectNum = HeatOnlyNum;
     822             :             } else {
     823           1 :                 CurrentModuleObject = "AirLoopHVAC:UnitaryHeatOnly";
     824           1 :                 currentModuleObjectType = DataLoopNode::ConnectionObjectType::AirLoopHVACUnitaryHeatOnly;
     825           1 :                 thisFurnace.type = HVAC::UnitarySysType::Unitary_HeatOnly;
     826           1 :                 GetObjectNum = HeatOnlyNum - NumHeatOnly;
     827             :             }
     828             : 
     829           4 :             thisFurnace.iterationMode.allocate(3);
     830             : 
     831           4 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     832             :                                                                      CurrentModuleObject,
     833             :                                                                      GetObjectNum,
     834             :                                                                      Alphas,
     835             :                                                                      NumAlphas,
     836             :                                                                      Numbers,
     837             :                                                                      NumNumbers,
     838             :                                                                      IOStatus,
     839             :                                                                      lNumericBlanks,
     840             :                                                                      lAlphaBlanks,
     841             :                                                                      cAlphaFields,
     842             :                                                                      cNumericFields);
     843             : 
     844           8 :             GlobalNames::VerifyUniqueInterObjectName(
     845           4 :                 state, state.dataFurnaces->UniqueFurnaceNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
     846             : 
     847           4 :             thisFurnace.Name = Alphas(1);
     848           4 :             ErrorObjectHeader eoh{routineName, cAlphaFields(1), thisFurnace.Name};
     849             : 
     850           4 :             if (lAlphaBlanks(2)) {
     851           0 :                 thisFurnace.SchedPtr = ScheduleManager::ScheduleAlwaysOn;
     852             :             } else {
     853           4 :                 thisFurnace.SchedPtr = ScheduleManager::GetScheduleIndex(state, Alphas(2));
     854           4 :                 if (thisFurnace.SchedPtr == 0) {
     855           0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
     856           0 :                     ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(2), Alphas(2)));
     857           0 :                     ErrorsFound = true;
     858             :                 }
     859             :             }
     860             : 
     861           4 :             thisFurnace.FurnaceInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
     862           4 :                                                                                   Alphas(3),
     863             :                                                                                   ErrorsFound,
     864             :                                                                                   currentModuleObjectType,
     865           4 :                                                                                   Alphas(1),
     866             :                                                                                   DataLoopNode::NodeFluidType::Air,
     867             :                                                                                   DataLoopNode::ConnectionType::Inlet,
     868             :                                                                                   NodeInputManager::CompFluidStream::Primary,
     869             :                                                                                   DataLoopNode::ObjectIsParent);
     870           4 :             thisFurnace.FurnaceOutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
     871           4 :                                                                                    Alphas(4),
     872             :                                                                                    ErrorsFound,
     873             :                                                                                    currentModuleObjectType,
     874           4 :                                                                                    Alphas(1),
     875             :                                                                                    DataLoopNode::NodeFluidType::Air,
     876             :                                                                                    DataLoopNode::ConnectionType::Outlet,
     877             :                                                                                    NodeInputManager::CompFluidStream::Primary,
     878             :                                                                                    DataLoopNode::ObjectIsParent);
     879             : 
     880           4 :             BranchNodeConnections::TestCompSet(state, CurrentModuleObject, Alphas(1), Alphas(3), Alphas(4), "Air Nodes");
     881             : 
     882           4 :             thisFurnace.FanSchedPtr = ScheduleManager::GetScheduleIndex(state, Alphas(5));
     883           4 :             if (!lAlphaBlanks(5) && thisFurnace.FanSchedPtr == 0) {
     884           0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
     885           0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(5), Alphas(5)));
     886           0 :                 ErrorsFound = true;
     887           4 :             } else if (lAlphaBlanks(5)) {
     888           0 :                 thisFurnace.fanOp = HVAC::FanOp::Cycling;
     889             :             }
     890             : 
     891             :             // Get the Controlling Zone or Location of the Furnace Thermostat
     892             : 
     893           4 :             thisFurnace.ControlZoneNum = Util::FindItemInList(Alphas(6), state.dataHeatBal->Zone);
     894           4 :             if (thisFurnace.ControlZoneNum == 0) {
     895           0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
     896           0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(6), Alphas(6)));
     897           0 :                 ErrorsFound = true;
     898             :             }
     899             : 
     900             :             // Get the node number for the zone with the thermostat
     901           4 :             if (thisFurnace.ControlZoneNum > 0) {
     902           4 :                 AirNodeFound = false;
     903           4 :                 AirLoopFound = false;
     904           4 :                 int ControlledZoneNum = thisFurnace.ControlZoneNum;
     905             :                 //             Find the controlled zone number for the specified thermostat location
     906           4 :                 thisFurnace.NodeNumOfControlledZone = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).ZoneNode;
     907             :                 //             Determine if furnace is on air loop served by the thermostat location specified
     908           4 :                 for (int zoneInNode = 1; zoneInNode <= state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).NumInletNodes; ++zoneInNode) {
     909           4 :                     int AirLoopNumber = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).InletNodeAirLoopNum(zoneInNode);
     910           4 :                     if (AirLoopNumber > 0) {
     911           4 :                         for (int BranchNum = 1; BranchNum <= state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).NumBranches; ++BranchNum) {
     912           4 :                             for (int CompNum = 1;
     913           4 :                                  CompNum <= state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).Branch(BranchNum).TotalComponents;
     914             :                                  ++CompNum) {
     915           4 :                                 if (!Util::SameString(state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).Branch(BranchNum).Comp(CompNum).Name,
     916           8 :                                                       thisFurnace.Name) ||
     917           4 :                                     !Util::SameString(
     918           4 :                                         state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).Branch(BranchNum).Comp(CompNum).TypeOf,
     919             :                                         CurrentModuleObject))
     920           0 :                                     continue;
     921           4 :                                 AirLoopFound = true;
     922           4 :                                 thisFurnace.ZoneInletNode = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).InletNode(zoneInNode);
     923           4 :                                 break;
     924             :                             }
     925           4 :                             if (AirLoopFound) break;
     926             :                         }
     927          10 :                         for (TstatZoneNum = 1; TstatZoneNum <= state.dataZoneCtrls->NumTempControlledZones; ++TstatZoneNum) {
     928           6 :                             if (state.dataZoneCtrls->TempControlledZone(TstatZoneNum).ActualZoneNum != thisFurnace.ControlZoneNum) continue;
     929           4 :                             AirNodeFound = true;
     930             :                         }
     931           4 :                         for (TstatZoneNum = 1; TstatZoneNum <= state.dataZoneCtrls->NumComfortControlledZones; ++TstatZoneNum) {
     932           0 :                             if (state.dataZoneCtrls->ComfortControlledZone(TstatZoneNum).ActualZoneNum != thisFurnace.ControlZoneNum) continue;
     933           0 :                             AirNodeFound = true;
     934             :                         }
     935             :                     }
     936           4 :                     if (AirLoopFound) break;
     937             :                 }
     938           4 :                 if (!AirNodeFound) {
     939           0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
     940           0 :                     ShowContinueError(state, "Did not find Air Node (Zone with Thermostat).");
     941           0 :                     ShowContinueError(state, format("Specified {} = {}", cAlphaFields(6), Alphas(6)));
     942           0 :                     ShowContinueError(
     943             :                         state, "Both a ZoneHVAC:EquipmentConnections object and a ZoneControl:Thermostat object must be specified for this zone.");
     944           0 :                     ErrorsFound = true;
     945             :                 }
     946           4 :                 if (!AirLoopFound) {
     947           0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
     948           0 :                     ShowContinueError(state, "Did not find correct Primary Air Loop.");
     949           0 :                     ShowContinueError(state, format("Specified {} = {} is not served by this AirLoopHVAC equipment.", cAlphaFields(6), Alphas(6)));
     950           0 :                     ErrorsFound = true;
     951             :                 }
     952             :             }
     953             : 
     954             :             // Get fan data
     955           4 :             FanName = Alphas(8);
     956           4 :             errFlag = false;
     957             : 
     958           4 :             thisFurnace.fanType = static_cast<HVAC::FanType>(getEnumValue(HVAC::fanTypeNamesUC, Alphas(7)));
     959           4 :             if (thisFurnace.fanType != HVAC::FanType::OnOff && thisFurnace.fanType != HVAC::FanType::Constant) {
     960           0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
     961           0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(7), Alphas(7)));
     962           0 :                 ErrorsFound = true;
     963             : 
     964           4 :             } else if ((thisFurnace.FanIndex = Fans::GetFanIndex(state, FanName)) == 0) {
     965           0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(8), FanName);
     966           0 :                 ErrorsFound = true;
     967             : 
     968             :             } else {
     969           4 :                 auto *fan = state.dataFans->fans(thisFurnace.FanIndex);
     970           4 :                 thisFurnace.ActualFanVolFlowRate = fan->maxAirFlowRate;
     971           4 :                 FanInletNode = fan->inletNodeNum;
     972           4 :                 FanOutletNode = fan->outletNodeNum;
     973           4 :                 thisFurnace.FanAvailSchedPtr = fan->availSchedNum;
     974             : 
     975             :                 // Check fan's schedule for cycling fan operation if constant volume fan is used
     976           4 :                 if (thisFurnace.FanSchedPtr > 0 && thisFurnace.fanType == HVAC::FanType::Constant) {
     977           0 :                     if (!ScheduleManager::CheckScheduleValueMinMax(
     978             :                             state, thisFurnace.FanSchedPtr, ScheduleManager::Clusivity::Exclusive, 0.0, ScheduleManager::Clusivity::Inclusive, 1.0)) {
     979           0 :                         ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
     980           0 :                         ShowContinueError(state, format("For {} = {}", cAlphaFields(7), Alphas(7)));
     981           0 :                         ShowContinueError(state, "Fan operating mode must be continuous (fan operating mode schedule values > 0).");
     982           0 :                         ShowContinueError(state, format("Error found in {} = {}", cAlphaFields(5), Alphas(5)));
     983           0 :                         ShowContinueError(state, "...schedule values must be (>0., <=1.)");
     984           0 :                         ErrorsFound = true;
     985             :                     }
     986           4 :                 } else if (lAlphaBlanks(5) && thisFurnace.fanType != HVAC::FanType::OnOff) {
     987           0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, thisFurnace.Name));
     988           0 :                     ShowContinueError(state, format("{} = {}", cAlphaFields(7), Alphas(7)));
     989           0 :                     ShowContinueError(state, format("Fan type must be Fan:OnOff when {} = Blank.", cAlphaFields(5)));
     990           0 :                     ErrorsFound = true;
     991             :                 }
     992             :             }
     993             : 
     994           4 :             thisFurnace.fanPlace = static_cast<HVAC::FanPlace>(getEnumValue(HVAC::fanPlaceNamesUC, Alphas(9)));
     995           4 :             assert(thisFurnace.fanPlace != HVAC::FanPlace::Invalid);
     996             : 
     997             :             // Get coil data
     998           4 :             HeatingCoilType = Alphas(10);
     999           4 :             HeatingCoilName = Alphas(11);
    1000           4 :             thisFurnace.HeatingCoilType = HeatingCoilType;
    1001           4 :             thisFurnace.HeatingCoilName = HeatingCoilName;
    1002           4 :             if (Util::SameString(HeatingCoilType, "Coil:Heating:Fuel") || Util::SameString(HeatingCoilType, "Coil:Heating:Electric")) {
    1003           4 :                 errFlag = false;
    1004           4 :                 thisFurnace.HeatingCoilType_Num = HeatingCoils::GetHeatingCoilTypeNum(state, HeatingCoilType, HeatingCoilName, errFlag);
    1005           4 :                 if (errFlag) {
    1006           0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1007           0 :                     ErrorsFound = true;
    1008             :                 } else {
    1009           4 :                     ValidateComponent(state, HeatingCoilType, HeatingCoilName, IsNotOK, CurrentModuleObject);
    1010           4 :                     if (IsNotOK) {
    1011           0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1012           0 :                         ErrorsFound = true;
    1013             : 
    1014             :                     } else { // mine data from heating coil object
    1015             : 
    1016             :                         // Get index to Heating Coil
    1017           4 :                         errFlag = false;
    1018           4 :                         HeatingCoils::GetCoilIndex(state, HeatingCoilName, thisFurnace.HeatingCoilIndex, errFlag);
    1019           4 :                         if (errFlag) {
    1020           0 :                             ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1021           0 :                             ErrorsFound = true;
    1022             :                         }
    1023             : 
    1024             :                         // Get the furnace design capacity
    1025           4 :                         errFlag = false;
    1026           4 :                         thisFurnace.DesignHeatingCapacity = HeatingCoils::GetCoilCapacity(state, HeatingCoilType, HeatingCoilName, errFlag);
    1027           4 :                         if (errFlag) {
    1028           0 :                             ShowContinueError(state, format("...occurs in {} ={}", CurrentModuleObject, Alphas(1)));
    1029           0 :                             ErrorsFound = true;
    1030             :                         }
    1031             : 
    1032             :                         // Get the Heating Coil Inlet Node
    1033           4 :                         errFlag = false;
    1034           4 :                         HeatingCoilInletNode = HeatingCoils::GetCoilInletNode(state, HeatingCoilType, HeatingCoilName, errFlag);
    1035           4 :                         thisFurnace.HWCoilAirInletNode = HeatingCoilInletNode;
    1036           4 :                         if (errFlag) {
    1037           0 :                             ShowContinueError(state, format("...occurs in {} ={}", CurrentModuleObject, Alphas(1)));
    1038           0 :                             ErrorsFound = true;
    1039             :                         }
    1040             : 
    1041             :                         // Get the Heating Coil Outlet Node
    1042           4 :                         errFlag = false;
    1043           4 :                         HeatingCoilOutletNode = HeatingCoils::GetCoilOutletNode(state, HeatingCoilType, HeatingCoilName, errFlag);
    1044           4 :                         if (errFlag) {
    1045           0 :                             ShowContinueError(state, format("...occurs in {} ={}", CurrentModuleObject, Alphas(1)));
    1046           0 :                             ErrorsFound = true;
    1047             :                         }
    1048             : 
    1049             :                     } // IF (IsNotOK) THEN
    1050             :                 }
    1051             : 
    1052           0 :             } else if (Util::SameString(HeatingCoilType, "Coil:Heating:Water")) {
    1053           0 :                 thisFurnace.HeatingCoilType_Num = HVAC::Coil_HeatingWater;
    1054           0 :                 ValidateComponent(state, HeatingCoilType, HeatingCoilName, IsNotOK, CurrentModuleObject);
    1055           0 :                 if (IsNotOK) {
    1056           0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1057           0 :                     ErrorsFound = true;
    1058             :                 } else { // mine data from heating coil object
    1059             : 
    1060             :                     // Get the Heating Coil water Inlet or control Node number
    1061           0 :                     errFlag = false;
    1062           0 :                     thisFurnace.CoilControlNode = WaterCoils::GetCoilWaterInletNode(state, "Coil:Heating:Water", HeatingCoilName, errFlag);
    1063           0 :                     if (errFlag) {
    1064           0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1065           0 :                         ErrorsFound = true;
    1066             :                     }
    1067             : 
    1068             :                     // Get the Heating Coil hot water max volume flow rate
    1069           0 :                     errFlag = false;
    1070           0 :                     thisFurnace.MaxHeatCoilFluidFlow = WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", HeatingCoilName, errFlag);
    1071           0 :                     if (errFlag) {
    1072           0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1073           0 :                         ErrorsFound = true;
    1074             :                     }
    1075             : 
    1076             :                     // Get the Heating Coil Inlet Node
    1077           0 :                     errFlag = false;
    1078           0 :                     HeatingCoilInletNode = WaterCoils::GetCoilInletNode(state, "Coil:Heating:Water", HeatingCoilName, errFlag);
    1079           0 :                     thisFurnace.HWCoilAirInletNode = HeatingCoilInletNode;
    1080           0 :                     if (errFlag) {
    1081           0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1082           0 :                         ErrorsFound = true;
    1083             :                     }
    1084             : 
    1085             :                     // Get the Heating Coil Outlet Node
    1086           0 :                     errFlag = false;
    1087           0 :                     HeatingCoilOutletNode = WaterCoils::GetCoilOutletNode(state, "Coil:Heating:Water", HeatingCoilName, errFlag);
    1088           0 :                     thisFurnace.HWCoilAirOutletNode = HeatingCoilOutletNode;
    1089           0 :                     if (errFlag) {
    1090           0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1091           0 :                         ErrorsFound = true;
    1092             :                     }
    1093             : 
    1094             :                     // check if user has also used a water coil controller, which they should not do
    1095           0 :                     errFlag = false;
    1096           0 :                     HVACControllers::CheckCoilWaterInletNode(state, thisFurnace.CoilControlNode, errFlag);
    1097           0 :                     if (!errFlag) { // then did find a controller so that is bad
    1098           0 :                         ShowSevereError(state,
    1099           0 :                                         format("{} = {} has a conflicting Controller:WaterCoil object", CurrentModuleObject, thisFurnace.Name));
    1100           0 :                         ShowContinueError(state, "Hot water coils are controlled directly by unitary and furnace systems.");
    1101           0 :                         ShowContinueError(state, "No water coil controller should be input for the coil.");
    1102           0 :                         ErrorsFound = true;
    1103             :                     }
    1104             :                 }
    1105             : 
    1106           0 :             } else if (Util::SameString(HeatingCoilType, "Coil:Heating:Steam")) {
    1107           0 :                 thisFurnace.HeatingCoilType_Num = HVAC::Coil_HeatingSteam;
    1108           0 :                 ValidateComponent(state, HeatingCoilType, HeatingCoilName, IsNotOK, CurrentModuleObject);
    1109           0 :                 if (IsNotOK) {
    1110           0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1111           0 :                     ErrorsFound = true;
    1112             :                 } else { // mine data from heating coil object
    1113             : 
    1114           0 :                     errFlag = false;
    1115           0 :                     thisFurnace.HeatingCoilIndex = SteamCoils::GetSteamCoilIndex(state, "COIL:HEATING:STEAM", HeatingCoilName, errFlag);
    1116           0 :                     if (thisFurnace.HeatingCoilIndex == 0) {
    1117           0 :                         ShowSevereError(state, format("{} illegal {} = {}", CurrentModuleObject, cAlphaFields(11), HeatingCoilName));
    1118           0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1119           0 :                         ErrorsFound = true;
    1120             :                     }
    1121             : 
    1122             :                     // Get the Heating Coil steam inlet node number
    1123           0 :                     errFlag = false;
    1124           0 :                     thisFurnace.CoilControlNode = SteamCoils::GetCoilSteamInletNode(state, "COIL:HEATING:STEAM", HeatingCoilName, errFlag);
    1125           0 :                     if (errFlag) {
    1126           0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1127           0 :                         ErrorsFound = true;
    1128             :                     }
    1129             : 
    1130             :                     // Get the Heating Coil steam max volume flow rate
    1131           0 :                     thisFurnace.MaxHeatCoilFluidFlow = SteamCoils::GetCoilMaxSteamFlowRate(state, thisFurnace.HeatingCoilIndex, errFlag);
    1132           0 :                     if (thisFurnace.MaxHeatCoilFluidFlow > 0.0) {
    1133           0 :                         SteamIndex = 0; // Function GetSatDensityRefrig will look up steam index if 0 is passed
    1134           0 :                         SteamDensity = FluidProperties::GetSatDensityRefrig(
    1135           0 :                             state, fluidNameSteam, state.dataFurnaces->TempSteamIn, 1.0, SteamIndex, getUnitaryHeatOnly);
    1136           0 :                         thisFurnace.MaxHeatCoilFluidFlow *= SteamDensity;
    1137             :                     }
    1138             : 
    1139             :                     // Get the Heating Coil Inlet Node
    1140           0 :                     errFlag = false;
    1141           0 :                     HeatingCoilInletNode = SteamCoils::GetCoilAirInletNode(state, thisFurnace.HeatingCoilIndex, HeatingCoilName, errFlag);
    1142           0 :                     thisFurnace.HWCoilAirInletNode = HeatingCoilInletNode;
    1143           0 :                     if (errFlag) {
    1144           0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1145           0 :                         ErrorsFound = true;
    1146             :                     }
    1147             : 
    1148             :                     // Get the Heating Coil Outlet Node
    1149           0 :                     errFlag = false;
    1150           0 :                     HeatingCoilOutletNode = SteamCoils::GetCoilAirOutletNode(state, thisFurnace.HeatingCoilIndex, HeatingCoilName, errFlag);
    1151           0 :                     thisFurnace.HWCoilAirOutletNode = HeatingCoilOutletNode;
    1152           0 :                     if (errFlag) {
    1153           0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1154           0 :                         ErrorsFound = true;
    1155             :                     }
    1156             :                 }
    1157             : 
    1158             :             } else {
    1159           0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1160           0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(11), Alphas(11)));
    1161           0 :                 ErrorsFound = true;
    1162             :             } // IF (Furnace(FurnaceNum)%HeatingCoilType_Num == Coil_HeatingGasOrOtherFuel .OR. &, etc.
    1163             : 
    1164             :             // Add component sets array
    1165           4 :             if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
    1166           4 :                 CompSetFanInlet = Alphas(3);
    1167           4 :                 CompSetFanOutlet = state.dataLoopNodes->NodeID(FanOutletNode);
    1168           4 :                 CompSetHeatInlet = state.dataLoopNodes->NodeID(FanOutletNode);
    1169           4 :                 CompSetHeatOutlet = Alphas(4);
    1170             :                 // Fan inlet node name must not be the same as the furnace inlet node name
    1171           4 :                 if (FanInletNode != thisFurnace.FurnaceInletNodeNum) {
    1172           0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1173           0 :                     if (thisFurnace.type == HVAC::UnitarySysType::Furnace_HeatOnly) {
    1174           0 :                         ShowContinueError(
    1175             :                             state, "When a blow through fan is specified, the fan inlet node name must be the same as the furnace inlet node name.");
    1176           0 :                         ShowContinueError(state, format("...Fan inlet node name     = {}", state.dataLoopNodes->NodeID(FanInletNode)));
    1177           0 :                         ShowContinueError(state,
    1178           0 :                                           format("...Furnace inlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceInletNodeNum)));
    1179             :                     } else {
    1180           0 :                         ShowContinueError(
    1181             :                             state,
    1182             :                             "When a blow through fan is specified, the fan inlet node name must be the same as the unitary system inlet node name.");
    1183           0 :                         ShowContinueError(state, format("...Fan inlet node name            = {}", state.dataLoopNodes->NodeID(FanInletNode)));
    1184           0 :                         ShowContinueError(
    1185           0 :                             state, format("...Unitary System inlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceInletNodeNum)));
    1186             :                     }
    1187           0 :                     ErrorsFound = true;
    1188             :                 }
    1189             :                 // Fan outlet node name must be the same as the heating coil inlet node name
    1190           4 :                 if (FanOutletNode != HeatingCoilInletNode) {
    1191           0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1192           0 :                     ShowContinueError(
    1193             :                         state,
    1194             :                         "When a blow through fan is specified, the fan outlet node name must be the same as the heating coil inlet node name.");
    1195           0 :                     ShowContinueError(state, format("...Fan outlet node name         = {}", state.dataLoopNodes->NodeID(FanOutletNode)));
    1196           0 :                     ShowContinueError(state, format("...Heating coil inlet node name = {}", state.dataLoopNodes->NodeID(HeatingCoilInletNode)));
    1197           0 :                     ErrorsFound = true;
    1198             :                 }
    1199             :                 // Heating coil outlet node name must be the same as the furnace outlet node name
    1200           4 :                 if (HeatingCoilOutletNode != thisFurnace.FurnaceOutletNodeNum) {
    1201           0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1202           0 :                     if (thisFurnace.type == HVAC::UnitarySysType::Furnace_HeatOnly) {
    1203           0 :                         ShowContinueError(state,
    1204             :                                           "When a blow through fan is specified, the heating coil outlet node name must be the same as the furnace "
    1205             :                                           "outlet node name.");
    1206           0 :                         ShowContinueError(state, format("...Heating coil outlet node name = {}", state.dataLoopNodes->NodeID(HeatingCoilOutletNode)));
    1207           0 :                         ShowContinueError(
    1208           0 :                             state, format("...Furnace outlet node name      = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    1209             :                     } else {
    1210           0 :                         ShowContinueError(state,
    1211             :                                           "When a blow through fan is specified, the heating coil outlet node name must be the same as the unitary "
    1212             :                                           "system outlet node name.");
    1213           0 :                         ShowContinueError(state,
    1214           0 :                                           format("...Heating coil outlet node name  = {}", state.dataLoopNodes->NodeID(HeatingCoilOutletNode)));
    1215           0 :                         ShowContinueError(
    1216           0 :                             state, format("...UnitarySystem outlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    1217             :                     }
    1218           0 :                     ErrorsFound = true;
    1219             :                 }
    1220             :             } else { // draw through fan
    1221           0 :                 CompSetHeatInlet = Alphas(3);
    1222           0 :                 CompSetHeatOutlet = state.dataLoopNodes->NodeID(FanInletNode);
    1223           0 :                 CompSetFanInlet = state.dataLoopNodes->NodeID(FanInletNode);
    1224           0 :                 CompSetFanOutlet = Alphas(4);
    1225             :                 // Heating coil inlet node name must not be the same as the furnace inlet node name
    1226           0 :                 if (HeatingCoilInletNode != thisFurnace.FurnaceInletNodeNum) {
    1227           0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1228           0 :                     if (thisFurnace.type == HVAC::UnitarySysType::Furnace_HeatOnly) {
    1229           0 :                         ShowContinueError(state,
    1230             :                                           "When a draw through fan is specified, the heating coil inlet node name must be the same as the furnace "
    1231             :                                           "inlet node name.");
    1232           0 :                         ShowContinueError(state, format("...Heating coil inlet node name = {}", state.dataLoopNodes->NodeID(HeatingCoilInletNode)));
    1233           0 :                         ShowContinueError(
    1234           0 :                             state, format("...Furnace inlet node name      = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceInletNodeNum)));
    1235             :                     } else {
    1236           0 :                         ShowContinueError(state,
    1237             :                                           "When a draw through fan is specified, the heating coil inlet node name must be the same as the unitary "
    1238             :                                           "system inlet node name.");
    1239           0 :                         ShowContinueError(state, format("...Heating coil inlet node name  = {}", state.dataLoopNodes->NodeID(HeatingCoilInletNode)));
    1240           0 :                         ShowContinueError(
    1241           0 :                             state, format("...UnitarySystem inlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceInletNodeNum)));
    1242             :                     }
    1243           0 :                     ErrorsFound = true;
    1244             :                 }
    1245             :                 // Heating coil outlet node name must be the same as the fan inlet node name
    1246           0 :                 if (HeatingCoilOutletNode != FanInletNode) {
    1247           0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1248           0 :                     ShowContinueError(
    1249             :                         state,
    1250             :                         "When a draw through fan is specified, the heating coil outlet node name must be the same as the fan inlet node name.");
    1251           0 :                     ShowContinueError(state, format("...Heating coil outlet node name = {}", state.dataLoopNodes->NodeID(HeatingCoilOutletNode)));
    1252           0 :                     ShowContinueError(state, format("...Fan inlet node name           = {}", state.dataLoopNodes->NodeID(FanInletNode)));
    1253           0 :                     ErrorsFound = true;
    1254             :                 }
    1255             :                 // Fan coil outlet node name must be the same as the furnace outlet node name
    1256           0 :                 if (FanOutletNode != thisFurnace.FurnaceOutletNodeNum) {
    1257           0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1258           0 :                     if (thisFurnace.type == HVAC::UnitarySysType::Furnace_HeatOnly) {
    1259           0 :                         ShowContinueError(
    1260             :                             state,
    1261             :                             "When a draw through fan is specified, the fan outlet node name must be the same as the furnace outlet node name.");
    1262           0 :                         ShowContinueError(state, format("...Fan outlet node name     = {}", state.dataLoopNodes->NodeID(FanOutletNode)));
    1263           0 :                         ShowContinueError(state,
    1264           0 :                                           format("...Furnace outlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    1265             :                     } else {
    1266           0 :                         ShowContinueError(state,
    1267             :                                           "When a draw through fan is specified, the fan outlet node name must be the same as the unitary system "
    1268             :                                           "outlet node name.");
    1269           0 :                         ShowContinueError(state, format("...Fan outlet node name           = {}", state.dataLoopNodes->NodeID(FanOutletNode)));
    1270           0 :                         ShowContinueError(
    1271           0 :                             state, format("...UnitarySystem outlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    1272             :                     }
    1273           0 :                     ErrorsFound = true;
    1274             :                 }
    1275             :             }
    1276             : 
    1277             :             // Add fan to component sets array
    1278           8 :             BranchNodeConnections::SetUpCompSets(
    1279           4 :                 state, CurrentModuleObject, thisFurnace.Name, Alphas(7), Alphas(8), CompSetFanInlet, CompSetFanOutlet);
    1280             :             // Add heating coil to component sets array
    1281           8 :             BranchNodeConnections::SetUpCompSets(
    1282           4 :                 state, CurrentModuleObject, thisFurnace.Name, Alphas(10), Alphas(11), CompSetHeatInlet, CompSetHeatOutlet);
    1283             : 
    1284             :             // Set the furnace max outlet temperature
    1285           4 :             thisFurnace.DesignMaxOutletTemp = Numbers(1);
    1286             : 
    1287             :             // Set the furnace design fan volumetric flow rate
    1288           4 :             thisFurnace.DesignFanVolFlowRate = Numbers(2);
    1289             : 
    1290             :             // Compare the flow rates.
    1291           4 :             if (thisFurnace.ActualFanVolFlowRate != DataSizing::AutoSize && thisFurnace.DesignFanVolFlowRate != DataSizing::AutoSize) {
    1292           4 :                 if (thisFurnace.DesignFanVolFlowRate > thisFurnace.ActualFanVolFlowRate) {
    1293           0 :                     ShowWarningError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1294           0 :                     ShowContinueError(
    1295           0 :                         state, format("... The {} > Max Volume Flow Rate defined in the associated fan object, should be <=.", cNumericFields(2)));
    1296           0 :                     ShowContinueError(state,
    1297           0 :                                       format("... Entered value = {:.4R}... Fan [{} = {}] Max Value = {:.4R}",
    1298           0 :                                              thisFurnace.DesignFanVolFlowRate,
    1299           0 :                                              HVAC::fanTypeNames[(int)thisFurnace.fanType],
    1300             :                                              FanName,
    1301           0 :                                              thisFurnace.ActualFanVolFlowRate));
    1302           0 :                     ShowContinueError(state, " The HVAC system  flow rate is reset to the fan flow rate and the simulation continues.");
    1303           0 :                     thisFurnace.DesignFanVolFlowRate = thisFurnace.ActualFanVolFlowRate;
    1304             :                 }
    1305             :             }
    1306           4 :             if (thisFurnace.DesignFanVolFlowRate != DataSizing::AutoSize) {
    1307           4 :                 if (thisFurnace.DesignFanVolFlowRate <= 0.0) {
    1308           0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1309           0 :                     ShowContinueError(state, format("... The {} <= 0.0, it must be > 0.0.", cNumericFields(2)));
    1310           0 :                     ShowContinueError(state, format("... Entered value = {:.2R}", thisFurnace.DesignFanVolFlowRate));
    1311           0 :                     ErrorsFound = true;
    1312             :                 }
    1313             :             }
    1314             : 
    1315             :             //       HeatOnly furnace has only 1 flow rate, initialize other variables used in this module
    1316           4 :             thisFurnace.MaxHeatAirVolFlow = thisFurnace.DesignFanVolFlowRate;
    1317           4 :             thisFurnace.MaxCoolAirVolFlow = thisFurnace.DesignFanVolFlowRate;
    1318           4 :             thisFurnace.MaxNoCoolHeatAirVolFlow = thisFurnace.DesignFanVolFlowRate;
    1319           4 :             thisFurnace.AirFlowControl = AirFlowControlConstFan::UseCompressorOnFlow;
    1320             : 
    1321             :             // Set heating convergence tolerance
    1322           4 :             thisFurnace.HeatingConvergenceTolerance = 0.001;
    1323             : 
    1324             :             // set minimum outdoor temperature for compressor operation
    1325           4 :             SetMinOATCompressor(state, FurnaceNum, cCurrentModuleObject, ErrorsFound);
    1326             : 
    1327             :         } // End of the HeatOnly Furnace Loop
    1328             : 
    1329             :         // Get the data for the HeatCool Furnace or UnitarySystem
    1330         278 :         for (int HeatCoolNum = 1; HeatCoolNum <= NumHeatCool + NumUnitaryHeatCool; ++HeatCoolNum) {
    1331             : 
    1332         181 :             FanInletNode = 0;
    1333         181 :             FanOutletNode = 0;
    1334         181 :             CoolingCoilInletNode = 0;
    1335         181 :             CoolingCoilOutletNode = 0;
    1336         181 :             HeatingCoilInletNode = 0;
    1337         181 :             HeatingCoilOutletNode = 0;
    1338         181 :             int ReheatCoilInletNode = 0;
    1339         181 :             int ReheatCoilOutletNode = 0;
    1340         181 :             CoolingCoilType = ' ';
    1341         181 :             CoolingCoilName = ' ';
    1342         181 :             HeatingCoilType = ' ';
    1343         181 :             HeatingCoilName = ' ';
    1344             : 
    1345         181 :             FurnaceNum = HeatCoolNum + NumHeatOnly + NumUnitaryHeatOnly;
    1346         181 :             auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    1347             : 
    1348             :             //      Furnace and UnitarySystem objects are both read in here.
    1349             :             //      Will still have 2 differently named objects for the user, but read in with 1 DO loop.
    1350         181 :             if (HeatCoolNum <= NumHeatCool) {
    1351         108 :                 CurrentModuleObject = "AirLoopHVAC:Unitary:Furnace:HeatCool";
    1352         108 :                 currentModuleObjectType = DataLoopNode::ConnectionObjectType::AirLoopHVACUnitaryFurnaceHeatCool;
    1353         108 :                 thisFurnace.type = HVAC::UnitarySysType::Furnace_HeatCool;
    1354         108 :                 GetObjectNum = HeatCoolNum;
    1355             :             } else {
    1356          73 :                 CurrentModuleObject = "AirLoopHVAC:UnitaryHeatCool";
    1357          73 :                 currentModuleObjectType = DataLoopNode::ConnectionObjectType::AirLoopHVACUnitaryHeatCool;
    1358          73 :                 thisFurnace.type = HVAC::UnitarySysType::Unitary_HeatCool;
    1359          73 :                 GetObjectNum = HeatCoolNum - NumHeatCool;
    1360             :             }
    1361             : 
    1362         181 :             thisFurnace.iterationMode.allocate(3);
    1363             : 
    1364         181 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1365             :                                                                      CurrentModuleObject,
    1366             :                                                                      GetObjectNum,
    1367             :                                                                      Alphas,
    1368             :                                                                      NumAlphas,
    1369             :                                                                      Numbers,
    1370             :                                                                      NumNumbers,
    1371             :                                                                      IOStatus,
    1372             :                                                                      lNumericBlanks,
    1373             :                                                                      lAlphaBlanks,
    1374             :                                                                      cAlphaFields,
    1375             :                                                                      cNumericFields);
    1376             : 
    1377         362 :             GlobalNames::VerifyUniqueInterObjectName(
    1378         181 :                 state, state.dataFurnaces->UniqueFurnaceNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
    1379             : 
    1380         181 :             thisFurnace.Name = Alphas(1);
    1381             : 
    1382         181 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, thisFurnace.Name};
    1383             : 
    1384         181 :             if (lAlphaBlanks(2)) {
    1385          58 :                 thisFurnace.SchedPtr = ScheduleManager::ScheduleAlwaysOn;
    1386             :             } else {
    1387         123 :                 thisFurnace.SchedPtr = ScheduleManager::GetScheduleIndex(state, Alphas(2));
    1388         123 :                 if (thisFurnace.SchedPtr == 0) {
    1389           0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1390           0 :                     ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(2), Alphas(2)));
    1391           0 :                     ErrorsFound = true;
    1392             :                 }
    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         181 :             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 :             thisFurnace.FanSchedPtr = ScheduleManager::GetScheduleIndex(state, Alphas(5));
    1417         181 :             if (!lAlphaBlanks(5) && thisFurnace.FanSchedPtr == 0) {
    1418           0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1419           0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(5), Alphas(5)));
    1420           0 :                 ErrorsFound = true;
    1421         181 :             } else if (lAlphaBlanks(5)) {
    1422          20 :                 thisFurnace.fanOp = HVAC::FanOp::Cycling;
    1423             :             }
    1424             : 
    1425             :             // Get the Controlling Zone or Location of the Furnace Thermostat
    1426         181 :             thisFurnace.ControlZoneNum = Util::FindItemInList(Alphas(6), state.dataHeatBal->Zone);
    1427         181 :             if (thisFurnace.ControlZoneNum == 0) {
    1428           0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1429           0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(6), Alphas(6)));
    1430           0 :                 ErrorsFound = true;
    1431             :             }
    1432             : 
    1433             :             // Get the node number for the zone with the thermostat
    1434         181 :             if (thisFurnace.ControlZoneNum > 0) {
    1435         181 :                 AirNodeFound = false;
    1436         181 :                 AirLoopFound = false;
    1437         181 :                 int ControlledZoneNum = thisFurnace.ControlZoneNum;
    1438             :                 //             Find the controlled zone number for the specified thermostat location
    1439         181 :                 thisFurnace.NodeNumOfControlledZone = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).ZoneNode;
    1440             :                 //             Determine if system is on air loop served by the thermostat location specified
    1441         186 :                 for (int zoneInNode = 1; zoneInNode <= state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).NumInletNodes; ++zoneInNode) {
    1442         186 :                     int AirLoopNumber = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).InletNodeAirLoopNum(zoneInNode);
    1443         186 :                     if (AirLoopNumber > 0) {
    1444         191 :                         for (int BranchNum = 1; BranchNum <= state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).NumBranches; ++BranchNum) {
    1445         354 :                             for (int CompNum = 1;
    1446         354 :                                  CompNum <= state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).Branch(BranchNum).TotalComponents;
    1447             :                                  ++CompNum) {
    1448         349 :                                 if (!Util::SameString(state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).Branch(BranchNum).Comp(CompNum).Name,
    1449         879 :                                                       Alphas(1)) ||
    1450         181 :                                     !Util::SameString(
    1451         181 :                                         state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).Branch(BranchNum).Comp(CompNum).TypeOf,
    1452             :                                         CurrentModuleObject))
    1453         168 :                                     continue;
    1454         181 :                                 AirLoopFound = true;
    1455         181 :                                 thisFurnace.ZoneInletNode = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).InletNode(zoneInNode);
    1456         181 :                                 break;
    1457             :                             }
    1458         186 :                             if (AirLoopFound) break;
    1459             :                         }
    1460        2184 :                         for (TstatZoneNum = 1; TstatZoneNum <= state.dataZoneCtrls->NumTempControlledZones; ++TstatZoneNum) {
    1461        1998 :                             if (state.dataZoneCtrls->TempControlledZone(TstatZoneNum).ActualZoneNum != thisFurnace.ControlZoneNum) continue;
    1462         186 :                             AirNodeFound = true;
    1463             :                         }
    1464         187 :                         for (TstatZoneNum = 1; TstatZoneNum <= state.dataZoneCtrls->NumComfortControlledZones; ++TstatZoneNum) {
    1465           1 :                             if (state.dataZoneCtrls->ComfortControlledZone(TstatZoneNum).ActualZoneNum != thisFurnace.ControlZoneNum) continue;
    1466           1 :                             AirNodeFound = true;
    1467             :                         }
    1468             :                     }
    1469         186 :                     if (AirLoopFound) break;
    1470             :                 }
    1471         181 :                 if (!AirNodeFound) {
    1472           0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1473           0 :                     ShowContinueError(state, "Did not find air node (zone with thermostat).");
    1474           0 :                     ShowContinueError(state, format("Specified {} = {}", cAlphaFields(6), Alphas(6)));
    1475           0 :                     ShowContinueError(
    1476             :                         state, "Both a ZoneHVAC:EquipmentConnections object and a ZoneControl:Thermostat object must be specified for this zone.");
    1477           0 :                     ErrorsFound = true;
    1478             :                 }
    1479         181 :                 if (!AirLoopFound) {
    1480           0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1481           0 :                     ShowContinueError(state, "Did not find correct AirLoopHVAC.");
    1482           0 :                     ShowContinueError(state, format("Specified {} = {}", cAlphaFields(6), Alphas(6)));
    1483           0 :                     ErrorsFound = true;
    1484             :                 }
    1485             :             }
    1486             : 
    1487             :             // Get fan data
    1488         181 :             FanName = Alphas(8);
    1489             : 
    1490         181 :             thisFurnace.fanType = static_cast<HVAC::FanType>(getEnumValue(HVAC::fanTypeNamesUC, Alphas(7)));
    1491             : 
    1492         181 :             if (thisFurnace.fanType != HVAC::FanType::OnOff && thisFurnace.fanType != HVAC::FanType::Constant) {
    1493           0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1494           0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(7), Alphas(7)));
    1495           0 :                 ErrorsFound = true;
    1496             : 
    1497         181 :             } else if ((thisFurnace.FanIndex = Fans::GetFanIndex(state, FanName)) == 0) {
    1498           0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(8), FanName);
    1499           0 :                 ErrorsFound = true;
    1500             : 
    1501             :             } else {
    1502         181 :                 auto *fan = state.dataFans->fans(thisFurnace.FanIndex);
    1503         181 :                 thisFurnace.ActualFanVolFlowRate = fan->maxAirFlowRate;
    1504         181 :                 FanInletNode = fan->inletNodeNum;
    1505         181 :                 FanOutletNode = fan->outletNodeNum;
    1506         181 :                 thisFurnace.FanAvailSchedPtr = fan->availSchedNum;
    1507             : 
    1508             :                 // Check fan's schedule for cycling fan operation if constant volume fan is used
    1509         181 :                 if (thisFurnace.FanSchedPtr > 0 && thisFurnace.fanType == HVAC::FanType::Constant) {
    1510           5 :                     if (!ScheduleManager::CheckScheduleValueMinMax(
    1511             :                             state, thisFurnace.FanSchedPtr, ScheduleManager::Clusivity::Exclusive, 0.0, ScheduleManager::Clusivity::Inclusive, 1.0)) {
    1512           0 :                         ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1513           0 :                         ShowContinueError(state, format("For {} = {}", cAlphaFields(7), Alphas(7)));
    1514           0 :                         ShowContinueError(state, "Fan operating mode must be continuous (fan operating mode schedule values > 0).");
    1515           0 :                         ShowContinueError(state, format("Error found in {} = {}", cAlphaFields(5), Alphas(5)));
    1516           0 :                         ShowContinueError(state, "...schedule values must be (>0., <=1.)");
    1517           0 :                         ErrorsFound = true;
    1518             :                     }
    1519         176 :                 } else if (lAlphaBlanks(5) && thisFurnace.fanType != HVAC::FanType::OnOff) {
    1520           0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, thisFurnace.Name));
    1521           0 :                     ShowContinueError(state, format("{} = {}", cAlphaFields(7), Alphas(7)));
    1522           0 :                     ShowContinueError(state, format("Fan type must be Fan:OnOff when {} = Blank.", cAlphaFields(5)));
    1523           0 :                     ErrorsFound = true;
    1524             :                 }
    1525             :             }
    1526             : 
    1527         181 :             thisFurnace.fanPlace = static_cast<HVAC::FanPlace>(getEnumValue(HVAC::fanPlaceNamesUC, Alphas(9)));
    1528         181 :             assert(thisFurnace.fanPlace != HVAC::FanPlace::Invalid);
    1529             : 
    1530             :             // Get coil data
    1531         181 :             HeatingCoilType = Alphas(10);
    1532         181 :             HeatingCoilName = Alphas(11);
    1533         181 :             HeatingCoilPLFCurveIndex = 0;
    1534         181 :             thisFurnace.HeatingCoilType = HeatingCoilType;
    1535         181 :             thisFurnace.HeatingCoilName = HeatingCoilName;
    1536         181 :             if (Util::SameString(HeatingCoilType, "Coil:Heating:Fuel") || Util::SameString(HeatingCoilType, "Coil:Heating:Electric")) {
    1537         181 :                 errFlag = false;
    1538         181 :                 thisFurnace.HeatingCoilType_Num = HeatingCoils::GetHeatingCoilTypeNum(state, HeatingCoilType, HeatingCoilName, errFlag);
    1539         181 :                 if (errFlag) {
    1540           0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1541           0 :                     ErrorsFound = true;
    1542             :                 } else {
    1543             : 
    1544         181 :                     ValidateComponent(state, HeatingCoilType, HeatingCoilName, IsNotOK, CurrentModuleObject);
    1545         181 :                     if (IsNotOK) {
    1546           0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1547           0 :                         ErrorsFound = true;
    1548             : 
    1549             :                     } else { // mine data from heating coil
    1550             : 
    1551             :                         // Get heating coil index
    1552         181 :                         errFlag = false;
    1553         181 :                         HeatingCoils::GetCoilIndex(state, HeatingCoilName, thisFurnace.HeatingCoilIndex, errFlag);
    1554         181 :                         if (errFlag) {
    1555           0 :                             ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1556           0 :                             ErrorsFound = true;
    1557             :                         }
    1558             : 
    1559             :                         // Get the design heating capacity
    1560         181 :                         errFlag = false;
    1561         181 :                         thisFurnace.DesignHeatingCapacity = HeatingCoils::GetCoilCapacity(state, HeatingCoilType, HeatingCoilName, errFlag);
    1562         181 :                         if (errFlag) {
    1563           0 :                             ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1564           0 :                             ErrorsFound = true;
    1565             :                         }
    1566             : 
    1567             :                         // Get the Heating Coil Inlet Node
    1568         181 :                         errFlag = false;
    1569         181 :                         HeatingCoilInletNode = HeatingCoils::GetCoilInletNode(state, HeatingCoilType, HeatingCoilName, errFlag);
    1570         181 :                         if (errFlag) {
    1571           0 :                             ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1572           0 :                             ErrorsFound = true;
    1573             :                         }
    1574             : 
    1575             :                         // Get the Heating Coil Outlet Node
    1576         181 :                         errFlag = false;
    1577         181 :                         HeatingCoilOutletNode = HeatingCoils::GetCoilOutletNode(state, HeatingCoilType, HeatingCoilName, errFlag);
    1578         181 :                         if (errFlag) {
    1579           0 :                             ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1580           0 :                             ErrorsFound = true;
    1581             :                         }
    1582             : 
    1583             :                         // Get the Heating Coil PLF Curve Index
    1584         181 :                         errFlag = false;
    1585         181 :                         HeatingCoilPLFCurveIndex = HeatingCoils::GetHeatingCoilPLFCurveIndex(state, HeatingCoilType, HeatingCoilName, errFlag);
    1586         181 :                         if (errFlag) {
    1587           0 :                             ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1588           0 :                             ErrorsFound = true;
    1589             :                         }
    1590             : 
    1591             :                     } // IF (IsNotOK) THEN
    1592             :                 }
    1593             : 
    1594           0 :             } else if (Util::SameString(HeatingCoilType, "Coil:Heating:Water")) {
    1595           0 :                 thisFurnace.HeatingCoilType_Num = HVAC::Coil_HeatingWater;
    1596           0 :                 ValidateComponent(state, HeatingCoilType, HeatingCoilName, IsNotOK, CurrentModuleObject);
    1597           0 :                 if (IsNotOK) {
    1598           0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1599           0 :                     ErrorsFound = true;
    1600             :                 } else { // mine data from heating coil object
    1601             : 
    1602             :                     // Get the Heating Coil water Inlet or control Node number
    1603           0 :                     errFlag = false;
    1604           0 :                     thisFurnace.CoilControlNode = WaterCoils::GetCoilWaterInletNode(state, "Coil:Heating:Water", HeatingCoilName, errFlag);
    1605           0 :                     if (errFlag) {
    1606           0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1607           0 :                         ErrorsFound = true;
    1608             :                     }
    1609             : 
    1610             :                     // Get the Heating Coil hot water max volume flow rate
    1611           0 :                     errFlag = false;
    1612           0 :                     thisFurnace.MaxHeatCoilFluidFlow = WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", HeatingCoilName, errFlag);
    1613           0 :                     if (errFlag) {
    1614           0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1615           0 :                         ErrorsFound = true;
    1616             :                     }
    1617             : 
    1618             :                     // Get the Heating Coil Inlet Node
    1619           0 :                     errFlag = false;
    1620           0 :                     HeatingCoilInletNode = WaterCoils::GetCoilInletNode(state, "Coil:Heating:Water", HeatingCoilName, errFlag);
    1621           0 :                     thisFurnace.HWCoilAirInletNode = HeatingCoilInletNode;
    1622           0 :                     if (errFlag) {
    1623           0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1624           0 :                         ErrorsFound = true;
    1625             :                     }
    1626             : 
    1627             :                     // Get the Heating Coil Outlet Node
    1628           0 :                     errFlag = false;
    1629           0 :                     HeatingCoilOutletNode = WaterCoils::GetCoilOutletNode(state, "Coil:Heating:Water", HeatingCoilName, errFlag);
    1630           0 :                     thisFurnace.HWCoilAirOutletNode = HeatingCoilOutletNode;
    1631           0 :                     if (errFlag) {
    1632           0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1633           0 :                         ErrorsFound = true;
    1634             :                     }
    1635             : 
    1636             :                     // check if user has also used a water coil controller, which they should not do
    1637           0 :                     errFlag = false;
    1638           0 :                     HVACControllers::CheckCoilWaterInletNode(state, thisFurnace.CoilControlNode, errFlag);
    1639           0 :                     if (!errFlag) { // then did find a controller so that is bad
    1640           0 :                         ShowSevereError(state,
    1641           0 :                                         format("{} = {} has a conflicting Controller:WaterCoil object", CurrentModuleObject, thisFurnace.Name));
    1642           0 :                         ShowContinueError(state, "Hot water coils are controlled directly by unitary and furnace systems.");
    1643           0 :                         ShowContinueError(state, "No water coil controller should be input for the coil.");
    1644           0 :                         ErrorsFound = true;
    1645             :                     }
    1646             :                 }
    1647             : 
    1648           0 :             } else if (Util::SameString(HeatingCoilType, "Coil:Heating:Steam")) {
    1649           0 :                 thisFurnace.HeatingCoilType_Num = HVAC::Coil_HeatingSteam;
    1650           0 :                 ValidateComponent(state, HeatingCoilType, HeatingCoilName, IsNotOK, CurrentModuleObject);
    1651           0 :                 if (IsNotOK) {
    1652           0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1653           0 :                     ErrorsFound = true;
    1654             :                 } else { // mine data from heating coil object
    1655             : 
    1656           0 :                     errFlag = false;
    1657           0 :                     thisFurnace.HeatingCoilIndex = SteamCoils::GetSteamCoilIndex(state, "COIL:HEATING:STEAM", HeatingCoilName, errFlag);
    1658           0 :                     if (thisFurnace.HeatingCoilIndex == 0) {
    1659           0 :                         ShowSevereError(state, format("{} illegal {} = {}", CurrentModuleObject, cAlphaFields(11), HeatingCoilName));
    1660           0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1661           0 :                         ErrorsFound = true;
    1662             :                     }
    1663             : 
    1664             :                     // Get the Heating Coil steam inlet node number
    1665           0 :                     errFlag = false;
    1666           0 :                     thisFurnace.CoilControlNode = SteamCoils::GetCoilSteamInletNode(state, "Coil:Heating:Steam", HeatingCoilName, errFlag);
    1667           0 :                     if (errFlag) {
    1668           0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1669           0 :                         ErrorsFound = true;
    1670             :                     }
    1671             : 
    1672             :                     // Get the Heating Coil steam max volume flow rate
    1673           0 :                     thisFurnace.MaxHeatCoilFluidFlow = SteamCoils::GetCoilMaxSteamFlowRate(state, thisFurnace.HeatingCoilIndex, errFlag);
    1674           0 :                     if (thisFurnace.MaxHeatCoilFluidFlow > 0.0) {
    1675           0 :                         SteamIndex = 0; // Function GetSatDensityRefrig will look up steam index if 0 is passed
    1676           0 :                         SteamDensity = FluidProperties::GetSatDensityRefrig(
    1677           0 :                             state, fluidNameSteam, state.dataFurnaces->TempSteamIn, 1.0, SteamIndex, getAirLoopHVACHeatCoolInput);
    1678           0 :                         thisFurnace.MaxHeatCoilFluidFlow *= SteamDensity;
    1679             :                     }
    1680             : 
    1681             :                     // Get the Heating Coil Inlet Node
    1682           0 :                     errFlag = false;
    1683           0 :                     HeatingCoilInletNode = SteamCoils::GetCoilAirInletNode(state, thisFurnace.HeatingCoilIndex, HeatingCoilName, errFlag);
    1684           0 :                     thisFurnace.HWCoilAirInletNode = HeatingCoilInletNode;
    1685           0 :                     if (errFlag) {
    1686           0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1687           0 :                         ErrorsFound = true;
    1688             :                     }
    1689             : 
    1690             :                     // Get the Heating Coil Outlet Node
    1691           0 :                     errFlag = false;
    1692           0 :                     HeatingCoilOutletNode = SteamCoils::GetCoilAirOutletNode(state, thisFurnace.HeatingCoilIndex, HeatingCoilName, errFlag);
    1693           0 :                     thisFurnace.HWCoilAirOutletNode = HeatingCoilOutletNode;
    1694           0 :                     if (errFlag) {
    1695           0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1696           0 :                         ErrorsFound = true;
    1697             :                     }
    1698             :                 }
    1699             : 
    1700             :             } else {
    1701           0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1702           0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(11), Alphas(11)));
    1703           0 :                 ErrorsFound = true;
    1704             :             } // IF (Furnace(FurnaceNum)%HeatingCoilType_Num == Coil_HeatingGasOrOtherFuel .OR. &, etc.
    1705             : 
    1706             :             // Get Cooling Coil Information if available
    1707         181 :             CoolingCoilType = Alphas(12);
    1708         181 :             CoolingCoilName = Alphas(13);
    1709             :             //       Find the type of coil. Do not print message since this may not be the correct coil type.
    1710         181 :             errFlag = false;
    1711         181 :             PrintMessage = false;
    1712             : 
    1713         358 :             if (Util::SameString(CoolingCoilType, "COIL:COOLING:DX:VARIABLESPEED") ||
    1714         358 :                 Util::SameString(CoolingCoilType, "COILSYSTEM:INTEGRATEDHEATPUMP:AIRSOURCE")) {
    1715           4 :                 thisFurnace.CoolingCoilType_Num = HVAC::Coil_CoolingAirToAirVariableSpeed;
    1716           4 :                 if (Util::SameString(CoolingCoilType, "COILSYSTEM:INTEGRATEDHEATPUMP:AIRSOURCE")) thisFurnace.bIsIHP = true;
    1717             :             } else {
    1718         177 :                 thisFurnace.CoolingCoilType_Num = DXCoils::GetCoilTypeNum(state, CoolingCoilType, CoolingCoilName, errFlag, PrintMessage);
    1719             :             }
    1720             : 
    1721             :             // If coil type not found, check to see if a HX assisted cooling coil is used.
    1722         181 :             if (thisFurnace.CoolingCoilType_Num == 0) {
    1723           3 :                 errFlag = false;
    1724           3 :                 thisFurnace.CoolingCoilType_Num =
    1725           3 :                     HVACHXAssistedCoolingCoil::GetCoilGroupTypeNum(state, CoolingCoilType, CoolingCoilName, errFlag, PrintMessage);
    1726             :             }
    1727             : 
    1728         181 :             if (thisFurnace.CoolingCoilType_Num == HVAC::CoilDX_CoolingSingleSpeed) {
    1729         174 :                 ValidateComponent(state, CoolingCoilType, CoolingCoilName, IsNotOK, CurrentModuleObject);
    1730         174 :                 if (IsNotOK) {
    1731           0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1732           0 :                     ErrorsFound = true;
    1733             : 
    1734             :                 } else { // mine data from DX cooling coil
    1735             : 
    1736             :                     // Get DX cooling coil index
    1737         174 :                     DXCoils::GetDXCoilIndex(state, CoolingCoilName, thisFurnace.CoolingCoilIndex, IsNotOK);
    1738         174 :                     if (IsNotOK) {
    1739           0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1740           0 :                         ErrorsFound = true;
    1741             :                     }
    1742             : 
    1743             :                     // Get DX cooling coil capacity
    1744         174 :                     errFlag = false;
    1745         174 :                     thisFurnace.DesignCoolingCapacity = DXCoils::GetCoilCapacity(state, CoolingCoilType, CoolingCoilName, errFlag);
    1746         174 :                     if (errFlag) {
    1747           0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1748           0 :                         ErrorsFound = true;
    1749             :                     }
    1750             : 
    1751             :                     // Get the Cooling Coil Nodes
    1752         174 :                     errFlag = false;
    1753         174 :                     CoolingCoilInletNode = DXCoils::GetCoilInletNode(state, CoolingCoilType, CoolingCoilName, errFlag);
    1754         174 :                     CoolingCoilOutletNode = DXCoils::GetCoilOutletNode(state, CoolingCoilType, CoolingCoilName, errFlag);
    1755         174 :                     if (errFlag) {
    1756           0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1757           0 :                         ErrorsFound = true;
    1758             :                     }
    1759             : 
    1760             :                     // Get outdoor condenser node from DX coil object
    1761         174 :                     errFlag = false;
    1762         174 :                     if (thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingAirToAirVariableSpeed) {
    1763           0 :                         if (thisFurnace.bIsIHP) {
    1764           0 :                             IHPCoilIndex = IntegratedHeatPump::GetCoilIndexIHP(state, CoolingCoilType, CoolingCoilName, errFlag);
    1765           0 :                             IHPCoilName = state.dataIntegratedHP->IntegratedHeatPumps(IHPCoilIndex).SCCoilName;
    1766           0 :                             thisFurnace.CondenserNodeNum = VariableSpeedCoils::GetVSCoilCondenserInletNode(state, IHPCoilName, errFlag);
    1767             :                         } else {
    1768           0 :                             thisFurnace.CondenserNodeNum = VariableSpeedCoils::GetVSCoilCondenserInletNode(state, CoolingCoilName, errFlag);
    1769             :                         }
    1770             :                     } else {
    1771         174 :                         thisFurnace.CondenserNodeNum = DXCoils::GetCoilCondenserInletNode(state, CoolingCoilType, CoolingCoilName, errFlag);
    1772             :                     }
    1773         174 :                     if (errFlag) {
    1774           0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1775           0 :                         ErrorsFound = true;
    1776             :                     }
    1777             : 
    1778             :                 } // IF (IsNotOK) THEN
    1779             : 
    1780             :                 // Push heating coil PLF curve index to DX coil
    1781         174 :                 if (HeatingCoilPLFCurveIndex > 0) {
    1782          48 :                     DXCoils::SetDXCoolingCoilData(state, thisFurnace.CoolingCoilIndex, ErrorsFound, HeatingCoilPLFCurveIndex);
    1783             :                 }
    1784             : 
    1785           7 :             } else if (thisFurnace.CoolingCoilType_Num == HVAC::CoilDX_CoolingHXAssisted) {
    1786           3 :                 ValidateComponent(state, CoolingCoilType, CoolingCoilName, IsNotOK, CurrentModuleObject);
    1787           3 :                 if (IsNotOK) {
    1788           0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1789           0 :                     ErrorsFound = true;
    1790             : 
    1791             :                 } else { // mine data from heat exchanger assisted cooling coil
    1792             : 
    1793             :                     // Get DX heat exchanger assisted cooling coil index
    1794           3 :                     HVACHXAssistedCoolingCoil::GetHXDXCoilIndex(state, CoolingCoilName, thisFurnace.CoolingCoilIndex, IsNotOK);
    1795           3 :                     if (IsNotOK) {
    1796           0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1797           0 :                         ErrorsFound = true;
    1798             :                     }
    1799             : 
    1800             :                     // Get DX cooling coil capacity
    1801           3 :                     errFlag = false;
    1802           3 :                     thisFurnace.DesignCoolingCapacity = HVACHXAssistedCoolingCoil::GetCoilCapacity(state, CoolingCoilType, CoolingCoilName, errFlag);
    1803           3 :                     if (errFlag) {
    1804           0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1805           0 :                         ErrorsFound = true;
    1806             :                     }
    1807             : 
    1808             :                     // Get the Cooling Coil Nodes
    1809           3 :                     errFlag = false;
    1810           3 :                     CoolingCoilInletNode = HVACHXAssistedCoolingCoil::GetCoilInletNode(state, CoolingCoilType, CoolingCoilName, errFlag);
    1811           3 :                     CoolingCoilOutletNode = HVACHXAssistedCoolingCoil::GetCoilOutletNode(state, CoolingCoilType, CoolingCoilName, errFlag);
    1812           3 :                     if (errFlag) {
    1813           0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1814           0 :                         ErrorsFound = true;
    1815             :                     }
    1816             : 
    1817             :                     // Get outdoor condenser node from heat exchanger assisted DX coil object
    1818           3 :                     errFlag = false;
    1819           3 :                     std::string ChildCoolingCoilName = HVACHXAssistedCoolingCoil::GetHXDXCoilName(state, CoolingCoilType, CoolingCoilName, IsNotOK);
    1820           3 :                     std::string ChildCoolingCoilType = HVACHXAssistedCoolingCoil::GetHXDXCoilType(state, CoolingCoilType, CoolingCoilName, IsNotOK);
    1821           3 :                     if (IsNotOK) {
    1822           0 :                         ShowContinueError(state, format("Occurs in {} = {}", cCurrentModuleObject, Alphas(1)));
    1823           0 :                         ErrorsFound = true;
    1824             :                     }
    1825             : 
    1826             :                     // if (thisFurnace.CoolingCoilType_Num == CoilDX_CoolingHXAssisted) {
    1827           3 :                     if (Util::SameString(ChildCoolingCoilType, "COIL:COOLING:DX")) {
    1828             : 
    1829           1 :                         int childCCIndex = CoilCoolingDX::factory(state, ChildCoolingCoilName);
    1830           1 :                         if (childCCIndex < 0) {
    1831           0 :                             ShowContinueError(state, format("Occurs in {} = {}", cCurrentModuleObject, Alphas(1)));
    1832           0 :                             errFlag = true;
    1833           0 :                             ErrorsFound = true;
    1834             :                         }
    1835           1 :                         auto const &newCoil = state.dataCoilCooingDX->coilCoolingDXs[childCCIndex];
    1836             : 
    1837           1 :                         thisFurnace.CondenserNodeNum = newCoil.condInletNodeIndex;
    1838             : 
    1839             :                     }
    1840             :                     // else if (thisFurnace.CoolingCoilType_Num == Coil_CoolingAirToAirVariableSpeed) {
    1841           2 :                     else if (Util::SameString(ChildCoolingCoilType, "Coil:Cooling:DX:VariableSpeed")) {
    1842           0 :                         if (thisFurnace.bIsIHP) {
    1843           0 :                             IHPCoilIndex = IntegratedHeatPump::GetCoilIndexIHP(state, CoolingCoilType, CoolingCoilName, errFlag);
    1844           0 :                             IHPCoilName = state.dataIntegratedHP->IntegratedHeatPumps(IHPCoilIndex).SCCoilName;
    1845           0 :                             thisFurnace.CondenserNodeNum = VariableSpeedCoils::GetVSCoilCondenserInletNode(state, IHPCoilName, errFlag);
    1846             :                         } else {
    1847           0 :                             thisFurnace.CondenserNodeNum = VariableSpeedCoils::GetVSCoilCondenserInletNode(state, CoolingCoilName, errFlag);
    1848             :                         }
    1849             :                     } else {
    1850           2 :                         thisFurnace.CondenserNodeNum = DXCoils::GetCoilCondenserInletNode(
    1851             :                             state,
    1852             :                             "COIL:COOLING:DX:SINGLESPEED",
    1853           4 :                             HVACHXAssistedCoolingCoil::GetHXDXCoilName(state, CoolingCoilType, CoolingCoilName, errFlag),
    1854             :                             errFlag);
    1855             :                     }
    1856             : 
    1857           3 :                     if (errFlag) {
    1858           0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1859           0 :                         ErrorsFound = true;
    1860             :                     }
    1861             : 
    1862             :                     // Push heating coil PLF curve index to DX coil
    1863           3 :                     if (HeatingCoilPLFCurveIndex > 0) {
    1864             :                         // get the actual index to the DX cooling coil object
    1865           0 :                         DXCoilIndex = HVACHXAssistedCoolingCoil::GetActualDXCoilIndex(state, CoolingCoilType, CoolingCoilName, ErrorsFound);
    1866           0 :                         thisFurnace.ActualDXCoilIndexForHXAssisted = DXCoilIndex;
    1867             :                         int ActualCoolCoilType =
    1868           0 :                             HVACHXAssistedCoolingCoil::GetCoilObjectTypeNum(state, CoolingCoilType, CoolingCoilName, errFlag, true);
    1869           0 :                         if (ActualCoolCoilType == HVAC::CoilDX_CoolingSingleSpeed) {
    1870           0 :                             DXCoils::SetDXCoolingCoilData(state, DXCoilIndex, ErrorsFound, HeatingCoilPLFCurveIndex);
    1871             :                         }
    1872             :                         // what could we do for VS coil here? odd thing here
    1873             :                     }
    1874             : 
    1875           3 :                 } // IF (IsNotOK) THEN
    1876           4 :             } else if (thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingAirToAirVariableSpeed) {
    1877             :                 // BOS ADDED, AUG/2012, VARIIABLE SPEED DX COOLING COIL
    1878             :                 //  Furnace(FurnaceNum)%DXCoolCoilType = 'COIL:COOLING:DX:VARIABLESPEED'
    1879             :                 //  Furnace(FurnaceNum)%DXCoolCoilName = CoolingCoilName
    1880           4 :                 if (Util::SameString(CoolingCoilType, "COILSYSTEM:INTEGRATEDHEATPUMP:AIRSOURCE")) thisFurnace.bIsIHP = true;
    1881           4 :                 ValidateComponent(state, CoolingCoilType, CoolingCoilName, IsNotOK, CurrentModuleObject);
    1882             : 
    1883           4 :                 if (IsNotOK) {
    1884           0 :                     ShowContinueError(state, format("...specified in {}=\"{}\".", CurrentModuleObject, Alphas(1)));
    1885           0 :                     ErrorsFound = true;
    1886             :                 } else {
    1887           4 :                     errFlag = false;
    1888           4 :                     if (thisFurnace.bIsIHP) {
    1889           0 :                         thisFurnace.CoolingCoilIndex = IntegratedHeatPump::GetCoilIndexIHP(state, CoolingCoilType, CoolingCoilName, errFlag);
    1890           0 :                         IHPCoilName = state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).SCCoilName;
    1891             :                     } else {
    1892           4 :                         thisFurnace.CoolingCoilIndex =
    1893           4 :                             VariableSpeedCoils::GetCoilIndexVariableSpeed(state, CoolingCoilType, CoolingCoilName, errFlag);
    1894           4 :                         IHPCoilName = CoolingCoilName;
    1895             :                     }
    1896             : 
    1897           4 :                     if (errFlag) {
    1898           0 :                         ShowContinueError(state, format("...specified in {}=\"{}\".", CurrentModuleObject, Alphas(1)));
    1899           0 :                         ErrorsFound = true;
    1900             :                     }
    1901             : 
    1902           4 :                     if (thisFurnace.bIsIHP) {
    1903             :                         CoolingCoilInletNode =
    1904           0 :                             VariableSpeedCoils::GetCoilInletNodeVariableSpeed(state, "COIL:COOLING:DX:VARIABLESPEED", IHPCoilName, errFlag);
    1905             :                         CoolingCoilOutletNode =
    1906           0 :                             VariableSpeedCoils::GetCoilOutletNodeVariableSpeed(state, "COIL:COOLING:DX:VARIABLESPEED", IHPCoilName, errFlag);
    1907           0 :                         thisFurnace.CondenserNodeNum = VariableSpeedCoils::GetVSCoilCondenserInletNode(state, IHPCoilName, errFlag);
    1908             :                     } else {
    1909           4 :                         CoolingCoilInletNode = VariableSpeedCoils::GetCoilInletNodeVariableSpeed(state, CoolingCoilType, CoolingCoilName, errFlag);
    1910           4 :                         CoolingCoilOutletNode = VariableSpeedCoils::GetCoilOutletNodeVariableSpeed(state, CoolingCoilType, CoolingCoilName, errFlag);
    1911           4 :                         thisFurnace.CondenserNodeNum = VariableSpeedCoils::GetVSCoilCondenserInletNode(state, CoolingCoilName, errFlag);
    1912             :                     }
    1913             : 
    1914           4 :                     if (errFlag) {
    1915           0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1916           0 :                         ErrorsFound = true;
    1917             :                     }
    1918             :                 }
    1919             :             } else {
    1920           0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1921           0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(12), Alphas(12)));
    1922           0 :                 ErrorsFound = true;
    1923             :             }
    1924             : 
    1925         181 :             if (Util::SameString(Alphas(14), "None") || Util::SameString(Alphas(14), "Multimode") || Util::SameString(Alphas(14), "CoolReheat")) {
    1926         181 :                 AirNodeFound = false;
    1927         181 :                 if (Util::SameString(Alphas(14), "Multimode")) {
    1928           3 :                     thisFurnace.DehumidControlType_Num = DehumidificationControlMode::Multimode;
    1929           3 :                     thisFurnace.Humidistat = true;
    1930           3 :                     if (thisFurnace.CoolingCoilType_Num != HVAC::CoilDX_CoolingHXAssisted) {
    1931           0 :                         ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1932           0 :                         ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(14), Alphas(14)));
    1933           0 :                         ShowContinueError(state, "Multimode control must be used with a Heat Exchanger Assisted Cooling Coil.");
    1934           0 :                         if (lAlphaBlanks(15)) {
    1935           0 :                             ShowContinueError(state,
    1936             :                                               "Dehumidification control type is assumed to be None since a reheat coil has not been specified and "
    1937             :                                               "the simulation continues.");
    1938           0 :                             thisFurnace.Humidistat = false;
    1939           0 :                             thisFurnace.DehumidControlType_Num = DehumidificationControlMode::None;
    1940             :                         } else {
    1941           0 :                             ShowContinueError(state, "Dehumidification control type is assumed to be CoolReheat and the simulation continues.");
    1942           0 :                             thisFurnace.DehumidControlType_Num = DehumidificationControlMode::CoolReheat;
    1943             :                         }
    1944             :                     }
    1945             :                 }
    1946         181 :                 if (Util::SameString(Alphas(14), "CoolReheat")) {
    1947          22 :                     thisFurnace.DehumidControlType_Num = DehumidificationControlMode::CoolReheat;
    1948          22 :                     thisFurnace.Humidistat = true;
    1949          22 :                     if (lAlphaBlanks(15)) {
    1950           0 :                         ShowWarningError(state, format("{} \"{}\"", CurrentModuleObject, Alphas(1)));
    1951           0 :                         ShowContinueError(state,
    1952             :                                           "Dehumidification control type is assumed to be None since a reheat coil has not been specified and the "
    1953             :                                           "simulation continues.");
    1954           0 :                         thisFurnace.Humidistat = false;
    1955           0 :                         thisFurnace.DehumidControlType_Num = DehumidificationControlMode::None;
    1956             :                     }
    1957             :                 }
    1958         181 :                 if (Util::SameString(Alphas(14), "None")) {
    1959         156 :                     thisFurnace.DehumidControlType_Num = DehumidificationControlMode::None;
    1960         156 :                     thisFurnace.Humidistat = false;
    1961             :                 }
    1962         181 :                 if (thisFurnace.Humidistat) {
    1963          62 :                     for (HStatZoneNum = 1; HStatZoneNum <= state.dataZoneCtrls->NumHumidityControlZones; ++HStatZoneNum) {
    1964          37 :                         if (state.dataZoneCtrls->HumidityControlZone(HStatZoneNum).ActualZoneNum != thisFurnace.ControlZoneNum) continue;
    1965          25 :                         AirNodeFound = true;
    1966             :                     }
    1967          25 :                     if (!AirNodeFound) {
    1968           0 :                         ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1969           0 :                         ShowContinueError(state, "Did not find Air Node (Zone with Humidistat).");
    1970           0 :                         ShowContinueError(state, format("Specified {} = {}", cAlphaFields(6), Alphas(6)));
    1971           0 :                         ErrorsFound = true;
    1972             :                     }
    1973             :                 }
    1974             :             } else { // invalid input
    1975           0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1976           0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(14), Alphas(14)));
    1977           0 :                 thisFurnace.Humidistat = false;
    1978           0 :                 ErrorsFound = true;
    1979             :             }
    1980             : 
    1981             :             //       Check placement of cooling coil with respect to fan placement and dehumidification control type
    1982         181 :             if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
    1983         178 :                 if (FanOutletNode == HeatingCoilInletNode && thisFurnace.DehumidControlType_Num != DehumidificationControlMode::CoolReheat) {
    1984         102 :                     thisFurnace.CoolingCoilUpstream = false;
    1985             :                 }
    1986             :             } else {
    1987           3 :                 if (HeatingCoilOutletNode == CoolingCoilInletNode && thisFurnace.DehumidControlType_Num != DehumidificationControlMode::CoolReheat) {
    1988           2 :                     thisFurnace.CoolingCoilUpstream = false;
    1989             :                 }
    1990             :             }
    1991             : 
    1992             :             // Get reheat coil data if humidistat is used
    1993         181 :             ReheatingCoilType = Alphas(15);
    1994         181 :             ReheatingCoilName = Alphas(16);
    1995         181 :             thisFurnace.SuppHeatCoilType = ReheatingCoilType;
    1996         181 :             thisFurnace.SuppHeatCoilName = ReheatingCoilName;
    1997         181 :             errFlag = false;
    1998         181 :             if (!lAlphaBlanks(15)) {
    1999          25 :                 if (Util::SameString(ReheatingCoilType, "Coil:Heating:Fuel") || Util::SameString(ReheatingCoilType, "Coil:Heating:Electric") ||
    2000          25 :                     Util::SameString(ReheatingCoilType, "Coil:Heating:Desuperheater")) {
    2001             : 
    2002          23 :                     thisFurnace.SuppHeatCoilType_Num = HeatingCoils::GetHeatingCoilTypeNum(state, ReheatingCoilType, ReheatingCoilName, errFlag);
    2003          23 :                     if (errFlag) {
    2004           0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2005           0 :                         ErrorsFound = true;
    2006             :                     } else {
    2007             : 
    2008          23 :                         ValidateComponent(state, ReheatingCoilType, ReheatingCoilName, IsNotOK, CurrentModuleObject);
    2009          23 :                         if (IsNotOK) {
    2010           0 :                             ShowContinueError(state, format("In {} \"{}\"", CurrentModuleObject, Alphas(1)));
    2011           0 :                             ErrorsFound = true;
    2012             : 
    2013             :                         } else { // mine data from reheat coil
    2014             : 
    2015             :                             // Get the heating coil index
    2016          23 :                             HeatingCoils::GetCoilIndex(state, ReheatingCoilName, thisFurnace.SuppHeatCoilIndex, IsNotOK);
    2017          23 :                             if (IsNotOK) {
    2018           0 :                                 ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2019           0 :                                 ErrorsFound = true;
    2020             :                             }
    2021             : 
    2022             :                             // Get the design supplemental heating capacity
    2023          23 :                             errFlag = false;
    2024          23 :                             thisFurnace.DesignSuppHeatingCapacity =
    2025          23 :                                 HeatingCoils::GetCoilCapacity(state, ReheatingCoilType, ReheatingCoilName, errFlag);
    2026          23 :                             if (errFlag) {
    2027           0 :                                 ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2028           0 :                                 ErrorsFound = true;
    2029             :                             }
    2030             : 
    2031             :                             // Get the Reheat Coil Inlet Node
    2032          23 :                             errFlag = false;
    2033          23 :                             ReheatCoilInletNode = HeatingCoils::GetCoilInletNode(state, ReheatingCoilType, ReheatingCoilName, errFlag);
    2034          23 :                             if (errFlag) {
    2035           0 :                                 ShowContinueError(state, format("...occurs in {} \"{}\"", CurrentModuleObject, Alphas(1)));
    2036           0 :                                 ErrorsFound = true;
    2037             :                             }
    2038             : 
    2039             :                             // Get the Reheat Coil Outlet Node
    2040          23 :                             errFlag = false;
    2041          23 :                             ReheatCoilOutletNode = HeatingCoils::GetCoilOutletNode(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             :                         } // IF (IsNotOK) THEN
    2048             :                     }
    2049             : 
    2050           0 :                 } else if (Util::SameString(ReheatingCoilType, "Coil:Heating:Water")) {
    2051           0 :                     thisFurnace.SuppHeatCoilType_Num = HVAC::Coil_HeatingWater;
    2052           0 :                     ValidateComponent(state, ReheatingCoilType, ReheatingCoilName, IsNotOK, CurrentModuleObject);
    2053           0 :                     if (IsNotOK) {
    2054           0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2055           0 :                         ErrorsFound = true;
    2056             :                     } else { // mine data from heating coil object
    2057             : 
    2058             :                         // Get the Heating Coil water Inlet or control Node number
    2059           0 :                         errFlag = false;
    2060           0 :                         thisFurnace.SuppCoilControlNode = WaterCoils::GetCoilWaterInletNode(state, "Coil:Heating:Water", ReheatingCoilName, errFlag);
    2061           0 :                         if (errFlag) {
    2062           0 :                             ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    2063           0 :                             ErrorsFound = true;
    2064             :                         }
    2065             : 
    2066             :                         // Get the ReHeat Coil hot water max volume flow rate
    2067           0 :                         errFlag = false;
    2068           0 :                         thisFurnace.MaxSuppCoilFluidFlow =
    2069           0 :                             WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", ReheatingCoilName, errFlag);
    2070           0 :                         if (errFlag) {
    2071           0 :                             ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    2072           0 :                             ErrorsFound = true;
    2073             :                         }
    2074             : 
    2075             :                         // Get the ReHeat Coil Inlet Node
    2076           0 :                         errFlag = false;
    2077           0 :                         ReheatCoilInletNode = WaterCoils::GetCoilInletNode(state, "Coil:Heating:Water", ReheatingCoilName, errFlag);
    2078           0 :                         thisFurnace.SuppCoilAirInletNode = ReheatCoilInletNode;
    2079           0 :                         if (errFlag) {
    2080           0 :                             ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    2081           0 :                             ErrorsFound = true;
    2082             :                         }
    2083             : 
    2084             :                         // Get the ReHeat Coil Outlet Node
    2085           0 :                         errFlag = false;
    2086           0 :                         ReheatCoilOutletNode = WaterCoils::GetCoilOutletNode(state, "Coil:Heating:Water", ReheatingCoilName, errFlag);
    2087           0 :                         thisFurnace.SuppCoilAirOutletNode = ReheatCoilOutletNode;
    2088           0 :                         if (errFlag) {
    2089           0 :                             ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    2090           0 :                             ErrorsFound = true;
    2091             :                         }
    2092             : 
    2093             :                         // check if user has also used a water coil controller, which they should not do
    2094           0 :                         errFlag = false;
    2095           0 :                         HVACControllers::CheckCoilWaterInletNode(state, thisFurnace.CoilControlNode, errFlag);
    2096           0 :                         if (!errFlag) { // then did find a controller so that is bad
    2097           0 :                             ShowSevereError(state,
    2098           0 :                                             format("{} = {} has a conflicting Controller:WaterCoil object", CurrentModuleObject, thisFurnace.Name));
    2099           0 :                             ShowContinueError(state, "Hot water coils are controlled directly by unitary and furnace systems.");
    2100           0 :                             ShowContinueError(state, "No water coil controller should be input for the coil.");
    2101           0 :                             ErrorsFound = true;
    2102             :                         }
    2103             :                     }
    2104             : 
    2105           0 :                 } else if (Util::SameString(ReheatingCoilType, "Coil:Heating:Steam")) {
    2106           0 :                     thisFurnace.SuppHeatCoilType_Num = HVAC::Coil_HeatingSteam;
    2107           0 :                     ValidateComponent(state, ReheatingCoilType, ReheatingCoilName, IsNotOK, CurrentModuleObject);
    2108           0 :                     if (IsNotOK) {
    2109           0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2110           0 :                         ErrorsFound = true;
    2111             :                     } else { // mine data from heating coil object
    2112             : 
    2113           0 :                         errFlag = false;
    2114           0 :                         thisFurnace.SuppHeatCoilIndex = SteamCoils::GetSteamCoilIndex(state, "COIL:HEATING:STEAM", ReheatingCoilName, errFlag);
    2115           0 :                         if (thisFurnace.SuppHeatCoilIndex == 0) {
    2116           0 :                             ShowSevereError(state, format("{} illegal {} = {}", CurrentModuleObject, cAlphaFields(11), ReheatingCoilName));
    2117           0 :                             ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    2118           0 :                             ErrorsFound = true;
    2119             :                         }
    2120             : 
    2121             :                         // Get the Heating Coil steam inlet node number
    2122           0 :                         errFlag = false;
    2123           0 :                         thisFurnace.SuppCoilControlNode = SteamCoils::GetCoilSteamInletNode(state, "Coil:Heating:Steam", ReheatingCoilName, errFlag);
    2124           0 :                         if (errFlag) {
    2125           0 :                             ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    2126           0 :                             ErrorsFound = true;
    2127             :                         }
    2128             : 
    2129             :                         // Get the Heating Coil steam max volume flow rate
    2130           0 :                         thisFurnace.MaxSuppCoilFluidFlow = SteamCoils::GetCoilMaxSteamFlowRate(state, thisFurnace.SuppHeatCoilIndex, errFlag);
    2131           0 :                         if (thisFurnace.MaxSuppCoilFluidFlow > 0.0) {
    2132           0 :                             SteamIndex = 0; // Function GetSatDensityRefrig will look up steam index if 0 is passed
    2133           0 :                             SteamDensity = FluidProperties::GetSatDensityRefrig(
    2134           0 :                                 state, fluidNameSteam, state.dataFurnaces->TempSteamIn, 1.0, SteamIndex, getAirLoopHVACHeatCoolInput);
    2135           0 :                             thisFurnace.MaxSuppCoilFluidFlow =
    2136           0 :                                 SteamCoils::GetCoilMaxSteamFlowRate(state, thisFurnace.SuppHeatCoilIndex, errFlag) * SteamDensity;
    2137             :                         }
    2138             : 
    2139             :                         // Get the Heating Coil Inlet Node
    2140           0 :                         errFlag = false;
    2141           0 :                         ReheatCoilInletNode = SteamCoils::GetCoilAirInletNode(state, thisFurnace.SuppHeatCoilIndex, ReheatingCoilName, errFlag);
    2142           0 :                         thisFurnace.SuppCoilAirInletNode = ReheatCoilInletNode;
    2143           0 :                         if (errFlag) {
    2144           0 :                             ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    2145           0 :                             ErrorsFound = true;
    2146             :                         }
    2147             : 
    2148             :                         // Get the Heating Coil Outlet Node
    2149           0 :                         errFlag = false;
    2150           0 :                         ReheatCoilOutletNode = SteamCoils::GetCoilAirOutletNode(state, thisFurnace.SuppHeatCoilIndex, ReheatingCoilName, errFlag);
    2151           0 :                         thisFurnace.SuppCoilAirOutletNode = ReheatCoilOutletNode;
    2152           0 :                         if (errFlag) {
    2153           0 :                             ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    2154           0 :                             ErrorsFound = true;
    2155             :                         }
    2156             :                     }
    2157             : 
    2158             :                 } else { // Illeagal heating coil
    2159           0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    2160           0 :                     ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(15), Alphas(15)));
    2161           0 :                     ErrorsFound = true;
    2162             :                 } // IF (Furnace(FurnaceNum)%SuppHeatCoilType_Num == Coil_HeatingGasOrOtherFuel .OR. &, etc.
    2163             : 
    2164             :             } // IF(.NOT. lAlphaBlanks(15))THEN
    2165             : 
    2166         181 :             if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
    2167             : 
    2168         178 :                 if (FanInletNode != thisFurnace.FurnaceInletNodeNum) {
    2169           0 :                     ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2170           0 :                     if (thisFurnace.type == HVAC::UnitarySysType::Furnace_HeatCool) {
    2171           0 :                         ShowContinueError(
    2172             :                             state, "When a blow through fan is specified, the fan inlet node name must be the same as the furnace inlet node name.");
    2173           0 :                         ShowContinueError(state, format("...Fan inlet node name     = {}", state.dataLoopNodes->NodeID(FanInletNode)));
    2174           0 :                         ShowContinueError(state,
    2175           0 :                                           format("...Furnace inlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceInletNodeNum)));
    2176             :                     } else {
    2177           0 :                         ShowContinueError(
    2178             :                             state,
    2179             :                             "When a blow through fan is specified, the fan inlet node name must be the same as the unitary system inlet node name.");
    2180           0 :                         ShowContinueError(state, format("...Fan inlet node name           = {}", state.dataLoopNodes->NodeID(FanInletNode)));
    2181           0 :                         ShowContinueError(
    2182           0 :                             state, format("...UnitarySystem inlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceInletNodeNum)));
    2183             :                     }
    2184           0 :                     ErrorsFound = true;
    2185             :                 }
    2186         178 :                 if (thisFurnace.CoolingCoilUpstream) {
    2187          76 :                     if (FanOutletNode != CoolingCoilInletNode) {
    2188           0 :                         ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2189           0 :                         ShowContinueError(
    2190             :                             state,
    2191             :                             "When a blow through fan is specified, the fan outlet node name must be the same as the cooling coil inlet node name.");
    2192           0 :                         ShowContinueError(state, format("...Fan outlet node name         = {}", state.dataLoopNodes->NodeID(FanOutletNode)));
    2193           0 :                         ShowContinueError(state, format("...Cooling coil inlet node name = {}", state.dataLoopNodes->NodeID(CoolingCoilInletNode)));
    2194           0 :                         ErrorsFound = true;
    2195             :                     }
    2196          76 :                     if (CoolingCoilOutletNode != HeatingCoilInletNode) {
    2197           0 :                         ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2198           0 :                         ShowContinueError(state, "The cooling coil outlet node name must be the same as the heating coil inlet node name.");
    2199           0 :                         ShowContinueError(state, format("...Cooling coil outlet node name = {}", state.dataLoopNodes->NodeID(CoolingCoilOutletNode)));
    2200           0 :                         ShowContinueError(state, format("...Heating coil inlet node name  = {}", state.dataLoopNodes->NodeID(HeatingCoilInletNode)));
    2201           0 :                         ErrorsFound = true;
    2202             :                     }
    2203          76 :                     if ((thisFurnace.Humidistat && thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat) ||
    2204             :                         ReheatCoilInletNode > 0) {
    2205          22 :                         if (HeatingCoilOutletNode != ReheatCoilInletNode) {
    2206           0 :                             ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2207           0 :                             ShowContinueError(state,
    2208             :                                               "When a blow through fan is specified, the heating coil outlet node name must be the same as the "
    2209             :                                               "reheat coil inlet node name.");
    2210           0 :                             ShowContinueError(state,
    2211           0 :                                               format("...Heating coil outlet node name = {}", state.dataLoopNodes->NodeID(HeatingCoilOutletNode)));
    2212           0 :                             ShowContinueError(state,
    2213           0 :                                               format("...Reheat coil inlet node name   = {}", state.dataLoopNodes->NodeID(ReheatCoilInletNode)));
    2214           0 :                             ErrorsFound = true;
    2215             :                         }
    2216          22 :                         if (ReheatCoilOutletNode != thisFurnace.FurnaceOutletNodeNum) {
    2217           0 :                             ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2218           0 :                             if (thisFurnace.type == HVAC::UnitarySysType::Furnace_HeatCool) {
    2219           0 :                                 ShowContinueError(state, "The reheat coil outlet node name must be the same as the furnace outlet node name.");
    2220           0 :                                 ShowContinueError(state,
    2221           0 :                                                   format("...Reheat coil outlet node name = {}", state.dataLoopNodes->NodeID(ReheatCoilOutletNode)));
    2222           0 :                                 ShowContinueError(
    2223             :                                     state,
    2224           0 :                                     format("...Furnace outlet node name     = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    2225             :                             } else {
    2226           0 :                                 ShowContinueError(state, "The reheat coil outlet node name must be the same as the unitary system outlet node name.");
    2227           0 :                                 ShowContinueError(
    2228           0 :                                     state, format("...Reheat coil outlet node name   = {}", state.dataLoopNodes->NodeID(ReheatCoilOutletNode)));
    2229           0 :                                 ShowContinueError(
    2230             :                                     state,
    2231           0 :                                     format("...UnitarySystem outlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    2232             :                             }
    2233           0 :                             ErrorsFound = true;
    2234             :                         }
    2235             :                     } else { // IF((Furnace(FurnaceNum)%Humidistat ...
    2236             :                         // Heating coil outlet node name must be the same as the furnace outlet node name
    2237          54 :                         if (HeatingCoilOutletNode != thisFurnace.FurnaceOutletNodeNum) {
    2238           0 :                             ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    2239           0 :                             if (thisFurnace.type == HVAC::UnitarySysType::Furnace_HeatOnly) {
    2240           0 :                                 ShowContinueError(state,
    2241             :                                                   "When a blow through fan is specified, the heating coil outlet node name must be the same as the "
    2242             :                                                   "furnace outlet node name.");
    2243           0 :                                 ShowContinueError(
    2244           0 :                                     state, format("...Heating coil outlet node name = {}", state.dataLoopNodes->NodeID(HeatingCoilOutletNode)));
    2245           0 :                                 ShowContinueError(
    2246             :                                     state,
    2247           0 :                                     format("...Furnace outlet node name      = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    2248             :                             } else {
    2249           0 :                                 ShowContinueError(state,
    2250             :                                                   "When a blow through fan is specified, the heating coil outlet node name must be the same as the "
    2251             :                                                   "unitary system outlet node name.");
    2252           0 :                                 ShowContinueError(
    2253           0 :                                     state, format("...Heating coil outlet node name  = {}", state.dataLoopNodes->NodeID(HeatingCoilOutletNode)));
    2254           0 :                                 ShowContinueError(
    2255             :                                     state,
    2256           0 :                                     format("...UnitarySystem outlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    2257             :                             }
    2258           0 :                             ErrorsFound = true;
    2259             :                         }
    2260             :                     }
    2261             :                 } else { // IF(Furnace(FurnaceNum)%CoolingCoilUpstream)THEN
    2262         102 :                     if (FanOutletNode != HeatingCoilInletNode) {
    2263           0 :                         ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2264           0 :                         ShowContinueError(
    2265             :                             state,
    2266             :                             "When a blow through fan is specified, the fan outlet node name must be the same as the heating coil inlet node name.");
    2267           0 :                         ShowContinueError(state, format("...Fan outlet node name         = {}", state.dataLoopNodes->NodeID(FanOutletNode)));
    2268           0 :                         ShowContinueError(state, format("...Heating coil inlet node name = {}", state.dataLoopNodes->NodeID(HeatingCoilInletNode)));
    2269           0 :                         ErrorsFound = true;
    2270             :                     }
    2271         102 :                     if (HeatingCoilOutletNode != CoolingCoilInletNode) {
    2272           0 :                         ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2273           0 :                         ShowContinueError(state, "The heating coil outlet node name must be the same as the cooling coil inlet node name.");
    2274           0 :                         ShowContinueError(state, format("...Heating coil outlet node name = {}", state.dataLoopNodes->NodeID(HeatingCoilOutletNode)));
    2275           0 :                         ShowContinueError(state, format("...Cooling coil inlet node name  = {}", state.dataLoopNodes->NodeID(CoolingCoilInletNode)));
    2276           0 :                         ErrorsFound = true;
    2277             :                     }
    2278         102 :                     if (CoolingCoilOutletNode != thisFurnace.FurnaceOutletNodeNum) {
    2279           0 :                         ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2280           0 :                         if (thisFurnace.type == HVAC::UnitarySysType::Furnace_HeatCool) {
    2281           0 :                             ShowContinueError(state,
    2282             :                                               "When a blow through fan is specified, the cooling coil outlet node name must be the same as the "
    2283             :                                               "furnace outlet node name.");
    2284           0 :                             ShowContinueError(state,
    2285           0 :                                               format("...Cooling coil outlet node name = {}", state.dataLoopNodes->NodeID(CoolingCoilOutletNode)));
    2286           0 :                             ShowContinueError(
    2287             :                                 state,
    2288           0 :                                 format("...Furnace outlet node name      = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    2289             :                         } else {
    2290           0 :                             ShowContinueError(state,
    2291             :                                               "When a blow through fan is specified, the cooling coil outlet node name must be the same as the "
    2292             :                                               "unitary system outlet node name.");
    2293           0 :                             ShowContinueError(state,
    2294           0 :                                               format("...Cooling coil outlet node name   = {}", state.dataLoopNodes->NodeID(CoolingCoilOutletNode)));
    2295           0 :                             ShowContinueError(
    2296             :                                 state,
    2297           0 :                                 format("...UnitarySystem outlet node name  = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    2298             :                         }
    2299           0 :                         ErrorsFound = true;
    2300             :                     }
    2301             :                 }
    2302             : 
    2303             :             } else { // ELSE from IF(Furnace(FurnaceNum)%FanPlace .EQ. BlowThru)THEN
    2304             : 
    2305           3 :                 if (thisFurnace.CoolingCoilUpstream) {
    2306           1 :                     if (CoolingCoilInletNode != thisFurnace.FurnaceInletNodeNum) {
    2307           0 :                         ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2308           0 :                         if (thisFurnace.type == HVAC::UnitarySysType::Furnace_HeatCool) {
    2309           0 :                             ShowContinueError(state,
    2310             :                                               "When a draw through fan is specified, the cooling coil inlet node name must be the same as the "
    2311             :                                               "furnace inlet node name.");
    2312           0 :                             ShowContinueError(state,
    2313           0 :                                               format("...Cooling coil inlet node name = {}", state.dataLoopNodes->NodeID(CoolingCoilInletNode)));
    2314           0 :                             ShowContinueError(
    2315           0 :                                 state, format("...Furnace inlet node name      = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceInletNodeNum)));
    2316             :                         } else {
    2317           0 :                             ShowContinueError(state,
    2318             :                                               "When a draw through fan is specified, the cooling coil inlet node name must be the same as the "
    2319             :                                               "unitary system inlet node name.");
    2320           0 :                             ShowContinueError(state,
    2321           0 :                                               format("...Cooling coil inlet node name  = {}", state.dataLoopNodes->NodeID(CoolingCoilInletNode)));
    2322           0 :                             ShowContinueError(
    2323           0 :                                 state, format("...UnitarySystem inlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceInletNodeNum)));
    2324             :                         }
    2325           0 :                         ErrorsFound = true;
    2326             :                     }
    2327           1 :                     if (CoolingCoilOutletNode != HeatingCoilInletNode) {
    2328           0 :                         ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2329           0 :                         ShowContinueError(state, "The cooling coil outlet node name must be the same as the heating coil inlet node name.");
    2330           0 :                         ShowContinueError(state, format("...Cooling coil outlet node name = {}", state.dataLoopNodes->NodeID(CoolingCoilOutletNode)));
    2331           0 :                         ShowContinueError(state, format("...Heating coil inlet node name  = {}", state.dataLoopNodes->NodeID(HeatingCoilInletNode)));
    2332           0 :                         ErrorsFound = true;
    2333             :                     }
    2334           1 :                     if (HeatingCoilOutletNode != FanInletNode) {
    2335           0 :                         ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2336           0 :                         ShowContinueError(
    2337             :                             state,
    2338             :                             "When a draw through fan is specified, the heating coil outlet node name must be the same as the fan inlet node name.");
    2339           0 :                         ShowContinueError(state, format("...Heating coil outlet node name = {}", state.dataLoopNodes->NodeID(HeatingCoilOutletNode)));
    2340           0 :                         ShowContinueError(state, format("...Fan inlet node name           = {}", state.dataLoopNodes->NodeID(FanInletNode)));
    2341           0 :                         ErrorsFound = true;
    2342             :                     }
    2343           1 :                     if ((thisFurnace.Humidistat && thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat) ||
    2344             :                         ReheatCoilInletNode > 0) {
    2345           1 :                         if (FanOutletNode != ReheatCoilInletNode) {
    2346           0 :                             ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2347           0 :                             ShowContinueError(state,
    2348             :                                               "When a draw through fan is specified, the fan outlet node name must be the same as the reheat coil "
    2349             :                                               "inlet node name.");
    2350           0 :                             ShowContinueError(state, format("...Fan outlet node name        = {}", state.dataLoopNodes->NodeID(FanOutletNode)));
    2351           0 :                             ShowContinueError(state, format("...Reheat coil inlet node name = {}", state.dataLoopNodes->NodeID(ReheatCoilInletNode)));
    2352           0 :                             ErrorsFound = true;
    2353             :                         }
    2354           1 :                         if (ReheatCoilOutletNode != thisFurnace.FurnaceOutletNodeNum) {
    2355           0 :                             ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2356           0 :                             if (thisFurnace.type == HVAC::UnitarySysType::Furnace_HeatCool) {
    2357           0 :                                 ShowContinueError(state, "The reheat coil outlet node name must be the same as the furnace outlet node name.");
    2358           0 :                                 ShowContinueError(state,
    2359           0 :                                                   format("...Reheat coil outlet node name = {}", state.dataLoopNodes->NodeID(ReheatCoilOutletNode)));
    2360           0 :                                 ShowContinueError(
    2361             :                                     state,
    2362           0 :                                     format("...Furnace outlet node name     = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    2363             :                             } else {
    2364           0 :                                 ShowContinueError(state, "The reheat coil outlet node name must be the same as the unitary system outlet node name.");
    2365           0 :                                 ShowContinueError(
    2366           0 :                                     state, format("...Reheat coil outlet node name   = {}", state.dataLoopNodes->NodeID(ReheatCoilOutletNode)));
    2367           0 :                                 ShowContinueError(
    2368             :                                     state,
    2369           0 :                                     format("...UnitarySystem outlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    2370             :                             }
    2371           0 :                             ErrorsFound = true;
    2372             :                         }
    2373             :                     } else {
    2374           0 :                         if (FanOutletNode != thisFurnace.FurnaceOutletNodeNum) {
    2375           0 :                             ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2376           0 :                             ShowContinueError(state,
    2377             :                                               "When a draw through fan is specified, the fan outlet node name must be the same as the unitary system "
    2378             :                                               "outlet node name.");
    2379           0 :                             ShowContinueError(state, format("...Fan outlet node name        = {}", state.dataLoopNodes->NodeID(FanOutletNode)));
    2380           0 :                             ShowContinueError(
    2381             :                                 state,
    2382           0 :                                 format("...Unitary system outlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    2383           0 :                             ErrorsFound = true;
    2384             :                         }
    2385             :                     }
    2386             :                 } else { // IF(Furnace(FurnaceNum)%CoolingCoilUpstream)THEN
    2387           2 :                     if (HeatingCoilInletNode != thisFurnace.FurnaceInletNodeNum) {
    2388           0 :                         ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2389           0 :                         if (thisFurnace.type == HVAC::UnitarySysType::Furnace_HeatCool) {
    2390           0 :                             ShowContinueError(state,
    2391             :                                               "When a draw through fan is specified, the heating coil inlet node name must be the same as the "
    2392             :                                               "furnace inlet node name.");
    2393           0 :                             ShowContinueError(state,
    2394           0 :                                               format("...Heating coil inlet node name = {}", state.dataLoopNodes->NodeID(HeatingCoilInletNode)));
    2395           0 :                             ShowContinueError(
    2396           0 :                                 state, format("...Furnace inlet node name      = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceInletNodeNum)));
    2397             :                         } else {
    2398           0 :                             ShowContinueError(state,
    2399             :                                               "When a draw through fan is specified, the heating coil inlet node name must be the same as the "
    2400             :                                               "unitary system inlet node name.");
    2401           0 :                             ShowContinueError(state,
    2402           0 :                                               format("...Heating coil inlet node name  = {}", state.dataLoopNodes->NodeID(HeatingCoilInletNode)));
    2403           0 :                             ShowContinueError(
    2404           0 :                                 state, format("...UnitarySystem inlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceInletNodeNum)));
    2405             :                         }
    2406           0 :                         ErrorsFound = true;
    2407             :                     }
    2408           2 :                     if (HeatingCoilOutletNode != CoolingCoilInletNode) {
    2409           0 :                         ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2410           0 :                         ShowContinueError(state, "The heating coil outlet node name must be the same as the cooling coil inlet node name.");
    2411           0 :                         ShowContinueError(state, format("...Heating coil outlet node name = {}", state.dataLoopNodes->NodeID(HeatingCoilOutletNode)));
    2412           0 :                         ShowContinueError(state, format("...Cooling coil inlet node name  = {}", state.dataLoopNodes->NodeID(CoolingCoilInletNode)));
    2413           0 :                         ErrorsFound = true;
    2414             :                     }
    2415           2 :                     if (CoolingCoilOutletNode != FanInletNode) {
    2416           0 :                         ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2417           0 :                         ShowContinueError(
    2418             :                             state,
    2419             :                             "When a draw through fan is specified, the cooling coil outlet node name must be the same as the fan inlet node name.");
    2420           0 :                         ShowContinueError(state, format("...Cooling coil outlet node name = {}", state.dataLoopNodes->NodeID(CoolingCoilOutletNode)));
    2421           0 :                         ShowContinueError(state, format("...Fan inlet node name           = {}", state.dataLoopNodes->NodeID(FanInletNode)));
    2422           0 :                         ErrorsFound = true;
    2423             :                     }
    2424           2 :                     if (FanOutletNode != thisFurnace.FurnaceOutletNodeNum) {
    2425           0 :                         ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2426           0 :                         if (thisFurnace.type == HVAC::UnitarySysType::Furnace_HeatCool) {
    2427           0 :                             ShowContinueError(
    2428             :                                 state,
    2429             :                                 "When a draw through fan is specified, the fan outlet node name must be the same as the furnace outlet node name.");
    2430           0 :                             ShowContinueError(state, format("...Fan outlet node name     = {}", state.dataLoopNodes->NodeID(FanOutletNode)));
    2431           0 :                             ShowContinueError(
    2432           0 :                                 state, format("...Furnace outlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    2433             :                         } else {
    2434           0 :                             ShowContinueError(state,
    2435             :                                               "When a draw through fan is specified, the fan outlet node name must be the same as the unitary system "
    2436             :                                               "outlet node name.");
    2437           0 :                             ShowContinueError(state, format("...Fan outlet node name           = {}", state.dataLoopNodes->NodeID(FanOutletNode)));
    2438           0 :                             ShowContinueError(
    2439             :                                 state,
    2440           0 :                                 format("...UnitarySystem outlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    2441             :                         }
    2442           0 :                         ErrorsFound = true;
    2443             :                     }
    2444             :                 }
    2445             :             } // ELSE from IF(Furnace(FurnaceNum)%FanPlace .EQ. BlowThru)THEN
    2446             : 
    2447             :             // Add fan to component sets array
    2448         362 :             BranchNodeConnections::SetUpCompSets(state,
    2449             :                                                  CurrentModuleObject,
    2450         181 :                                                  Alphas(1),
    2451         181 :                                                  Alphas(7),
    2452         181 :                                                  Alphas(8),
    2453         181 :                                                  state.dataLoopNodes->NodeID(FanInletNode),
    2454         181 :                                                  state.dataLoopNodes->NodeID(FanOutletNode));
    2455             : 
    2456             :             // Add DX cooling coil to component sets array
    2457         181 :             if (thisFurnace.bIsIHP) {
    2458           0 :                 BranchNodeConnections::SetUpCompSets(state,
    2459             :                                                      CurrentModuleObject,
    2460           0 :                                                      Alphas(1),
    2461           0 :                                                      Alphas(12),
    2462           0 :                                                      Alphas(13) + " Cooling Coil",
    2463           0 :                                                      state.dataLoopNodes->NodeID(CoolingCoilInletNode),
    2464           0 :                                                      state.dataLoopNodes->NodeID(CoolingCoilOutletNode));
    2465             :             } else {
    2466         362 :                 BranchNodeConnections::SetUpCompSets(state,
    2467             :                                                      CurrentModuleObject,
    2468         181 :                                                      Alphas(1),
    2469         181 :                                                      Alphas(12),
    2470         181 :                                                      Alphas(13),
    2471         181 :                                                      state.dataLoopNodes->NodeID(CoolingCoilInletNode),
    2472         181 :                                                      state.dataLoopNodes->NodeID(CoolingCoilOutletNode));
    2473             :             }
    2474             : 
    2475             :             // Add heating coil to component sets array
    2476         181 :             if (thisFurnace.bIsIHP) {
    2477           0 :                 BranchNodeConnections::SetUpCompSets(state,
    2478             :                                                      CurrentModuleObject,
    2479           0 :                                                      Alphas(1),
    2480           0 :                                                      Alphas(10),
    2481           0 :                                                      Alphas(11) + " Heating Coil",
    2482           0 :                                                      state.dataLoopNodes->NodeID(HeatingCoilInletNode),
    2483           0 :                                                      state.dataLoopNodes->NodeID(HeatingCoilOutletNode));
    2484             :             } else {
    2485         362 :                 BranchNodeConnections::SetUpCompSets(state,
    2486             :                                                      CurrentModuleObject,
    2487         181 :                                                      Alphas(1),
    2488         181 :                                                      Alphas(10),
    2489         181 :                                                      Alphas(11),
    2490         181 :                                                      state.dataLoopNodes->NodeID(HeatingCoilInletNode),
    2491         181 :                                                      state.dataLoopNodes->NodeID(HeatingCoilOutletNode));
    2492             :             }
    2493             : 
    2494         181 :             if (ReheatCoilInletNode > 0) {
    2495             : 
    2496             :                 // Add reheating coil to component sets array
    2497          46 :                 BranchNodeConnections::SetUpCompSets(state,
    2498             :                                                      CurrentModuleObject,
    2499          23 :                                                      Alphas(1),
    2500          23 :                                                      Alphas(15),
    2501          23 :                                                      Alphas(16),
    2502          23 :                                                      state.dataLoopNodes->NodeID(ReheatCoilInletNode),
    2503          23 :                                                      state.dataLoopNodes->NodeID(ReheatCoilOutletNode));
    2504             :             }
    2505             : 
    2506             :             // Set the furnace max outlet temperature
    2507         181 :             thisFurnace.DesignMaxOutletTemp = Numbers(1);
    2508             : 
    2509         181 :             thisFurnace.MaxCoolAirVolFlow = Numbers(2);
    2510         181 :             if (thisFurnace.MaxCoolAirVolFlow <= 0 && thisFurnace.MaxCoolAirVolFlow != DataSizing::AutoSize) {
    2511           0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    2512           0 :                 ShowContinueError(state, format("Illegal {} = {:.7T}", cNumericFields(2), Numbers(2)));
    2513           0 :                 ErrorsFound = true;
    2514             :             }
    2515             : 
    2516         181 :             thisFurnace.MaxHeatAirVolFlow = Numbers(3);
    2517         181 :             if (thisFurnace.MaxHeatAirVolFlow <= 0 && thisFurnace.MaxHeatAirVolFlow != DataSizing::AutoSize) {
    2518           0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    2519           0 :                 ShowContinueError(state, format("Illegal {} = {:.7T}", cNumericFields(3), Numbers(3)));
    2520           0 :                 ErrorsFound = true;
    2521             :             }
    2522             : 
    2523         181 :             thisFurnace.MaxNoCoolHeatAirVolFlow = Numbers(4);
    2524         181 :             if (thisFurnace.MaxNoCoolHeatAirVolFlow < 0 && thisFurnace.MaxNoCoolHeatAirVolFlow != DataSizing::AutoSize) {
    2525           0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    2526           0 :                 ShowContinueError(state, format("Illegal {} = {:.7T}", cNumericFields(4), Numbers(4)));
    2527           0 :                 ErrorsFound = true;
    2528             :             }
    2529             : 
    2530         181 :             if (Numbers(2) != DataSizing::AutoSize && Numbers(3) != DataSizing::AutoSize && Numbers(4) != DataSizing::AutoSize) {
    2531          25 :                 thisFurnace.DesignFanVolFlowRate = max(Numbers(2), Numbers(3), Numbers(4));
    2532             :             } else {
    2533         156 :                 thisFurnace.DesignFanVolFlowRate = DataSizing::AutoSize;
    2534             :             }
    2535             : 
    2536         181 :             if (thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingAirToAirVariableSpeed) {
    2537           4 :                 errFlag = false;
    2538           4 :                 if (thisFurnace.bIsIHP) {
    2539           0 :                     thisFurnace.CoolingCoilIndex = IntegratedHeatPump::GetCoilIndexIHP(state, CoolingCoilType, CoolingCoilName, errFlag);
    2540           0 :                     IHPCoilName = state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).SCCoilName;
    2541           0 :                     thisFurnace.MaxCoolAirVolFlow =
    2542           0 :                         VariableSpeedCoils::GetCoilAirFlowRateVariableSpeed(state, "COIL:COOLING:DX:VARIABLESPEED", IHPCoilName, errFlag);
    2543             :                 } else {
    2544           4 :                     thisFurnace.MaxCoolAirVolFlow =
    2545           4 :                         VariableSpeedCoils::GetCoilAirFlowRateVariableSpeed(state, CoolingCoilType, CoolingCoilName, errFlag);
    2546             :                 }
    2547             : 
    2548           4 :                 if (errFlag) {
    2549           0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2550           0 :                     ErrorsFound = true;
    2551             :                 }
    2552             : 
    2553           4 :                 thisFurnace.MaxNoCoolHeatAirVolFlow = min(thisFurnace.MaxHeatAirVolFlow, thisFurnace.MaxCoolAirVolFlow);
    2554           4 :                 if (thisFurnace.MaxHeatAirVolFlow != DataSizing::AutoSize && thisFurnace.MaxCoolAirVolFlow != DataSizing::AutoSize) {
    2555           0 :                     thisFurnace.DesignFanVolFlowRate = max(thisFurnace.MaxHeatAirVolFlow, thisFurnace.MaxCoolAirVolFlow);
    2556             :                 } else {
    2557           4 :                     thisFurnace.DesignFanVolFlowRate = DataSizing::AutoSize;
    2558             :                 }
    2559             :             }
    2560             : 
    2561         181 :             if (thisFurnace.ActualFanVolFlowRate != DataSizing::AutoSize) {
    2562          25 :                 if (thisFurnace.ActualFanVolFlowRate < thisFurnace.MaxCoolAirVolFlow && thisFurnace.MaxCoolAirVolFlow != DataSizing::AutoSize) {
    2563           0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    2564           0 :                     ShowContinueError(
    2565             :                         state,
    2566           0 :                         format("... air flow rate = {:.7T} in fan object {} is less than the maximum HVAC system air flow rate in cooling mode.",
    2567           0 :                                thisFurnace.ActualFanVolFlowRate,
    2568             :                                FanName));
    2569           0 :                     ShowContinueError(state, format(" The {} is reset to the fan flow rate and the simulation continues.", cNumericFields(2)));
    2570           0 :                     thisFurnace.MaxCoolAirVolFlow = thisFurnace.ActualFanVolFlowRate;
    2571           0 :                     thisFurnace.DesignFanVolFlowRate = thisFurnace.ActualFanVolFlowRate;
    2572             :                 }
    2573          25 :                 if (thisFurnace.ActualFanVolFlowRate < thisFurnace.MaxHeatAirVolFlow && thisFurnace.MaxHeatAirVolFlow != DataSizing::AutoSize) {
    2574           0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    2575           0 :                     ShowContinueError(
    2576             :                         state,
    2577           0 :                         format("... air flow rate = {:.7T} in fan object {} is less than the maximum HVAC system air flow rate in heating mode.",
    2578           0 :                                thisFurnace.ActualFanVolFlowRate,
    2579             :                                FanName));
    2580           0 :                     ShowContinueError(state, format(" The {} is reset to the fan flow rate and the simulation continues.", cNumericFields(3)));
    2581           0 :                     thisFurnace.MaxHeatAirVolFlow = thisFurnace.ActualFanVolFlowRate;
    2582           0 :                     thisFurnace.DesignFanVolFlowRate = thisFurnace.ActualFanVolFlowRate;
    2583             :                 }
    2584             :             }
    2585             : 
    2586         181 :             if (thisFurnace.FanSchedPtr > 0) {
    2587         161 :                 if (!ScheduleManager::CheckScheduleValueMinMax(state, thisFurnace.FanSchedPtr, ">=", 0.0, "<=", 0.0)) {
    2588             :                     //           set air flow control mode:
    2589             :                     //             UseCompressorOnFlow = operate at last cooling or heating air flow requested when compressor is off
    2590             :                     //             UseCompressorOffFlow = operate at value specified by user
    2591             :                     //           AirFlowControl only valid if fan opmode = ContFanCycComp
    2592          96 :                     if (thisFurnace.MaxNoCoolHeatAirVolFlow == 0.0) {
    2593           1 :                         thisFurnace.AirFlowControl = AirFlowControlConstFan::UseCompressorOnFlow;
    2594             :                     } else {
    2595          95 :                         thisFurnace.AirFlowControl = AirFlowControlConstFan::UseCompressorOffFlow;
    2596             :                     }
    2597             :                 }
    2598             :             }
    2599             : 
    2600         181 :             if (thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingAirToAirVariableSpeed) {
    2601           4 :                 errFlag = false;
    2602           4 :                 if (thisFurnace.bIsIHP) {
    2603           0 :                     thisFurnace.CoolingCoilIndex = IntegratedHeatPump::GetCoilIndexIHP(state, CoolingCoilType, CoolingCoilName, errFlag);
    2604           0 :                     IHPCoilName = state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).SCCoilName;
    2605           0 :                     thisFurnace.DesignCoolingCapacity =
    2606           0 :                         VariableSpeedCoils::GetCoilCapacityVariableSpeed(state, "COIL:COOLING:DX:VARIABLESPEED", IHPCoilName, errFlag);
    2607             :                 } else {
    2608           4 :                     thisFurnace.DesignCoolingCapacity =
    2609           4 :                         VariableSpeedCoils::GetCoilCapacityVariableSpeed(state, CoolingCoilType, CoolingCoilName, errFlag);
    2610             :                 }
    2611             : 
    2612           4 :                 if (errFlag) {
    2613           0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2614           0 :                     ErrorsFound = true;
    2615             :                 }
    2616             :             }
    2617             : 
    2618             :             // Set heating convergence tolerance
    2619         181 :             thisFurnace.HeatingConvergenceTolerance = 0.001;
    2620             : 
    2621             :             // Set cooling convergence tolerance
    2622         181 :             thisFurnace.CoolingConvergenceTolerance = 0.001;
    2623             : 
    2624             :             // set minimum outdoor temperature for compressor operation
    2625         181 :             SetMinOATCompressor(state, FurnaceNum, cCurrentModuleObject, ErrorsFound);
    2626             : 
    2627             :         } // End of the HeatCool Furnace Loop
    2628             : 
    2629             :         // Get the data for the Unitary System HeatPump AirToAir (UnitarySystem:HeatPump:AirToAir)
    2630         132 :         for (int HeatPumpNum = 1; HeatPumpNum <= NumHeatPump; ++HeatPumpNum) {
    2631             : 
    2632          35 :             CurrentModuleObject = "AirLoopHVAC:UnitaryHeatPump:AirToAir";
    2633          35 :             FanInletNode = 0;
    2634          35 :             FanOutletNode = 0;
    2635          35 :             CoolingCoilInletNode = 0;
    2636          35 :             CoolingCoilOutletNode = 0;
    2637          35 :             HeatingCoilInletNode = 0;
    2638          35 :             HeatingCoilOutletNode = 0;
    2639          35 :             SupHeatCoilInletNode = 0;
    2640          35 :             SupHeatCoilOutletNode = 0;
    2641          35 :             CoolingCoilType = ' ';
    2642          35 :             CoolingCoilName = ' ';
    2643          35 :             HeatingCoilType = ' ';
    2644          35 :             HeatingCoilName = ' ';
    2645             : 
    2646          35 :             FurnaceNum = NumHeatOnly + NumHeatCool + NumUnitaryHeatOnly + NumUnitaryHeatCool + HeatPumpNum;
    2647          35 :             auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    2648          35 :             thisFurnace.iterationMode.allocate(3);
    2649             : 
    2650          35 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    2651             :                                                                      CurrentModuleObject,
    2652             :                                                                      HeatPumpNum,
    2653             :                                                                      Alphas,
    2654             :                                                                      NumAlphas,
    2655             :                                                                      Numbers,
    2656             :                                                                      NumNumbers,
    2657             :                                                                      IOStatus,
    2658             :                                                                      lNumericBlanks,
    2659             :                                                                      lAlphaBlanks,
    2660             :                                                                      cAlphaFields,
    2661             :                                                                      cNumericFields);
    2662             : 
    2663          70 :             GlobalNames::VerifyUniqueInterObjectName(
    2664          35 :                 state, state.dataFurnaces->UniqueFurnaceNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
    2665             : 
    2666          35 :             thisFurnace.type = HVAC::UnitarySysType::Unitary_HeatPump_AirToAir;
    2667          35 :             thisFurnace.Name = Alphas(1);
    2668             : 
    2669          35 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, thisFurnace.Name};
    2670             : 
    2671          35 :             if (lAlphaBlanks(2)) {
    2672           6 :                 thisFurnace.SchedPtr = ScheduleManager::ScheduleAlwaysOn;
    2673             :             } else {
    2674          29 :                 thisFurnace.SchedPtr = ScheduleManager::GetScheduleIndex(state, Alphas(2));
    2675          29 :                 if (thisFurnace.SchedPtr == 0) {
    2676           0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    2677           0 :                     ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(2), Alphas(2)));
    2678           0 :                     ErrorsFound = true;
    2679             :                 }
    2680             :             }
    2681             : 
    2682          35 :             thisFurnace.FurnaceInletNodeNum =
    2683          35 :                 NodeInputManager::GetOnlySingleNode(state,
    2684          35 :                                                     Alphas(3),
    2685             :                                                     ErrorsFound,
    2686             :                                                     DataLoopNode::ConnectionObjectType::AirLoopHVACUnitaryHeatPumpAirToAir,
    2687          35 :                                                     Alphas(1),
    2688             :                                                     DataLoopNode::NodeFluidType::Air,
    2689             :                                                     DataLoopNode::ConnectionType::Inlet,
    2690             :                                                     NodeInputManager::CompFluidStream::Primary,
    2691             :                                                     DataLoopNode::ObjectIsParent);
    2692             : 
    2693          35 :             thisFurnace.FurnaceOutletNodeNum =
    2694          35 :                 NodeInputManager::GetOnlySingleNode(state,
    2695          35 :                                                     Alphas(4),
    2696             :                                                     ErrorsFound,
    2697             :                                                     DataLoopNode::ConnectionObjectType::AirLoopHVACUnitaryHeatPumpAirToAir,
    2698          35 :                                                     Alphas(1),
    2699             :                                                     DataLoopNode::NodeFluidType::Air,
    2700             :                                                     DataLoopNode::ConnectionType::Outlet,
    2701             :                                                     NodeInputManager::CompFluidStream::Primary,
    2702             :                                                     DataLoopNode::ObjectIsParent);
    2703             : 
    2704          35 :             BranchNodeConnections::TestCompSet(state, CurrentModuleObject, Alphas(1), Alphas(3), Alphas(4), "Air Nodes");
    2705             : 
    2706             :             // Get the Controlling Zone or Location of the Furnace Thermostat
    2707          35 :             thisFurnace.ControlZoneNum = Util::FindItemInList(Alphas(5), state.dataHeatBal->Zone);
    2708          35 :             if (thisFurnace.ControlZoneNum == 0) {
    2709           0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    2710           0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(5), Alphas(5)));
    2711           0 :                 ErrorsFound = true;
    2712             :             }
    2713             : 
    2714             :             // Get the node number for the zone with the thermostat
    2715          35 :             if (thisFurnace.ControlZoneNum > 0) {
    2716          35 :                 AirNodeFound = false;
    2717          35 :                 AirLoopFound = false;
    2718          35 :                 int ControlledZoneNum = thisFurnace.ControlZoneNum;
    2719             :                 //             Find the controlled zone number for the specified thermostat location
    2720          35 :                 thisFurnace.NodeNumOfControlledZone = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).ZoneNode;
    2721             :                 //             Determine if furnace is on air loop served by the thermostat location specified
    2722          35 :                 for (int zoneInNode = 1; zoneInNode <= state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).NumInletNodes; ++zoneInNode) {
    2723          35 :                     int AirLoopNumber = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).InletNodeAirLoopNum(zoneInNode);
    2724          35 :                     if (AirLoopNumber > 0) {
    2725          35 :                         for (int BranchNum = 1; BranchNum <= state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).NumBranches; ++BranchNum) {
    2726          65 :                             for (int CompNum = 1;
    2727          65 :                                  CompNum <= state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).Branch(BranchNum).TotalComponents;
    2728             :                                  ++CompNum) {
    2729          65 :                                 if (!Util::SameString(state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).Branch(BranchNum).Comp(CompNum).Name,
    2730         165 :                                                       Alphas(1)) ||
    2731          35 :                                     !Util::SameString(
    2732          35 :                                         state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).Branch(BranchNum).Comp(CompNum).TypeOf,
    2733             :                                         CurrentModuleObject))
    2734          30 :                                     continue;
    2735          35 :                                 AirLoopFound = true;
    2736          35 :                                 thisFurnace.ZoneInletNode = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).InletNode(zoneInNode);
    2737          35 :                                 break;
    2738             :                             }
    2739          35 :                             if (AirLoopFound) break;
    2740             :                         }
    2741         115 :                         for (TstatZoneNum = 1; TstatZoneNum <= state.dataZoneCtrls->NumTempControlledZones; ++TstatZoneNum) {
    2742          80 :                             if (state.dataZoneCtrls->TempControlledZone(TstatZoneNum).ActualZoneNum != thisFurnace.ControlZoneNum) continue;
    2743          35 :                             AirNodeFound = true;
    2744             :                         }
    2745          35 :                         for (TstatZoneNum = 1; TstatZoneNum <= state.dataZoneCtrls->NumComfortControlledZones; ++TstatZoneNum) {
    2746           0 :                             if (state.dataZoneCtrls->ComfortControlledZone(TstatZoneNum).ActualZoneNum != thisFurnace.ControlZoneNum) continue;
    2747           0 :                             AirNodeFound = true;
    2748             :                         }
    2749             :                     }
    2750          35 :                     if (AirLoopFound) break;
    2751             :                 }
    2752          35 :                 if (!AirNodeFound) {
    2753           0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    2754           0 :                     ShowContinueError(state, "Did not find air node (zone with thermostat).");
    2755           0 :                     ShowContinueError(state, format("Specified {} = {}", cAlphaFields(5), Alphas(5)));
    2756           0 :                     ShowContinueError(
    2757             :                         state, "Both a ZoneHVAC:EquipmentConnections object and a ZoneControl:Thermostat object must be specified for this zone.");
    2758           0 :                     ErrorsFound = true;
    2759             :                 }
    2760          35 :                 if (!AirLoopFound) {
    2761           0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    2762           0 :                     ShowContinueError(state, "Did not find correct AirLoopHVAC.");
    2763           0 :                     ShowContinueError(state, format("Specified {} = {}", cAlphaFields(5), Alphas(5)));
    2764           0 :                     ErrorsFound = true;
    2765             :                 }
    2766             :             }
    2767             : 
    2768             :             // Get fan data
    2769          35 :             FanName = Alphas(7);
    2770             : 
    2771          35 :             thisFurnace.fanType = static_cast<HVAC::FanType>(getEnumValue(HVAC::fanTypeNamesUC, Alphas(6)));
    2772             : 
    2773          35 :             if (thisFurnace.fanType == HVAC::FanType::OnOff || thisFurnace.fanType == HVAC::FanType::Constant) {
    2774             : 
    2775          35 :                 if ((thisFurnace.FanIndex = Fans::GetFanIndex(state, FanName)) == 0) {
    2776           0 :                     ShowSevereItemNotFound(state, eoh, cAlphaFields(7), FanName);
    2777           0 :                     ErrorsFound = true;
    2778             :                 } else {
    2779          35 :                     auto *fan = state.dataFans->fans(thisFurnace.FanIndex);
    2780          35 :                     FanInletNode = fan->inletNodeNum;
    2781          35 :                     FanOutletNode = fan->outletNodeNum;
    2782          35 :                     thisFurnace.FanAvailSchedPtr = fan->availSchedNum;
    2783          35 :                     thisFurnace.ActualFanVolFlowRate = fan->maxAirFlowRate;
    2784             :                 }
    2785             :             }
    2786             : 
    2787             :             // Get heating coil type and name data
    2788          35 :             HeatingCoilType = Alphas(8);
    2789          35 :             HeatingCoilName = Alphas(9);
    2790             : 
    2791          35 :             errFlag = false;
    2792             : 
    2793          68 :             if (Util::SameString(HeatingCoilType, "COIL:HEATING:DX:VARIABLESPEED") ||
    2794          68 :                 Util::SameString(HeatingCoilType, "COILSYSTEM:INTEGRATEDHEATPUMP:AIRSOURCE")) {
    2795           3 :                 thisFurnace.HeatingCoilType_Num = HVAC::Coil_HeatingAirToAirVariableSpeed;
    2796           3 :                 if (Util::SameString(HeatingCoilType, "COILSYSTEM:INTEGRATEDHEATPUMP:AIRSOURCE")) thisFurnace.bIsIHP = true;
    2797             :             } else {
    2798          32 :                 thisFurnace.HeatingCoilType_Num = DXCoils::GetCoilTypeNum(state, HeatingCoilType, HeatingCoilName, errFlag);
    2799             :             }
    2800             : 
    2801          35 :             if (errFlag) {
    2802           0 :                 ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2803           0 :                 ErrorsFound = true;
    2804             :             }
    2805             : 
    2806          35 :             if (thisFurnace.HeatingCoilType_Num == HVAC::CoilDX_HeatingEmpirical) {
    2807          32 :                 ValidateComponent(state, HeatingCoilType, HeatingCoilName, IsNotOK, CurrentModuleObject);
    2808          32 :                 if (IsNotOK) {
    2809           0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2810           0 :                     ErrorsFound = true;
    2811             : 
    2812             :                 } else { // mine data from DX heating coil
    2813             : 
    2814          32 :                     DXCoils::GetDXCoilIndex(state, HeatingCoilName, thisFurnace.HeatingCoilIndex, IsNotOK);
    2815          32 :                     if (IsNotOK) {
    2816           0 :                         ShowContinueError(state, format("...occurs {} = {}", CurrentModuleObject, Alphas(1)));
    2817           0 :                         ErrorsFound = true;
    2818             :                     }
    2819             : 
    2820             :                     // Get the Heating Coil Node Names
    2821          32 :                     errFlag = false;
    2822          32 :                     HeatingCoilInletNode = DXCoils::GetCoilInletNode(state, HeatingCoilType, HeatingCoilName, errFlag);
    2823          32 :                     HeatingCoilOutletNode = DXCoils::GetCoilOutletNode(state, HeatingCoilType, HeatingCoilName, errFlag);
    2824          32 :                     if (errFlag) {
    2825           0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2826           0 :                         ErrorsFound = true;
    2827             :                     }
    2828             : 
    2829             :                     // Get the design heating capacity
    2830          32 :                     errFlag = false;
    2831          32 :                     thisFurnace.DesignHeatingCapacity = DXCoils::GetCoilCapacity(state, HeatingCoilType, HeatingCoilName, errFlag);
    2832          32 :                     if (errFlag) {
    2833           0 :                         ShowContinueError(state, format("...occurs in {} ={}", CurrentModuleObject, Alphas(1)));
    2834           0 :                         ErrorsFound = true;
    2835             :                     }
    2836             : 
    2837             :                 } // IF (IsNotOK) THEN
    2838           3 :             } else if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingAirToAirVariableSpeed) {
    2839           3 :                 ValidateComponent(state, HeatingCoilType, HeatingCoilName, IsNotOK, CurrentModuleObject);
    2840           3 :                 if (IsNotOK) {
    2841           0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2842           0 :                     ErrorsFound = true;
    2843             :                 } else {
    2844           3 :                     if (thisFurnace.bIsIHP) {
    2845           1 :                         thisFurnace.HeatingCoilIndex = IntegratedHeatPump::GetCoilIndexIHP(state, HeatingCoilType, HeatingCoilName, errFlag);
    2846           1 :                         IHPCoilIndex = thisFurnace.HeatingCoilIndex;
    2847           1 :                         IHPCoilName = state.dataIntegratedHP->IntegratedHeatPumps(IHPCoilIndex).SHCoilName;
    2848             :                         HeatingCoilInletNode =
    2849           1 :                             VariableSpeedCoils::GetCoilInletNodeVariableSpeed(state, "COIL:HEATING:DX:VARIABLESPEED", IHPCoilName, errFlag);
    2850             :                         HeatingCoilOutletNode =
    2851           1 :                             VariableSpeedCoils::GetCoilOutletNodeVariableSpeed(state, "COIL:HEATING:DX:VARIABLESPEED", IHPCoilName, errFlag);
    2852             :                     } else {
    2853           2 :                         thisFurnace.HeatingCoilIndex =
    2854           2 :                             VariableSpeedCoils::GetCoilIndexVariableSpeed(state, HeatingCoilType, HeatingCoilName, errFlag);
    2855           2 :                         HeatingCoilInletNode = VariableSpeedCoils::GetCoilInletNodeVariableSpeed(state, HeatingCoilType, HeatingCoilName, errFlag);
    2856           2 :                         HeatingCoilOutletNode = VariableSpeedCoils::GetCoilOutletNodeVariableSpeed(state, HeatingCoilType, HeatingCoilName, errFlag);
    2857             :                     }
    2858             :                 }
    2859             :             } else {
    2860           0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    2861           0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(8), Alphas(8)));
    2862           0 :                 ErrorsFound = true;
    2863             :             }
    2864             : 
    2865             :             // Get Cooling Coil Information if available
    2866          35 :             CoolingCoilType = Alphas(10);
    2867          35 :             CoolingCoilName = Alphas(11);
    2868             : 
    2869          68 :             if (Util::SameString(CoolingCoilType, "COIL:COOLING:DX:VARIABLESPEED") ||
    2870          68 :                 Util::SameString(CoolingCoilType, "COILSYSTEM:INTEGRATEDHEATPUMP:AIRSOURCE")) {
    2871           3 :                 thisFurnace.CoolingCoilType_Num = HVAC::Coil_CoolingAirToAirVariableSpeed;
    2872           3 :                 if (Util::SameString(CoolingCoilType, "COILSYSTEM:INTEGRATEDHEATPUMP:AIRSOURCE")) thisFurnace.bIsIHP = true;
    2873             :             }
    2874             : 
    2875          35 :             ValidateComponent(state, CoolingCoilType, CoolingCoilName, IsNotOK, CurrentModuleObject);
    2876             : 
    2877          35 :             if (IsNotOK) {
    2878           0 :                 ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2879           0 :                 ErrorsFound = true;
    2880             : 
    2881             :             } else { // mine data from DX cooling coil
    2882             : 
    2883          35 :                 errFlag = false;
    2884          35 :                 PrintMessage = false;
    2885             : 
    2886          35 :                 if (thisFurnace.CoolingCoilType_Num != HVAC::Coil_CoolingAirToAirVariableSpeed) {
    2887          32 :                     thisFurnace.CoolingCoilType_Num = DXCoils::GetCoilTypeNum(state, CoolingCoilType, CoolingCoilName, errFlag, PrintMessage);
    2888             :                 }
    2889             : 
    2890             :                 // If coil type not found, check to see if a HX assisted cooling coil is used.
    2891          35 :                 if (thisFurnace.CoolingCoilType_Num == 0) {
    2892           0 :                     errFlag = false;
    2893           0 :                     PrintMessage = false;
    2894           0 :                     thisFurnace.CoolingCoilType_Num =
    2895           0 :                         HVACHXAssistedCoolingCoil::GetCoilGroupTypeNum(state, CoolingCoilType, CoolingCoilName, errFlag, PrintMessage);
    2896             :                 }
    2897             : 
    2898          35 :                 if (thisFurnace.CoolingCoilType_Num == HVAC::CoilDX_CoolingSingleSpeed) {
    2899             : 
    2900             :                     // Get the cooling coil node numbers
    2901          32 :                     errFlag = false;
    2902          32 :                     DXCoils::GetDXCoilIndex(state, CoolingCoilName, thisFurnace.CoolingCoilIndex, errFlag);
    2903          32 :                     CoolingCoilInletNode = DXCoils::GetCoilInletNode(state, CoolingCoilType, CoolingCoilName, errFlag);
    2904          32 :                     CoolingCoilOutletNode = DXCoils::GetCoilOutletNode(state, CoolingCoilType, CoolingCoilName, errFlag);
    2905          32 :                     if (errFlag) {
    2906           0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2907           0 :                         ErrorsFound = true;
    2908             :                     }
    2909             : 
    2910             :                     // Get the DX cooling coil design capacity
    2911          32 :                     errFlag = false;
    2912          32 :                     thisFurnace.DesignCoolingCapacity = DXCoils::GetCoilCapacity(state, CoolingCoilType, CoolingCoilName, errFlag);
    2913          32 :                     if (errFlag) {
    2914           0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2915           0 :                         ErrorsFound = true;
    2916             :                     }
    2917             : 
    2918           3 :                 } else if (thisFurnace.CoolingCoilType_Num == HVAC::CoilDX_CoolingHXAssisted) {
    2919             : 
    2920             :                     // Get the cooling coil node numbers
    2921           0 :                     errFlag = false;
    2922           0 :                     HVACHXAssistedCoolingCoil::GetHXDXCoilIndex(state, CoolingCoilName, thisFurnace.CoolingCoilIndex, errFlag);
    2923           0 :                     CoolingCoilInletNode = HVACHXAssistedCoolingCoil::GetCoilInletNode(state, CoolingCoilType, CoolingCoilName, errFlag);
    2924           0 :                     CoolingCoilOutletNode = HVACHXAssistedCoolingCoil::GetCoilOutletNode(state, CoolingCoilType, CoolingCoilName, errFlag);
    2925           0 :                     if (errFlag) {
    2926           0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2927           0 :                         ErrorsFound = true;
    2928             :                     }
    2929             : 
    2930             :                     // Get the heat exchanger assisted cooling coil design capacity
    2931           0 :                     errFlag = false;
    2932           0 :                     thisFurnace.DesignCoolingCapacity = HVACHXAssistedCoolingCoil::GetCoilCapacity(state, CoolingCoilType, CoolingCoilName, errFlag);
    2933           0 :                     if (errFlag) {
    2934           0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2935           0 :                         ErrorsFound = true;
    2936             :                     }
    2937             : 
    2938             :                     // get the actual index to the DX cooling coil object
    2939           0 :                     DXCoilIndex = HVACHXAssistedCoolingCoil::GetActualDXCoilIndex(state, CoolingCoilType, CoolingCoilName, ErrorsFound);
    2940           0 :                     thisFurnace.ActualDXCoilIndexForHXAssisted = DXCoilIndex;
    2941             : 
    2942           3 :                 } else if (thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingAirToAirVariableSpeed) {
    2943             :                     // BOS ADDED, AUG/2012, VARIIABLE SPEED DX COOLING COIL
    2944             :                     //  Furnace(FurnaceNum)%DXCoolCoilType = 'COIL:COOLING:DX:VARIABLESPEED'
    2945             :                     //  Furnace(FurnaceNum)%DXCoolCoilName = CoolingCoilName
    2946           3 :                     ValidateComponent(state, CoolingCoilType, CoolingCoilName, IsNotOK, CurrentModuleObject);
    2947           3 :                     if (IsNotOK) {
    2948           0 :                         ShowContinueError(state, format("...specified in {}=\"{}\".", CurrentModuleObject, Alphas(1)));
    2949           0 :                         ErrorsFound = true;
    2950             :                     } else {
    2951           3 :                         errFlag = false;
    2952           3 :                         if (thisFurnace.bIsIHP) {
    2953           1 :                             thisFurnace.CoolingCoilIndex = IntegratedHeatPump::GetCoilIndexIHP(state, CoolingCoilType, CoolingCoilName, errFlag);
    2954           1 :                             IHPCoilName = state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).SCCoilName;
    2955             :                         } else {
    2956           2 :                             thisFurnace.CoolingCoilIndex =
    2957           2 :                                 VariableSpeedCoils::GetCoilIndexVariableSpeed(state, CoolingCoilType, CoolingCoilName, errFlag);
    2958           2 :                             IHPCoilName = CoolingCoilName;
    2959             :                         }
    2960             : 
    2961           3 :                         if (errFlag) {
    2962           0 :                             ShowContinueError(state, format("...specified in {}=\"{}\".", CurrentModuleObject, Alphas(1)));
    2963           0 :                             ErrorsFound = true;
    2964             :                         }
    2965             : 
    2966           3 :                         if (thisFurnace.bIsIHP) {
    2967             :                             CoolingCoilInletNode =
    2968           1 :                                 VariableSpeedCoils::GetCoilInletNodeVariableSpeed(state, "COIL:COOLING:DX:VARIABLESPEED", IHPCoilName, errFlag);
    2969             :                             CoolingCoilOutletNode =
    2970           1 :                                 VariableSpeedCoils::GetCoilOutletNodeVariableSpeed(state, "COIL:COOLING:DX:VARIABLESPEED", IHPCoilName, errFlag);
    2971           1 :                             thisFurnace.CondenserNodeNum = VariableSpeedCoils::GetVSCoilCondenserInletNode(state, IHPCoilName, errFlag);
    2972             :                         } else {
    2973             :                             CoolingCoilInletNode =
    2974           2 :                                 VariableSpeedCoils::GetCoilInletNodeVariableSpeed(state, CoolingCoilType, CoolingCoilName, errFlag);
    2975             :                             CoolingCoilOutletNode =
    2976           2 :                                 VariableSpeedCoils::GetCoilOutletNodeVariableSpeed(state, CoolingCoilType, CoolingCoilName, errFlag);
    2977           2 :                             thisFurnace.CondenserNodeNum = VariableSpeedCoils::GetVSCoilCondenserInletNode(state, CoolingCoilName, errFlag);
    2978             :                         }
    2979             : 
    2980           3 :                         if (errFlag) {
    2981           0 :                             ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2982           0 :                             ErrorsFound = true;
    2983             :                         }
    2984             :                     }
    2985             :                 } else {
    2986           0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    2987           0 :                     ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(10), Alphas(10)));
    2988           0 :                     ErrorsFound = true;
    2989             :                 }
    2990             :             }
    2991             : 
    2992          35 :             if (thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingAirToAirVariableSpeed &&
    2993           3 :                 thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingAirToAirVariableSpeed) {
    2994             :                 // Furnace(FurnaceNum)%WatertoAirHPType = WatertoAir_VarSpeedEquationFit
    2995           3 :                 if (thisFurnace.bIsIHP) {
    2996           3 :                     VariableSpeedCoils::SetVarSpeedCoilData(state,
    2997           1 :                                                             state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).SCCoilIndex,
    2998             :                                                             ErrorsFound,
    2999             :                                                             _,
    3000           1 :                                                             state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).SHCoilIndex);
    3001             :                 } else {
    3002           2 :                     VariableSpeedCoils::SetVarSpeedCoilData(state, thisFurnace.CoolingCoilIndex, ErrorsFound, _, thisFurnace.HeatingCoilIndex);
    3003             :                 }
    3004             :             }
    3005             : 
    3006             :             // Get supplemental heating coil information
    3007          35 :             SuppHeatCoilType = Alphas(12);
    3008          35 :             SuppHeatCoilName = Alphas(13);
    3009          35 :             thisFurnace.SuppHeatCoilType = SuppHeatCoilType;
    3010          35 :             thisFurnace.SuppHeatCoilName = SuppHeatCoilName;
    3011          35 :             errFlag = false;
    3012          35 :             if (Util::SameString(SuppHeatCoilType, "Coil:Heating:Fuel") || Util::SameString(SuppHeatCoilType, "Coil:Heating:Electric")) {
    3013             : 
    3014          34 :                 thisFurnace.SuppHeatCoilType_Num = HeatingCoils::GetHeatingCoilTypeNum(state, SuppHeatCoilType, SuppHeatCoilName, errFlag);
    3015          34 :                 if (errFlag) {
    3016           0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3017           0 :                     ErrorsFound = true;
    3018             :                 } else {
    3019          34 :                     IsNotOK = false;
    3020          34 :                     ValidateComponent(state, SuppHeatCoilType, SuppHeatCoilName, IsNotOK, CurrentModuleObject);
    3021          34 :                     if (IsNotOK) {
    3022           0 :                         ShowContinueError(state, format("In {} \"{}\"", CurrentModuleObject, Alphas(1)));
    3023           0 :                         ErrorsFound = true;
    3024             : 
    3025             :                     } else { // mine data from the supplemental heating coil
    3026             : 
    3027          34 :                         HeatingCoils::GetCoilIndex(state, SuppHeatCoilName, thisFurnace.SuppHeatCoilIndex, IsNotOK);
    3028          34 :                         if (IsNotOK) {
    3029           0 :                             ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3030           0 :                             ErrorsFound = true;
    3031             :                         }
    3032             : 
    3033             :                         // Get the Supplemental Heating Coil Inlet Node Number
    3034          34 :                         errFlag = false;
    3035          34 :                         SupHeatCoilInletNode = HeatingCoils::GetCoilInletNode(state, SuppHeatCoilType, SuppHeatCoilName, errFlag);
    3036          34 :                         if (errFlag) {
    3037           0 :                             ShowContinueError(state, format("...occurs in {} \"{}\"", CurrentModuleObject, Alphas(1)));
    3038           0 :                             ErrorsFound = true;
    3039             :                         }
    3040             : 
    3041             :                         // Get the Supplemental Heating Coil Outlet Node Number
    3042          34 :                         errFlag = false;
    3043          34 :                         SupHeatCoilOutletNode = HeatingCoils::GetCoilOutletNode(state, SuppHeatCoilType, SuppHeatCoilName, errFlag);
    3044             : 
    3045          34 :                         if (errFlag) {
    3046           0 :                             ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3047           0 :                             ErrorsFound = true;
    3048             :                         }
    3049             : 
    3050             :                         // Get the supplemental heating coil design capacity
    3051          34 :                         errFlag = false;
    3052          34 :                         thisFurnace.DesignSuppHeatingCapacity = HeatingCoils::GetCoilCapacity(state, SuppHeatCoilType, SuppHeatCoilName, errFlag);
    3053          34 :                         if (errFlag) {
    3054           0 :                             ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3055           0 :                             ErrorsFound = true;
    3056             :                         }
    3057             : 
    3058             :                     } // IF (IsNotOK) THEN
    3059             :                 }
    3060           1 :             } else if (Util::SameString(SuppHeatCoilType, "Coil:Heating:Water")) {
    3061           1 :                 thisFurnace.SuppHeatCoilType_Num = HVAC::Coil_HeatingWater;
    3062           1 :                 ValidateComponent(state, SuppHeatCoilType, SuppHeatCoilName, IsNotOK, CurrentModuleObject);
    3063           1 :                 if (IsNotOK) {
    3064           0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3065           0 :                     ErrorsFound = true;
    3066             :                 } else { // mine data from heating coil object
    3067             : 
    3068             :                     // Get the Heating Coil water Inlet or control Node number
    3069           1 :                     errFlag = false;
    3070           1 :                     thisFurnace.SuppCoilControlNode = WaterCoils::GetCoilWaterInletNode(state, "Coil:Heating:Water", SuppHeatCoilName, errFlag);
    3071           1 :                     if (errFlag) {
    3072           0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3073           0 :                         ErrorsFound = true;
    3074             :                     }
    3075             : 
    3076             :                     // Get the ReHeat Coil hot water max volume flow rate
    3077           1 :                     errFlag = false;
    3078           1 :                     thisFurnace.MaxSuppCoilFluidFlow = WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", SuppHeatCoilName, errFlag);
    3079           1 :                     if (errFlag) {
    3080           0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3081           0 :                         ErrorsFound = true;
    3082             :                     }
    3083             : 
    3084             :                     // Get the ReHeat Coil Inlet Node
    3085           1 :                     errFlag = false;
    3086           1 :                     SupHeatCoilInletNode = WaterCoils::GetCoilInletNode(state, "Coil:Heating:Water", SuppHeatCoilName, errFlag);
    3087           1 :                     thisFurnace.SuppCoilAirInletNode = SupHeatCoilInletNode;
    3088           1 :                     if (errFlag) {
    3089           0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3090           0 :                         ErrorsFound = true;
    3091             :                     }
    3092             : 
    3093             :                     // Get the ReHeat Coil Outlet Node
    3094           1 :                     errFlag = false;
    3095           1 :                     SupHeatCoilOutletNode = WaterCoils::GetCoilOutletNode(state, "Coil:Heating:Water", SuppHeatCoilName, errFlag);
    3096           1 :                     thisFurnace.SuppCoilAirOutletNode = SupHeatCoilOutletNode;
    3097           1 :                     if (errFlag) {
    3098           0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3099           0 :                         ErrorsFound = true;
    3100             :                     }
    3101           1 :                     errFlag = false;
    3102           1 :                     HVACControllers::CheckCoilWaterInletNode(state, thisFurnace.CoilControlNode, errFlag);
    3103           1 :                     if (!errFlag) { // then did find a controller so that is bad
    3104           0 :                         ShowSevereError(state,
    3105           0 :                                         format("{} = {} has a conflicting Controller:WaterCoil object", CurrentModuleObject, thisFurnace.Name));
    3106           0 :                         ShowContinueError(state, "Hot water coils are controlled directly by unitary and furnace systems.");
    3107           0 :                         ShowContinueError(state, "No water coil controller should be input for the coil.");
    3108           0 :                         ErrorsFound = true;
    3109             :                     }
    3110             :                 }
    3111             : 
    3112           0 :             } else if (Util::SameString(SuppHeatCoilType, "Coil:Heating:Steam")) {
    3113           0 :                 thisFurnace.SuppHeatCoilType_Num = HVAC::Coil_HeatingSteam;
    3114           0 :                 ValidateComponent(state, SuppHeatCoilType, SuppHeatCoilName, IsNotOK, CurrentModuleObject);
    3115           0 :                 if (IsNotOK) {
    3116           0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3117           0 :                     ErrorsFound = true;
    3118             :                 } else { // mine data from heating coil object
    3119             : 
    3120           0 :                     errFlag = false;
    3121           0 :                     thisFurnace.SuppHeatCoilIndex = SteamCoils::GetSteamCoilIndex(state, "COIL:HEATING:STEAM", SuppHeatCoilName, errFlag);
    3122           0 :                     if (thisFurnace.SuppHeatCoilIndex == 0) {
    3123           0 :                         ShowSevereError(state, format("{} illegal {} = {}", CurrentModuleObject, cAlphaFields(12), SuppHeatCoilName));
    3124           0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3125           0 :                         ErrorsFound = true;
    3126             :                     }
    3127             : 
    3128             :                     // Get the Heating Coil steam inlet node number
    3129           0 :                     errFlag = false;
    3130           0 :                     thisFurnace.SuppCoilControlNode = SteamCoils::GetCoilSteamInletNode(state, "Coil:Heating:Steam", SuppHeatCoilName, errFlag);
    3131           0 :                     if (errFlag) {
    3132           0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3133           0 :                         ErrorsFound = true;
    3134             :                     }
    3135             : 
    3136             :                     // Get the Heating Coil steam max volume flow rate
    3137           0 :                     thisFurnace.MaxSuppCoilFluidFlow = SteamCoils::GetCoilMaxSteamFlowRate(state, thisFurnace.SuppHeatCoilIndex, errFlag);
    3138           0 :                     if (thisFurnace.MaxSuppCoilFluidFlow > 0.0) {
    3139           0 :                         SteamIndex = 0; // Function GetSatDensityRefrig will look up steam index if 0 is passed
    3140           0 :                         SteamDensity = FluidProperties::GetSatDensityRefrig(
    3141           0 :                             state, fluidNameSteam, state.dataFurnaces->TempSteamIn, 1.0, SteamIndex, getAirLoopHVACHeatCoolInput);
    3142           0 :                         thisFurnace.MaxSuppCoilFluidFlow =
    3143           0 :                             SteamCoils::GetCoilMaxSteamFlowRate(state, thisFurnace.SuppHeatCoilIndex, errFlag) * SteamDensity;
    3144             :                     }
    3145             : 
    3146             :                     // Get the Heating Coil Inlet Node
    3147           0 :                     errFlag = false;
    3148           0 :                     SupHeatCoilInletNode = SteamCoils::GetCoilAirInletNode(state, thisFurnace.SuppHeatCoilIndex, SuppHeatCoilName, errFlag);
    3149           0 :                     thisFurnace.SuppCoilAirInletNode = SupHeatCoilInletNode;
    3150           0 :                     if (errFlag) {
    3151           0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3152           0 :                         ErrorsFound = true;
    3153             :                     }
    3154             : 
    3155             :                     // Get the Heating Coil Outlet Node
    3156           0 :                     errFlag = false;
    3157           0 :                     SupHeatCoilOutletNode = SteamCoils::GetCoilAirOutletNode(state, thisFurnace.SuppHeatCoilIndex, SuppHeatCoilName, errFlag);
    3158           0 :                     thisFurnace.SuppCoilAirOutletNode = SupHeatCoilOutletNode;
    3159           0 :                     if (errFlag) {
    3160           0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3161           0 :                         ErrorsFound = true;
    3162             :                     }
    3163             :                 }
    3164             : 
    3165             :             } else {
    3166           0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3167           0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(12), Alphas(12)));
    3168           0 :                 ErrorsFound = true;
    3169             :             } // IF (Furnace(FurnaceNum)%HeatingCoilType_Num == Coil_HeatingGasOrOtherFuel .OR. &, etc.
    3170             : 
    3171          35 :             thisFurnace.fanPlace = static_cast<HVAC::FanPlace>(getEnumValue(HVAC::fanPlaceNamesUC, Alphas(14)));
    3172          35 :             assert(thisFurnace.fanPlace != HVAC::FanPlace::Invalid);
    3173             : 
    3174          35 :             thisFurnace.FanSchedPtr = ScheduleManager::GetScheduleIndex(state, Alphas(15));
    3175          35 :             if (!lAlphaBlanks(15) && thisFurnace.FanSchedPtr == 0) {
    3176           0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3177           0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(15), Alphas(15)));
    3178           0 :                 ErrorsFound = true;
    3179          35 :             } else if (lAlphaBlanks(15)) {
    3180           0 :                 thisFurnace.fanOp = HVAC::FanOp::Cycling;
    3181           0 :                 if (thisFurnace.fanType != HVAC::FanType::OnOff) {
    3182           0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, thisFurnace.Name));
    3183           0 :                     ShowContinueError(state, format("{} = {}", cAlphaFields(6), Alphas(6)));
    3184           0 :                     ShowContinueError(state, format("Fan type must be Fan:OnOff when {} = Blank.", cAlphaFields(15)));
    3185           0 :                     ErrorsFound = true;
    3186             :                 }
    3187             :             }
    3188             : 
    3189          35 :             if (thisFurnace.fanType == HVAC::FanType::Constant) {
    3190           0 :                 if (thisFurnace.FanSchedPtr > 0) {
    3191           0 :                     if (!ScheduleManager::CheckScheduleValueMinMax(state, thisFurnace.FanSchedPtr, ">", 0.0, "<=", 1.0)) {
    3192           0 :                         ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3193           0 :                         ShowContinueError(state, format("For {} = {}", cAlphaFields(7), Alphas(7)));
    3194           0 :                         ShowContinueError(state, "Fan operating mode must be continuous (fan operating mode schedule values > 0).");
    3195           0 :                         ShowContinueError(state, format("Error found in {} = {}", cAlphaFields(15), Alphas(15)));
    3196           0 :                         ShowContinueError(state, "...schedule values must be (>0., <=1.)");
    3197           0 :                         ErrorsFound = true;
    3198             :                     }
    3199             :                 }
    3200             :             }
    3201             : 
    3202             :             // Dehumidification Control Type
    3203          35 :             if (Util::SameString(Alphas(16), "None") || Util::SameString(Alphas(16), "Multimode") || Util::SameString(Alphas(16), "CoolReheat")) {
    3204          35 :                 AirNodeFound = false;
    3205          35 :                 if (Util::SameString(Alphas(16), "Multimode")) {
    3206           0 :                     thisFurnace.DehumidControlType_Num = DehumidificationControlMode::Multimode;
    3207           0 :                     thisFurnace.Humidistat = true;
    3208           0 :                     if (thisFurnace.CoolingCoilType_Num != HVAC::CoilDX_CoolingHXAssisted) {
    3209           0 :                         ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3210           0 :                         ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(16), Alphas(16)));
    3211           0 :                         ShowContinueError(state, "Multimode control must be used with a Heat Exchanger Assisted Cooling Coil.");
    3212           0 :                         ErrorsFound = true;
    3213             :                     }
    3214             :                 }
    3215          35 :                 if (Util::SameString(Alphas(16), "CoolReheat")) {
    3216           3 :                     thisFurnace.DehumidControlType_Num = DehumidificationControlMode::CoolReheat;
    3217           3 :                     thisFurnace.Humidistat = true;
    3218             :                 }
    3219          35 :                 if (Util::SameString(Alphas(16), "None")) {
    3220          32 :                     thisFurnace.DehumidControlType_Num = DehumidificationControlMode::None;
    3221          32 :                     thisFurnace.Humidistat = false;
    3222             :                 }
    3223          35 :                 if (thisFurnace.Humidistat) {
    3224           6 :                     for (HStatZoneNum = 1; HStatZoneNum <= state.dataZoneCtrls->NumHumidityControlZones; ++HStatZoneNum) {
    3225           3 :                         if (state.dataZoneCtrls->HumidityControlZone(HStatZoneNum).ActualZoneNum != thisFurnace.ControlZoneNum) continue;
    3226           3 :                         AirNodeFound = true;
    3227             :                     }
    3228           3 :                     if (!AirNodeFound) {
    3229           0 :                         ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3230           0 :                         ShowContinueError(state, "Did not find Air Node (Zone with Humidistat).");
    3231           0 :                         ShowContinueError(state, format("Specified {} = {}", cAlphaFields(5), Alphas(5)));
    3232           0 :                         ErrorsFound = true;
    3233             :                     }
    3234             :                 }
    3235             :             } else { // invalid input or blank
    3236           0 :                 if (!lAlphaBlanks(16)) {
    3237           0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3238           0 :                     ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(16), Alphas(16)));
    3239           0 :                     ErrorsFound = true;
    3240             :                 } else {
    3241           0 :                     thisFurnace.Humidistat = false;
    3242           0 :                     thisFurnace.DehumidControlType_Num = DehumidificationControlMode::None;
    3243             :                 }
    3244             :             }
    3245             : 
    3246             :             // Check node names for child components
    3247          35 :             if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
    3248          35 :                 if (FanInletNode != thisFurnace.FurnaceInletNodeNum) {
    3249           0 :                     ShowSevereError(state, format("For {} \"{}\"", CurrentModuleObject, Alphas(1)));
    3250           0 :                     ShowContinueError(
    3251             :                         state,
    3252             :                         "When a blow through fan is specified, the fan inlet node name must be the same as the unitary system inlet node name.");
    3253           0 :                     ShowContinueError(state, format("...Fan inlet node name            = {}", state.dataLoopNodes->NodeID(FanInletNode)));
    3254           0 :                     ShowContinueError(state,
    3255           0 :                                       format("...Unitary system inlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceInletNodeNum)));
    3256           0 :                     ErrorsFound = true;
    3257             :                 }
    3258          35 :                 if (FanOutletNode != CoolingCoilInletNode) {
    3259           0 :                     ShowSevereError(state, format("For {} \"{}\"", CurrentModuleObject, Alphas(1)));
    3260           0 :                     ShowContinueError(
    3261             :                         state,
    3262             :                         "When a blow through fan is specified, the fan outlet node name must be the same as the cooling coil inlet node name.");
    3263           0 :                     ShowContinueError(state, format("...Fan outlet node name         = {}", state.dataLoopNodes->NodeID(FanOutletNode)));
    3264           0 :                     ShowContinueError(state, format("...Cooling coil inlet node name = {}", state.dataLoopNodes->NodeID(CoolingCoilInletNode)));
    3265           0 :                     ErrorsFound = true;
    3266             :                 }
    3267          35 :                 if (CoolingCoilOutletNode != HeatingCoilInletNode) {
    3268           0 :                     ShowSevereError(state, format("For {} \"{}\"", CurrentModuleObject, Alphas(1)));
    3269           0 :                     ShowContinueError(state, "The cooling coil outlet node name must be the same as the heating coil inlet node name.");
    3270           0 :                     ShowContinueError(state, format("...Cooling coil outlet node name = {}", state.dataLoopNodes->NodeID(CoolingCoilOutletNode)));
    3271           0 :                     ShowContinueError(state, format("...Heating coil inlet node name  = {}", state.dataLoopNodes->NodeID(HeatingCoilInletNode)));
    3272           0 :                     ErrorsFound = true;
    3273             :                 }
    3274          35 :                 if (HeatingCoilOutletNode != SupHeatCoilInletNode) {
    3275           0 :                     ShowSevereError(state, format("For {} \"{}\"", CurrentModuleObject, Alphas(1)));
    3276           0 :                     ShowContinueError(state,
    3277             :                                       "When a blow through fan is specified, the heating coil outlet node name must be the same as the supplemental "
    3278             :                                       "heating coil inlet node name.");
    3279           0 :                     ShowContinueError(
    3280           0 :                         state, format("...Heating coil outlet node name              = {}", state.dataLoopNodes->NodeID(HeatingCoilOutletNode)));
    3281           0 :                     ShowContinueError(
    3282           0 :                         state, format("...Supplemental heating coil inlet node name  = {}", state.dataLoopNodes->NodeID(SupHeatCoilInletNode)));
    3283           0 :                     ErrorsFound = true;
    3284             :                 }
    3285          35 :                 if (SupHeatCoilOutletNode != thisFurnace.FurnaceOutletNodeNum) {
    3286           0 :                     ShowSevereError(state, format("For {} \"{}\"", CurrentModuleObject, Alphas(1)));
    3287           0 :                     ShowContinueError(state,
    3288             :                                       "The supplemental heating coil outlet node name must be the same as the unitary system outlet node name.");
    3289           0 :                     ShowContinueError(
    3290           0 :                         state, format("...Supplemental heating coil outlet node name = {}", state.dataLoopNodes->NodeID(SupHeatCoilOutletNode)));
    3291           0 :                     ShowContinueError(
    3292             :                         state,
    3293           0 :                         format("...Unitary system outlet node name            = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    3294           0 :                     ErrorsFound = true;
    3295             :                 }
    3296             :             } else {
    3297           0 :                 if (CoolingCoilInletNode != thisFurnace.FurnaceInletNodeNum) {
    3298           0 :                     ShowSevereError(state, format("For {} \"{}\"", CurrentModuleObject, Alphas(1)));
    3299           0 :                     ShowContinueError(state,
    3300             :                                       "When a draw through fan is specified, the cooling coil inlet node name must be the same as the unitary system "
    3301             :                                       "inlet node name.");
    3302           0 :                     ShowContinueError(state, format("...Cooling coil inlet node name   = {}", state.dataLoopNodes->NodeID(CoolingCoilInletNode)));
    3303           0 :                     ShowContinueError(state,
    3304           0 :                                       format("...Unitary system inlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceInletNodeNum)));
    3305           0 :                     ErrorsFound = true;
    3306             :                 }
    3307           0 :                 if (CoolingCoilOutletNode != HeatingCoilInletNode) {
    3308           0 :                     ShowSevereError(state, format("For {} \"{}\"", CurrentModuleObject, Alphas(1)));
    3309           0 :                     ShowContinueError(state, "The cooling coil outlet node name must be the same as the heating coil inlet node name.");
    3310           0 :                     ShowContinueError(state, format("...Cooling coil outlet node name = {}", state.dataLoopNodes->NodeID(CoolingCoilOutletNode)));
    3311           0 :                     ShowContinueError(state, format("...Heating coil inlet node name  = {}", state.dataLoopNodes->NodeID(HeatingCoilInletNode)));
    3312           0 :                     ErrorsFound = true;
    3313             :                 }
    3314           0 :                 if (HeatingCoilOutletNode != FanInletNode) {
    3315           0 :                     ShowSevereError(state, format("For {} \"{}\"", CurrentModuleObject, Alphas(1)));
    3316           0 :                     ShowContinueError(
    3317             :                         state,
    3318             :                         "When a draw through fan is specified, the heating coil outlet node name must be the same as the fan inlet node name.");
    3319           0 :                     ShowContinueError(state, format("...Heating coil outlet node name = {}", state.dataLoopNodes->NodeID(HeatingCoilOutletNode)));
    3320           0 :                     ShowContinueError(state, format("...Fan inlet node name           = {}", state.dataLoopNodes->NodeID(FanInletNode)));
    3321           0 :                     ErrorsFound = true;
    3322             :                 }
    3323           0 :                 if (FanOutletNode != SupHeatCoilInletNode) {
    3324           0 :                     ShowSevereError(state, format("For {} \"{}\"", CurrentModuleObject, Alphas(1)));
    3325           0 :                     ShowContinueError(state,
    3326             :                                       "When a draw through fan is specified, the fan outlet node name must be the same as the supplemental heating "
    3327             :                                       "coil inlet node name.");
    3328           0 :                     ShowContinueError(state,
    3329           0 :                                       format("...Fan outlet node name                       = {}", state.dataLoopNodes->NodeID(FanOutletNode)));
    3330           0 :                     ShowContinueError(
    3331           0 :                         state, format("...Supplemental heating coil inlet node name  = {}", state.dataLoopNodes->NodeID(SupHeatCoilInletNode)));
    3332           0 :                     ErrorsFound = true;
    3333             :                 }
    3334           0 :                 if (SupHeatCoilOutletNode != thisFurnace.FurnaceOutletNodeNum) {
    3335           0 :                     ShowSevereError(state, format("For {} \"{}\"", CurrentModuleObject, Alphas(1)));
    3336           0 :                     ShowContinueError(state,
    3337             :                                       "The supplemental heating coil outlet node name must be the same as the unitary system outlet node name.");
    3338           0 :                     ShowContinueError(
    3339           0 :                         state, format("...Supplemental heating coil outlet node name = {}", state.dataLoopNodes->NodeID(SupHeatCoilOutletNode)));
    3340           0 :                     ShowContinueError(
    3341             :                         state,
    3342           0 :                         format("...Unitary system outlet node name            = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    3343           0 :                     ErrorsFound = true;
    3344             :                 }
    3345             :             }
    3346             : 
    3347             :             // Add component sets array
    3348          35 :             if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
    3349          35 :                 CompSetFanInlet = Alphas(3);
    3350          35 :                 CompSetCoolInlet = "UNDEFINED";
    3351             :             } else {
    3352           0 :                 CompSetFanInlet = "UNDEFINED";
    3353           0 :                 CompSetCoolInlet = Alphas(3);
    3354             :             }
    3355          35 :             BranchNodeConnections::SetUpCompSets(state, CurrentModuleObject, Alphas(1), Alphas(6), Alphas(7), CompSetFanInlet, "UNDEFINED");
    3356             : 
    3357             :             // Add DX cooling coil to component sets array
    3358          35 :             if (thisFurnace.bIsIHP) {
    3359           3 :                 BranchNodeConnections::SetUpCompSets(
    3360           3 :                     state, CurrentModuleObject, Alphas(1), Alphas(10), Alphas(11) + " Cooling Coil", CompSetCoolInlet, "UNDEFINED");
    3361             :             } else {
    3362          34 :                 BranchNodeConnections::SetUpCompSets(state, CurrentModuleObject, Alphas(1), Alphas(10), Alphas(11), CompSetCoolInlet, "UNDEFINED");
    3363             :             }
    3364             :             // Add DX heating coil to component sets array
    3365          35 :             if (thisFurnace.bIsIHP) {
    3366           3 :                 BranchNodeConnections::SetUpCompSets(
    3367           3 :                     state, CurrentModuleObject, Alphas(1), Alphas(8), Alphas(9) + " Heating Coil", "UNDEFINED", "UNDEFINED");
    3368             :             } else {
    3369          34 :                 BranchNodeConnections::SetUpCompSets(state, CurrentModuleObject, Alphas(1), Alphas(8), Alphas(9), "UNDEFINED", "UNDEFINED");
    3370             :             }
    3371             : 
    3372             :             // Add supplemental heating coil to component sets array
    3373          35 :             BranchNodeConnections::SetUpCompSets(state, CurrentModuleObject, Alphas(1), Alphas(12), Alphas(13), "UNDEFINED", Alphas(4));
    3374             : 
    3375          35 :             thisFurnace.MaxCoolAirVolFlow = Numbers(1);
    3376          35 :             if (thisFurnace.MaxCoolAirVolFlow <= 0 && thisFurnace.MaxCoolAirVolFlow != DataSizing::AutoSize) {
    3377           0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3378           0 :                 ShowContinueError(state, format("Illegal {} = {:.7T}", cNumericFields(1), Numbers(1)));
    3379           0 :                 ErrorsFound = true;
    3380             :             }
    3381             : 
    3382          35 :             thisFurnace.MaxHeatAirVolFlow = Numbers(2);
    3383          35 :             if (thisFurnace.MaxHeatAirVolFlow <= 0 && thisFurnace.MaxHeatAirVolFlow != DataSizing::AutoSize) {
    3384           0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3385           0 :                 ShowContinueError(state, format("Illegal {} = {:.7T}", cNumericFields(2), Numbers(2)));
    3386           0 :                 ErrorsFound = true;
    3387             :             }
    3388             : 
    3389          35 :             thisFurnace.MaxNoCoolHeatAirVolFlow = Numbers(3);
    3390          35 :             if (thisFurnace.MaxNoCoolHeatAirVolFlow < 0 && thisFurnace.MaxNoCoolHeatAirVolFlow != DataSizing::AutoSize) {
    3391           0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3392           0 :                 ShowContinueError(state, format("Illegal {} = {:.7T}", cNumericFields(3), Numbers(3)));
    3393           0 :                 ErrorsFound = true;
    3394             :             }
    3395             : 
    3396          35 :             if (thisFurnace.FanSchedPtr > 0) {
    3397          35 :                 if (!ScheduleManager::CheckScheduleValueMinMax(
    3398             :                         state, thisFurnace.FanSchedPtr, ">=", 0.0, "<=", 0.0)) { // Autodesk:Note Range is 0 to 0?
    3399             :                     //           set air flow control mode:
    3400             :                     //             UseCompressorOnFlow = operate at last cooling or heating air flow requested when compressor is off
    3401             :                     //             UseCompressorOffFlow = operate at value specified by user
    3402             :                     //           AirFlowControl only valid if fan opmode = ContFanCycComp
    3403          16 :                     if (thisFurnace.MaxNoCoolHeatAirVolFlow == 0.0) {
    3404           0 :                         thisFurnace.AirFlowControl = AirFlowControlConstFan::UseCompressorOnFlow;
    3405             :                     } else {
    3406          16 :                         thisFurnace.AirFlowControl = AirFlowControlConstFan::UseCompressorOffFlow;
    3407             :                     }
    3408             :                 }
    3409             :             }
    3410             : 
    3411          35 :             if (Numbers(1) != DataSizing::AutoSize && Numbers(2) != DataSizing::AutoSize && Numbers(3) != DataSizing::AutoSize) {
    3412          21 :                 thisFurnace.DesignFanVolFlowRate = max(Numbers(1), Numbers(2), Numbers(3));
    3413             :             } else {
    3414          14 :                 thisFurnace.DesignFanVolFlowRate = DataSizing::AutoSize;
    3415             :             }
    3416             : 
    3417          35 :             if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingAirToAirVariableSpeed) {
    3418           3 :                 errFlag = false;
    3419             : 
    3420           3 :                 if (thisFurnace.bIsIHP) {
    3421           1 :                     IHPCoilName = state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).SHCoilName;
    3422           1 :                     thisFurnace.MaxHeatAirVolFlow =
    3423           1 :                         VariableSpeedCoils::GetCoilAirFlowRateVariableSpeed(state, "COIL:HEATING:DX:VARIABLESPEED", IHPCoilName, errFlag);
    3424           1 :                     IHPCoilName = state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).SCCoilName;
    3425           1 :                     thisFurnace.MaxCoolAirVolFlow =
    3426           1 :                         VariableSpeedCoils::GetCoilAirFlowRateVariableSpeed(state, "COIL:COOLING:DX:VARIABLESPEED", IHPCoilName, errFlag);
    3427             :                 } else {
    3428           2 :                     thisFurnace.MaxHeatAirVolFlow =
    3429           2 :                         VariableSpeedCoils::GetCoilAirFlowRateVariableSpeed(state, HeatingCoilType, HeatingCoilName, errFlag);
    3430           2 :                     thisFurnace.MaxCoolAirVolFlow =
    3431           2 :                         VariableSpeedCoils::GetCoilAirFlowRateVariableSpeed(state, CoolingCoilType, CoolingCoilName, errFlag);
    3432             :                 }
    3433             : 
    3434           3 :                 if (errFlag) {
    3435           0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3436           0 :                     ErrorsFound = true;
    3437             :                 }
    3438             : 
    3439           3 :                 thisFurnace.MaxNoCoolHeatAirVolFlow = min(thisFurnace.MaxHeatAirVolFlow, thisFurnace.MaxCoolAirVolFlow);
    3440           3 :                 if (thisFurnace.MaxHeatAirVolFlow != DataSizing::AutoSize && thisFurnace.MaxCoolAirVolFlow != DataSizing::AutoSize) {
    3441           3 :                     thisFurnace.DesignFanVolFlowRate = max(thisFurnace.MaxHeatAirVolFlow, thisFurnace.MaxCoolAirVolFlow);
    3442             :                 } else {
    3443           0 :                     thisFurnace.DesignFanVolFlowRate = DataSizing::AutoSize;
    3444             :                 }
    3445             :             }
    3446             : 
    3447          35 :             if (thisFurnace.ActualFanVolFlowRate != DataSizing::AutoSize) {
    3448          21 :                 if (thisFurnace.ActualFanVolFlowRate < thisFurnace.MaxCoolAirVolFlow && thisFurnace.MaxCoolAirVolFlow != DataSizing::AutoSize) {
    3449           0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3450           0 :                     ShowContinueError(
    3451             :                         state,
    3452           0 :                         format("... air flow rate = {:.7T} in fan object {} is less than the maximum HVAC system air flow rate in cooling mode.",
    3453           0 :                                thisFurnace.ActualFanVolFlowRate,
    3454             :                                FanName));
    3455           0 :                     ShowContinueError(state, format(" The {} is reset to the fan flow rate and the simulation continues.", cNumericFields(1)));
    3456           0 :                     thisFurnace.MaxCoolAirVolFlow = thisFurnace.ActualFanVolFlowRate;
    3457           0 :                     thisFurnace.DesignFanVolFlowRate = thisFurnace.ActualFanVolFlowRate;
    3458             :                 }
    3459          21 :                 if (thisFurnace.ActualFanVolFlowRate < thisFurnace.MaxHeatAirVolFlow && thisFurnace.MaxHeatAirVolFlow != DataSizing::AutoSize) {
    3460           0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3461           0 :                     ShowContinueError(
    3462             :                         state,
    3463           0 :                         format("... air flow rate = {:.7T} in fan object {} is less than the maximum HVAC system air flow rate in heating mode.",
    3464           0 :                                thisFurnace.ActualFanVolFlowRate,
    3465             :                                FanName));
    3466           0 :                     ShowContinueError(state, format(" The {} is reset to the fan flow rate and the simulation continues.", cNumericFields(2)));
    3467           0 :                     thisFurnace.MaxHeatAirVolFlow = thisFurnace.ActualFanVolFlowRate;
    3468           0 :                     thisFurnace.DesignFanVolFlowRate = thisFurnace.ActualFanVolFlowRate;
    3469             :                 }
    3470             :             }
    3471             : 
    3472             :             // Set heating convergence tolerance
    3473          35 :             thisFurnace.HeatingConvergenceTolerance = 0.001;
    3474             : 
    3475             :             //       Mine heatpump outdoor condenser node from DX coil object
    3476          35 :             errFlag = false;
    3477          35 :             if (thisFurnace.CoolingCoilType_Num == HVAC::CoilDX_CoolingSingleSpeed) {
    3478          32 :                 thisFurnace.CondenserNodeNum = DXCoils::GetCoilCondenserInletNode(state, CoolingCoilType, CoolingCoilName, errFlag);
    3479           3 :             } else if (thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingAirToAirVariableSpeed) {
    3480           3 :                 if (thisFurnace.bIsIHP) {
    3481           1 :                     IHPCoilName = state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).SCCoilName;
    3482           1 :                     thisFurnace.CondenserNodeNum = VariableSpeedCoils::GetVSCoilCondenserInletNode(state, IHPCoilName, errFlag);
    3483             :                 } else {
    3484           2 :                     thisFurnace.CondenserNodeNum = VariableSpeedCoils::GetVSCoilCondenserInletNode(state, CoolingCoilName, errFlag);
    3485             :                 }
    3486             :             } else {
    3487           0 :                 thisFurnace.CondenserNodeNum =
    3488           0 :                     DXCoils::GetCoilCondenserInletNode(state,
    3489             :                                                        "Coil:Cooling:DX:SingleSpeed",
    3490           0 :                                                        HVACHXAssistedCoolingCoil::GetHXDXCoilName(state, CoolingCoilType, CoolingCoilName, errFlag),
    3491             :                                                        errFlag);
    3492             :             }
    3493          35 :             if (errFlag) {
    3494           0 :                 ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3495           0 :                 ErrorsFound = true;
    3496             :             }
    3497             : 
    3498          35 :             if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingAirToAirVariableSpeed) {
    3499           3 :                 errFlag = false;
    3500           3 :                 if (thisFurnace.bIsIHP) {
    3501           1 :                     IHPCoilName = state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).SHCoilName;
    3502           1 :                     thisFurnace.DesignHeatingCapacity =
    3503           1 :                         VariableSpeedCoils::GetCoilCapacityVariableSpeed(state, "Coil:Heating:DX:VariableSpeed", IHPCoilName, errFlag);
    3504             :                 } else {
    3505           2 :                     thisFurnace.DesignHeatingCapacity =
    3506           2 :                         VariableSpeedCoils::GetCoilCapacityVariableSpeed(state, HeatingCoilType, HeatingCoilName, errFlag);
    3507             :                 }
    3508             : 
    3509           3 :                 if (errFlag) {
    3510           0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3511           0 :                     ErrorsFound = true;
    3512             :                 }
    3513             :             }
    3514             : 
    3515          35 :             if (thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingAirToAirVariableSpeed) {
    3516           3 :                 errFlag = false;
    3517           3 :                 if (thisFurnace.bIsIHP) {
    3518           1 :                     IHPCoilName = state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).SCCoilName;
    3519           1 :                     thisFurnace.DesignCoolingCapacity =
    3520           1 :                         VariableSpeedCoils::GetCoilCapacityVariableSpeed(state, "COIL:COOLING:DX:VARIABLESPEED", IHPCoilName, errFlag);
    3521             :                 } else {
    3522           2 :                     thisFurnace.DesignCoolingCapacity =
    3523           2 :                         VariableSpeedCoils::GetCoilCapacityVariableSpeed(state, CoolingCoilType, CoolingCoilName, errFlag);
    3524             :                 }
    3525             : 
    3526           3 :                 if (errFlag) {
    3527           0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3528           0 :                     ErrorsFound = true;
    3529             :                 }
    3530             :             }
    3531             : 
    3532             :             // Set cooling convergence tolerance
    3533          35 :             thisFurnace.CoolingConvergenceTolerance = 0.001;
    3534             : 
    3535             :             // Set the furnace max outlet temperature
    3536          35 :             thisFurnace.DesignMaxOutletTemp = Numbers(4);
    3537             : 
    3538             :             // Set maximum supply air temperature for supplemental heating coil
    3539          35 :             thisFurnace.MaxOATSuppHeat = Numbers(5);
    3540          70 :             OutputReportPredefined::PreDefTableEntry(
    3541          35 :                 state, state.dataOutRptPredefined->pdchDXHeatCoilSuppHiT, HeatingCoilName, thisFurnace.MaxOATSuppHeat);
    3542             : 
    3543             :             // set minimum outdoor temperature for compressor operation
    3544          35 :             SetMinOATCompressor(state, FurnaceNum, cCurrentModuleObject, ErrorsFound);
    3545             : 
    3546             :         } // End of the Unitary System HeatPump Loop
    3547             : 
    3548             :         // Get the Input for the Water to Air Heat Pump (UnitarySystem:HeatPump:WaterToAir)
    3549         236 :         for (int HeatPumpNum = 1; HeatPumpNum <= NumWaterToAirHeatPump; ++HeatPumpNum) {
    3550             : 
    3551         139 :             CurrentModuleObject = "AirLoopHVAC:UnitaryHeatPump:WaterToAir";
    3552         139 :             FanInletNode = 0;
    3553         139 :             FanOutletNode = 0;
    3554         139 :             CoolingCoilInletNode = 0;
    3555         139 :             CoolingCoilOutletNode = 0;
    3556         139 :             HeatingCoilInletNode = 0;
    3557         139 :             HeatingCoilOutletNode = 0;
    3558         139 :             SupHeatCoilInletNode = 0;
    3559         139 :             SupHeatCoilOutletNode = 0;
    3560         139 :             CoolingCoilType = ' ';
    3561         139 :             CoolingCoilName = ' ';
    3562         139 :             HeatingCoilType = ' ';
    3563         139 :             HeatingCoilName = ' ';
    3564             : 
    3565         139 :             FurnaceNum = NumHeatOnly + NumHeatCool + NumUnitaryHeatOnly + NumUnitaryHeatCool + NumHeatPump + HeatPumpNum;
    3566         139 :             auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    3567         139 :             thisFurnace.iterationMode.allocate(3);
    3568             : 
    3569         139 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    3570             :                                                                      CurrentModuleObject,
    3571             :                                                                      HeatPumpNum,
    3572             :                                                                      Alphas,
    3573             :                                                                      NumAlphas,
    3574             :                                                                      Numbers,
    3575             :                                                                      NumNumbers,
    3576             :                                                                      IOStatus,
    3577             :                                                                      lNumericBlanks,
    3578             :                                                                      lAlphaBlanks,
    3579             :                                                                      cAlphaFields,
    3580             :                                                                      cNumericFields);
    3581             : 
    3582         278 :             GlobalNames::VerifyUniqueInterObjectName(
    3583         139 :                 state, state.dataFurnaces->UniqueFurnaceNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
    3584             : 
    3585         139 :             thisFurnace.type = HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir;
    3586         139 :             thisFurnace.Name = Alphas(1);
    3587             : 
    3588         139 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, thisFurnace.Name};
    3589             : 
    3590         139 :             if (lAlphaBlanks(2)) {
    3591           0 :                 thisFurnace.SchedPtr = ScheduleManager::ScheduleAlwaysOn;
    3592             :             } else {
    3593         139 :                 thisFurnace.SchedPtr = ScheduleManager::GetScheduleIndex(state, Alphas(2));
    3594         139 :                 if (thisFurnace.SchedPtr == 0) {
    3595           0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3596           0 :                     ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(2), Alphas(2)));
    3597           0 :                     ErrorsFound = true;
    3598             :                 }
    3599             :             }
    3600             : 
    3601         139 :             thisFurnace.FurnaceInletNodeNum =
    3602         139 :                 NodeInputManager::GetOnlySingleNode(state,
    3603         139 :                                                     Alphas(3),
    3604             :                                                     ErrorsFound,
    3605             :                                                     DataLoopNode::ConnectionObjectType::AirLoopHVACUnitaryHeatPumpWaterToAir,
    3606         139 :                                                     Alphas(1),
    3607             :                                                     DataLoopNode::NodeFluidType::Air,
    3608             :                                                     DataLoopNode::ConnectionType::Inlet,
    3609             :                                                     NodeInputManager::CompFluidStream::Primary,
    3610             :                                                     DataLoopNode::ObjectIsParent);
    3611             : 
    3612         139 :             thisFurnace.FurnaceOutletNodeNum =
    3613         139 :                 NodeInputManager::GetOnlySingleNode(state,
    3614         139 :                                                     Alphas(4),
    3615             :                                                     ErrorsFound,
    3616             :                                                     DataLoopNode::ConnectionObjectType::AirLoopHVACUnitaryHeatPumpWaterToAir,
    3617         139 :                                                     Alphas(1),
    3618             :                                                     DataLoopNode::NodeFluidType::Air,
    3619             :                                                     DataLoopNode::ConnectionType::Outlet,
    3620             :                                                     NodeInputManager::CompFluidStream::Primary,
    3621             :                                                     DataLoopNode::ObjectIsParent);
    3622             : 
    3623         139 :             BranchNodeConnections::TestCompSet(state, CurrentModuleObject, Alphas(1), Alphas(3), Alphas(4), "Air Nodes");
    3624             : 
    3625             :             // Get the Controlling Zone or Location of the Furnace Thermostat
    3626         139 :             thisFurnace.ControlZoneNum = Util::FindItemInList(Alphas(5), state.dataHeatBal->Zone);
    3627         139 :             if (thisFurnace.ControlZoneNum == 0) {
    3628           0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3629           0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(5), Alphas(5)));
    3630           0 :                 ErrorsFound = true;
    3631             :             }
    3632             : 
    3633             :             // Get the node number for the zone with the thermostat
    3634         139 :             if (thisFurnace.ControlZoneNum > 0) {
    3635         139 :                 AirNodeFound = false;
    3636         139 :                 AirLoopFound = false;
    3637         139 :                 int ControlledZoneNum = thisFurnace.ControlZoneNum;
    3638             :                 //             Find the controlled zone number for the specified thermostat location
    3639         139 :                 thisFurnace.NodeNumOfControlledZone = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).ZoneNode;
    3640             :                 //             Determine if furnace is on air loop served by the thermostat location specified
    3641         139 :                 for (int zoneInNode = 1; zoneInNode <= state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).NumInletNodes; ++zoneInNode) {
    3642         139 :                     int AirLoopNumber = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).InletNodeAirLoopNum(zoneInNode);
    3643         139 :                     if (AirLoopNumber > 0) {
    3644         139 :                         for (int BranchNum = 1; BranchNum <= state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).NumBranches; ++BranchNum) {
    3645         268 :                             for (int CompNum = 1;
    3646         268 :                                  CompNum <= state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).Branch(BranchNum).TotalComponents;
    3647             :                                  ++CompNum) {
    3648         268 :                                 if (!Util::SameString(state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).Branch(BranchNum).Comp(CompNum).Name,
    3649         675 :                                                       Alphas(1)) ||
    3650         139 :                                     !Util::SameString(
    3651         139 :                                         state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).Branch(BranchNum).Comp(CompNum).TypeOf,
    3652             :                                         CurrentModuleObject))
    3653         129 :                                     continue;
    3654         139 :                                 AirLoopFound = true;
    3655         139 :                                 thisFurnace.ZoneInletNode = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).InletNode(zoneInNode);
    3656         139 :                                 break;
    3657             :                             }
    3658         139 :                             if (AirLoopFound) break;
    3659             :                         }
    3660        7066 :                         for (TstatZoneNum = 1; TstatZoneNum <= state.dataZoneCtrls->NumTempControlledZones; ++TstatZoneNum) {
    3661        6927 :                             if (state.dataZoneCtrls->TempControlledZone(TstatZoneNum).ActualZoneNum != thisFurnace.ControlZoneNum) continue;
    3662         139 :                             AirNodeFound = true;
    3663             :                         }
    3664         139 :                         for (TstatZoneNum = 1; TstatZoneNum <= state.dataZoneCtrls->NumComfortControlledZones; ++TstatZoneNum) {
    3665           0 :                             if (state.dataZoneCtrls->ComfortControlledZone(TstatZoneNum).ActualZoneNum != thisFurnace.ControlZoneNum) continue;
    3666           0 :                             AirNodeFound = true;
    3667             :                         }
    3668             :                     }
    3669         139 :                     if (AirLoopFound) break;
    3670             :                 }
    3671         139 :                 if (!AirNodeFound) {
    3672           0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3673           0 :                     ShowContinueError(state, "Did not find air node (zone with thermostat).");
    3674           0 :                     ShowContinueError(state, format("Specified {} = {}", cAlphaFields(5), Alphas(5)));
    3675           0 :                     ShowContinueError(
    3676             :                         state, "Both a ZoneHVAC:EquipmentConnections object and a ZoneControl:Thermostat object must be specified for this zone.");
    3677           0 :                     ErrorsFound = true;
    3678             :                 }
    3679         139 :                 if (!AirLoopFound) {
    3680           0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3681           0 :                     ShowContinueError(state, "Did not find correct AirLoopHVAC.");
    3682           0 :                     ShowContinueError(state, format("Specified {} = {}", cAlphaFields(5), Alphas(5)));
    3683           0 :                     ErrorsFound = true;
    3684             :                 }
    3685             :             }
    3686             : 
    3687             :             // Get fan data
    3688         139 :             FanName = Alphas(7);
    3689         139 :             errFlag = false;
    3690         139 :             thisFurnace.fanType = static_cast<HVAC::FanType>(getEnumValue(HVAC::fanTypeNamesUC, Alphas(6)));
    3691             : 
    3692         139 :             if (thisFurnace.fanType != HVAC::FanType::OnOff) {
    3693           0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3694           0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(6), Alphas(6)));
    3695           0 :                 ErrorsFound = true;
    3696             : 
    3697         139 :             } else if ((thisFurnace.FanIndex = Fans::GetFanIndex(state, FanName)) == 0) {
    3698           0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(7), FanName);
    3699           0 :                 ErrorsFound = true;
    3700             : 
    3701             :             } else {
    3702         139 :                 auto *fan = state.dataFans->fans(thisFurnace.FanIndex);
    3703         139 :                 FanInletNode = fan->inletNodeNum;
    3704         139 :                 FanOutletNode = fan->outletNodeNum;
    3705         139 :                 thisFurnace.FanAvailSchedPtr = fan->availSchedNum;
    3706             :             }
    3707             : 
    3708             :             // Get heating coil type and name data
    3709         139 :             if (Alphas(8) == "COIL:HEATING:WATERTOAIRHEATPUMP:PARAMETERESTIMATION") {
    3710          14 :                 HeatingCoilType = Alphas(8);
    3711          14 :                 thisFurnace.HeatingCoilType_Num = HVAC::Coil_HeatingWaterToAirHP;
    3712          14 :                 HeatingCoilName = Alphas(9);
    3713          14 :                 ValidateComponent(state, HeatingCoilType, HeatingCoilName, IsNotOK, CurrentModuleObject);
    3714          14 :                 if (IsNotOK) {
    3715           0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3716           0 :                     ErrorsFound = true;
    3717             :                 } else {
    3718          14 :                     thisFurnace.HeatingCoilIndex = WaterToAirHeatPump::GetCoilIndex(state, HeatingCoilType, HeatingCoilName, errFlag);
    3719          14 :                     HeatingCoilInletNode = WaterToAirHeatPump::GetCoilInletNode(state, HeatingCoilType, HeatingCoilName, errFlag);
    3720          14 :                     HeatingCoilOutletNode = WaterToAirHeatPump::GetCoilOutletNode(state, HeatingCoilType, HeatingCoilName, errFlag);
    3721             :                 }
    3722         125 :             } else if (Alphas(8) == "COIL:HEATING:WATERTOAIRHEATPUMP:EQUATIONFIT") {
    3723         111 :                 HeatingCoilType = Alphas(8);
    3724         111 :                 thisFurnace.HeatingCoilType_Num = HVAC::Coil_HeatingWaterToAirHPSimple;
    3725         111 :                 HeatingCoilName = Alphas(9);
    3726         111 :                 ValidateComponent(state, HeatingCoilType, HeatingCoilName, IsNotOK, CurrentModuleObject);
    3727         111 :                 if (IsNotOK) {
    3728           0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3729           0 :                     ErrorsFound = true;
    3730             :                 } else {
    3731         111 :                     thisFurnace.HeatingCoilIndex = WaterToAirHeatPumpSimple::GetCoilIndex(state, HeatingCoilType, HeatingCoilName, errFlag);
    3732         111 :                     HeatingCoilInletNode = WaterToAirHeatPumpSimple::GetCoilInletNode(state, HeatingCoilType, HeatingCoilName, errFlag);
    3733         111 :                     HeatingCoilOutletNode = WaterToAirHeatPumpSimple::GetCoilOutletNode(state, HeatingCoilType, HeatingCoilName, errFlag);
    3734             :                 }
    3735          14 :             } else if (Alphas(8) == "COIL:HEATING:WATERTOAIRHEATPUMP:VARIABLESPEEDEQUATIONFIT") {
    3736          14 :                 HeatingCoilType = Alphas(8);
    3737          14 :                 thisFurnace.HeatingCoilType_Num = HVAC::Coil_HeatingWaterToAirHPVSEquationFit;
    3738          14 :                 HeatingCoilName = Alphas(9);
    3739          14 :                 ValidateComponent(state, HeatingCoilType, HeatingCoilName, IsNotOK, CurrentModuleObject);
    3740          14 :                 if (IsNotOK) {
    3741           0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3742           0 :                     ErrorsFound = true;
    3743             :                 } else {
    3744          14 :                     thisFurnace.HeatingCoilIndex = VariableSpeedCoils::GetCoilIndexVariableSpeed(state, HeatingCoilType, HeatingCoilName, errFlag);
    3745          14 :                     HeatingCoilInletNode = VariableSpeedCoils::GetCoilInletNodeVariableSpeed(state, HeatingCoilType, HeatingCoilName, errFlag);
    3746          14 :                     HeatingCoilOutletNode = VariableSpeedCoils::GetCoilOutletNodeVariableSpeed(state, HeatingCoilType, HeatingCoilName, errFlag);
    3747             :                 }
    3748             :             } else {
    3749           0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3750           0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(8), Alphas(8)));
    3751           0 :                 ErrorsFound = true;
    3752             :             }
    3753             : 
    3754             :             // Get Cooling Coil Information if available
    3755         139 :             if (Alphas(10) == "COIL:COOLING:WATERTOAIRHEATPUMP:PARAMETERESTIMATION") {
    3756          14 :                 CoolingCoilType = Alphas(10);
    3757          14 :                 thisFurnace.CoolingCoilType_Num = HVAC::Coil_CoolingWaterToAirHP;
    3758          14 :                 CoolingCoilName = Alphas(11);
    3759          14 :                 ValidateComponent(state, CoolingCoilType, CoolingCoilName, IsNotOK, CurrentModuleObject);
    3760          14 :                 if (IsNotOK) {
    3761           0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3762           0 :                     ErrorsFound = true;
    3763             :                 } else {
    3764          14 :                     thisFurnace.CoolingCoilIndex = WaterToAirHeatPump::GetCoilIndex(state, CoolingCoilType, CoolingCoilName, errFlag);
    3765          14 :                     CoolingCoilInletNode = WaterToAirHeatPump::GetCoilInletNode(state, CoolingCoilType, CoolingCoilName, errFlag);
    3766          14 :                     CoolingCoilOutletNode = WaterToAirHeatPump::GetCoilOutletNode(state, CoolingCoilType, CoolingCoilName, errFlag);
    3767             :                 }
    3768         125 :             } else if (Alphas(10) == "COIL:COOLING:WATERTOAIRHEATPUMP:EQUATIONFIT") {
    3769         111 :                 CoolingCoilType = Alphas(10);
    3770         111 :                 thisFurnace.CoolingCoilType_Num = HVAC::Coil_CoolingWaterToAirHPSimple;
    3771         111 :                 CoolingCoilName = Alphas(11);
    3772         111 :                 ValidateComponent(state, CoolingCoilType, CoolingCoilName, IsNotOK, CurrentModuleObject);
    3773         111 :                 if (IsNotOK) {
    3774           0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3775           0 :                     ErrorsFound = true;
    3776             :                 } else {
    3777         111 :                     thisFurnace.CoolingCoilIndex = WaterToAirHeatPumpSimple::GetCoilIndex(state, CoolingCoilType, CoolingCoilName, errFlag);
    3778         111 :                     CoolingCoilInletNode = WaterToAirHeatPumpSimple::GetCoilInletNode(state, CoolingCoilType, CoolingCoilName, errFlag);
    3779         111 :                     CoolingCoilOutletNode = WaterToAirHeatPumpSimple::GetCoilOutletNode(state, CoolingCoilType, CoolingCoilName, errFlag);
    3780             :                 }
    3781          14 :             } else if (Alphas(10) == "COIL:COOLING:WATERTOAIRHEATPUMP:VARIABLESPEEDEQUATIONFIT") {
    3782          14 :                 CoolingCoilType = Alphas(10);
    3783          14 :                 thisFurnace.CoolingCoilType_Num = HVAC::Coil_CoolingWaterToAirHPVSEquationFit;
    3784          14 :                 CoolingCoilName = Alphas(11);
    3785          14 :                 ValidateComponent(state, CoolingCoilType, CoolingCoilName, IsNotOK, CurrentModuleObject);
    3786          14 :                 if (IsNotOK) {
    3787           0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3788           0 :                     ErrorsFound = true;
    3789             :                 } else {
    3790          14 :                     thisFurnace.CoolingCoilIndex = VariableSpeedCoils::GetCoilIndexVariableSpeed(state, CoolingCoilType, CoolingCoilName, errFlag);
    3791          14 :                     CoolingCoilInletNode = VariableSpeedCoils::GetCoilInletNodeVariableSpeed(state, CoolingCoilType, CoolingCoilName, errFlag);
    3792          14 :                     CoolingCoilOutletNode = VariableSpeedCoils::GetCoilOutletNodeVariableSpeed(state, CoolingCoilType, CoolingCoilName, errFlag);
    3793             :                 }
    3794             :             } else {
    3795           0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3796           0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(10), Alphas(10)));
    3797           0 :                 ErrorsFound = true;
    3798             :             }
    3799             : 
    3800           0 :             thisFurnace.WaterCyclingMode = (NumAlphas < 18 || lAlphaBlanks(18))
    3801         139 :                                                ? HVAC::WaterFlow::Cycling
    3802           0 :                                                : static_cast<HVAC::WaterFlow>(getEnumValue(HVAC::waterFlowNamesUC, Alphas(18)));
    3803             : 
    3804             :             // end get water flow mode info
    3805         139 :             if (Alphas(8) == "COIL:HEATING:WATERTOAIRHEATPUMP:EQUATIONFIT" && Alphas(10) == "COIL:COOLING:WATERTOAIRHEATPUMP:EQUATIONFIT") {
    3806         111 :                 thisFurnace.WatertoAirHPType = WAHPCoilType::Simple;
    3807         111 :                 WaterToAirHeatPumpSimple::SetSimpleWSHPData(
    3808         111 :                     state, thisFurnace.CoolingCoilIndex, ErrorsFound, thisFurnace.WaterCyclingMode, _, thisFurnace.HeatingCoilIndex);
    3809          42 :             } else if (Alphas(8) == "COIL:HEATING:WATERTOAIRHEATPUMP:PARAMETERESTIMATION" &&
    3810          14 :                        Alphas(10) == "COIL:COOLING:WATERTOAIRHEATPUMP:PARAMETERESTIMATION") {
    3811          14 :                 thisFurnace.WatertoAirHPType = WAHPCoilType::ParEst;
    3812          28 :             } else if (Alphas(8) == "COIL:HEATING:WATERTOAIRHEATPUMP:VARIABLESPEEDEQUATIONFIT" &&
    3813          14 :                        Alphas(10) == "COIL:COOLING:WATERTOAIRHEATPUMP:VARIABLESPEEDEQUATIONFIT") {
    3814          14 :                 thisFurnace.WatertoAirHPType = WAHPCoilType::VarSpeedEquationFit;
    3815          14 :                 VariableSpeedCoils::SetVarSpeedCoilData(state, thisFurnace.CoolingCoilIndex, ErrorsFound, _, thisFurnace.HeatingCoilIndex);
    3816             :             } else {
    3817           0 :                 ShowContinueError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    3818           0 :                 ShowContinueError(state, "Cooling coil and heating coil should be of same general type");
    3819           0 :                 ErrorsFound = true;
    3820             :             }
    3821             : 
    3822             :             // Get supplemental heating coil information
    3823             : 
    3824         139 :             SuppHeatCoilType = Alphas(12);
    3825         139 :             SuppHeatCoilName = Alphas(13);
    3826         139 :             thisFurnace.SuppHeatCoilType = SuppHeatCoilType;
    3827         139 :             thisFurnace.SuppHeatCoilName = SuppHeatCoilName;
    3828         139 :             errFlag = false;
    3829         139 :             if (Util::SameString(SuppHeatCoilType, "Coil:Heating:Fuel") || Util::SameString(SuppHeatCoilType, "Coil:Heating:Electric")) {
    3830             : 
    3831         139 :                 thisFurnace.SuppHeatCoilType_Num = HeatingCoils::GetHeatingCoilTypeNum(state, SuppHeatCoilType, SuppHeatCoilName, errFlag);
    3832         139 :                 if (errFlag) {
    3833           0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3834           0 :                     ErrorsFound = true;
    3835             :                 } else {
    3836         139 :                     IsNotOK = false;
    3837         139 :                     ValidateComponent(state, SuppHeatCoilType, SuppHeatCoilName, IsNotOK, CurrentModuleObject);
    3838         139 :                     if (IsNotOK) {
    3839           0 :                         ShowContinueError(state, format("In {} \"{}\"", CurrentModuleObject, Alphas(1)));
    3840           0 :                         ErrorsFound = true;
    3841             : 
    3842             :                     } else { // mine data from the supplemental heating coil
    3843             : 
    3844         139 :                         HeatingCoils::GetCoilIndex(state, SuppHeatCoilName, thisFurnace.SuppHeatCoilIndex, IsNotOK);
    3845         139 :                         if (IsNotOK) {
    3846           0 :                             ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3847           0 :                             ErrorsFound = true;
    3848             :                         }
    3849             : 
    3850             :                         // Get the Supplemental Heating Coil Inlet Node Number
    3851         139 :                         errFlag = false;
    3852         139 :                         SupHeatCoilInletNode = HeatingCoils::GetCoilInletNode(state, SuppHeatCoilType, SuppHeatCoilName, errFlag);
    3853         139 :                         if (errFlag) {
    3854           0 :                             ShowContinueError(state, format("...occurs in {} \"{}\"", CurrentModuleObject, Alphas(1)));
    3855           0 :                             ErrorsFound = true;
    3856             :                         }
    3857             : 
    3858             :                         // Get the Supplemental Heating Coil Outlet Node Number
    3859         139 :                         errFlag = false;
    3860         139 :                         SupHeatCoilOutletNode = HeatingCoils::GetCoilOutletNode(state, SuppHeatCoilType, SuppHeatCoilName, errFlag);
    3861         139 :                         if (errFlag) {
    3862           0 :                             ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3863           0 :                             ErrorsFound = true;
    3864             :                         }
    3865             : 
    3866             :                         // Get the supplemental heating coil design capacity
    3867         139 :                         errFlag = false;
    3868         139 :                         thisFurnace.DesignSuppHeatingCapacity = HeatingCoils::GetCoilCapacity(state, SuppHeatCoilType, SuppHeatCoilName, errFlag);
    3869         139 :                         if (errFlag) {
    3870           0 :                             ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3871           0 :                             ErrorsFound = true;
    3872             :                         }
    3873             : 
    3874             :                     } // IF (IsNotOK) THEN
    3875             :                 }
    3876           0 :             } else if (Util::SameString(SuppHeatCoilType, "Coil:Heating:Water")) {
    3877           0 :                 thisFurnace.SuppHeatCoilType_Num = HVAC::Coil_HeatingWater;
    3878           0 :                 ValidateComponent(state, SuppHeatCoilType, SuppHeatCoilName, IsNotOK, CurrentModuleObject);
    3879           0 :                 if (IsNotOK) {
    3880           0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3881           0 :                     ErrorsFound = true;
    3882             :                 } else { // mine data from heating coil object
    3883             : 
    3884             :                     // Get the Heating Coil water Inlet or control Node number
    3885           0 :                     errFlag = false;
    3886           0 :                     thisFurnace.SuppCoilControlNode = WaterCoils::GetCoilWaterInletNode(state, "Coil:Heating:Water", SuppHeatCoilName, errFlag);
    3887           0 :                     if (errFlag) {
    3888           0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3889           0 :                         ErrorsFound = true;
    3890             :                     }
    3891             : 
    3892             :                     // Get the ReHeat Coil hot water max volume flow rate
    3893           0 :                     errFlag = false;
    3894           0 :                     thisFurnace.MaxSuppCoilFluidFlow = WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", SuppHeatCoilName, errFlag);
    3895           0 :                     if (errFlag) {
    3896           0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3897           0 :                         ErrorsFound = true;
    3898             :                     }
    3899             : 
    3900             :                     // Get the ReHeat Coil Inlet Node
    3901           0 :                     errFlag = false;
    3902           0 :                     SupHeatCoilInletNode = WaterCoils::GetCoilInletNode(state, "Coil:Heating:Water", SuppHeatCoilName, errFlag);
    3903           0 :                     thisFurnace.SuppCoilAirInletNode = SupHeatCoilInletNode;
    3904           0 :                     if (errFlag) {
    3905           0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3906           0 :                         ErrorsFound = true;
    3907             :                     }
    3908             : 
    3909             :                     // Get the ReHeat Coil Outlet Node
    3910           0 :                     errFlag = false;
    3911           0 :                     SupHeatCoilOutletNode = WaterCoils::GetCoilOutletNode(state, "Coil:Heating:Water", SuppHeatCoilName, errFlag);
    3912           0 :                     thisFurnace.SuppCoilAirOutletNode = SupHeatCoilOutletNode;
    3913           0 :                     if (errFlag) {
    3914           0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3915           0 :                         ErrorsFound = true;
    3916             :                     }
    3917             : 
    3918           0 :                     errFlag = false;
    3919           0 :                     HVACControllers::CheckCoilWaterInletNode(state, thisFurnace.CoilControlNode, errFlag);
    3920           0 :                     if (!errFlag) { // then did find a controller so that is bad
    3921           0 :                         ShowSevereError(state,
    3922           0 :                                         format("{} = {} has a conflicting Controller:WaterCoil object", CurrentModuleObject, thisFurnace.Name));
    3923           0 :                         ShowContinueError(state, "Hot water coils are controlled directly by unitary and furnace systems.");
    3924           0 :                         ShowContinueError(state, "No water coil controller should be input for the coil.");
    3925           0 :                         ErrorsFound = true;
    3926             :                     }
    3927             :                 }
    3928             : 
    3929           0 :             } else if (Util::SameString(SuppHeatCoilType, "Coil:Heating:Steam")) {
    3930           0 :                 thisFurnace.SuppHeatCoilType_Num = HVAC::Coil_HeatingSteam;
    3931           0 :                 ValidateComponent(state, SuppHeatCoilType, SuppHeatCoilName, IsNotOK, CurrentModuleObject);
    3932           0 :                 if (IsNotOK) {
    3933           0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3934           0 :                     ErrorsFound = true;
    3935             :                 } else { // mine data from heating coil object
    3936             : 
    3937           0 :                     errFlag = false;
    3938           0 :                     thisFurnace.SuppHeatCoilIndex = SteamCoils::GetSteamCoilIndex(state, SuppHeatCoilType, SuppHeatCoilName, errFlag);
    3939           0 :                     if (thisFurnace.SuppHeatCoilIndex == 0) {
    3940           0 :                         ShowSevereError(state, format("{} illegal {} = {}", CurrentModuleObject, cAlphaFields(12), SuppHeatCoilName));
    3941           0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3942           0 :                         ErrorsFound = true;
    3943             :                     }
    3944             : 
    3945             :                     // Get the Heating Coil steam inlet node number
    3946           0 :                     errFlag = false;
    3947           0 :                     thisFurnace.SuppCoilControlNode = SteamCoils::GetCoilSteamInletNode(state, "Coil:Heating:Steam", SuppHeatCoilName, errFlag);
    3948           0 :                     if (errFlag) {
    3949           0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3950           0 :                         ErrorsFound = true;
    3951             :                     }
    3952             : 
    3953             :                     // Get the Heating Coil steam max volume flow rate
    3954           0 :                     thisFurnace.MaxSuppCoilFluidFlow = SteamCoils::GetCoilMaxSteamFlowRate(state, thisFurnace.SuppHeatCoilIndex, errFlag);
    3955           0 :                     if (thisFurnace.MaxSuppCoilFluidFlow > 0.0) {
    3956           0 :                         SteamIndex = 0; // Function GetSatDensityRefrig will look up steam index if 0 is passed
    3957           0 :                         SteamDensity = FluidProperties::GetSatDensityRefrig(
    3958           0 :                             state, fluidNameSteam, state.dataFurnaces->TempSteamIn, 1.0, SteamIndex, getAirLoopHVACHeatCoolInput);
    3959           0 :                         thisFurnace.MaxSuppCoilFluidFlow =
    3960           0 :                             SteamCoils::GetCoilMaxSteamFlowRate(state, thisFurnace.SuppHeatCoilIndex, errFlag) * SteamDensity;
    3961             :                     }
    3962             : 
    3963             :                     // Get the Heating Coil Inlet Node
    3964           0 :                     errFlag = false;
    3965           0 :                     SupHeatCoilInletNode = SteamCoils::GetCoilAirInletNode(state, thisFurnace.SuppHeatCoilIndex, SuppHeatCoilName, errFlag);
    3966           0 :                     thisFurnace.SuppCoilAirInletNode = SupHeatCoilInletNode;
    3967           0 :                     if (errFlag) {
    3968           0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3969           0 :                         ErrorsFound = true;
    3970             :                     }
    3971             : 
    3972             :                     // Get the Heating Coil Outlet Node
    3973           0 :                     errFlag = false;
    3974           0 :                     SupHeatCoilOutletNode = SteamCoils::GetCoilAirOutletNode(state, thisFurnace.SuppHeatCoilIndex, SuppHeatCoilName, errFlag);
    3975           0 :                     thisFurnace.SuppCoilAirOutletNode = SupHeatCoilOutletNode;
    3976           0 :                     if (errFlag) {
    3977           0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3978           0 :                         ErrorsFound = true;
    3979             :                     }
    3980             :                 }
    3981             : 
    3982             :             } else {
    3983           0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3984           0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(12), Alphas(12)));
    3985           0 :                 ErrorsFound = true;
    3986             :             } // IF (Furnace(FurnaceNum)%HeatingCoilType_Num == Coil_HeatingGasOrOtherFuel .OR. &, etc.
    3987             : 
    3988         139 :             if (lAlphaBlanks(14)) {
    3989           0 :                 thisFurnace.CondenserNodeNum = 0;
    3990             :             } else {
    3991         139 :                 thisFurnace.CondenserNodeNum =
    3992         139 :                     NodeInputManager::GetOnlySingleNode(state,
    3993         139 :                                                         Alphas(14),
    3994             :                                                         ErrorsFound,
    3995             :                                                         DataLoopNode::ConnectionObjectType::AirLoopHVACUnitaryHeatPumpWaterToAir,
    3996         139 :                                                         Alphas(1),
    3997             :                                                         DataLoopNode::NodeFluidType::Air,
    3998             :                                                         DataLoopNode::ConnectionType::OutsideAirReference,
    3999             :                                                         NodeInputManager::CompFluidStream::Primary,
    4000             :                                                         DataLoopNode::ObjectIsNotParent);
    4001             :                 // need better verification.
    4002         139 :                 if (!OutAirNodeManager::CheckOutAirNodeNumber(state, thisFurnace.CondenserNodeNum)) {
    4003           0 :                     ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    4004           0 :                     ShowContinueError(state, format(" Node name of outdoor dry-bulb temperature sensor not valid outdoor air node= {}", Alphas(14)));
    4005           0 :                     ShowContinueError(state, "...does not appear in an OutdoorAir:NodeList or as an OutdoorAir:Node.");
    4006           0 :                     ErrorsFound = true;
    4007             :                 }
    4008             :             }
    4009             : 
    4010         139 :             thisFurnace.fanPlace = static_cast<HVAC::FanPlace>(getEnumValue(HVAC::fanPlaceNamesUC, Alphas(15)));
    4011         139 :             assert(thisFurnace.fanPlace != HVAC::FanPlace::Invalid);
    4012             : 
    4013         139 :             thisFurnace.FanSchedPtr = ScheduleManager::GetScheduleIndex(state, Alphas(16));
    4014         139 :             if (!lAlphaBlanks(16) && thisFurnace.FanSchedPtr == 0) {
    4015           0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    4016           0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(16), Alphas(16)));
    4017           0 :                 ErrorsFound = true;
    4018         139 :             } else if (lAlphaBlanks(16)) {
    4019           0 :                 thisFurnace.fanOp = HVAC::FanOp::Cycling;
    4020           0 :                 if (thisFurnace.fanType != HVAC::FanType::OnOff) {
    4021           0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, thisFurnace.Name));
    4022           0 :                     ShowContinueError(state, format("{} = {}", cAlphaFields(6), Alphas(6)));
    4023           0 :                     ShowContinueError(state, format("Fan type must be Fan:OnOff when {} = Blank.", cAlphaFields(16)));
    4024           0 :                     ErrorsFound = true;
    4025             :                 }
    4026             :             }
    4027             : 
    4028             :             // add the Dehumidification Type
    4029         139 :             if (Util::SameString(Alphas(17), "None") || Util::SameString(Alphas(17), "CoolReheat")) {
    4030         139 :                 AirNodeFound = false;
    4031         139 :                 if (Util::SameString(Alphas(17), "CoolReheat")) {
    4032          10 :                     thisFurnace.DehumidControlType_Num = DehumidificationControlMode::CoolReheat;
    4033          10 :                     thisFurnace.Humidistat = true;
    4034          10 :                     if (lAlphaBlanks(17)) {
    4035           0 :                         ShowWarningError(state, format("{} \"{}\"", CurrentModuleObject, Alphas(1)));
    4036           0 :                         ShowContinueError(state,
    4037             :                                           "Dehumidification control type is assumed to be None since a supplemental reheat coil has not been "
    4038             :                                           "specified and the simulation continues.");
    4039           0 :                         thisFurnace.Humidistat = false;
    4040           0 :                         thisFurnace.DehumidControlType_Num = DehumidificationControlMode::None;
    4041             :                     }
    4042             :                 }
    4043         139 :                 if (Util::SameString(Alphas(17), "None")) {
    4044         129 :                     thisFurnace.DehumidControlType_Num = DehumidificationControlMode::None;
    4045         129 :                     thisFurnace.Humidistat = false;
    4046             :                 }
    4047         139 :                 if (thisFurnace.Humidistat) {
    4048          60 :                     for (HStatZoneNum = 1; HStatZoneNum <= state.dataZoneCtrls->NumHumidityControlZones; ++HStatZoneNum) {
    4049          50 :                         if (state.dataZoneCtrls->HumidityControlZone(HStatZoneNum).ActualZoneNum != thisFurnace.ControlZoneNum) continue;
    4050          10 :                         AirNodeFound = true;
    4051             :                     }
    4052          10 :                     if (!AirNodeFound) {
    4053           0 :                         ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    4054           0 :                         ShowContinueError(state, "Did not find Air Node (Zone with Humidistat).");
    4055           0 :                         ShowContinueError(state, format("Specified {} = {}", cAlphaFields(5), Alphas(5)));
    4056           0 :                         ErrorsFound = true;
    4057             :                     }
    4058             :                 }
    4059             :             } else { // invalid input or blank
    4060           0 :                 if (!lAlphaBlanks(17)) {
    4061           0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    4062           0 :                     ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(17), Alphas(17)));
    4063           0 :                     ErrorsFound = true;
    4064             :                 } else {
    4065           0 :                     thisFurnace.Humidistat = false;
    4066           0 :                     thisFurnace.DehumidControlType_Num = DehumidificationControlMode::None;
    4067             :                 }
    4068             :             }
    4069             : 
    4070             :             // Add fan to component sets array
    4071             : 
    4072         139 :             if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
    4073         139 :                 CompSetFanInlet = Alphas(3);
    4074         139 :                 CompSetCoolInlet = "UNDEFINED";
    4075         139 :                 if (FanInletNode != thisFurnace.FurnaceInletNodeNum) {
    4076           0 :                     ShowSevereError(
    4077           0 :                         state, format("For {} = {}, Mismatch between unitary system inlet node and fan inlet node.", CurrentModuleObject, Alphas(1)));
    4078           0 :                     ShowContinueError(state, "..For \"BlowThrough\" fan, the inlet node name for the HeatPump should match the fan inlet node name.");
    4079           0 :                     ShowContinueError(state, format("..HeatPump Inlet Node = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceInletNodeNum)));
    4080           0 :                     ShowContinueError(state, format("..Fan Inlet Node      = {}", state.dataLoopNodes->NodeID(FanInletNode)));
    4081           0 :                     ErrorsFound = true;
    4082             :                 }
    4083         139 :                 if (FanOutletNode != CoolingCoilInletNode) {
    4084           0 :                     ShowSevereError(
    4085           0 :                         state, format("For {} = {}, Mismatch between fan outlet node and cooling coil inlet node.", CurrentModuleObject, Alphas(1)));
    4086           0 :                     ShowContinueError(state, "..For \"BlowThrough\" fan, the fan outlet node name must match the cooling coil inlet node name.");
    4087           0 :                     ShowContinueError(state, format("..Fan outlet node         = {}", state.dataLoopNodes->NodeID(FanOutletNode)));
    4088           0 :                     ShowContinueError(state, format("..Cooling coil inlet node = {}", state.dataLoopNodes->NodeID(CoolingCoilInletNode)));
    4089           0 :                     ErrorsFound = true;
    4090             :                 }
    4091         139 :                 if (CoolingCoilOutletNode != HeatingCoilInletNode) {
    4092           0 :                     ShowSevereError(state,
    4093           0 :                                     format("For {} = {}, Mismatch between cooling coil outlet node and heating coil inlet node.",
    4094             :                                            CurrentModuleObject,
    4095             :                                            Alphas(1)));
    4096           0 :                     ShowContinueError(state, "..The cooling coil outlet node name must match the heating coil inlet node name.");
    4097           0 :                     ShowContinueError(state, format("..Cooling coil outlet node = {}", state.dataLoopNodes->NodeID(CoolingCoilOutletNode)));
    4098           0 :                     ShowContinueError(state, format("..Heating coil inlet node  = {}", state.dataLoopNodes->NodeID(HeatingCoilInletNode)));
    4099           0 :                     ErrorsFound = true;
    4100             :                 }
    4101         139 :                 if (HeatingCoilOutletNode != SupHeatCoilInletNode) {
    4102           0 :                     ShowSevereError(state,
    4103           0 :                                     format("For {} = {}, Mismatch between heating coil outlet node and supplemental heating coil inlet node.",
    4104             :                                            CurrentModuleObject,
    4105             :                                            Alphas(1)));
    4106           0 :                     ShowContinueError(
    4107             :                         state,
    4108             :                         "..For \"BlowThrough\" fan, the heating coil outlet node name must match the supplemental heating coil inlet node name.");
    4109           0 :                     ShowContinueError(state,
    4110           0 :                                       format("..Heating coil outlet node             = {}", state.dataLoopNodes->NodeID(HeatingCoilOutletNode)));
    4111           0 :                     ShowContinueError(state,
    4112           0 :                                       format("..Supplemental heating coil inlet node = {}", state.dataLoopNodes->NodeID(SupHeatCoilInletNode)));
    4113           0 :                     ErrorsFound = true;
    4114             :                 }
    4115         139 :                 if (SupHeatCoilOutletNode != thisFurnace.FurnaceOutletNodeNum) {
    4116           0 :                     ShowSevereError(state,
    4117           0 :                                     format("For {} = {}, Mismatch between supplemental heating coil outlet node and HeatPump outlet node.",
    4118             :                                            CurrentModuleObject,
    4119             :                                            Alphas(1)));
    4120           0 :                     ShowContinueError(state, "..The supplemental heating coil outlet node name must match the HeatPump outlet node name.");
    4121           0 :                     ShowContinueError(state,
    4122           0 :                                       format("..Supplemental heating coil outlet node = {}", state.dataLoopNodes->NodeID(SupHeatCoilOutletNode)));
    4123           0 :                     ShowContinueError(
    4124           0 :                         state, format("..HeatPump outlet node                  = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    4125           0 :                     ErrorsFound = true;
    4126             :                 }
    4127             :             } else {
    4128           0 :                 CompSetFanInlet = "UNDEFINED";
    4129           0 :                 CompSetCoolInlet = Alphas(3);
    4130           0 :                 if (CoolingCoilInletNode != thisFurnace.FurnaceInletNodeNum) {
    4131           0 :                     ShowSevereError(state,
    4132           0 :                                     format("For {} = {}, Mismatch between unitary system inlet node and cooling coil inlet node.",
    4133             :                                            CurrentModuleObject,
    4134             :                                            Alphas(1)));
    4135           0 :                     ShowContinueError(
    4136             :                         state, "..For \"DrawThrough\" fan, the inlet node name for the HeatPump should match the cooling coil inlet node name.");
    4137           0 :                     ShowContinueError(state, format("..HeatPump inlet node     = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceInletNodeNum)));
    4138           0 :                     ShowContinueError(state, format("..Cooling coil inlet node = {}", state.dataLoopNodes->NodeID(CoolingCoilInletNode)));
    4139           0 :                     ErrorsFound = true;
    4140             :                 }
    4141           0 :                 if (CoolingCoilOutletNode != HeatingCoilInletNode) {
    4142           0 :                     ShowSevereError(state,
    4143           0 :                                     format("For {} = {}, Mismatch between cooling coil outlet node and heating coil inlet node.",
    4144             :                                            CurrentModuleObject,
    4145             :                                            Alphas(1)));
    4146           0 :                     ShowContinueError(state, "..The outlet node name for the cooling coil should match the heating coil inlet node name.");
    4147           0 :                     ShowContinueError(state, format("..Cooling coil outlet node = {}", state.dataLoopNodes->NodeID(CoolingCoilOutletNode)));
    4148           0 :                     ShowContinueError(state, format("..Heating coil inlet node  = {}", state.dataLoopNodes->NodeID(HeatingCoilInletNode)));
    4149           0 :                     ErrorsFound = true;
    4150             :                 }
    4151           0 :                 if (HeatingCoilOutletNode != FanInletNode) {
    4152           0 :                     ShowSevereError(
    4153           0 :                         state, format("For {} = {}, Mismatch between heating coil outlet node and fan inlet node.", CurrentModuleObject, Alphas(1)));
    4154           0 :                     ShowContinueError(state,
    4155             :                                       "..For \"DrawThrough\" fan, the outlet node name for the heating coil should match the fan inlet node name.");
    4156           0 :                     ShowContinueError(state, format("..Heating coil outlet node = {}", state.dataLoopNodes->NodeID(HeatingCoilOutletNode)));
    4157           0 :                     ShowContinueError(state, format("..Fan inlet node           = {}", state.dataLoopNodes->NodeID(FanInletNode)));
    4158           0 :                     ErrorsFound = true;
    4159             :                 }
    4160           0 :                 if (FanOutletNode != SupHeatCoilInletNode) {
    4161           0 :                     ShowSevereError(state,
    4162           0 :                                     format("For {} = {}, Mismatch between fan outlet node and supplemental heating coil inlet node.",
    4163             :                                            CurrentModuleObject,
    4164             :                                            Alphas(1)));
    4165           0 :                     ShowContinueError(
    4166             :                         state,
    4167             :                         "..For \"DrawThrough\" fan, the outlet node name for the fan should match the supplemental heating coil inlet node name.");
    4168           0 :                     ShowContinueError(state, format("..Fan outlet node                      = {}", state.dataLoopNodes->NodeID(FanOutletNode)));
    4169           0 :                     ShowContinueError(state,
    4170           0 :                                       format("..Supplemental heating coil inlet node = {}", state.dataLoopNodes->NodeID(SupHeatCoilInletNode)));
    4171           0 :                     ErrorsFound = true;
    4172             :                 }
    4173           0 :                 if (SupHeatCoilOutletNode != thisFurnace.FurnaceOutletNodeNum) {
    4174           0 :                     ShowSevereError(state,
    4175           0 :                                     format("For {} = {}, Mismatch between supplemental heating coil outlet node and HeatPump outlet node.",
    4176             :                                            CurrentModuleObject,
    4177             :                                            Alphas(1)));
    4178           0 :                     ShowContinueError(state, "..The supplemental heating coil outlet node name must match the HeatPump outlet node name.");
    4179           0 :                     ShowContinueError(state,
    4180           0 :                                       format("..Supplemental heating coil outlet node = {}", state.dataLoopNodes->NodeID(SupHeatCoilOutletNode)));
    4181           0 :                     ShowContinueError(
    4182           0 :                         state, format("..HeatPump outlet node                  = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    4183           0 :                     ErrorsFound = true;
    4184             :                 }
    4185             :             }
    4186             :             //  (Set up validation here for the fan or cooling coil inlet?)
    4187         139 :             BranchNodeConnections::SetUpCompSets(state, CurrentModuleObject, Alphas(1), Alphas(6), Alphas(7), CompSetFanInlet, "UNDEFINED");
    4188             : 
    4189             :             // Add DX heating coil to component sets array
    4190         139 :             BranchNodeConnections::SetUpCompSets(state, CurrentModuleObject, Alphas(1), Alphas(8), Alphas(9), "UNDEFINED", "UNDEFINED");
    4191             : 
    4192             :             // Add DX cooling coil to component sets array
    4193         139 :             BranchNodeConnections::SetUpCompSets(state, CurrentModuleObject, Alphas(1), Alphas(10), Alphas(11), CompSetCoolInlet, "UNDEFINED");
    4194             : 
    4195             :             // Add supplemental heating coil to component sets array
    4196         139 :             BranchNodeConnections::SetUpCompSets(state, CurrentModuleObject, Alphas(1), Alphas(12), Alphas(13), "UNDEFINED", Alphas(4));
    4197             : 
    4198             :             // Set the Design Fan Volume Flow Rate
    4199         139 :             thisFurnace.ActualFanVolFlowRate = state.dataFans->fans(thisFurnace.FanIndex)->maxAirFlowRate;
    4200             : 
    4201             :             // CR8094 - simple water to air heat pump MUST operate at the same flow rate specified in the coil objects
    4202             :             //        Furnace(FurnaceNum)%DesignFanVolFlowRate = Numbers(1)
    4203             :             //        Furnace(FurnaceNum)%MaxHeatAirVolFlow    = Furnace(FurnaceNum)%DesignFanVolFlowRate
    4204             :             //        Furnace(FurnaceNum)%MaxCoolAirVolFlow    = Furnace(FurnaceNum)%DesignFanVolFlowRate
    4205             : 
    4206             :             // parameter estimate model only specifies air flow rate in parent object
    4207         139 :             if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingWaterToAirHP) {
    4208          14 :                 thisFurnace.MaxHeatAirVolFlow = Numbers(1);
    4209          14 :                 thisFurnace.MaxCoolAirVolFlow = Numbers(1);
    4210             :                 // simple HP model specifies air flow rate in both the parent and child coils. Use coil air flow rates.
    4211             :                 // simple HP model air flow rate input will not be used.
    4212         125 :             } else if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingWaterToAirHPSimple) {
    4213         111 :                 errFlag = false;
    4214         111 :                 thisFurnace.MaxHeatAirVolFlow = WaterToAirHeatPumpSimple::GetCoilAirFlowRate(state, HeatingCoilType, HeatingCoilName, errFlag);
    4215         111 :                 thisFurnace.MaxCoolAirVolFlow = WaterToAirHeatPumpSimple::GetCoilAirFlowRate(state, CoolingCoilType, CoolingCoilName, errFlag);
    4216         111 :                 if (errFlag) {
    4217           0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    4218           0 :                     ErrorsFound = true;
    4219             :                 }
    4220          14 :             } else if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingWaterToAirHPVSEquationFit) {
    4221          14 :                 errFlag = false;
    4222          14 :                 thisFurnace.MaxHeatAirVolFlow = VariableSpeedCoils::GetCoilAirFlowRateVariableSpeed(state, HeatingCoilType, HeatingCoilName, errFlag);
    4223          14 :                 thisFurnace.MaxCoolAirVolFlow = VariableSpeedCoils::GetCoilAirFlowRateVariableSpeed(state, CoolingCoilType, CoolingCoilName, errFlag);
    4224          14 :                 if (errFlag) {
    4225           0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    4226           0 :                     ErrorsFound = true;
    4227             :                 }
    4228             :             }
    4229             : 
    4230         139 :             thisFurnace.MaxNoCoolHeatAirVolFlow = min(thisFurnace.MaxHeatAirVolFlow, thisFurnace.MaxCoolAirVolFlow);
    4231         139 :             if (thisFurnace.MaxHeatAirVolFlow != DataSizing::AutoSize && thisFurnace.MaxCoolAirVolFlow != DataSizing::AutoSize) {
    4232          43 :                 thisFurnace.DesignFanVolFlowRate = max(thisFurnace.MaxHeatAirVolFlow, thisFurnace.MaxCoolAirVolFlow);
    4233             :             } else {
    4234          96 :                 thisFurnace.DesignFanVolFlowRate = DataSizing::AutoSize;
    4235             :             }
    4236             : 
    4237         139 :             thisFurnace.AirFlowControl = AirFlowControlConstFan::UseCompressorOnFlow;
    4238             : 
    4239         139 :             if (thisFurnace.ActualFanVolFlowRate != DataSizing::AutoSize && thisFurnace.DesignFanVolFlowRate != DataSizing::AutoSize) {
    4240          43 :                 if (thisFurnace.DesignFanVolFlowRate > thisFurnace.ActualFanVolFlowRate) {
    4241           0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    4242           0 :                     ShowContinueError(state, "... has a Cooling or Heating Air Flow Rate > Max Fan Volume Flow Rate, should be <=.");
    4243           0 :                     ShowContinueError(state,
    4244           0 :                                       format("... Entered value={:.2R}... Fan [{}:{}] Max Value={:.2R}",
    4245           0 :                                              thisFurnace.DesignFanVolFlowRate,
    4246           0 :                                              HVAC::fanTypeNames[(int)thisFurnace.fanType],
    4247             :                                              FanName,
    4248           0 :                                              thisFurnace.ActualFanVolFlowRate));
    4249             :                 }
    4250             :             }
    4251         139 :             if (thisFurnace.ActualFanVolFlowRate != DataSizing::AutoSize && thisFurnace.DesignFanVolFlowRate != DataSizing::AutoSize) {
    4252          43 :                 if (thisFurnace.DesignFanVolFlowRate <= 0.0) {
    4253           0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    4254           0 :                     ShowContinueError(state, "... has a Design Fan Flow Rate <= 0.0, it must be >0.0");
    4255           0 :                     ShowContinueError(state, format("... Entered value={:.2R}", thisFurnace.DesignFanVolFlowRate));
    4256           0 :                     ErrorsFound = true;
    4257             :                 }
    4258             :             }
    4259             : 
    4260             :             // Set the heat pump heating coil capacity
    4261             :             //  Get from coil module.
    4262         139 :             if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingWaterToAirHP) {
    4263          14 :                 errFlag = false;
    4264          14 :                 thisFurnace.DesignHeatingCapacity = WaterToAirHeatPump::GetCoilCapacity(state, HeatingCoilType, HeatingCoilName, errFlag);
    4265          14 :                 if (errFlag) {
    4266           0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    4267           0 :                     ErrorsFound = true;
    4268             :                 }
    4269         125 :             } else if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingWaterToAirHPSimple) {
    4270         111 :                 errFlag = false;
    4271         111 :                 thisFurnace.DesignHeatingCapacity = WaterToAirHeatPumpSimple::GetCoilCapacity(state, HeatingCoilType, HeatingCoilName, errFlag);
    4272         111 :                 if (errFlag) {
    4273           0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    4274           0 :                     ErrorsFound = true;
    4275             :                 }
    4276          14 :             } else if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingWaterToAirHPVSEquationFit) {
    4277          14 :                 errFlag = false;
    4278          14 :                 thisFurnace.DesignHeatingCapacity =
    4279          14 :                     VariableSpeedCoils::GetCoilCapacityVariableSpeed(state, HeatingCoilType, HeatingCoilName, errFlag);
    4280          14 :                 if (errFlag) {
    4281           0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    4282           0 :                     ErrorsFound = true;
    4283             :                 }
    4284             :             }
    4285             :             // Set the heat pump heating coil convergence
    4286         139 :             thisFurnace.HeatingConvergenceTolerance = Numbers(2);
    4287             :             // Set the heat pump cooling coil capacity (Total capacity)
    4288             :             //  Get from coil module.
    4289         139 :             if (thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingWaterToAirHP) {
    4290          14 :                 errFlag = false;
    4291          14 :                 thisFurnace.DesignCoolingCapacity = WaterToAirHeatPump::GetCoilCapacity(state, CoolingCoilType, CoolingCoilName, errFlag);
    4292          14 :                 if (errFlag) {
    4293           0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    4294           0 :                     ErrorsFound = true;
    4295             :                 }
    4296         125 :             } else if (thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingWaterToAirHPSimple) {
    4297         111 :                 errFlag = false;
    4298         111 :                 thisFurnace.DesignCoolingCapacity = WaterToAirHeatPumpSimple::GetCoilCapacity(state, CoolingCoilType, CoolingCoilName, errFlag);
    4299         111 :                 if (errFlag) {
    4300           0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    4301           0 :                     ErrorsFound = true;
    4302             :                 }
    4303          14 :             } else if (thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingWaterToAirHPVSEquationFit) {
    4304          14 :                 errFlag = false;
    4305          14 :                 thisFurnace.DesignCoolingCapacity =
    4306          14 :                     VariableSpeedCoils::GetCoilCapacityVariableSpeed(state, CoolingCoilType, CoolingCoilName, errFlag);
    4307          14 :                 if (errFlag) {
    4308           0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    4309           0 :                     ErrorsFound = true;
    4310             :                 }
    4311             :             }
    4312             :             // Set the heat pump cooling coil convergence
    4313         139 :             thisFurnace.CoolingConvergenceTolerance = Numbers(3);
    4314             : 
    4315             :             // Set the heatpump design supplemental heating capacity
    4316             :             //  Get from coil module.
    4317             : 
    4318             :             // Set the heatpump max outlet temperature
    4319         139 :             thisFurnace.DesignMaxOutletTemp = Numbers(4);
    4320             : 
    4321             :             // Set maximum supply air temperature for supplemental heating coil
    4322         139 :             thisFurnace.MaxOATSuppHeat = Numbers(5);
    4323         278 :             OutputReportPredefined::PreDefTableEntry(
    4324         139 :                 state, state.dataOutRptPredefined->pdchDXHeatCoilSuppHiT, HeatingCoilName, thisFurnace.MaxOATSuppHeat);
    4325             : 
    4326             :             // set minimum outdoor temperature for compressor operation
    4327         139 :             SetMinOATCompressor(state, FurnaceNum, cCurrentModuleObject, ErrorsFound);
    4328             : 
    4329             :         } // End of the Unitary System WaterToAirHeatPump Loop
    4330             : 
    4331          97 :         Alphas.deallocate();
    4332          97 :         Numbers.deallocate();
    4333             : 
    4334          97 :         if (ErrorsFound) {
    4335           0 :             ShowFatalError(state, "Errors found in getting Furnace or Unitary System input.");
    4336             :         }
    4337             : 
    4338         100 :         for (int HeatOnlyNum = 1; HeatOnlyNum <= NumHeatOnly; ++HeatOnlyNum) {
    4339           3 :             FurnaceNum = HeatOnlyNum;
    4340           3 :             auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    4341             :             // Setup Report variables for the Furnace that are not reported in the components themselves
    4342           6 :             SetupOutputVariable(state,
    4343             :                                 "Unitary System Fan Part Load Ratio",
    4344             :                                 Constant::Units::None,
    4345           3 :                                 thisFurnace.FanPartLoadRatio,
    4346             :                                 OutputProcessor::TimeStepType::System,
    4347             :                                 OutputProcessor::StoreType::Average,
    4348           3 :                                 thisFurnace.Name);
    4349           3 :             if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
    4350           0 :                 SetupEMSActuator(state,
    4351             :                                  "AirLoopHVAC:Unitary:Furnace:HeatOnly",
    4352             :                                  thisFurnace.Name,
    4353             :                                  "Autosized Supply Air Flow Rate",
    4354             :                                  "[m3/s]",
    4355           0 :                                  thisFurnace.DesignFanVolFlowRateEMSOverrideOn,
    4356           0 :                                  thisFurnace.DesignFanVolFlowRateEMSOverrideValue);
    4357             :             }
    4358             :         }
    4359             : 
    4360          98 :         for (int UnitaryHeatOnlyNum = NumHeatOnly + 1; UnitaryHeatOnlyNum <= NumHeatOnly + NumUnitaryHeatOnly; ++UnitaryHeatOnlyNum) {
    4361           1 :             FurnaceNum = UnitaryHeatOnlyNum;
    4362           1 :             auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    4363             :             // Setup Report variables for Unitary System that are not reported in the components themselves
    4364           2 :             SetupOutputVariable(state,
    4365             :                                 "Unitary System Fan Part Load Ratio",
    4366             :                                 Constant::Units::None,
    4367           1 :                                 thisFurnace.FanPartLoadRatio,
    4368             :                                 OutputProcessor::TimeStepType::System,
    4369             :                                 OutputProcessor::StoreType::Average,
    4370           1 :                                 thisFurnace.Name);
    4371           1 :             if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
    4372           0 :                 SetupEMSActuator(state,
    4373             :                                  "AirLoopHVAC:UnitaryHeatOnly",
    4374             :                                  thisFurnace.Name,
    4375             :                                  "Autosized Supply Air Flow Rate",
    4376             :                                  "[m3/s]",
    4377           0 :                                  thisFurnace.DesignFanVolFlowRateEMSOverrideOn,
    4378           0 :                                  thisFurnace.DesignFanVolFlowRateEMSOverrideValue);
    4379             :             }
    4380             :         }
    4381             : 
    4382         205 :         for (int HeatCoolNum = NumHeatOnly + NumUnitaryHeatOnly + 1; HeatCoolNum <= NumHeatOnly + NumUnitaryHeatOnly + NumHeatCool; ++HeatCoolNum) {
    4383         108 :             FurnaceNum = HeatCoolNum;
    4384         108 :             auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    4385             :             // Setup Report variables for the Furnace that are not reported in the components themselves
    4386         216 :             SetupOutputVariable(state,
    4387             :                                 "Unitary System Fan Part Load Ratio",
    4388             :                                 Constant::Units::None,
    4389         108 :                                 thisFurnace.FanPartLoadRatio,
    4390             :                                 OutputProcessor::TimeStepType::System,
    4391             :                                 OutputProcessor::StoreType::Average,
    4392         108 :                                 thisFurnace.Name);
    4393         216 :             SetupOutputVariable(state,
    4394             :                                 "Unitary System Compressor Part Load Ratio",
    4395             :                                 Constant::Units::None,
    4396         108 :                                 thisFurnace.CompPartLoadRatio,
    4397             :                                 OutputProcessor::TimeStepType::System,
    4398             :                                 OutputProcessor::StoreType::Average,
    4399         108 :                                 thisFurnace.Name);
    4400             : 
    4401         108 :             if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
    4402          24 :                 SetupEMSActuator(state,
    4403             :                                  "AirLoopHVAC:Unitary:Furnace:HeatCool",
    4404             :                                  thisFurnace.Name,
    4405             :                                  "Autosized Supply Air Flow Rate",
    4406             :                                  "[m3/s]",
    4407          24 :                                  thisFurnace.DesignFanVolFlowRateEMSOverrideOn,
    4408          24 :                                  thisFurnace.DesignFanVolFlowRateEMSOverrideValue);
    4409          24 :                 SetupEMSActuator(state,
    4410             :                                  "AirLoopHVAC:Unitary:Furnace:HeatCool",
    4411             :                                  thisFurnace.Name,
    4412             :                                  "Autosized Supply Air Flow Rate During Cooling Operation",
    4413             :                                  "[m3/s]",
    4414          24 :                                  thisFurnace.MaxCoolAirVolFlowEMSOverrideOn,
    4415          24 :                                  thisFurnace.MaxCoolAirVolFlowEMSOverrideValue);
    4416          24 :                 SetupEMSActuator(state,
    4417             :                                  "AirLoopHVAC:Unitary:Furnace:HeatCool",
    4418             :                                  thisFurnace.Name,
    4419             :                                  "Autosized Supply Air Flow Rate During Heating Operation",
    4420             :                                  "[m3/s]",
    4421          24 :                                  thisFurnace.MaxHeatAirVolFlowEMSOverrideOn,
    4422          24 :                                  thisFurnace.MaxHeatAirVolFlowEMSOverrideValue);
    4423          24 :                 SetupEMSActuator(state,
    4424             :                                  "AirLoopHVAC:Unitary:Furnace:HeatCool",
    4425             :                                  thisFurnace.Name,
    4426             :                                  "Autosized Supply Air Flow Rate During No Heating or Cooling Operation",
    4427             :                                  "[m3/s]",
    4428          24 :                                  thisFurnace.MaxNoCoolHeatAirVolFlowEMSOverrideOn,
    4429          24 :                                  thisFurnace.MaxNoCoolHeatAirVolFlowEMSOverrideValue);
    4430             :             }
    4431             :         }
    4432             : 
    4433         170 :         for (int UnitaryHeatCoolNum = NumHeatOnly + NumHeatCool + NumUnitaryHeatOnly + 1;
    4434         170 :              UnitaryHeatCoolNum <= NumHeatOnly + NumHeatCool + NumUnitaryHeatOnly + NumUnitaryHeatCool;
    4435             :              ++UnitaryHeatCoolNum) {
    4436          73 :             FurnaceNum = UnitaryHeatCoolNum;
    4437          73 :             auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    4438             :             // Setup Report variables for Unitary System that are not reported in the components themselves
    4439         146 :             SetupOutputVariable(state,
    4440             :                                 "Unitary System Fan Part Load Ratio",
    4441             :                                 Constant::Units::None,
    4442          73 :                                 thisFurnace.FanPartLoadRatio,
    4443             :                                 OutputProcessor::TimeStepType::System,
    4444             :                                 OutputProcessor::StoreType::Average,
    4445          73 :                                 thisFurnace.Name);
    4446         146 :             SetupOutputVariable(state,
    4447             :                                 "Unitary System Compressor Part Load Ratio",
    4448             :                                 Constant::Units::None,
    4449          73 :                                 thisFurnace.CompPartLoadRatio,
    4450             :                                 OutputProcessor::TimeStepType::System,
    4451             :                                 OutputProcessor::StoreType::Average,
    4452          73 :                                 thisFurnace.Name);
    4453          73 :             if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
    4454          20 :                 SetupEMSActuator(state,
    4455             :                                  "AirLoopHVAC:UnitaryHeatCool",
    4456             :                                  thisFurnace.Name,
    4457             :                                  "Autosized Supply Air Flow Rate",
    4458             :                                  "[m3/s]",
    4459          20 :                                  thisFurnace.DesignFanVolFlowRateEMSOverrideOn,
    4460          20 :                                  thisFurnace.DesignFanVolFlowRateEMSOverrideValue);
    4461          20 :                 SetupEMSActuator(state,
    4462             :                                  "AirLoopHVAC:UnitaryHeatCool",
    4463             :                                  thisFurnace.Name,
    4464             :                                  "Autosized Supply Air Flow Rate During Cooling Operation",
    4465             :                                  "[m3/s]",
    4466          20 :                                  thisFurnace.MaxCoolAirVolFlowEMSOverrideOn,
    4467          20 :                                  thisFurnace.MaxCoolAirVolFlowEMSOverrideValue);
    4468          20 :                 SetupEMSActuator(state,
    4469             :                                  "AirLoopHVAC:UnitaryHeatCool",
    4470             :                                  thisFurnace.Name,
    4471             :                                  "Autosized Supply Air Flow Rate During Heating Operation",
    4472             :                                  "[m3/s]",
    4473          20 :                                  thisFurnace.MaxHeatAirVolFlowEMSOverrideOn,
    4474          20 :                                  thisFurnace.MaxHeatAirVolFlowEMSOverrideValue);
    4475          20 :                 SetupEMSActuator(state,
    4476             :                                  "AirLoopHVAC:UnitaryHeatCool",
    4477             :                                  thisFurnace.Name,
    4478             :                                  "Autosized Supply Air Flow Rate During No Heating or Cooling Operation",
    4479             :                                  "[m3/s]",
    4480          20 :                                  thisFurnace.MaxNoCoolHeatAirVolFlowEMSOverrideOn,
    4481          20 :                                  thisFurnace.MaxNoCoolHeatAirVolFlowEMSOverrideValue);
    4482             :             }
    4483             :         }
    4484             : 
    4485         132 :         for (int HeatPumpNum = NumHeatOnly + NumHeatCool + NumUnitaryHeatOnly + NumUnitaryHeatCool + 1;
    4486         132 :              HeatPumpNum <= state.dataFurnaces->NumFurnaces - NumWaterToAirHeatPump;
    4487             :              ++HeatPumpNum) {
    4488          35 :             FurnaceNum = HeatPumpNum;
    4489          35 :             auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    4490             :             // Setup Report variables for Unitary System that are not reported in the components themselves
    4491          70 :             SetupOutputVariable(state,
    4492             :                                 "Unitary System Fan Part Load Ratio",
    4493             :                                 Constant::Units::None,
    4494          35 :                                 thisFurnace.FanPartLoadRatio,
    4495             :                                 OutputProcessor::TimeStepType::System,
    4496             :                                 OutputProcessor::StoreType::Average,
    4497          35 :                                 thisFurnace.Name);
    4498          70 :             SetupOutputVariable(state,
    4499             :                                 "Unitary System Compressor Part Load Ratio",
    4500             :                                 Constant::Units::None,
    4501          35 :                                 thisFurnace.CompPartLoadRatio,
    4502             :                                 OutputProcessor::TimeStepType::System,
    4503             :                                 OutputProcessor::StoreType::Average,
    4504          35 :                                 thisFurnace.Name);
    4505          70 :             SetupOutputVariable(state,
    4506             :                                 "Unitary System Dehumidification Induced Heating Demand Rate",
    4507             :                                 Constant::Units::W,
    4508          35 :                                 thisFurnace.DehumidInducedHeatingDemandRate,
    4509             :                                 OutputProcessor::TimeStepType::System,
    4510             :                                 OutputProcessor::StoreType::Average,
    4511          35 :                                 thisFurnace.Name);
    4512             : 
    4513          35 :             if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
    4514           5 :                 SetupEMSActuator(state,
    4515             :                                  "AirLoopHVAC:UnitaryHeatPump:AirToAir",
    4516             :                                  thisFurnace.Name,
    4517             :                                  "Autosized Supply Air Flow Rate",
    4518             :                                  "[m3/s]",
    4519           5 :                                  thisFurnace.DesignFanVolFlowRateEMSOverrideOn,
    4520           5 :                                  thisFurnace.DesignFanVolFlowRateEMSOverrideValue);
    4521             :             }
    4522             :         }
    4523             : 
    4524         236 :         for (int HeatPumpNum = NumHeatOnly + NumHeatCool + NumUnitaryHeatOnly + NumUnitaryHeatCool + NumHeatPump + 1;
    4525         236 :              HeatPumpNum <= state.dataFurnaces->NumFurnaces;
    4526             :              ++HeatPumpNum) {
    4527         139 :             FurnaceNum = HeatPumpNum;
    4528         139 :             auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    4529             :             // Setup Report variables for Unitary System that are not reported in the components themselves
    4530         278 :             SetupOutputVariable(state,
    4531             :                                 "Unitary System Fan Part Load Ratio",
    4532             :                                 Constant::Units::None,
    4533         139 :                                 thisFurnace.FanPartLoadRatio,
    4534             :                                 OutputProcessor::TimeStepType::System,
    4535             :                                 OutputProcessor::StoreType::Average,
    4536         139 :                                 thisFurnace.Name);
    4537         278 :             SetupOutputVariable(state,
    4538             :                                 "Unitary System Compressor Part Load Ratio",
    4539             :                                 Constant::Units::None,
    4540         139 :                                 thisFurnace.CompPartLoadRatio,
    4541             :                                 OutputProcessor::TimeStepType::System,
    4542             :                                 OutputProcessor::StoreType::Average,
    4543         139 :                                 thisFurnace.Name);
    4544         278 :             SetupOutputVariable(state,
    4545             :                                 "Unitary System Requested Sensible Cooling Rate",
    4546             :                                 Constant::Units::W,
    4547         139 :                                 thisFurnace.CoolingCoilSensDemand,
    4548             :                                 OutputProcessor::TimeStepType::System,
    4549             :                                 OutputProcessor::StoreType::Average,
    4550         139 :                                 thisFurnace.Name);
    4551         278 :             SetupOutputVariable(state,
    4552             :                                 "Unitary System Requested Latent Cooling Rate",
    4553             :                                 Constant::Units::W,
    4554         139 :                                 thisFurnace.CoolingCoilLatentDemand,
    4555             :                                 OutputProcessor::TimeStepType::System,
    4556             :                                 OutputProcessor::StoreType::Average,
    4557         139 :                                 thisFurnace.Name);
    4558         278 :             SetupOutputVariable(state,
    4559             :                                 "Unitary System Requested Heating Rate",
    4560             :                                 Constant::Units::W,
    4561         139 :                                 thisFurnace.HeatingCoilSensDemand,
    4562             :                                 OutputProcessor::TimeStepType::System,
    4563             :                                 OutputProcessor::StoreType::Average,
    4564         139 :                                 thisFurnace.Name);
    4565         278 :             SetupOutputVariable(state,
    4566             :                                 "Unitary System Dehumidification Induced Heating Demand Rate",
    4567             :                                 Constant::Units::W,
    4568         139 :                                 thisFurnace.DehumidInducedHeatingDemandRate,
    4569             :                                 OutputProcessor::TimeStepType::System,
    4570             :                                 OutputProcessor::StoreType::Average,
    4571         139 :                                 thisFurnace.Name);
    4572             : 
    4573         139 :             if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
    4574          96 :                 SetupEMSActuator(state,
    4575             :                                  "AirLoopHVAC:UnitaryHeatPump:WaterToAir",
    4576             :                                  thisFurnace.Name,
    4577             :                                  "Autosized Supply Air Flow Rate",
    4578             :                                  "[m3/s]",
    4579          96 :                                  thisFurnace.DesignFanVolFlowRateEMSOverrideOn,
    4580          96 :                                  thisFurnace.DesignFanVolFlowRateEMSOverrideValue);
    4581             :             }
    4582             :         }
    4583             : 
    4584          97 :         if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
    4585         154 :             for (FurnaceNum = 1; FurnaceNum <= state.dataFurnaces->NumFurnaces; ++FurnaceNum) {
    4586         145 :                 auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    4587         145 :                 SetupEMSInternalVariable(state, "Unitary HVAC Design Heating Capacity", thisFurnace.Name, "[W]", thisFurnace.DesignHeatingCapacity);
    4588         145 :                 SetupEMSInternalVariable(state, "Unitary HVAC Design Cooling Capacity", thisFurnace.Name, "[W]", thisFurnace.DesignCoolingCapacity);
    4589         145 :                 SetupEMSActuator(state,
    4590             :                                  "Unitary HVAC",
    4591             :                                  thisFurnace.Name,
    4592             :                                  "Sensible Load Request",
    4593             :                                  "[W]",
    4594         145 :                                  thisFurnace.EMSOverrideSensZoneLoadRequest,
    4595         145 :                                  thisFurnace.EMSSensibleZoneLoadValue);
    4596         145 :                 SetupEMSActuator(state,
    4597             :                                  "Unitary HVAC",
    4598             :                                  thisFurnace.Name,
    4599             :                                  "Moisture Load Request",
    4600             :                                  "[W]",
    4601         145 :                                  thisFurnace.EMSOverrideMoistZoneLoadRequest,
    4602         145 :                                  thisFurnace.EMSMoistureZoneLoadValue);
    4603             :             }
    4604             :         }
    4605             :         bool anyRan;
    4606          97 :         EMSManager::ManageEMS(state, EMSManager::EMSCallFrom::ComponentGetInput, anyRan, ObjexxFCL::Optional_int_const());
    4607          97 :     }
    4608             : 
    4609             :     // End of Get Input subroutines for this Module
    4610             :     //******************************************************************************
    4611             : 
    4612             :     // Beginning Initialization Section of the Module
    4613             :     //******************************************************************************
    4614             : 
    4615     6243009 :     void InitFurnace(EnergyPlusData &state,
    4616             :                      int const FurnaceNum,         // index to Furnace
    4617             :                      int const AirLoopNum,         // index to air loop
    4618             :                      Real64 &OnOffAirFlowRatio,    // ratio of on to off air mass flow rate
    4619             :                      HVAC::FanOp &fanOp,           // fan operating mode
    4620             :                      Real64 &ZoneLoad,             // zone sensible load to be met (modified here as needed) (W)
    4621             :                      Real64 &MoistureLoad,         // zone moisture load (W)
    4622             :                      bool const FirstHVACIteration // TRUE if first HVAC iteration
    4623             :     )
    4624             :     {
    4625             : 
    4626             :         // SUBROUTINE INFORMATION:
    4627             :         //       AUTHOR         Richard J. Liesen
    4628             :         //       DATE WRITTEN   Feb 2001
    4629             :         //       MODIFIED       Oct 2001, Richard Raustad
    4630             :         //                      Sep 2008, R. Raustad - revised logic to determine load to be met
    4631             :         //                      Bereket Nigusse, June 2010 - added a procedure to calculate supply air flow fraction
    4632             :         //                      through controlled zone
    4633             :         //                      Bo Shen, March 2012 - for VS WSHP
    4634             :         //                      Bo Shen, ORNL, July 2012 - added variable-speed air source heat pump cooling and heating coils, using curve-fits
    4635             : 
    4636             :         // PURPOSE OF THIS SUBROUTINE:
    4637             :         // This subroutine is for initializations of the Furnace Components.
    4638             : 
    4639             :         // METHODOLOGY EMPLOYED:
    4640             :         // Uses the status flags to trigger initializations.
    4641             :         // The HeatCool furnace/unitarysystem and air-to-air heat pump may have alternate air flow rates
    4642             :         // in cooling, heating, and when no cooling or heating is needed. Set up the coil (comp) ON and OFF
    4643             :         // air flow rates during InitFurnace. Use these flow rates during the Calc routines to set the
    4644             :         // average mass flow rates based on PLR.
    4645             : 
    4646             :         // SUBROUTINE PARAMETER DEFINITIONS:
    4647     6243009 :         Real64 constexpr Small5WLoad(5.0);
    4648     6243009 :         std::string_view constexpr RoutineName("InitFurnace");
    4649             : 
    4650             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    4651             :         bool errFlag;          // error flag for mining functions
    4652             :         Real64 QZnReq;         // furnace load based on control zone frac (W)
    4653             :         Real64 PartLoadRatio;  // furnace part-load ratio
    4654             :         Real64 SensibleOutput; // no load sensible output (coils off) (W)
    4655             :         Real64 LatentOutput;   // no load latent output (coils off) (W)
    4656             :         Real64 QToCoolSetPt;   // sensible load to cooling setpoint (W)
    4657             :         Real64 QToHeatSetPt;   // sensible load to heating setpoint (W)
    4658             :         // calculation (kg/kg)
    4659             :         Real64 DeltaMassRate; // Difference of mass flow rate between
    4660             :         // inlet node and system outlet node
    4661             :         Real64 MassFlowRate; // mass flow rate to calculate loss
    4662             : 
    4663     6243009 :         Real64 SumOfMassFlowRateMax(0.0);                 // the sum of mass flow rates at inlet to zones in an airloop
    4664     6243009 :         Real64 CntrlZoneTerminalUnitMassFlowRateMax(0.0); // Maximum mass flow rate through controlled zone terminal unit
    4665             : 
    4666     6243009 :         bool ErrorsFound(false);                 // flag returned from mining call
    4667     6243009 :         Real64 mdot(0.0);                        // local temporary for mass flow rate (kg/s)
    4668     6243009 :         Real64 rho(0.0);                         // local for fluid density
    4669     6243009 :         Real64 SteamDensity(0.0);                // density of steam at 100C, used for steam heating coils
    4670     6243009 :         Real64 CoilMaxVolFlowRate(0.0);          // coil fluid maximum volume flow rate
    4671     6243009 :         Real64 QActual(0.0);                     // coil actual capacity
    4672     6243009 :         Real64 SUPHEATERLOAD(0.0);               // SUPPLEMENTAL HEATER LOAD
    4673             :         Real64 RhoAir;                           // Air density at InNode
    4674             :         Furnaces::ModeOfOperation OperatingMode; // track cooling, heating, and no cooling or heating modes
    4675             :         Furnaces::ModeOfOperation OperatingModeMinusOne;
    4676             :         Furnaces::ModeOfOperation OperatingModeMinusTwo;
    4677             :         bool Oscillate; // detection of oscillating operating modes
    4678             : 
    4679     6243009 :         auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    4680     6243009 :         int InNode = thisFurnace.FurnaceInletNodeNum;
    4681     6243009 :         int OutNode = thisFurnace.FurnaceOutletNodeNum;
    4682             : 
    4683     6243009 :         if (state.dataFurnaces->InitFurnaceMyOneTimeFlag) {
    4684             :             // initialize the environment and sizing flags
    4685          97 :             state.dataFurnaces->MyEnvrnFlag.allocate(state.dataFurnaces->NumFurnaces);
    4686          97 :             state.dataFurnaces->MySizeFlag.allocate(state.dataFurnaces->NumFurnaces);
    4687          97 :             state.dataFurnaces->MySecondOneTimeFlag.allocate(state.dataFurnaces->NumFurnaces);
    4688          97 :             state.dataFurnaces->MyFanFlag.allocate(state.dataFurnaces->NumFurnaces);
    4689          97 :             state.dataFurnaces->MyCheckFlag.allocate(state.dataFurnaces->NumFurnaces);
    4690          97 :             state.dataFurnaces->MyFlowFracFlag.allocate(state.dataFurnaces->NumFurnaces);
    4691          97 :             state.dataFurnaces->MyPlantScanFlag.allocate(state.dataFurnaces->NumFurnaces);
    4692          97 :             state.dataFurnaces->MySuppCoilPlantScanFlag.allocate(state.dataFurnaces->NumFurnaces);
    4693          97 :             state.dataFurnaces->MyEnvrnFlag = true;
    4694          97 :             state.dataFurnaces->MySizeFlag = true;
    4695          97 :             state.dataFurnaces->MySecondOneTimeFlag = true;
    4696          97 :             state.dataFurnaces->MyFanFlag = true;
    4697          97 :             state.dataFurnaces->MyCheckFlag = true;
    4698          97 :             state.dataFurnaces->MyFlowFracFlag = true;
    4699          97 :             state.dataFurnaces->InitFurnaceMyOneTimeFlag = false;
    4700          97 :             state.dataFurnaces->MyPlantScanFlag = true;
    4701          97 :             state.dataFurnaces->MySuppCoilPlantScanFlag = true;
    4702             :         }
    4703             : 
    4704     6243009 :         if (state.dataGlobal->BeginEnvrnFlag && state.dataFurnaces->MyAirLoopPass) {
    4705         588 :             state.dataFurnaces->AirLoopPass = 0;
    4706         588 :             state.dataFurnaces->MyAirLoopPass = false;
    4707             :         }
    4708     6243009 :         if (!state.dataGlobal->BeginEnvrnFlag) {
    4709     6222832 :             state.dataFurnaces->MyAirLoopPass = true;
    4710             :         }
    4711             : 
    4712     6243009 :         ++state.dataFurnaces->AirLoopPass;
    4713     6243009 :         if (state.dataFurnaces->AirLoopPass > 2) state.dataFurnaces->AirLoopPass = 1;
    4714             : 
    4715     6243009 :         if (!state.dataGlobal->SysSizingCalc && state.dataFurnaces->MySizeFlag(FurnaceNum)) {
    4716             :             // for each furnace, do the sizing once.
    4717         359 :             SizeFurnace(state, FurnaceNum, FirstHVACIteration);
    4718         359 :             thisFurnace.ControlZoneMassFlowFrac = 1.0;
    4719             : 
    4720         359 :             state.dataFurnaces->MySizeFlag(FurnaceNum) = false;
    4721             :             // Pass the fan cycling schedule index up to the air loop. Set the air loop unitary system flag.
    4722         359 :             state.dataAirLoop->AirLoopControlInfo(AirLoopNum).CycFanSchedPtr = thisFurnace.FanSchedPtr;
    4723         359 :             state.dataAirLoop->AirLoopControlInfo(AirLoopNum).UnitarySys = true;
    4724             :             // RR this is wrong, Op mode needs to be updated each time atep
    4725         359 :             state.dataAirLoop->AirLoopControlInfo(AirLoopNum).fanOp = thisFurnace.fanOp;
    4726             : 
    4727             :             // Check that heat pump heating capacity is within 20% of cooling capacity
    4728         359 :             if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_AirToAir) {
    4729          35 :                 if (std::abs(thisFurnace.DesignCoolingCapacity - thisFurnace.DesignHeatingCapacity) / thisFurnace.DesignCoolingCapacity > 0.2) {
    4730           0 :                     ShowWarningError(state,
    4731           0 :                                      format("{} \"{}\" heating capacity is disproportionate (> 20% different) to total cooling capacity",
    4732           0 :                                             HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    4733           0 :                                             thisFurnace.Name));
    4734             :                 }
    4735             :             }
    4736             :         }
    4737             : 
    4738     6243009 :         if (!state.dataGlobal->DoingSizing && state.dataFurnaces->MySecondOneTimeFlag(FurnaceNum)) {
    4739             :             // sizing all done.  check fan air flow rates
    4740         625 :             thisFurnace.ActualFanVolFlowRate = state.dataFans->fans(thisFurnace.FanIndex)->maxAirFlowRate;
    4741         625 :             if (thisFurnace.ActualFanVolFlowRate != DataSizing::AutoSize) {
    4742         359 :                 if (thisFurnace.DesignFanVolFlowRate > thisFurnace.ActualFanVolFlowRate) {
    4743           0 :                     ShowWarningError(state,
    4744           0 :                                      format("{}={} has a Design Fan Volume Flow Rate > Max Fan Volume Flow Rate, should be <=",
    4745           0 :                                             HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    4746           0 :                                             thisFurnace.Name));
    4747           0 :                     ShowContinueError(state,
    4748           0 :                                       format("... Entered value={:.2R}... Fan [{}] Max Value={:.2R}",
    4749           0 :                                              thisFurnace.DesignFanVolFlowRate,
    4750           0 :                                              HVAC::fanTypeNames[(int)thisFurnace.fanType],
    4751           0 :                                              thisFurnace.ActualFanVolFlowRate));
    4752             :                 }
    4753         359 :                 if (thisFurnace.DesignFanVolFlowRate <= 0.0) {
    4754           0 :                     ShowSevereError(state,
    4755           0 :                                     format("{}={} has a Design Fan Volume Flow Rate <= 0.0, it must be >0.0",
    4756           0 :                                            HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    4757           0 :                                            thisFurnace.Name));
    4758           0 :                     ShowContinueError(state, format("... Entered value={:.2R}", thisFurnace.DesignFanVolFlowRate));
    4759             :                 }
    4760             : 
    4761         359 :                 state.dataFurnaces->MySecondOneTimeFlag(FurnaceNum) = false;
    4762             :             }
    4763             :         }
    4764             : 
    4765             :         // Scan hot water and steam heating coil plant components for one time initializations
    4766     6243009 :         if (state.dataFurnaces->MyPlantScanFlag(FurnaceNum) && allocated(state.dataPlnt->PlantLoop)) {
    4767         359 :             if ((thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingWater) || (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingSteam)) {
    4768             : 
    4769           0 :                 if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingWater) {
    4770             : 
    4771           0 :                     errFlag = false;
    4772           0 :                     PlantUtilities::ScanPlantLoopsForObject(state,
    4773             :                                                             thisFurnace.HeatingCoilName,
    4774             :                                                             DataPlant::PlantEquipmentType::CoilWaterSimpleHeating,
    4775           0 :                                                             thisFurnace.plantLoc,
    4776             :                                                             errFlag,
    4777             :                                                             _,
    4778             :                                                             _,
    4779             :                                                             _,
    4780             :                                                             _,
    4781             :                                                             _);
    4782           0 :                     if (errFlag) {
    4783           0 :                         ShowFatalError(state, "InitFurnace: Program terminated for previous conditions.");
    4784             :                     }
    4785           0 :                     thisFurnace.MaxHeatCoilFluidFlow =
    4786           0 :                         WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", thisFurnace.HeatingCoilName, ErrorsFound);
    4787           0 :                     if (thisFurnace.MaxHeatCoilFluidFlow > 0.0) {
    4788           0 :                         rho = FluidProperties::GetDensityGlycol(state,
    4789           0 :                                                                 state.dataPlnt->PlantLoop(thisFurnace.plantLoc.loopNum).FluidName,
    4790             :                                                                 Constant::HWInitConvTemp,
    4791           0 :                                                                 state.dataPlnt->PlantLoop(thisFurnace.plantLoc.loopNum).FluidIndex,
    4792             :                                                                 RoutineName);
    4793           0 :                         thisFurnace.MaxHeatCoilFluidFlow *= rho;
    4794             :                     }
    4795           0 :                 } else if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingSteam) {
    4796             : 
    4797           0 :                     errFlag = false;
    4798           0 :                     PlantUtilities::ScanPlantLoopsForObject(state,
    4799             :                                                             thisFurnace.HeatingCoilName,
    4800             :                                                             DataPlant::PlantEquipmentType::CoilSteamAirHeating,
    4801           0 :                                                             thisFurnace.plantLoc,
    4802             :                                                             errFlag,
    4803             :                                                             _,
    4804             :                                                             _,
    4805             :                                                             _,
    4806             :                                                             _,
    4807             :                                                             _);
    4808           0 :                     if (errFlag) {
    4809           0 :                         ShowFatalError(state, "InitFurnace: Program terminated for previous conditions.");
    4810             :                     }
    4811           0 :                     thisFurnace.MaxHeatCoilFluidFlow = SteamCoils::GetCoilMaxSteamFlowRate(state, thisFurnace.HeatingCoilIndex, ErrorsFound);
    4812           0 :                     if (thisFurnace.MaxHeatCoilFluidFlow > 0.0) {
    4813           0 :                         int SteamIndex = 0; // Function GetSatDensityRefrig will look up steam index if 0 is passed
    4814           0 :                         SteamDensity = FluidProperties::GetSatDensityRefrig(
    4815           0 :                             state, fluidNameSteam, state.dataFurnaces->TempSteamIn, 1.0, SteamIndex, RoutineName);
    4816           0 :                         thisFurnace.MaxHeatCoilFluidFlow *= SteamDensity;
    4817             :                     }
    4818             :                 }
    4819             :                 // fill outlet node for coil
    4820           0 :                 thisFurnace.CoilOutletNode = DataPlant::CompData::getPlantComponent(state, thisFurnace.plantLoc).NodeNumOut;
    4821           0 :                 state.dataFurnaces->MyPlantScanFlag(FurnaceNum) = false;
    4822           0 :             } else { // pthp not connected to plant
    4823         359 :                 state.dataFurnaces->MyPlantScanFlag(FurnaceNum) = false;
    4824             :             }
    4825     6242650 :         } else if (state.dataFurnaces->MyPlantScanFlag(FurnaceNum) && !state.dataGlobal->AnyPlantInModel) {
    4826           0 :             state.dataFurnaces->MyPlantScanFlag(FurnaceNum) = false;
    4827             :         }
    4828             : 
    4829             :         // Scan Supplemental hot water and steam heating coil plant components for one time initializations
    4830     6243009 :         if (state.dataFurnaces->MySuppCoilPlantScanFlag(FurnaceNum) && allocated(state.dataPlnt->PlantLoop)) {
    4831         359 :             if ((thisFurnace.SuppHeatCoilType_Num == HVAC::Coil_HeatingWater) || (thisFurnace.SuppHeatCoilType_Num == HVAC::Coil_HeatingSteam)) {
    4832             : 
    4833           1 :                 if (thisFurnace.SuppHeatCoilType_Num == HVAC::Coil_HeatingWater) {
    4834           1 :                     errFlag = false;
    4835           2 :                     PlantUtilities::ScanPlantLoopsForObject(state,
    4836             :                                                             thisFurnace.SuppHeatCoilName,
    4837             :                                                             DataPlant::PlantEquipmentType::CoilWaterSimpleHeating,
    4838           1 :                                                             thisFurnace.SuppPlantLoc,
    4839             :                                                             errFlag,
    4840             :                                                             _,
    4841             :                                                             _,
    4842             :                                                             _,
    4843             :                                                             _,
    4844             :                                                             _);
    4845           1 :                     if (errFlag) {
    4846           0 :                         ShowFatalError(state, "InitFurnace: Program terminated for previous conditions.");
    4847             :                     }
    4848           1 :                     thisFurnace.MaxSuppCoilFluidFlow =
    4849           1 :                         WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", thisFurnace.SuppHeatCoilName, ErrorsFound);
    4850           1 :                     if (thisFurnace.MaxSuppCoilFluidFlow > 0.0) {
    4851           1 :                         rho = FluidProperties::GetDensityGlycol(state,
    4852           1 :                                                                 state.dataPlnt->PlantLoop(thisFurnace.SuppPlantLoc.loopNum).FluidName,
    4853             :                                                                 Constant::HWInitConvTemp,
    4854           1 :                                                                 state.dataPlnt->PlantLoop(thisFurnace.SuppPlantLoc.loopNum).FluidIndex,
    4855             :                                                                 RoutineName);
    4856           1 :                         thisFurnace.MaxSuppCoilFluidFlow *= rho;
    4857             :                     }
    4858           0 :                 } else if (thisFurnace.SuppHeatCoilType_Num == HVAC::Coil_HeatingSteam) {
    4859           0 :                     errFlag = false;
    4860           0 :                     PlantUtilities::ScanPlantLoopsForObject(state,
    4861             :                                                             thisFurnace.SuppHeatCoilName,
    4862             :                                                             DataPlant::PlantEquipmentType::CoilSteamAirHeating,
    4863           0 :                                                             thisFurnace.SuppPlantLoc,
    4864             :                                                             errFlag,
    4865             :                                                             _,
    4866             :                                                             _,
    4867             :                                                             _,
    4868             :                                                             _,
    4869             :                                                             _);
    4870           0 :                     if (errFlag) {
    4871           0 :                         ShowFatalError(state, "InitFurnace: Program terminated for previous conditions.");
    4872             :                     }
    4873           0 :                     thisFurnace.MaxSuppCoilFluidFlow = SteamCoils::GetCoilMaxSteamFlowRate(state, thisFurnace.SuppHeatCoilIndex, ErrorsFound);
    4874           0 :                     if (thisFurnace.MaxSuppCoilFluidFlow > 0.0) {
    4875           0 :                         int SteamIndex = 0; // Function GetSatDensityRefrig will look up steam index if 0 is passed
    4876           0 :                         SteamDensity = FluidProperties::GetSatDensityRefrig(
    4877           0 :                             state, fluidNameSteam, state.dataFurnaces->TempSteamIn, 1.0, SteamIndex, RoutineName);
    4878           0 :                         thisFurnace.MaxSuppCoilFluidFlow *= SteamDensity;
    4879             :                     }
    4880             :                 }
    4881             :                 // fill outlet node for coil
    4882           1 :                 thisFurnace.SuppCoilOutletNode = DataPlant::CompData::getPlantComponent(state, thisFurnace.SuppPlantLoc).NodeNumOut;
    4883           1 :                 state.dataFurnaces->MySuppCoilPlantScanFlag(FurnaceNum) = false;
    4884           1 :             } else { // pthp not connected to plant
    4885         358 :                 state.dataFurnaces->MySuppCoilPlantScanFlag(FurnaceNum) = false;
    4886             :             }
    4887             : 
    4888     6242650 :         } else if (state.dataFurnaces->MySuppCoilPlantScanFlag(FurnaceNum) && !state.dataGlobal->AnyPlantInModel) {
    4889           0 :             state.dataFurnaces->MySuppCoilPlantScanFlag(FurnaceNum) = false;
    4890             :         }
    4891             : 
    4892             :         // Do the Begin Environment initializations
    4893     6243009 :         if (state.dataGlobal->BeginEnvrnFlag && state.dataFurnaces->MyEnvrnFlag(FurnaceNum)) {
    4894             :             // Change the Volume Flow Rates to Mass Flow Rates
    4895        2286 :             thisFurnace.DesignMassFlowRate = thisFurnace.DesignFanVolFlowRate * state.dataEnvrn->StdRhoAir;
    4896        2286 :             thisFurnace.MaxCoolAirMassFlow = thisFurnace.MaxCoolAirVolFlow * state.dataEnvrn->StdRhoAir;
    4897        2286 :             thisFurnace.MaxHeatAirMassFlow = thisFurnace.MaxHeatAirVolFlow * state.dataEnvrn->StdRhoAir;
    4898        2286 :             thisFurnace.MaxNoCoolHeatAirMassFlow = thisFurnace.MaxNoCoolHeatAirVolFlow * state.dataEnvrn->StdRhoAir;
    4899        2286 :             thisFurnace.CompPartLoadRatio = 0.0;
    4900        2286 :             thisFurnace.CoolingCoilSensDemand = 0.0;
    4901        2286 :             thisFurnace.CoolingCoilLatentDemand = 0.0;
    4902        2286 :             thisFurnace.HeatingCoilSensDemand = 0.0;
    4903             : 
    4904        2286 :             thisFurnace.SenLoadLoss = 0.0;
    4905        2286 :             if (thisFurnace.Humidistat) {
    4906         351 :                 thisFurnace.LatLoadLoss = 0.0;
    4907             :             }
    4908             : 
    4909             :             //   set fluid-side hardware limits
    4910        2286 :             if (thisFurnace.CoilControlNode > 0) {
    4911             : 
    4912           0 :                 if (thisFurnace.MaxHeatCoilFluidFlow == DataSizing::AutoSize) {
    4913             :                     // If water coil max water flow rate is autosized, simulate once in order to mine max flow rate
    4914           0 :                     if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingWater) {
    4915           0 :                         WaterCoils::SimulateWaterCoilComponents(state, thisFurnace.HeatingCoilName, FirstHVACIteration, thisFurnace.HeatingCoilIndex);
    4916             :                         CoilMaxVolFlowRate =
    4917           0 :                             WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", thisFurnace.HeatingCoilName, ErrorsFound);
    4918           0 :                         if (CoilMaxVolFlowRate != DataSizing::AutoSize) {
    4919           0 :                             rho = FluidProperties::GetDensityGlycol(state,
    4920           0 :                                                                     state.dataPlnt->PlantLoop(thisFurnace.plantLoc.loopNum).FluidName,
    4921             :                                                                     Constant::HWInitConvTemp,
    4922           0 :                                                                     state.dataPlnt->PlantLoop(thisFurnace.plantLoc.loopNum).FluidIndex,
    4923             :                                                                     RoutineName);
    4924           0 :                             thisFurnace.MaxHeatCoilFluidFlow = CoilMaxVolFlowRate * rho;
    4925             :                         }
    4926             :                     }
    4927             :                     // If steam coil max steam flow rate is autosized, simulate once in order to mine max flow rate
    4928           0 :                     if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingSteam) {
    4929           0 :                         SteamCoils::SimulateSteamCoilComponents(state,
    4930             :                                                                 thisFurnace.HeatingCoilName,
    4931             :                                                                 FirstHVACIteration,
    4932           0 :                                                                 thisFurnace.HeatingCoilIndex,
    4933           0 :                                                                 1.0,
    4934             :                                                                 QActual); // QCoilReq, simulate any load > 0 to get max capacity
    4935           0 :                         CoilMaxVolFlowRate = SteamCoils::GetCoilMaxSteamFlowRate(state, thisFurnace.HeatingCoilIndex, ErrorsFound);
    4936           0 :                         if (CoilMaxVolFlowRate != DataSizing::AutoSize) {
    4937           0 :                             int SteamIndex = 0; // Function GetSatDensityRefrig will look up steam index if 0 is passed
    4938           0 :                             SteamDensity = FluidProperties::GetSatDensityRefrig(
    4939           0 :                                 state, fluidNameSteam, state.dataFurnaces->TempSteamIn, 1.0, SteamIndex, RoutineName);
    4940           0 :                             thisFurnace.MaxHeatCoilFluidFlow = CoilMaxVolFlowRate * SteamDensity;
    4941             :                         }
    4942             :                     }
    4943             :                 }
    4944             : 
    4945           0 :                 PlantUtilities::InitComponentNodes(
    4946             :                     state, 0.0, thisFurnace.MaxHeatCoilFluidFlow, thisFurnace.CoilControlNode, thisFurnace.CoilOutletNode);
    4947             :             }
    4948        2286 :             if (thisFurnace.SuppCoilControlNode > 0) {
    4949           7 :                 if (thisFurnace.MaxSuppCoilFluidFlow == DataSizing::AutoSize) {
    4950           0 :                     if (thisFurnace.SuppHeatCoilType_Num == HVAC::Coil_HeatingWater) {
    4951             :                         // If water coil max water flow rate is autosized, simulate once in order to mine max flow rate
    4952           0 :                         WaterCoils::SimulateWaterCoilComponents(
    4953           0 :                             state, thisFurnace.SuppHeatCoilName, FirstHVACIteration, thisFurnace.SuppHeatCoilIndex);
    4954             :                         CoilMaxVolFlowRate =
    4955           0 :                             WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", thisFurnace.SuppHeatCoilName, ErrorsFound);
    4956           0 :                         if (CoilMaxVolFlowRate != DataSizing::AutoSize) {
    4957           0 :                             rho = FluidProperties::GetDensityGlycol(state,
    4958           0 :                                                                     state.dataPlnt->PlantLoop(thisFurnace.SuppPlantLoc.loopNum).FluidName,
    4959             :                                                                     Constant::HWInitConvTemp,
    4960           0 :                                                                     state.dataPlnt->PlantLoop(thisFurnace.SuppPlantLoc.loopNum).FluidIndex,
    4961             :                                                                     RoutineName);
    4962           0 :                             thisFurnace.MaxSuppCoilFluidFlow = CoilMaxVolFlowRate * rho;
    4963             :                         }
    4964             :                     }
    4965           0 :                     if (thisFurnace.SuppHeatCoilType_Num == HVAC::Coil_HeatingSteam) {
    4966           0 :                         SteamCoils::SimulateSteamCoilComponents(state,
    4967             :                                                                 thisFurnace.SuppHeatCoilName,
    4968             :                                                                 FirstHVACIteration,
    4969           0 :                                                                 thisFurnace.SuppHeatCoilIndex,
    4970           0 :                                                                 1.0,
    4971             :                                                                 QActual); // QCoilReq, simulate any load > 0 to get max capacity
    4972           0 :                         CoilMaxVolFlowRate = SteamCoils::GetCoilMaxSteamFlowRate(state, thisFurnace.SuppHeatCoilIndex, ErrorsFound);
    4973           0 :                         if (CoilMaxVolFlowRate != DataSizing::AutoSize) {
    4974           0 :                             int SteamIndex = 0; // Function GetSatDensityRefrig will look up steam index if 0 is passed
    4975           0 :                             SteamDensity = FluidProperties::GetSatDensityRefrig(
    4976           0 :                                 state, fluidNameSteam, state.dataFurnaces->TempSteamIn, 1.0, SteamIndex, RoutineName);
    4977           0 :                             thisFurnace.MaxSuppCoilFluidFlow = CoilMaxVolFlowRate * SteamDensity;
    4978             :                         }
    4979             :                     }
    4980           0 :                     PlantUtilities::InitComponentNodes(
    4981             :                         state, 0.0, thisFurnace.MaxSuppCoilFluidFlow, thisFurnace.SuppCoilControlNode, thisFurnace.SuppCoilOutletNode);
    4982             :                 }
    4983             :             }
    4984        2286 :             state.dataFurnaces->MyEnvrnFlag(FurnaceNum) = false;
    4985             :         }
    4986             : 
    4987     6243009 :         if (!state.dataGlobal->BeginEnvrnFlag) {
    4988     6222832 :             state.dataFurnaces->MyEnvrnFlag(FurnaceNum) = true;
    4989             :         }
    4990             : 
    4991     6243009 :         if (state.dataFurnaces->MyFanFlag(FurnaceNum)) {
    4992         625 :             if (thisFurnace.ActualFanVolFlowRate != DataSizing::AutoSize) {
    4993         359 :                 if (thisFurnace.ActualFanVolFlowRate > 0.0) {
    4994         359 :                     thisFurnace.HeatingSpeedRatio = thisFurnace.MaxHeatAirVolFlow / thisFurnace.ActualFanVolFlowRate;
    4995         359 :                     thisFurnace.CoolingSpeedRatio = thisFurnace.MaxCoolAirVolFlow / thisFurnace.ActualFanVolFlowRate;
    4996         359 :                     thisFurnace.NoHeatCoolSpeedRatio = thisFurnace.MaxNoCoolHeatAirVolFlow / thisFurnace.ActualFanVolFlowRate;
    4997             :                 }
    4998         359 :                 if (dynamic_cast<Fans::FanComponent *>(state.dataFans->fans(thisFurnace.FanIndex))->powerRatioAtSpeedRatioCurveNum > 0) {
    4999           0 :                     if (thisFurnace.ActualFanVolFlowRate == thisFurnace.MaxHeatAirVolFlow &&
    5000           0 :                         thisFurnace.ActualFanVolFlowRate == thisFurnace.MaxCoolAirVolFlow &&
    5001           0 :                         thisFurnace.ActualFanVolFlowRate == thisFurnace.MaxNoCoolHeatAirVolFlow) {
    5002           0 :                         std::string FanName = state.dataFans->fans(thisFurnace.FanIndex)->Name;
    5003           0 :                         ShowWarningError(state, format("{} \"{}\"", HVAC::unitarySysTypeNames[(int)thisFurnace.type], thisFurnace.Name));
    5004           0 :                         ShowContinueError(state,
    5005           0 :                                           format("...For fan type and name = {} \"{}\"", HVAC::fanTypeNames[(int)thisFurnace.fanType], FanName));
    5006           0 :                         ShowContinueError(state,
    5007             :                                           "...Fan power ratio function of speed ratio curve has no impact if fan volumetric flow rate is the same as "
    5008             :                                           "the unitary system volumetric flow rate.");
    5009           0 :                         ShowContinueError(state, format("...Fan volumetric flow rate            = {:.5R} m3/s.", thisFurnace.ActualFanVolFlowRate));
    5010           0 :                         ShowContinueError(state, format("...Unitary system volumetric flow rate = {:.5R} m3/s.", thisFurnace.MaxHeatAirVolFlow));
    5011           0 :                     }
    5012             :                 }
    5013         359 :                 state.dataFurnaces->MyFanFlag(FurnaceNum) = false;
    5014             :             } else {
    5015         266 :                 thisFurnace.ActualFanVolFlowRate = state.dataFans->fans(thisFurnace.FanIndex)->maxAirFlowRate;
    5016             :             }
    5017             :         }
    5018             : 
    5019     6243009 :         if (allocated(state.dataZoneEquip->ZoneEquipConfig) && state.dataFurnaces->MyCheckFlag(FurnaceNum)) {
    5020         359 :             int zoneNum = thisFurnace.ControlZoneNum;
    5021         359 :             int zoneInlet = thisFurnace.ZoneInletNode;
    5022             :             // setup furnace zone equipment sequence information based on finding matching air terminal
    5023         359 :             if (state.dataZoneEquip->ZoneEquipConfig(zoneNum).EquipListIndex > 0) {
    5024         359 :                 int coolingPriority = 0;
    5025         359 :                 int heatingPriority = 0;
    5026         359 :                 state.dataZoneEquip->ZoneEquipList(state.dataZoneEquip->ZoneEquipConfig(zoneNum).EquipListIndex)
    5027         359 :                     .getPrioritiesForInletNode(state, zoneInlet, coolingPriority, heatingPriority);
    5028         359 :                 thisFurnace.ZoneSequenceCoolingNum = coolingPriority;
    5029         359 :                 thisFurnace.ZoneSequenceHeatingNum = heatingPriority;
    5030             :             }
    5031         359 :             state.dataFurnaces->MyCheckFlag(FurnaceNum) = false;
    5032         359 :             if (thisFurnace.ZoneSequenceCoolingNum == 0 || thisFurnace.ZoneSequenceHeatingNum == 0) {
    5033           0 :                 ShowSevereError(state,
    5034           0 :                                 format("{} \"{}\": Airloop air terminal in the zone equipment list for zone = {} not found or is not allowed Zone "
    5035             :                                        "Equipment Cooling or Heating Sequence = 0.",
    5036           0 :                                        HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    5037           0 :                                        thisFurnace.Name,
    5038           0 :                                        state.dataHeatBal->Zone(thisFurnace.ControlZoneNum).Name));
    5039           0 :                 ShowFatalError(state,
    5040           0 :                                format("Subroutine InitFurnace: Errors found in getting {} input.  Preceding condition(s) causes termination.",
    5041           0 :                                       HVAC::unitarySysTypeNames[(int)thisFurnace.type]));
    5042             :             }
    5043             :         }
    5044             : 
    5045             :         // Find the number of zones (zone Inlet Nodes) attached to an air loop from the air loop number
    5046             :         int NumAirLoopZones =
    5047     6243009 :             state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).NumZonesCooled + state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).NumZonesHeated;
    5048     6243009 :         if (allocated(state.dataAirLoop->AirToZoneNodeInfo) && state.dataFurnaces->MyFlowFracFlag(FurnaceNum)) {
    5049         359 :             state.dataFurnaces->FlowFracFlagReady = true;
    5050         799 :             for (int ZoneInSysIndex = 1; ZoneInSysIndex <= NumAirLoopZones; ++ZoneInSysIndex) {
    5051             :                 // zone inlet nodes for cooling
    5052         440 :                 if (state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).NumZonesCooled > 0) {
    5053         440 :                     if (state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).TermUnitCoolInletNodes(ZoneInSysIndex) == -999) {
    5054             :                         // the data structure for the zones inlet nodes has not been filled
    5055           0 :                         state.dataFurnaces->FlowFracFlagReady = false;
    5056             :                     }
    5057             :                 }
    5058             :                 // zone inlet nodes for heating
    5059         440 :                 if (state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).NumZonesHeated > 0) {
    5060           0 :                     if (state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).TermUnitHeatInletNodes(ZoneInSysIndex) == -999) {
    5061             :                         // the data structure for the zones inlet nodes has not been filled
    5062           0 :                         state.dataFurnaces->FlowFracFlagReady = false;
    5063             :                     }
    5064             :                 }
    5065             :             }
    5066             :         }
    5067             : 
    5068     6243009 :         if (state.dataFurnaces->MyFlowFracFlag(FurnaceNum)) {
    5069         359 :             if (allocated(state.dataAirLoop->AirToZoneNodeInfo) && state.dataFurnaces->FlowFracFlagReady) {
    5070         359 :                 SumOfMassFlowRateMax = 0.0; // initialize the sum of the maximum flows
    5071         799 :                 for (int ZoneInSysIndex = 1; ZoneInSysIndex <= NumAirLoopZones; ++ZoneInSysIndex) {
    5072         440 :                     int ZoneInletNodeNum = state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).TermUnitCoolInletNodes(ZoneInSysIndex);
    5073         440 :                     SumOfMassFlowRateMax += state.dataLoopNodes->Node(ZoneInletNodeNum).MassFlowRateMax;
    5074         440 :                     if (state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).CoolCtrlZoneNums(ZoneInSysIndex) == thisFurnace.ControlZoneNum) {
    5075         359 :                         CntrlZoneTerminalUnitMassFlowRateMax = state.dataLoopNodes->Node(ZoneInletNodeNum).MassFlowRateMax;
    5076             :                     }
    5077             :                 }
    5078         359 :                 if (SumOfMassFlowRateMax != 0.0) {
    5079         359 :                     if (CntrlZoneTerminalUnitMassFlowRateMax >= HVAC::SmallAirVolFlow) {
    5080         359 :                         thisFurnace.ControlZoneMassFlowFrac = CntrlZoneTerminalUnitMassFlowRateMax / SumOfMassFlowRateMax;
    5081             :                     } else {
    5082           0 :                         ShowSevereError(state, format("{} = {}", HVAC::unitarySysTypeNames[(int)thisFurnace.type], thisFurnace.Name));
    5083           0 :                         ShowContinueError(state, " The Fraction of Supply Air Flow That Goes Through the Controlling Zone is set to 1.");
    5084             :                     }
    5085         718 :                     BaseSizer::reportSizerOutput(state,
    5086         359 :                                                  HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    5087             :                                                  thisFurnace.Name,
    5088             :                                                  "Fraction of Supply Air Flow That Goes Through the Controlling Zone",
    5089             :                                                  thisFurnace.ControlZoneMassFlowFrac);
    5090         359 :                     state.dataFurnaces->MyFlowFracFlag(FurnaceNum) = false;
    5091             :                 }
    5092             :             }
    5093             :         }
    5094             : 
    5095             :         // Calculate air distribution losses
    5096     6243009 :         if (!FirstHVACIteration && state.dataFurnaces->AirLoopPass == 1) {
    5097     2238178 :             int ZoneInNode = thisFurnace.ZoneInletNode;
    5098     2238178 :             MassFlowRate = state.dataLoopNodes->Node(ZoneInNode).MassFlowRate / thisFurnace.ControlZoneMassFlowFrac;
    5099     2238178 :             if (state.afn->distribution_simulated) {
    5100       72768 :                 DeltaMassRate = state.dataLoopNodes->Node(thisFurnace.FurnaceOutletNodeNum).MassFlowRate -
    5101       72768 :                                 state.dataLoopNodes->Node(ZoneInNode).MassFlowRate / thisFurnace.ControlZoneMassFlowFrac;
    5102       72768 :                 if (DeltaMassRate < 0.0) DeltaMassRate = 0.0;
    5103             :             } else {
    5104     2165410 :                 MassFlowRate = state.dataLoopNodes->Node(thisFurnace.FurnaceOutletNodeNum).MassFlowRate;
    5105     2165410 :                 DeltaMassRate = 0.0;
    5106             :             }
    5107     2238178 :             Real64 TotalOutput(0.0);         // total output rate, {W}
    5108     2238178 :             Real64 SensibleOutputDelta(0.0); // delta sensible output rate, {W}
    5109     2238178 :             Real64 LatentOutputDelta(0.0);   // delta latent output rate, {W}
    5110     2238178 :             Real64 TotalOutputDelta(0.0);    // delta total output rate, {W}
    5111     8952712 :             CalcZoneSensibleLatentOutput(MassFlowRate,
    5112     2238178 :                                          state.dataLoopNodes->Node(thisFurnace.FurnaceOutletNodeNum).Temp,
    5113     2238178 :                                          state.dataLoopNodes->Node(thisFurnace.FurnaceOutletNodeNum).HumRat,
    5114     2238178 :                                          state.dataLoopNodes->Node(ZoneInNode).Temp,
    5115     2238178 :                                          state.dataLoopNodes->Node(ZoneInNode).HumRat,
    5116     2238178 :                                          thisFurnace.SenLoadLoss,
    5117     2238178 :                                          thisFurnace.LatLoadLoss,
    5118             :                                          TotalOutput);
    5119     8952712 :             CalcZoneSensibleLatentOutput(DeltaMassRate,
    5120     2238178 :                                          state.dataLoopNodes->Node(thisFurnace.FurnaceOutletNodeNum).Temp,
    5121     2238178 :                                          state.dataLoopNodes->Node(thisFurnace.FurnaceOutletNodeNum).HumRat,
    5122     2238178 :                                          state.dataLoopNodes->Node(thisFurnace.NodeNumOfControlledZone).Temp,
    5123     2238178 :                                          state.dataLoopNodes->Node(thisFurnace.NodeNumOfControlledZone).HumRat,
    5124             :                                          SensibleOutputDelta,
    5125             :                                          LatentOutputDelta,
    5126             :                                          TotalOutputDelta);
    5127     2238178 :             thisFurnace.SenLoadLoss = thisFurnace.SenLoadLoss + SensibleOutputDelta;
    5128     2238178 :             if (std::abs(thisFurnace.SensibleLoadMet) > 0.0) {
    5129     1409029 :                 if (std::abs(thisFurnace.SenLoadLoss / thisFurnace.SensibleLoadMet) < 0.001) thisFurnace.SenLoadLoss = 0.0;
    5130             :             }
    5131     2238178 :             if (thisFurnace.Humidistat) {
    5132      260797 :                 thisFurnace.LatLoadLoss = thisFurnace.LatLoadLoss + LatentOutputDelta;
    5133      260797 :                 if (std::abs(thisFurnace.LatentLoadMet) > 0.0) {
    5134      231001 :                     if (std::abs(thisFurnace.LatLoadLoss / thisFurnace.LatentLoadMet) < 0.001) thisFurnace.LatLoadLoss = 0.0;
    5135             :                 }
    5136             :             }
    5137             :         }
    5138             : 
    5139     6243009 :         if (thisFurnace.FanSchedPtr > 0) {
    5140     5885489 :             if (ScheduleManager::GetCurrentScheduleValue(state, thisFurnace.FanSchedPtr) == 0.0) {
    5141     2501454 :                 thisFurnace.fanOp = HVAC::FanOp::Cycling;
    5142             :             } else {
    5143     3384035 :                 thisFurnace.fanOp = HVAC::FanOp::Continuous;
    5144             :             }
    5145     5885489 :             if (AirLoopNum > 0) {
    5146     5885489 :                 state.dataAirLoop->AirLoopControlInfo(AirLoopNum).fanOp = thisFurnace.fanOp;
    5147             :             }
    5148             :         }
    5149             : 
    5150     6243009 :         fanOp = thisFurnace.fanOp;
    5151     6243009 :         state.dataFurnaces->EconomizerFlag = state.dataAirLoop->AirLoopControlInfo(AirLoopNum).EconoActive;
    5152             : 
    5153     6243009 :         if (thisFurnace.ControlZoneMassFlowFrac > 0.0) {
    5154     6243009 :             QZnReq = ZoneLoad / thisFurnace.ControlZoneMassFlowFrac;
    5155     6243009 :             MoistureLoad /= thisFurnace.ControlZoneMassFlowFrac;
    5156     6243009 :             ZoneLoad = QZnReq;
    5157             :         } else {
    5158           0 :             QZnReq = ZoneLoad;
    5159             :         }
    5160             : 
    5161             :         // Original thermostat control logic (works only for cycling fan systems)
    5162     8269675 :         if (QZnReq > HVAC::SmallLoad && QZnReq > (Small5WLoad / thisFurnace.ControlZoneMassFlowFrac) &&
    5163     2026666 :             !state.dataZoneEnergyDemand->CurDeadBandOrSetback(thisFurnace.ControlZoneNum)) {
    5164     2014394 :             state.dataFurnaces->HeatingLoad = true;
    5165     2014394 :             state.dataFurnaces->CoolingLoad = false;
    5166     7270639 :         } else if (QZnReq < -HVAC::SmallLoad && std::abs(QZnReq) > (Small5WLoad / thisFurnace.ControlZoneMassFlowFrac) &&
    5167     3042024 :                    !state.dataZoneEnergyDemand->CurDeadBandOrSetback(thisFurnace.ControlZoneNum)) {
    5168     3041900 :             state.dataFurnaces->HeatingLoad = false;
    5169     3041900 :             state.dataFurnaces->CoolingLoad = true;
    5170             :         } else {
    5171     1186715 :             state.dataFurnaces->HeatingLoad = false;
    5172     1186715 :             state.dataFurnaces->CoolingLoad = false;
    5173             :         }
    5174             : 
    5175     6243009 :         if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_AirToAir ||
    5176     5821217 :             (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir &&
    5177     2058572 :              (thisFurnace.WatertoAirHPType == WAHPCoilType::Simple || thisFurnace.WatertoAirHPType == WAHPCoilType::VarSpeedEquationFit))) {
    5178     2361094 :             if (MoistureLoad < 0.0 && thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat) {
    5179      125668 :                 state.dataFurnaces->HPDehumidificationLoadFlag = true;
    5180      125668 :                 state.dataFurnaces->HeatingLoad = false;
    5181      125668 :                 state.dataFurnaces->CoolingLoad = true;
    5182             :             } else {
    5183     2235426 :                 state.dataFurnaces->HPDehumidificationLoadFlag = false;
    5184             :             }
    5185             :         }
    5186             : 
    5187             :         // Check for heat only furnace
    5188     6243009 :         if (thisFurnace.type != HVAC::UnitarySysType::Furnace_HeatOnly && thisFurnace.type != HVAC::UnitarySysType::Unitary_HeatOnly) {
    5189             : 
    5190     6218565 :             if (ScheduleManager::GetCurrentScheduleValue(state, thisFurnace.SchedPtr) > 0.0) {
    5191     5978520 :                 if ((state.dataFurnaces->HeatingLoad || state.dataFurnaces->CoolingLoad) || (thisFurnace.Humidistat && MoistureLoad < 0.0)) {
    5192     5267872 :                     PartLoadRatio = 1.0;
    5193             :                 } else {
    5194      710648 :                     PartLoadRatio = 0.0;
    5195             :                 }
    5196             :             } else {
    5197      240045 :                 PartLoadRatio = 0.0;
    5198             :             }
    5199             :         } else {
    5200       24444 :             PartLoadRatio = 1.0;
    5201             :         }
    5202             : 
    5203             :         // get current time step operating capacity of water and steam coils
    5204             :         // (dependent on entering water and steam temperature)
    5205     6243009 :         if (FirstHVACIteration) {
    5206     1733311 :             if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingWater) {
    5207             :                 // set water-side mass flow rates
    5208           0 :                 state.dataLoopNodes->Node(thisFurnace.HWCoilAirInletNode).MassFlowRate = state.dataFurnaces->CompOnMassFlow;
    5209           0 :                 mdot = thisFurnace.MaxHeatCoilFluidFlow;
    5210           0 :                 PlantUtilities::SetComponentFlowRate(state, mdot, thisFurnace.CoilControlNode, thisFurnace.CoilOutletNode, thisFurnace.plantLoc);
    5211             :                 //     simulate water coil to find operating capacity
    5212           0 :                 WaterCoils::SimulateWaterCoilComponents(
    5213           0 :                     state, thisFurnace.HeatingCoilName, FirstHVACIteration, thisFurnace.HeatingCoilIndex, QActual);
    5214           0 :                 thisFurnace.DesignHeatingCapacity = QActual;
    5215             : 
    5216             :             } // from IF(furnace%HeatingCoilType_Num == Coil_HeatingWater) THEN
    5217             : 
    5218     1733311 :             if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingSteam) {
    5219             :                 // set air-side and steam-side mass flow rates
    5220           0 :                 state.dataLoopNodes->Node(thisFurnace.HWCoilAirInletNode).MassFlowRate = state.dataFurnaces->CompOnMassFlow;
    5221           0 :                 mdot = thisFurnace.MaxHeatCoilFluidFlow;
    5222           0 :                 PlantUtilities::SetComponentFlowRate(state, mdot, thisFurnace.CoilControlNode, thisFurnace.CoilOutletNode, thisFurnace.plantLoc);
    5223             : 
    5224             :                 //     simulate steam coil to find operating capacity
    5225           0 :                 SteamCoils::SimulateSteamCoilComponents(state,
    5226             :                                                         thisFurnace.HeatingCoilName,
    5227             :                                                         FirstHVACIteration,
    5228           0 :                                                         thisFurnace.HeatingCoilIndex,
    5229           0 :                                                         1.0,
    5230             :                                                         QActual); // QCoilReq, simulate any load > 0 to get max capacity of steam coil
    5231           0 :                 thisFurnace.DesignHeatingCapacity =
    5232           0 :                     SteamCoils::GetCoilCapacity(state, thisFurnace.HeatingCoilType, thisFurnace.HeatingCoilName, ErrorsFound);
    5233             : 
    5234             :             } // from IF(Furnace(FurnaceNum)%HeatingCoilType_Num == Coil_HeatingSteam) THEN
    5235             : 
    5236     1733311 :             if (thisFurnace.SuppHeatCoilType_Num == HVAC::Coil_HeatingWater) {
    5237             : 
    5238             :                 //     set air-side and steam-side mass flow rates
    5239        3678 :                 state.dataLoopNodes->Node(thisFurnace.SuppCoilAirInletNode).MassFlowRate = state.dataFurnaces->CompOnMassFlow;
    5240        3678 :                 mdot = thisFurnace.MaxSuppCoilFluidFlow;
    5241        3678 :                 PlantUtilities::SetComponentFlowRate(
    5242        3678 :                     state, mdot, thisFurnace.SuppCoilControlNode, thisFurnace.SuppCoilOutletNode, thisFurnace.SuppPlantLoc);
    5243             : 
    5244             :                 //     simulate water coil to find operating capacity
    5245        7356 :                 WaterCoils::SimulateWaterCoilComponents(
    5246        3678 :                     state, thisFurnace.SuppHeatCoilName, FirstHVACIteration, thisFurnace.SuppHeatCoilIndex, QActual);
    5247        3678 :                 thisFurnace.DesignSuppHeatingCapacity = QActual;
    5248             : 
    5249             :             } // from IF(Furnace(FurnaceNum)%SuppHeatCoilType_Num == Coil_HeatingWater) THEN
    5250     1733311 :             if (thisFurnace.SuppHeatCoilType_Num == HVAC::Coil_HeatingSteam) {
    5251             :                 //     set air-side and steam-side mass flow rates
    5252           0 :                 state.dataLoopNodes->Node(thisFurnace.SuppCoilAirInletNode).MassFlowRate = state.dataFurnaces->CompOnMassFlow;
    5253           0 :                 mdot = thisFurnace.MaxSuppCoilFluidFlow;
    5254           0 :                 PlantUtilities::SetComponentFlowRate(
    5255           0 :                     state, mdot, thisFurnace.SuppCoilControlNode, thisFurnace.SuppCoilOutletNode, thisFurnace.SuppPlantLoc);
    5256             : 
    5257             :                 //     simulate steam coil to find operating capacity
    5258           0 :                 SteamCoils::SimulateSteamCoilComponents(state,
    5259             :                                                         thisFurnace.SuppHeatCoilName,
    5260             :                                                         FirstHVACIteration,
    5261           0 :                                                         thisFurnace.SuppHeatCoilIndex,
    5262           0 :                                                         1.0,
    5263             :                                                         QActual); // QCoilReq, simulate any load > 0 to get max capacity of steam coil
    5264           0 :                 thisFurnace.DesignSuppHeatingCapacity =
    5265           0 :                     SteamCoils::GetCoilCapacity(state, thisFurnace.SuppHeatCoilType, thisFurnace.SuppHeatCoilName, ErrorsFound);
    5266             : 
    5267             :             } // from IF(Furnace(FurnaceNum)%SuppHeatCoilType_Num == Coil_HeatingSteam) THEN
    5268             :         }     // from IF( FirstHVACIteration ) THEN
    5269             : 
    5270     6243009 :         if (thisFurnace.NumOfSpeedCooling > 0) { // BoS, variable-speed water source hp
    5271             :             // Furnace(FurnaceNum)%IdleMassFlowRate = RhoAir*Furnace(FurnaceNum)%IdleVolumeAirRate
    5272     1507624 :             int NumOfSpeedCooling = thisFurnace.NumOfSpeedCooling;
    5273     1507624 :             int NumOfSpeedHeating = thisFurnace.NumOfSpeedHeating;
    5274             :             // IF MSHP system was not autosized and the fan is autosized, check that fan volumetric flow rate is greater than MSHP flow rates
    5275     1507624 :             if (thisFurnace.CheckFanFlow) {
    5276          21 :                 state.dataFurnaces->CurrentModuleObject = "AirLoopHVAC:UnitaryHeatPump:VariableSpeed";
    5277          21 :                 thisFurnace.FanVolFlow = state.dataFans->fans(thisFurnace.FanIndex)->maxAirFlowRate;
    5278             : 
    5279          21 :                 if (thisFurnace.FanVolFlow != DataSizing::AutoSize) {
    5280             :                     //     Check fan versus system supply air flow rates
    5281          17 :                     if (thisFurnace.FanVolFlow + 1e-10 < thisFurnace.CoolVolumeFlowRate(NumOfSpeedCooling)) {
    5282           0 :                         ShowWarningError(state,
    5283           0 :                                          format("{} - air flow rate = {:.7T} in fan object is less than the MSHP system air flow rate when cooling "
    5284             :                                                 "is required ({:.7T}).",
    5285           0 :                                                 state.dataFurnaces->CurrentModuleObject,
    5286           0 :                                                 thisFurnace.FanVolFlow,
    5287             :                                                 thisFurnace.CoolVolumeFlowRate(NumOfSpeedCooling)));
    5288           0 :                         ShowContinueError(
    5289             :                             state, " The MSHP system flow rate when cooling is required is reset to the fan flow rate and the simulation continues.");
    5290           0 :                         ShowContinueError(state, format(" Occurs in {} = {}", state.dataFurnaces->CurrentModuleObject, thisFurnace.Name));
    5291           0 :                         thisFurnace.CoolVolumeFlowRate(NumOfSpeedCooling) = thisFurnace.FanVolFlow;
    5292             : 
    5293           0 :                         if (thisFurnace.bIsIHP) // set max fan flow rate to the IHP collection
    5294             :                         {
    5295           0 :                             state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).MaxCoolAirVolFlow = thisFurnace.FanVolFlow;
    5296           0 :                             state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).MaxCoolAirMassFlow =
    5297           0 :                                 thisFurnace.FanVolFlow * state.dataEnvrn->StdRhoAir;
    5298             :                         }
    5299             : 
    5300             :                         // Check flow rates in other speeds and ensure flow rates are not above the max flow rate
    5301           0 :                         for (int i = NumOfSpeedCooling - 1; i >= 1; --i) {
    5302           0 :                             if (thisFurnace.CoolVolumeFlowRate(i) > thisFurnace.CoolVolumeFlowRate(i + 1)) {
    5303           0 :                                 ShowContinueError(state,
    5304           0 :                                                   format(" The MSHP system flow rate when cooling is required is reset to the flow rate at higher "
    5305             :                                                          "speed and the simulation continues at Speed{}.",
    5306             :                                                          i));
    5307           0 :                                 ShowContinueError(state, format(" Occurs in {} = {}", state.dataFurnaces->CurrentModuleObject, thisFurnace.Name));
    5308           0 :                                 thisFurnace.CoolVolumeFlowRate(i) = thisFurnace.CoolVolumeFlowRate(i + 1);
    5309             :                             }
    5310             :                         }
    5311             :                     }
    5312          17 :                     if (NumOfSpeedHeating > 0) {
    5313          17 :                         if (thisFurnace.FanVolFlow + 1e-10 < thisFurnace.HeatVolumeFlowRate(NumOfSpeedHeating)) {
    5314           0 :                             ShowWarningError(state,
    5315           0 :                                              format("{} - air flow rate = {:.7T} in fan object is less than the MSHP system air flow rate when "
    5316             :                                                     "heating is required ({:.7T}).",
    5317           0 :                                                     state.dataFurnaces->CurrentModuleObject,
    5318           0 :                                                     thisFurnace.FanVolFlow,
    5319             :                                                     thisFurnace.HeatVolumeFlowRate(NumOfSpeedHeating)));
    5320           0 :                             ShowContinueError(
    5321             :                                 state,
    5322             :                                 " The MSHP system flow rate when heating is required is reset to the fan flow rate and the simulation continues.");
    5323           0 :                             ShowContinueError(state, format(" Occurs in {} = {}", state.dataFurnaces->CurrentModuleObject, thisFurnace.Name));
    5324           0 :                             thisFurnace.HeatVolumeFlowRate(NumOfSpeedHeating) = thisFurnace.FanVolFlow;
    5325             : 
    5326           0 :                             if (thisFurnace.bIsIHP) // set max fan flow rate to the IHP collection
    5327             :                             {
    5328           0 :                                 state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).MaxHeatAirVolFlow = thisFurnace.FanVolFlow;
    5329           0 :                                 state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).MaxHeatAirMassFlow =
    5330           0 :                                     thisFurnace.FanVolFlow * state.dataEnvrn->StdRhoAir;
    5331             :                             }
    5332             : 
    5333           0 :                             for (int i = NumOfSpeedHeating - 1; i >= 1; --i) {
    5334           0 :                                 if (thisFurnace.HeatVolumeFlowRate(i) > thisFurnace.HeatVolumeFlowRate(i + 1)) {
    5335           0 :                                     ShowContinueError(state,
    5336           0 :                                                       format(" The MSHP system flow rate when heating is required is reset to the flow rate at "
    5337             :                                                              "higher speed and the simulation continues at Speed{}.",
    5338             :                                                              i));
    5339           0 :                                     ShowContinueError(state,
    5340           0 :                                                       format(" Occurs in {} system = {}", state.dataFurnaces->CurrentModuleObject, thisFurnace.Name));
    5341           0 :                                     thisFurnace.HeatVolumeFlowRate(i) = thisFurnace.HeatVolumeFlowRate(i + 1);
    5342             :                                 }
    5343             :                             }
    5344             :                         }
    5345             :                     }
    5346          17 :                     if (thisFurnace.FanVolFlow < thisFurnace.IdleVolumeAirRate && thisFurnace.IdleVolumeAirRate != 0.0) {
    5347           0 :                         ShowWarningError(state,
    5348           0 :                                          format("{} - air flow rate = {:.7T} in fan object is less than the MSHP system air flow rate when no "
    5349             :                                                 "heating or cooling is needed ({:.7T}).",
    5350           0 :                                                 state.dataFurnaces->CurrentModuleObject,
    5351           0 :                                                 thisFurnace.FanVolFlow,
    5352           0 :                                                 thisFurnace.IdleVolumeAirRate));
    5353           0 :                         ShowContinueError(state,
    5354             :                                           " The MSHP system flow rate when no heating or cooling is needed is reset to the fan flow rate and the "
    5355             :                                           "simulation continues.");
    5356           0 :                         ShowContinueError(state, format(" Occurs in {} = {}", state.dataFurnaces->CurrentModuleObject, thisFurnace.Name));
    5357           0 :                         thisFurnace.IdleVolumeAirRate = thisFurnace.FanVolFlow;
    5358             :                     }
    5359          17 :                     RhoAir = state.dataEnvrn->StdRhoAir;
    5360             :                     // set the mass flow rates from the reset volume flow rates
    5361         187 :                     for (int i = 1; i <= NumOfSpeedCooling; ++i) {
    5362         170 :                         thisFurnace.CoolMassFlowRate(i) = RhoAir * thisFurnace.CoolVolumeFlowRate(i);
    5363         170 :                         if (thisFurnace.FanVolFlow > 0.0) {
    5364         170 :                             thisFurnace.MSCoolingSpeedRatio(i) = thisFurnace.CoolVolumeFlowRate(i) / thisFurnace.FanVolFlow;
    5365             :                         }
    5366             :                     }
    5367         187 :                     for (int i = 1; i <= NumOfSpeedHeating; ++i) {
    5368         170 :                         thisFurnace.HeatMassFlowRate(i) = RhoAir * thisFurnace.HeatVolumeFlowRate(i);
    5369         170 :                         if (thisFurnace.FanVolFlow > 0.0) {
    5370         170 :                             thisFurnace.MSHeatingSpeedRatio(i) = thisFurnace.HeatVolumeFlowRate(i) / thisFurnace.FanVolFlow;
    5371             :                         }
    5372             :                     }
    5373          17 :                     thisFurnace.IdleMassFlowRate = RhoAir * thisFurnace.IdleVolumeAirRate;
    5374          17 :                     if (thisFurnace.FanVolFlow > 0.0) {
    5375          17 :                         thisFurnace.IdleSpeedRatio = thisFurnace.IdleVolumeAirRate / thisFurnace.FanVolFlow;
    5376             :                     }
    5377             :                     // set the node max and min mass flow rates based on reset volume flow rates
    5378          17 :                     if (NumOfSpeedCooling > 0 && NumOfSpeedHeating == 0) {
    5379           0 :                         state.dataLoopNodes->Node(InNode).MassFlowRateMax =
    5380           0 :                             max(thisFurnace.CoolMassFlowRate(NumOfSpeedCooling), thisFurnace.MaxHeatAirMassFlow);
    5381           0 :                         state.dataLoopNodes->Node(InNode).MassFlowRateMaxAvail =
    5382           0 :                             max(thisFurnace.CoolMassFlowRate(NumOfSpeedCooling), thisFurnace.MaxHeatAirMassFlow);
    5383          17 :                     } else if (NumOfSpeedCooling == 0 && NumOfSpeedHeating > 0) {
    5384           0 :                         state.dataLoopNodes->Node(InNode).MassFlowRateMax =
    5385           0 :                             max(thisFurnace.MaxCoolAirMassFlow, thisFurnace.HeatMassFlowRate(NumOfSpeedHeating));
    5386           0 :                         state.dataLoopNodes->Node(InNode).MassFlowRateMaxAvail =
    5387           0 :                             max(thisFurnace.MaxCoolAirMassFlow, thisFurnace.HeatMassFlowRate(NumOfSpeedHeating));
    5388             :                     } else {
    5389          17 :                         state.dataLoopNodes->Node(InNode).MassFlowRateMax =
    5390          17 :                             max(thisFurnace.CoolMassFlowRate(NumOfSpeedCooling), thisFurnace.HeatMassFlowRate(NumOfSpeedHeating));
    5391          17 :                         state.dataLoopNodes->Node(InNode).MassFlowRateMaxAvail =
    5392          17 :                             max(thisFurnace.CoolMassFlowRate(NumOfSpeedCooling), thisFurnace.HeatMassFlowRate(NumOfSpeedHeating));
    5393             :                     }
    5394          17 :                     state.dataLoopNodes->Node(InNode).MassFlowRateMin = 0.0;
    5395          17 :                     state.dataLoopNodes->Node(InNode).MassFlowRateMinAvail = 0.0;
    5396          17 :                     state.dataLoopNodes->Node(OutNode) = state.dataLoopNodes->Node(InNode);
    5397             :                 }
    5398             :             }
    5399             : 
    5400     1507624 :             thisFurnace.CheckFanFlow = false;
    5401             :         }
    5402     6243009 :         SetOnOffMassFlowRate(state, FurnaceNum, AirLoopNum, OnOffAirFlowRatio, fanOp, QZnReq, MoistureLoad, PartLoadRatio);
    5403             : 
    5404             :         // Check ventilation/fan load for constant fan systems to see if load to be met changes
    5405             :         // Same IF logic used in Subroutine SetAverageAirFlow to determine if unit is ON or OFF
    5406             : 
    5407     6243009 :         QToCoolSetPt = 0.0;
    5408     6243009 :         QToHeatSetPt = 0.0;
    5409     9418627 :         if (fanOp == HVAC::FanOp::Continuous && ScheduleManager::GetCurrentScheduleValue(state, thisFurnace.SchedPtr) > 0.0 &&
    5410     3175618 :             ((ScheduleManager::GetCurrentScheduleValue(state, thisFurnace.FanAvailSchedPtr) > 0.0 || state.dataHVACGlobal->TurnFansOn) &&
    5411     3165070 :              !state.dataHVACGlobal->TurnFansOff)) {
    5412             : 
    5413     3165070 :             if (thisFurnace.NumOfSpeedCooling > 0) {
    5414     1465806 :                 CalcVarSpeedHeatPump(state,
    5415             :                                      FurnaceNum,
    5416             :                                      false,
    5417             :                                      HVAC::CompressorOp::Off,
    5418             :                                      1,
    5419             :                                      0.0,
    5420             :                                      0.0,
    5421             :                                      SensibleOutput,
    5422             :                                      LatentOutput,
    5423             :                                      0.0,
    5424             :                                      0.0,
    5425             :                                      OnOffAirFlowRatio,
    5426             :                                      SUPHEATERLOAD);
    5427             :             } else {
    5428     1699264 :                 CalcFurnaceOutput(state,
    5429             :                                   FurnaceNum,
    5430             :                                   false,
    5431             :                                   HVAC::FanOp::Invalid, // Looks like Invalid is used to mean that the fan is off here?
    5432             :                                   HVAC::CompressorOp::Off,
    5433             :                                   0.0,
    5434             :                                   0.0,
    5435             :                                   0.0,
    5436             :                                   0.0,
    5437             :                                   SensibleOutput,
    5438             :                                   LatentOutput,
    5439             :                                   OnOffAirFlowRatio,
    5440             :                                   false);
    5441             :             }
    5442             : 
    5443     3165070 :             if (thisFurnace.ControlZoneMassFlowFrac > 0.0) {
    5444     3165070 :                 if (thisFurnace.ZoneSequenceCoolingNum > 0 && thisFurnace.ZoneSequenceHeatingNum > 0) {
    5445     3165070 :                     QToCoolSetPt = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(thisFurnace.ControlZoneNum)
    5446     3165070 :                                        .SequencedOutputRequiredToCoolingSP(thisFurnace.ZoneSequenceCoolingNum) /
    5447     3165070 :                                    thisFurnace.ControlZoneMassFlowFrac;
    5448     3165070 :                     QToHeatSetPt = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(thisFurnace.ControlZoneNum)
    5449     3165070 :                                        .SequencedOutputRequiredToHeatingSP(thisFurnace.ZoneSequenceHeatingNum) /
    5450     3165070 :                                    thisFurnace.ControlZoneMassFlowFrac;
    5451             :                 } else {
    5452           0 :                     QToCoolSetPt = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(thisFurnace.ControlZoneNum).OutputRequiredToCoolingSP /
    5453           0 :                                    thisFurnace.ControlZoneMassFlowFrac;
    5454           0 :                     QToHeatSetPt = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(thisFurnace.ControlZoneNum).OutputRequiredToHeatingSP /
    5455           0 :                                    thisFurnace.ControlZoneMassFlowFrac;
    5456             :                 }
    5457             :                 //     If the furnace has a net cooling capacity (SensibleOutput < 0) and
    5458             :                 //     the zone temp is above the Tstat heating setpoint (QToHeatSetPt < 0) and
    5459             :                 //     the net cooling capacity does not just offset the cooling load
    5460     3867650 :                 if (SensibleOutput < 0.0 && QToHeatSetPt < 0.0 &&
    5461      702580 :                     std::abs(QToCoolSetPt - SensibleOutput) > (Small5WLoad / thisFurnace.ControlZoneMassFlowFrac)) {
    5462             :                     //       Only switch modes when humidistat is not used or no moisture load exists, otherwise let
    5463             :                     //       reheat coil pick up load
    5464             :                     //        IF((SensibleOutput .LT. QToHeatSetPt .AND. .NOT. Furnace(FurnaceNum)%Humidistat) .OR. &
    5465             :                     //           (SensibleOutput .LT. QToHeatSetPt .AND. Furnace(FurnaceNum)%Humidistat .AND. MoistureLoad .GE. 0.0))THEN
    5466      701883 :                     if ((SensibleOutput < QToHeatSetPt && !thisFurnace.Humidistat) ||
    5467      697867 :                         (SensibleOutput < QToHeatSetPt && thisFurnace.Humidistat && MoistureLoad >= 0.0)) {
    5468        4562 :                         QZnReq = QToHeatSetPt;
    5469        4562 :                         state.dataFurnaces->CoolingLoad = false;
    5470             :                         //         Don't set mode TRUE unless mode is allowed. Also check for floating zone.
    5471        9122 :                         if (state.dataHeatBalFanSys->TempControlType(thisFurnace.ControlZoneNum) == HVAC::ThermostatType::SingleCooling ||
    5472        4560 :                             state.dataHeatBalFanSys->TempControlType(thisFurnace.ControlZoneNum) == HVAC::ThermostatType::Uncontrolled) {
    5473           2 :                             state.dataFurnaces->HeatingLoad = false;
    5474             :                         } else {
    5475        4560 :                             state.dataFurnaces->HeatingLoad = true;
    5476             :                         }
    5477             : 
    5478        4562 :                         SetOnOffMassFlowRate(state, FurnaceNum, AirLoopNum, OnOffAirFlowRatio, fanOp, QZnReq, MoistureLoad, PartLoadRatio);
    5479        4562 :                         if (thisFurnace.NumOfSpeedCooling > 0) {
    5480         338 :                             CalcVarSpeedHeatPump(state,
    5481             :                                                  FurnaceNum,
    5482             :                                                  false,
    5483             :                                                  HVAC::CompressorOp::Off,
    5484             :                                                  1,
    5485             :                                                  0.0,
    5486             :                                                  0.0,
    5487             :                                                  SensibleOutput,
    5488             :                                                  LatentOutput,
    5489             :                                                  0.0,
    5490             :                                                  0.0,
    5491             :                                                  OnOffAirFlowRatio,
    5492             :                                                  SUPHEATERLOAD);
    5493             :                         } else {
    5494        4224 :                             CalcFurnaceOutput(state,
    5495             :                                               FurnaceNum,
    5496             :                                               false,
    5497             :                                               HVAC::FanOp::Invalid,
    5498             :                                               HVAC::CompressorOp::Off,
    5499             :                                               0.0,
    5500             :                                               0.0,
    5501             :                                               0.0,
    5502             :                                               0.0,
    5503             :                                               SensibleOutput,
    5504             :                                               LatentOutput,
    5505             :                                               OnOffAirFlowRatio,
    5506             :                                               false);
    5507             :                         }
    5508        4562 :                         if (SensibleOutput > QToHeatSetPt) {
    5509             :                             // If changing operating mode (flow rates) does not overshoot heating setpoint, turn off heating
    5510           0 :                             QZnReq = 0.0;
    5511           0 :                             state.dataFurnaces->HeatingLoad = false;
    5512           0 :                             SetOnOffMassFlowRate(state, FurnaceNum, AirLoopNum, OnOffAirFlowRatio, fanOp, QZnReq, MoistureLoad, PartLoadRatio);
    5513             :                         }
    5514      697321 :                     } else if (SensibleOutput < QZnReq) {
    5515             :                         //         If the net cooling capacity meets the zone cooling load but does not overshoot heating setpoint, turn off cooling
    5516             :                         //         (dehumidification may still occur)
    5517       63386 :                         QZnReq = 0.0;
    5518       63386 :                         state.dataFurnaces->CoolingLoad = false;
    5519       63386 :                         if (state.dataFurnaces->HPDehumidificationLoadFlag) {
    5520         134 :                             state.dataFurnaces->CoolingLoad = true;
    5521         134 :                             state.dataFurnaces->HeatingLoad = false;
    5522             :                         }
    5523       63386 :                         SetOnOffMassFlowRate(state, FurnaceNum, AirLoopNum, OnOffAirFlowRatio, fanOp, QZnReq, MoistureLoad, PartLoadRatio);
    5524             :                     }
    5525             :                     // the net cooling capacity just offsets the cooling load, turn off cooling
    5526     2463884 :                 } else if (SensibleOutput < 0.0 && QToCoolSetPt < 0.0 &&
    5527         697 :                            std::abs(QToCoolSetPt - SensibleOutput) < (Small5WLoad / thisFurnace.ControlZoneMassFlowFrac)) {
    5528         697 :                     state.dataFurnaces->CoolingLoad = false;
    5529         697 :                     if (state.dataFurnaces->HPDehumidificationLoadFlag) {
    5530           0 :                         state.dataFurnaces->CoolingLoad = true;
    5531           0 :                         state.dataFurnaces->HeatingLoad = false;
    5532             :                     }
    5533             :                 } // SensibleOutput .LT. 0.0d0 .AND. QToHeatSetPt .LT. 0.0d0
    5534             : 
    5535             :                 //     If the furnace has a net heating capacity and the zone temp is below the Tstat cooling setpoint and
    5536             :                 //     the net heating capacity does not just offset the heating load
    5537     4016225 :                 if (SensibleOutput > 0.0 && QToCoolSetPt > 0.0 &&
    5538      851155 :                     std::abs(SensibleOutput - QToHeatSetPt) > (Small5WLoad / thisFurnace.ControlZoneMassFlowFrac)) {
    5539      850898 :                     if (SensibleOutput > QToCoolSetPt) {
    5540       96234 :                         QZnReq = QToCoolSetPt;
    5541             :                         //         Don't set mode TRUE unless mode is allowed. Also check for floating zone.
    5542      192418 :                         if (state.dataHeatBalFanSys->TempControlType(thisFurnace.ControlZoneNum) == HVAC::ThermostatType::SingleHeating ||
    5543       96184 :                             state.dataHeatBalFanSys->TempControlType(thisFurnace.ControlZoneNum) == HVAC::ThermostatType::Uncontrolled) {
    5544          50 :                             state.dataFurnaces->CoolingLoad = false;
    5545             :                         } else {
    5546       96184 :                             state.dataFurnaces->CoolingLoad = true;
    5547             :                         }
    5548       96234 :                         state.dataFurnaces->HeatingLoad = false;
    5549             : 
    5550       96234 :                         SetOnOffMassFlowRate(state, FurnaceNum, AirLoopNum, OnOffAirFlowRatio, fanOp, QZnReq, MoistureLoad, PartLoadRatio);
    5551       96234 :                         if (thisFurnace.NumOfSpeedCooling > 0) {
    5552        6895 :                             CalcVarSpeedHeatPump(state,
    5553             :                                                  FurnaceNum,
    5554             :                                                  false,
    5555             :                                                  HVAC::CompressorOp::Off,
    5556             :                                                  1,
    5557             :                                                  0.0,
    5558             :                                                  0.0,
    5559             :                                                  SensibleOutput,
    5560             :                                                  LatentOutput,
    5561             :                                                  0.0,
    5562             :                                                  0.0,
    5563             :                                                  OnOffAirFlowRatio,
    5564             :                                                  SUPHEATERLOAD);
    5565             :                         } else {
    5566       89339 :                             CalcFurnaceOutput(state,
    5567             :                                               FurnaceNum,
    5568             :                                               false,
    5569             :                                               HVAC::FanOp::Invalid,
    5570             :                                               HVAC::CompressorOp::Off,
    5571             :                                               0.0,
    5572             :                                               0.0,
    5573             :                                               0.0,
    5574             :                                               0.0,
    5575             :                                               SensibleOutput,
    5576             :                                               LatentOutput,
    5577             :                                               OnOffAirFlowRatio,
    5578             :                                               false);
    5579             :                         }
    5580       96234 :                         if (SensibleOutput < QToCoolSetPt) {
    5581             :                             //           If changing operating mode (flow rates) does not overshoot cooling setpoint, turn off cooling
    5582           0 :                             if (state.dataFurnaces->HPDehumidificationLoadFlag) {
    5583           0 :                                 state.dataFurnaces->CoolingLoad = true;
    5584           0 :                                 state.dataFurnaces->HeatingLoad = false;
    5585             :                             } else {
    5586           0 :                                 QZnReq = 0.0;
    5587           0 :                                 state.dataFurnaces->CoolingLoad = false;
    5588             :                             }
    5589           0 :                             SetOnOffMassFlowRate(state, FurnaceNum, AirLoopNum, OnOffAirFlowRatio, fanOp, QZnReq, MoistureLoad, PartLoadRatio);
    5590             :                         }
    5591      754664 :                     } else if (SensibleOutput > QZnReq) {
    5592             :                         //         If the net heating capacity meets the zone heating load but does not overshoot, turn off heating
    5593      658456 :                         QZnReq = 0.0;
    5594      658456 :                         state.dataFurnaces->HeatingLoad = false;
    5595      658456 :                         SetOnOffMassFlowRate(state, FurnaceNum, AirLoopNum, OnOffAirFlowRatio, fanOp, QZnReq, MoistureLoad, PartLoadRatio);
    5596             :                     }
    5597             :                     //     the net heating capacity just offsets the heating load, turn off heating
    5598     2314429 :                 } else if (SensibleOutput > 0.0 && QToHeatSetPt > 0.0 &&
    5599         257 :                            std::abs(SensibleOutput - QToHeatSetPt) < (Small5WLoad / thisFurnace.ControlZoneMassFlowFrac)) {
    5600         257 :                     state.dataFurnaces->HeatingLoad = false;
    5601             :                 } // SensibleOutput .GT. 0.0d0 .AND. QToCoolSetPt .GT. 0.0d0
    5602             :             }     // Furnace(FurnaceNum)%ControlZoneMassFlowFrac .GT. 0.0d0
    5603     3165070 :             ZoneLoad = QZnReq;
    5604             :         } // fanOp .EQ. FanOp::Continuous
    5605             : 
    5606     6243009 :         if (FirstHVACIteration) {
    5607     1733311 :             thisFurnace.iterationCounter = 0;
    5608     1733311 :             thisFurnace.iterationMode = Furnaces::ModeOfOperation::NoCoolHeat;
    5609             :         }
    5610     6243009 :         thisFurnace.iterationCounter += 1;
    5611             : 
    5612             :         // push iteration mode stack and set current mode
    5613     6243009 :         thisFurnace.iterationMode(3) = thisFurnace.iterationMode(2);
    5614     6243009 :         thisFurnace.iterationMode(2) = thisFurnace.iterationMode(1);
    5615     6243009 :         if (state.dataFurnaces->CoolingLoad) {
    5616     3237836 :             thisFurnace.iterationMode(1) = Furnaces::ModeOfOperation::CoolingMode;
    5617     3005173 :         } else if (state.dataFurnaces->HeatingLoad) {
    5618     1974343 :             thisFurnace.iterationMode(1) = Furnaces::ModeOfOperation::HeatingMode;
    5619             :         } else {
    5620     1030830 :             thisFurnace.iterationMode(1) = Furnaces::ModeOfOperation::NoCoolHeat;
    5621             :         }
    5622             : 
    5623             :         // IF small loads to meet or not converging, just shut down unit
    5624     6243009 :         if (std::abs(ZoneLoad) < Small5WLoad) {
    5625     1103286 :             ZoneLoad = 0.0;
    5626     1103286 :             state.dataFurnaces->CoolingLoad = false;
    5627     1103286 :             state.dataFurnaces->HeatingLoad = false;
    5628     5139723 :         } else if (thisFurnace.iterationCounter > (state.dataHVACGlobal->MinAirLoopIterationsAfterFirst + 4)) {
    5629             :             // attempt to lock output (air flow) if oscillations are detected
    5630     1973783 :             OperatingMode = thisFurnace.iterationMode(1);
    5631     1973783 :             OperatingModeMinusOne = thisFurnace.iterationMode(2);
    5632     1973783 :             OperatingModeMinusTwo = thisFurnace.iterationMode(3);
    5633     1973783 :             Oscillate = true;
    5634     1973783 :             if (OperatingMode == OperatingModeMinusOne && OperatingMode == OperatingModeMinusTwo) Oscillate = false;
    5635     1973783 :             if (Oscillate) {
    5636          44 :                 if (QToCoolSetPt < 0.0) {
    5637           8 :                     state.dataFurnaces->HeatingLoad = false;
    5638           8 :                     state.dataFurnaces->CoolingLoad = true;
    5639           8 :                     ZoneLoad = QToCoolSetPt;
    5640          36 :                 } else if (QToHeatSetPt > 0.0) {
    5641          12 :                     state.dataFurnaces->HeatingLoad = true;
    5642          12 :                     state.dataFurnaces->CoolingLoad = false;
    5643          12 :                     ZoneLoad = QToHeatSetPt;
    5644             :                 } else {
    5645          24 :                     state.dataFurnaces->HeatingLoad = false;
    5646          24 :                     state.dataFurnaces->CoolingLoad = false;
    5647          24 :                     ZoneLoad = 0.0;
    5648             :                 }
    5649             :             }
    5650             :         }
    5651             : 
    5652             :         // EMS override point
    5653     6243009 :         if (thisFurnace.EMSOverrideSensZoneLoadRequest) ZoneLoad = thisFurnace.EMSSensibleZoneLoadValue;
    5654     6243009 :         if (thisFurnace.EMSOverrideMoistZoneLoadRequest) MoistureLoad = thisFurnace.EMSMoistureZoneLoadValue;
    5655     6243009 :         if (thisFurnace.EMSOverrideSensZoneLoadRequest || thisFurnace.EMSOverrideMoistZoneLoadRequest) {
    5656           0 :             if ((ZoneLoad != 0.0) && (thisFurnace.EMSOverrideSensZoneLoadRequest)) {
    5657           0 :                 PartLoadRatio = 1.0;
    5658           0 :             } else if ((MoistureLoad != 0.0) && (thisFurnace.EMSOverrideMoistZoneLoadRequest)) {
    5659           0 :                 PartLoadRatio = 1.0;
    5660             :             } else {
    5661           0 :                 PartLoadRatio = 0.0;
    5662             :             }
    5663           0 :             if (thisFurnace.NumOfSpeedCooling > 0) {
    5664           0 :                 SetOnOffMassFlowRate(state, FurnaceNum, AirLoopNum, OnOffAirFlowRatio, fanOp, QZnReq, MoistureLoad, PartLoadRatio);
    5665             :             } else {
    5666             :                 // This line is suspicious - all other calls to SetOnOffMassFlowRate pass in QZnReq, not ZoneLoad
    5667             :                 // either way, it seems these two should be using the same parameters.
    5668           0 :                 SetOnOffMassFlowRate(state, FurnaceNum, AirLoopNum, OnOffAirFlowRatio, fanOp, ZoneLoad, MoistureLoad, PartLoadRatio);
    5669             :             }
    5670             :         }
    5671             : 
    5672             :         // AirflowNetwork global variable
    5673     6243009 :         if (state.afn->distribution_simulated) {
    5674      214495 :             state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).AFNLoopHeatingCoilMaxRTF = 0.0;
    5675             :         }
    5676     6243009 :     }
    5677             : 
    5678     7065647 :     void SetOnOffMassFlowRate(EnergyPlusData &state,
    5679             :                               int const FurnaceNum,                   // index to furnace
    5680             :                               [[maybe_unused]] int const AirLoopNum,  // index to air loop !unused1208
    5681             :                               Real64 &OnOffAirFlowRatio,              // ratio of coil on to coil off air flow rate
    5682             :                               HVAC::FanOp const fanOp,                // fan operating mode
    5683             :                               [[maybe_unused]] Real64 const ZoneLoad, // sensible load to be met (W) !unused1208
    5684             :                               Real64 const MoistureLoad,              // moisture load to be met (W)
    5685             :                               Real64 const PartLoadRatio              // coil part-load ratio
    5686             :     )
    5687             :     {
    5688             : 
    5689             :         // SUBROUTINE INFORMATION:
    5690             :         //       AUTHOR         Richard Raustad
    5691             :         //       DATE WRITTEN   Sep 2008
    5692             : 
    5693             :         // PURPOSE OF THIS SUBROUTINE:
    5694             :         // This subroutine is for initializations of the Furnace Components.
    5695             : 
    5696             :         // METHODOLOGY EMPLOYED:
    5697             :         // The HeatCool furnace/unitarysystem and air-to-air heat pump may have alternate air flow rates
    5698             :         // in cooling, heating, and when no cooling or heating is needed. Set up the coil (comp) ON and OFF
    5699             :         // air flow rates. Use these flow rates during the Calc routines to set the average mass flow rates
    5700             :         // based on PLR.
    5701             : 
    5702     7065647 :         auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    5703             :         // Check for heat only furnace
    5704     7065647 :         if (thisFurnace.type != HVAC::UnitarySysType::Furnace_HeatOnly && thisFurnace.type != HVAC::UnitarySysType::Unitary_HeatOnly) {
    5705             : 
    5706             :             // Set the system mass flow rates
    5707     7041203 :             if (fanOp == HVAC::FanOp::Continuous) {
    5708             :                 // Set the compressor or coil ON mass flow rate
    5709             :                 // constant fan mode
    5710     4206673 :                 if (state.dataFurnaces->HeatingLoad) {
    5711             :                     //       IF a heating and moisture load exists, operate at the cooling mass flow rate ELSE operate at the heating flow rate
    5712      466631 :                     if (MoistureLoad < 0.0 && thisFurnace.Humidistat &&
    5713        7419 :                         thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat) {
    5714        6429 :                         state.dataFurnaces->CompOnMassFlow = thisFurnace.MaxCoolAirMassFlow;
    5715        6429 :                         state.dataFurnaces->CompOnFlowRatio = thisFurnace.CoolingSpeedRatio;
    5716             :                     } else {
    5717      460202 :                         state.dataFurnaces->CompOnMassFlow = thisFurnace.MaxHeatAirMassFlow;
    5718      460202 :                         state.dataFurnaces->CompOnFlowRatio = thisFurnace.HeatingSpeedRatio;
    5719             :                     }
    5720      466631 :                     thisFurnace.LastMode = Furnaces::ModeOfOperation::HeatingMode;
    5721             :                     //     IF a cooling load exists, operate at the cooling mass flow rate
    5722     3740042 :                 } else if (state.dataFurnaces->CoolingLoad) {
    5723     2201364 :                     state.dataFurnaces->CompOnMassFlow = thisFurnace.MaxCoolAirMassFlow;
    5724     2201364 :                     state.dataFurnaces->CompOnFlowRatio = thisFurnace.CoolingSpeedRatio;
    5725     2201364 :                     thisFurnace.LastMode = Furnaces::ModeOfOperation::CoolingMode;
    5726             :                     //     If no load exists, set the compressor on mass flow rate.
    5727             :                     //     Set equal the mass flow rate when no heating or cooling is needed if no moisture load exists.
    5728             :                     //     If the user has set the off mass flow rate to 0, set according to the last operating mode.
    5729             :                 } else {
    5730     1538678 :                     if (MoistureLoad < 0.0 && thisFurnace.Humidistat &&
    5731      513049 :                         thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat) {
    5732      482878 :                         state.dataFurnaces->CompOnMassFlow = thisFurnace.MaxCoolAirMassFlow;
    5733      482878 :                         state.dataFurnaces->CompOnFlowRatio = thisFurnace.CoolingSpeedRatio;
    5734             :                     } else {
    5735     1055800 :                         state.dataFurnaces->CompOnMassFlow = thisFurnace.MaxNoCoolHeatAirMassFlow;
    5736     1055800 :                         state.dataFurnaces->CompOnFlowRatio = thisFurnace.HeatingSpeedRatio;
    5737             :                         //         User may have entered a 0 for MaxNoCoolHeatAirMassFlow
    5738     1055800 :                         if (state.dataFurnaces->CompOnMassFlow == 0.0) {
    5739       33239 :                             if (thisFurnace.LastMode == Furnaces::ModeOfOperation::HeatingMode) {
    5740        3390 :                                 state.dataFurnaces->CompOnMassFlow = thisFurnace.MaxHeatAirMassFlow;
    5741        3390 :                                 state.dataFurnaces->CompOnFlowRatio = thisFurnace.HeatingSpeedRatio;
    5742             :                             } else {
    5743       29849 :                                 state.dataFurnaces->CompOnMassFlow = thisFurnace.MaxCoolAirMassFlow;
    5744       29849 :                                 state.dataFurnaces->CompOnFlowRatio = thisFurnace.CoolingSpeedRatio;
    5745             :                             }
    5746             :                         }
    5747             :                     }
    5748             :                 }
    5749             : 
    5750             :                 //     Set the compressor or coil OFF mass flow rate based on LOGICAL flag
    5751             :                 //     UseCompressorOnFlow is used when the user does not enter a value for no cooling or heating flow rate
    5752     4206673 :                 if (thisFurnace.AirFlowControl == AirFlowControlConstFan::UseCompressorOnFlow) {
    5753     1056944 :                     if (thisFurnace.LastMode == Furnaces::ModeOfOperation::HeatingMode) {
    5754      152149 :                         if (MoistureLoad < 0.0 && thisFurnace.Humidistat &&
    5755        4344 :                             thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat) {
    5756           0 :                             state.dataFurnaces->CompOffMassFlow = thisFurnace.MaxCoolAirMassFlow;
    5757           0 :                             state.dataFurnaces->CompOffFlowRatio = thisFurnace.CoolingSpeedRatio;
    5758             :                         } else {
    5759      152149 :                             state.dataFurnaces->CompOffMassFlow = thisFurnace.MaxHeatAirMassFlow;
    5760      152149 :                             state.dataFurnaces->CompOffFlowRatio = thisFurnace.HeatingSpeedRatio;
    5761             :                         }
    5762             :                     } else {
    5763      904795 :                         state.dataFurnaces->CompOffMassFlow = thisFurnace.MaxCoolAirMassFlow;
    5764      904795 :                         state.dataFurnaces->CompOffFlowRatio = thisFurnace.CoolingSpeedRatio;
    5765             :                     }
    5766             :                     //     ELSE use the user specified value
    5767             :                 } else {
    5768     3149729 :                     state.dataFurnaces->CompOffMassFlow = thisFurnace.MaxNoCoolHeatAirMassFlow;
    5769     3149729 :                     state.dataFurnaces->CompOffFlowRatio = thisFurnace.NoHeatCoolSpeedRatio;
    5770             :                 }
    5771             :             } else {
    5772             :                 //     cycling fan mode
    5773     4168116 :                 if (state.dataFurnaces->HeatingLoad ||
    5774     1333586 :                     (thisFurnace.Humidistat && MoistureLoad < 0.0 && thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat)) {
    5775             : 
    5776     1502100 :                     if (thisFurnace.Humidistat && MoistureLoad < 0.0 &&
    5777        4584 :                         thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat) {
    5778        1160 :                         state.dataFurnaces->CompOnMassFlow = thisFurnace.MaxCoolAirMassFlow;
    5779        1160 :                         state.dataFurnaces->CompOnFlowRatio = thisFurnace.CoolingSpeedRatio;
    5780        1160 :                         thisFurnace.LastMode = Furnaces::ModeOfOperation::CoolingMode;
    5781             :                     } else {
    5782     1500940 :                         state.dataFurnaces->CompOnMassFlow = thisFurnace.MaxHeatAirMassFlow;
    5783     1500940 :                         state.dataFurnaces->CompOnFlowRatio = thisFurnace.HeatingSpeedRatio;
    5784     1500940 :                         thisFurnace.LastMode = Furnaces::ModeOfOperation::HeatingMode;
    5785             :                     }
    5786     1332430 :                 } else if (state.dataFurnaces->CoolingLoad) {
    5787     1126036 :                     state.dataFurnaces->CompOnMassFlow = thisFurnace.MaxCoolAirMassFlow;
    5788     1126036 :                     state.dataFurnaces->CompOnFlowRatio = thisFurnace.CoolingSpeedRatio;
    5789             :                 } else {
    5790      206394 :                     state.dataFurnaces->CompOnMassFlow = 0.0;
    5791      206394 :                     state.dataFurnaces->CompOnFlowRatio = 0.0;
    5792             :                 }
    5793     2834530 :                 state.dataFurnaces->CompOffMassFlow = 0.0;
    5794     2834530 :                 state.dataFurnaces->CompOffFlowRatio = 0.0;
    5795             :             }
    5796             :         } else { //  Is a HeatOnly furnace
    5797             : 
    5798       24444 :             state.dataFurnaces->CompOnMassFlow = thisFurnace.DesignMassFlowRate;
    5799       24444 :             state.dataFurnaces->CompOnFlowRatio = thisFurnace.HeatingSpeedRatio;
    5800       24444 :             if (fanOp == HVAC::FanOp::Continuous) {
    5801           0 :                 state.dataFurnaces->CompOffMassFlow = thisFurnace.MaxNoCoolHeatAirMassFlow;
    5802           0 :                 state.dataFurnaces->CompOffFlowRatio = thisFurnace.HeatingSpeedRatio;
    5803             :             } else {
    5804       24444 :                 state.dataFurnaces->CompOffMassFlow = 0.0;
    5805       24444 :                 state.dataFurnaces->CompOffFlowRatio = 0.0;
    5806             :             }
    5807             : 
    5808             :         } // End check for heat only furnace or water-to-air heat pump
    5809             : 
    5810             :         // Set the system mass flow rates
    5811     7065647 :         SetAverageAirFlow(state, FurnaceNum, PartLoadRatio, OnOffAirFlowRatio);
    5812     7065647 :     }
    5813             : 
    5814         359 :     void SizeFurnace(EnergyPlusData &state, int const FurnaceNum, bool const FirstHVACIteration)
    5815             :     {
    5816             : 
    5817             :         // SUBROUTINE INFORMATION:
    5818             :         //       AUTHOR         Fred Buhl
    5819             :         //       DATE WRITTEN   January 2002
    5820             :         //       MODIFIED       Bereket Nigusse, May 2010, removed the autosize option for the input field supply air
    5821             :         //                                                 flow fraction through controlled zone.
    5822             :         //                      Bo Shen, March 2012, size the air flow rates at individual speed levels for VS WSHP
    5823             :         //                      Bo Shen, ORNL, July 2012 - added variable-speed air source heat pump cooling and heating coils, using curve-fits
    5824             : 
    5825             :         // PURPOSE OF THIS SUBROUTINE:
    5826             :         // This subroutine is for sizing Furnace Components for which nominal cpacities
    5827             :         // and flow rates have not been specified in the input
    5828             : 
    5829             :         // METHODOLOGY EMPLOYED:
    5830             :         // Obtains heating capacities and flow rates from the zone or system sizing arrays.
    5831             :         // NOTE: In UNITARYSYSTEM:HEATPUMP:AIRTOAIR we are sizing the heating capacity to be
    5832             :         // equal to the cooling capacity.  Thus the cooling and
    5833             :         // and heating capacities of a DX heat pump system will be identical. In real life the ARI
    5834             :         // heating and cooling capacities are close but not identical.
    5835             : 
    5836             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    5837             :         int Iter;                 // iteration count
    5838             :         Real64 MulSpeedFlowScale; // variable speed air flow scaling factor
    5839             :         int IHPCoilIndex;         // refer to cooling or heating coil in IHP
    5840         359 :         Real64 dummy(0.0);
    5841             :         bool anyRan;
    5842         359 :         EMSManager::ManageEMS(state, EMSManager::EMSCallFrom::UnitarySystemSizing, anyRan, ObjexxFCL::Optional_int_const()); // calling point
    5843             : 
    5844         359 :         state.dataSize->DXCoolCap = 0.0;
    5845         359 :         state.dataSize->UnitaryHeatCap = 0.0;
    5846         359 :         state.dataSize->SuppHeatCap = 0.0;
    5847         359 :         auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    5848             : 
    5849         359 :         state.dataAirSystemsData->PrimaryAirSystems(state.dataSize->CurSysNum).supFanNum = thisFurnace.FanIndex;
    5850         359 :         state.dataAirSystemsData->PrimaryAirSystems(state.dataSize->CurSysNum).supFanType = thisFurnace.fanType;
    5851         359 :         state.dataSize->DataFanType = thisFurnace.fanType;
    5852         359 :         state.dataSize->DataFanIndex = thisFurnace.FanIndex;
    5853             : 
    5854         359 :         state.dataAirSystemsData->PrimaryAirSystems(state.dataSize->CurSysNum).supFanPlace = thisFurnace.fanPlace;
    5855             : 
    5856         359 :         if (thisFurnace.CoolingCoilType_Num == HVAC::CoilDX_CoolingSingleSpeed) {
    5857         206 :             DXCoils::SimDXCoil(state, BlankString, HVAC::CompressorOp::On, true, thisFurnace.CoolingCoilIndex, HVAC::FanOp::Cycling, 0.0);
    5858         153 :         } else if (thisFurnace.CoolingCoilType_Num == HVAC::CoilDX_CoolingHXAssisted) {
    5859           3 :             int HXCC_Index = thisFurnace.CoolingCoilIndex;
    5860           3 :             int childCCType_Num = state.dataHVACAssistedCC->HXAssistedCoil(HXCC_Index).CoolingCoilType_Num;
    5861           3 :             if (childCCType_Num == HVAC::CoilDX_Cooling) {
    5862           1 :                 int childCCIndex = state.dataHVACAssistedCC->HXAssistedCoil(HXCC_Index).CoolingCoilIndex;
    5863           1 :                 if (childCCIndex < 0) {
    5864           0 :                     ShowContinueError(state, "Occurs in sizing HeatExchangerAssistedCoolingCoil.");
    5865             :                 }
    5866           1 :                 auto &newCoil = state.dataCoilCooingDX->coilCoolingDXs[childCCIndex];
    5867           1 :                 newCoil.size(state);
    5868             :             }
    5869           9 :             HVACHXAssistedCoolingCoil::SimHXAssistedCoolingCoil(
    5870           6 :                 state, BlankString, true, HVAC::CompressorOp::On, 0.0, thisFurnace.CoolingCoilIndex, HVAC::FanOp::Cycling, false, 1.0, false);
    5871         150 :         } else if (thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingWaterToAirHPSimple) {
    5872         111 :             WaterToAirHeatPumpSimple::SimWatertoAirHPSimple(state,
    5873             :                                                             BlankString,
    5874         111 :                                                             thisFurnace.CoolingCoilIndex,
    5875             :                                                             thisFurnace.CoolingCoilSensDemand,
    5876             :                                                             thisFurnace.CoolingCoilLatentDemand,
    5877             :                                                             HVAC::FanOp::Invalid, // Using invalid to mean off?
    5878             :                                                             HVAC::CompressorOp::Off,
    5879             :                                                             0.0,
    5880             :                                                             FirstHVACIteration); // CoolPartLoadRatio
    5881         111 :             if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingWaterToAirHPSimple) {
    5882         111 :                 WaterToAirHeatPumpSimple::SimWatertoAirHPSimple(state,
    5883             :                                                                 BlankString,
    5884         111 :                                                                 thisFurnace.HeatingCoilIndex,
    5885             :                                                                 thisFurnace.HeatingCoilSensDemand,
    5886             :                                                                 dummy,
    5887             :                                                                 HVAC::FanOp::Invalid, // using Invalid to mean off?
    5888             :                                                                 HVAC::CompressorOp::Off,
    5889             :                                                                 0.0,
    5890             :                                                                 FirstHVACIteration);
    5891             :             }
    5892          39 :         } else if (thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingWaterToAirHPVSEquationFit ||
    5893          25 :                    thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingAirToAirVariableSpeed) {
    5894          21 :             if (thisFurnace.bIsIHP) {
    5895           1 :                 IntegratedHeatPump::SizeIHP(state, thisFurnace.CoolingCoilIndex);
    5896           1 :                 IHPCoilIndex = state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).SCCoilIndex;
    5897           1 :                 thisFurnace.NumOfSpeedCooling = state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex).NumOfSpeeds;
    5898           1 :                 MulSpeedFlowScale = state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex).RatedAirVolFlowRate /
    5899           1 :                                     state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex)
    5900           1 :                                         .MSRatedAirVolFlowRate(state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex).NormSpedLevel);
    5901           1 :                 state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).CoolVolFlowScale = MulSpeedFlowScale;
    5902             :             } else {
    5903          20 :                 VariableSpeedCoils::SimVariableSpeedCoils(state,
    5904             :                                                           BlankString,
    5905          20 :                                                           thisFurnace.CoolingCoilIndex,
    5906             :                                                           HVAC::FanOp::Invalid, // USing Invalid for off?
    5907             :                                                           HVAC::CompressorOp::Off,
    5908             :                                                           0.0,
    5909             :                                                           1,
    5910             :                                                           0.0,
    5911             :                                                           0.0,
    5912             :                                                           0.0,
    5913             :                                                           0.0); // conduct the sizing operation in the VS WSHP
    5914          20 :                 thisFurnace.NumOfSpeedCooling = state.dataVariableSpeedCoils->VarSpeedCoil(thisFurnace.CoolingCoilIndex).NumOfSpeeds;
    5915          20 :                 MulSpeedFlowScale =
    5916          20 :                     state.dataVariableSpeedCoils->VarSpeedCoil(thisFurnace.CoolingCoilIndex).RatedAirVolFlowRate /
    5917          20 :                     state.dataVariableSpeedCoils->VarSpeedCoil(thisFurnace.CoolingCoilIndex)
    5918          20 :                         .MSRatedAirVolFlowRate(state.dataVariableSpeedCoils->VarSpeedCoil(thisFurnace.CoolingCoilIndex).NormSpedLevel);
    5919          20 :                 IHPCoilIndex = thisFurnace.CoolingCoilIndex;
    5920             :             }
    5921             : 
    5922         231 :             for (Iter = 1; Iter <= thisFurnace.NumOfSpeedCooling; ++Iter) {
    5923         420 :                 thisFurnace.CoolVolumeFlowRate(Iter) =
    5924         210 :                     state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex).MSRatedAirVolFlowRate(Iter) * MulSpeedFlowScale;
    5925         420 :                 thisFurnace.CoolMassFlowRate(Iter) =
    5926         210 :                     state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex).MSRatedAirMassFlowRate(Iter) * MulSpeedFlowScale;
    5927         210 :                 thisFurnace.MSCoolingSpeedRatio(Iter) =
    5928         210 :                     state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex).MSRatedAirVolFlowRate(Iter) /
    5929         210 :                     state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex).MSRatedAirVolFlowRate(thisFurnace.NumOfSpeedCooling);
    5930             :             }
    5931             : 
    5932          21 :             if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingWaterToAirHPVSEquationFit ||
    5933           7 :                 thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingAirToAirVariableSpeed) {
    5934             : 
    5935          17 :                 if (thisFurnace.bIsIHP) {
    5936           1 :                     IntegratedHeatPump::SizeIHP(state, thisFurnace.CoolingCoilIndex);
    5937           1 :                     IHPCoilIndex = state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).SHCoilIndex;
    5938           1 :                     thisFurnace.NumOfSpeedHeating = state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex).NumOfSpeeds;
    5939           1 :                     MulSpeedFlowScale = state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex).RatedAirVolFlowRate /
    5940           1 :                                         state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex)
    5941           1 :                                             .MSRatedAirVolFlowRate(state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex).NormSpedLevel);
    5942           1 :                     state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).HeatVolFlowScale = MulSpeedFlowScale;
    5943             :                 } else {
    5944          16 :                     VariableSpeedCoils::SimVariableSpeedCoils(state,
    5945             :                                                               BlankString,
    5946          16 :                                                               thisFurnace.HeatingCoilIndex,
    5947             :                                                               HVAC::FanOp::Invalid, // Invalid for off?
    5948             :                                                               HVAC::CompressorOp::Off,
    5949             :                                                               0.0,
    5950             :                                                               1,
    5951             :                                                               0.0,
    5952             :                                                               0.0,
    5953             :                                                               0.0,
    5954             :                                                               0.0); // conduct the sizing operation in the VS WSHP
    5955          16 :                     thisFurnace.NumOfSpeedHeating = state.dataVariableSpeedCoils->VarSpeedCoil(thisFurnace.HeatingCoilIndex).NumOfSpeeds;
    5956          16 :                     MulSpeedFlowScale =
    5957          16 :                         state.dataVariableSpeedCoils->VarSpeedCoil(thisFurnace.HeatingCoilIndex).RatedAirVolFlowRate /
    5958          16 :                         state.dataVariableSpeedCoils->VarSpeedCoil(thisFurnace.HeatingCoilIndex)
    5959          16 :                             .MSRatedAirVolFlowRate(state.dataVariableSpeedCoils->VarSpeedCoil(thisFurnace.HeatingCoilIndex).NormSpedLevel);
    5960          16 :                     IHPCoilIndex = thisFurnace.HeatingCoilIndex;
    5961             :                 }
    5962             : 
    5963         187 :                 for (Iter = 1; Iter <= thisFurnace.NumOfSpeedHeating; ++Iter) {
    5964         340 :                     thisFurnace.HeatVolumeFlowRate(Iter) =
    5965         170 :                         state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex).MSRatedAirVolFlowRate(Iter) * MulSpeedFlowScale;
    5966         340 :                     thisFurnace.HeatMassFlowRate(Iter) =
    5967         170 :                         state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex).MSRatedAirMassFlowRate(Iter) * MulSpeedFlowScale;
    5968         170 :                     thisFurnace.MSHeatingSpeedRatio(Iter) =
    5969         170 :                         state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex).MSRatedAirVolFlowRate(Iter) /
    5970         170 :                         state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex).MSRatedAirVolFlowRate(thisFurnace.NumOfSpeedHeating);
    5971             :                 }
    5972             :             }
    5973             : 
    5974          21 :             if (thisFurnace.NumOfSpeedHeating > 0) {
    5975          17 :                 thisFurnace.IdleMassFlowRate = min(thisFurnace.HeatMassFlowRate(1), thisFurnace.CoolMassFlowRate(1));
    5976          17 :                 thisFurnace.IdleSpeedRatio = min(thisFurnace.MSHeatingSpeedRatio(1), thisFurnace.MSCoolingSpeedRatio(1));
    5977          17 :                 thisFurnace.IdleVolumeAirRate = min(thisFurnace.HeatVolumeFlowRate(1), thisFurnace.CoolVolumeFlowRate(1));
    5978             :             } else {
    5979           4 :                 thisFurnace.IdleMassFlowRate = thisFurnace.CoolMassFlowRate(1);
    5980           4 :                 thisFurnace.IdleSpeedRatio = thisFurnace.MSCoolingSpeedRatio(1);
    5981           4 :                 thisFurnace.IdleVolumeAirRate = thisFurnace.CoolVolumeFlowRate(1);
    5982             :             }
    5983             : 
    5984          21 :             if (thisFurnace.fanOp == HVAC::FanOp::Continuous) {
    5985           0 :                 thisFurnace.MaxNoCoolHeatAirVolFlow = thisFurnace.IdleVolumeAirRate;
    5986           0 :                 thisFurnace.MaxNoCoolHeatAirMassFlow = thisFurnace.IdleMassFlowRate;
    5987           0 :                 thisFurnace.NoHeatCoolSpeedRatio = thisFurnace.IdleSpeedRatio;
    5988             :             }
    5989             :         }
    5990             : 
    5991         359 :         if (thisFurnace.DesignFanVolFlowRate == DataSizing::AutoSize) {
    5992             : 
    5993         266 :             if (state.dataSize->CurSysNum > 0) {
    5994             : 
    5995         266 :                 CheckSysSizing(state, HVAC::unitarySysTypeNames[(int)thisFurnace.type], thisFurnace.Name);
    5996         266 :                 if (state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesMainVolFlow >= HVAC::SmallAirVolFlow) {
    5997         266 :                     thisFurnace.DesignFanVolFlowRate = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesMainVolFlow;
    5998             :                 } else {
    5999           0 :                     thisFurnace.DesignFanVolFlowRate = 0.0;
    6000             :                 }
    6001             : 
    6002         266 :                 if (thisFurnace.DesignFanVolFlowRateEMSOverrideOn) {
    6003           0 :                     thisFurnace.DesignFanVolFlowRate = thisFurnace.DesignFanVolFlowRateEMSOverrideValue;
    6004             :                 }
    6005             : 
    6006         532 :                 BaseSizer::reportSizerOutput(state,
    6007         266 :                                              HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    6008             :                                              thisFurnace.Name,
    6009             :                                              "Supply Air Flow Rate [m3/s]",
    6010             :                                              thisFurnace.DesignFanVolFlowRate);
    6011             :             }
    6012             :         }
    6013             : 
    6014         359 :         if (thisFurnace.MaxHeatAirVolFlow == DataSizing::AutoSize) {
    6015             : 
    6016         266 :             if (state.dataSize->CurSysNum > 0) {
    6017             : 
    6018         266 :                 CheckSysSizing(state, HVAC::unitarySysTypeNames[(int)thisFurnace.type], thisFurnace.Name);
    6019         266 :                 if (state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesMainVolFlow >= HVAC::SmallAirVolFlow) {
    6020         266 :                     thisFurnace.MaxHeatAirVolFlow = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesMainVolFlow;
    6021             :                 } else {
    6022           0 :                     thisFurnace.MaxHeatAirVolFlow = 0.0;
    6023             :                 }
    6024             : 
    6025         266 :                 if (thisFurnace.MaxHeatAirVolFlowEMSOverrideOn) {
    6026           0 :                     thisFurnace.MaxHeatAirVolFlow = thisFurnace.MaxHeatAirVolFlowEMSOverrideValue;
    6027             :                 }
    6028         532 :                 BaseSizer::reportSizerOutput(state,
    6029         266 :                                              HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    6030             :                                              thisFurnace.Name,
    6031             :                                              "Supply Air Flow Rate During Heating Operation [m3/s]",
    6032             :                                              thisFurnace.MaxHeatAirVolFlow);
    6033             :             }
    6034             :         }
    6035             : 
    6036         359 :         if (thisFurnace.MaxCoolAirVolFlow == DataSizing::AutoSize) {
    6037             : 
    6038         266 :             if (state.dataSize->CurSysNum > 0) {
    6039             : 
    6040         266 :                 CheckSysSizing(state, HVAC::unitarySysTypeNames[(int)thisFurnace.type], thisFurnace.Name);
    6041         266 :                 if (state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesMainVolFlow >= HVAC::SmallAirVolFlow) {
    6042         266 :                     thisFurnace.MaxCoolAirVolFlow = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesMainVolFlow;
    6043             :                 } else {
    6044           0 :                     thisFurnace.MaxCoolAirVolFlow = 0.0;
    6045             :                 }
    6046             : 
    6047         266 :                 if (thisFurnace.MaxCoolAirVolFlowEMSOverrideOn) {
    6048           0 :                     thisFurnace.MaxCoolAirVolFlow = thisFurnace.MaxCoolAirVolFlowEMSOverrideValue;
    6049             :                 }
    6050             : 
    6051         532 :                 BaseSizer::reportSizerOutput(state,
    6052         266 :                                              HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    6053             :                                              thisFurnace.Name,
    6054             :                                              "Supply Air Flow Rate During Cooling Operation [m3/s]",
    6055             :                                              thisFurnace.MaxCoolAirVolFlow);
    6056             :             }
    6057             :         }
    6058             : 
    6059         359 :         if (thisFurnace.MaxNoCoolHeatAirVolFlow == DataSizing::AutoSize) {
    6060             : 
    6061         261 :             if (state.dataSize->CurSysNum > 0) {
    6062             : 
    6063         261 :                 CheckSysSizing(state, HVAC::unitarySysTypeNames[(int)thisFurnace.type], thisFurnace.Name);
    6064         261 :                 if (state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesMainVolFlow >= HVAC::SmallAirVolFlow) {
    6065         261 :                     thisFurnace.MaxNoCoolHeatAirVolFlow = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesMainVolFlow;
    6066             :                 } else {
    6067           0 :                     thisFurnace.MaxNoCoolHeatAirVolFlow = 0.0;
    6068             :                 }
    6069             : 
    6070         261 :                 if (thisFurnace.MaxNoCoolHeatAirVolFlowEMSOverrideOn) {
    6071           0 :                     thisFurnace.MaxNoCoolHeatAirVolFlow = thisFurnace.MaxNoCoolHeatAirVolFlowEMSOverrideValue;
    6072             :                 }
    6073             : 
    6074         522 :                 BaseSizer::reportSizerOutput(state,
    6075         261 :                                              HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    6076             :                                              thisFurnace.Name,
    6077             :                                              "Supply Air Flow Rate When No Cooling or Heating is Needed [m3/s]",
    6078             :                                              thisFurnace.MaxNoCoolHeatAirVolFlow);
    6079             :             }
    6080             :         }
    6081             : 
    6082         359 :         if (thisFurnace.DesignHeatingCapacity == DataSizing::AutoSize) {
    6083             : 
    6084         266 :             if (state.dataSize->CurSysNum > 0) {
    6085             : 
    6086         266 :                 if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_AirToAir ||
    6087         252 :                     thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir) {
    6088             : 
    6089         110 :                     CheckSysSizing(state, HVAC::unitarySysTypeNames[(int)thisFurnace.type], thisFurnace.Name);
    6090             : 
    6091         110 :                     if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingWaterToAirHPSimple) {
    6092          96 :                         thisFurnace.DesignHeatingCapacity =
    6093          96 :                             state.dataWaterToAirHeatPumpSimple->SimpleWatertoAirHP(thisFurnace.HeatingCoilIndex).RatedCapHeat;
    6094             :                     } else {
    6095          14 :                         thisFurnace.DesignHeatingCapacity = state.dataSize->DXCoolCap;
    6096             :                     }
    6097             : 
    6098             :                 } else {
    6099             : 
    6100         156 :                     CheckSysSizing(state, HVAC::unitarySysTypeNames[(int)thisFurnace.type], thisFurnace.Name);
    6101             : 
    6102         156 :                     thisFurnace.DesignHeatingCapacity = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).HeatCap;
    6103             :                 }
    6104             : 
    6105         266 :                 if (thisFurnace.DesignHeatingCapacity < HVAC::SmallLoad) {
    6106           0 :                     thisFurnace.DesignHeatingCapacity = 0.0;
    6107             :                 }
    6108             : 
    6109         532 :                 BaseSizer::reportSizerOutput(state,
    6110         266 :                                              HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    6111             :                                              thisFurnace.Name,
    6112             :                                              "Nominal Heating Capacity [W]",
    6113             :                                              thisFurnace.DesignHeatingCapacity);
    6114             :             }
    6115             :         }
    6116             : 
    6117         359 :         if (thisFurnace.DesignCoolingCapacity == DataSizing::AutoSize) {
    6118             : 
    6119         266 :             if (state.dataSize->CurSysNum > 0) {
    6120             : 
    6121         266 :                 CheckSysSizing(state, HVAC::unitarySysTypeNames[(int)thisFurnace.type], thisFurnace.Name);
    6122         266 :                 if (state.dataSize->DXCoolCap >= HVAC::SmallLoad) {
    6123         266 :                     thisFurnace.DesignCoolingCapacity = state.dataSize->DXCoolCap;
    6124             :                 } else {
    6125           0 :                     thisFurnace.DesignCoolingCapacity = 0.0;
    6126             :                 }
    6127         532 :                 BaseSizer::reportSizerOutput(state,
    6128         266 :                                              HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    6129             :                                              thisFurnace.Name,
    6130             :                                              "Nominal Cooling Capacity [W]",
    6131             :                                              thisFurnace.DesignCoolingCapacity);
    6132             :             }
    6133             :         }
    6134             : 
    6135         359 :         if (thisFurnace.DesignMaxOutletTemp == DataSizing::AutoSize) {
    6136             : 
    6137          83 :             if (state.dataSize->CurSysNum > 0) {
    6138             : 
    6139          83 :                 CheckSysSizing(state, HVAC::unitarySysTypeNames[(int)thisFurnace.type], thisFurnace.Name);
    6140          83 :                 thisFurnace.DesignMaxOutletTemp = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).HeatSupTemp;
    6141         166 :                 BaseSizer::reportSizerOutput(state,
    6142          83 :                                              HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    6143             :                                              thisFurnace.Name,
    6144             :                                              "Maximum Supply Air Temperature from Supplemental Heater [C]",
    6145             :                                              thisFurnace.DesignMaxOutletTemp);
    6146             :             }
    6147             :         }
    6148             : 
    6149         359 :         if (thisFurnace.DesignSuppHeatingCapacity == DataSizing::AutoSize) {
    6150             : 
    6151         110 :             if (state.dataSize->CurSysNum > 0) {
    6152             : 
    6153         110 :                 CheckSysSizing(state, HVAC::unitarySysTypeNames[(int)thisFurnace.type], thisFurnace.Name);
    6154         110 :                 if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_AirToAir ||
    6155          96 :                     thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir) {
    6156             :                     // set the supplemental heating capacity to the actual heating load
    6157         110 :                     thisFurnace.DesignSuppHeatingCapacity = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).HeatCap;
    6158             :                     // if reheat needed for humidity control, make sure supplemental heating is at least as big
    6159             :                     // as the cooling capacity
    6160         110 :                     if (thisFurnace.Humidistat && thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat) {
    6161           0 :                         thisFurnace.DesignSuppHeatingCapacity = max(thisFurnace.DesignSuppHeatingCapacity, thisFurnace.DesignCoolingCapacity);
    6162           0 :                         if (thisFurnace.DesignSuppHeatingCapacity < HVAC::SmallLoad) {
    6163           0 :                             thisFurnace.DesignSuppHeatingCapacity = 0.0;
    6164             :                         }
    6165             :                     }
    6166             : 
    6167             :                 } else {
    6168             : 
    6169           0 :                     if (thisFurnace.Humidistat && thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat) {
    6170           0 :                         thisFurnace.DesignSuppHeatingCapacity = thisFurnace.DesignCoolingCapacity;
    6171             :                     } else {
    6172           0 :                         thisFurnace.DesignSuppHeatingCapacity = 0.0;
    6173             :                     }
    6174             :                 }
    6175             : 
    6176         220 :                 BaseSizer::reportSizerOutput(state,
    6177         110 :                                              HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    6178             :                                              thisFurnace.Name,
    6179             :                                              "Supplemental Heating Coil Nominal Capacity [W]",
    6180             :                                              thisFurnace.DesignSuppHeatingCapacity);
    6181             :             }
    6182             :         }
    6183             : 
    6184         359 :         state.dataSize->UnitaryHeatCap = thisFurnace.DesignHeatingCapacity;
    6185         359 :         state.dataSize->SuppHeatCap = thisFurnace.DesignSuppHeatingCapacity;
    6186         359 :     }
    6187             : 
    6188             :     // End Initialization Section of the Module
    6189             :     //******************************************************************************
    6190             : 
    6191             :     // Beginning of Update subroutines for the Furnace Module
    6192             :     // *****************************************************************************
    6193             : 
    6194       24444 :     void CalcNewZoneHeatOnlyFlowRates(EnergyPlusData &state,
    6195             :                                       int const FurnaceNum,          // Index to furnace
    6196             :                                       bool const FirstHVACIteration, // Iteration flag
    6197             :                                       Real64 const ZoneLoad,         // load to be met by furnace (W)
    6198             :                                       Real64 &HeatCoilLoad,          // actual load passed to heating coil (W)
    6199             :                                       Real64 &OnOffAirFlowRatio      // ratio of coil on to coil off air flow rate
    6200             :     )
    6201             :     {
    6202             :         // SUBROUTINE INFORMATION:
    6203             :         //       AUTHOR         Richard Liesen
    6204             :         //       DATE WRITTEN   Feb 2001
    6205             :         //       MODIFIED       Don Shirey and R. Raustad, Mar 2001 & Mar 2003
    6206             : 
    6207             :         // PURPOSE OF THIS SUBROUTINE:
    6208             :         // This subroutine updates the coil outlet nodes by simulating a heat-only
    6209             :         // furnace or unitary system.
    6210             : 
    6211             :         // METHODOLOGY EMPLOYED:
    6212             :         // Determine the operating PLR to meet the zone sensible load.
    6213             : 
    6214             :         // SUBROUTINE PARAMETER DEFINITIONS:
    6215       24444 :         int constexpr MaxIter(15);    // maximum number of iterations
    6216       24444 :         Real64 constexpr MinPLR(0.0); // minimum part load ratio allowed
    6217             : 
    6218             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    6219       24444 :         Real64 Error(1.0);
    6220             :         Real64 SystemSensibleLoad;   // Sensible load to be met by furnace (W)
    6221             :         Real64 FullSensibleOutput;   // Full sensible output of furnace (W)
    6222             :         Real64 FullLatentOutput;     // Full latent output of furnace = 0 (W)
    6223             :         Real64 NoSensibleOutput;     // Sensible output of furnace with no heating allowed (W)
    6224             :         Real64 NoLatentOutput;       // Latent output of furnace = 0 (W)
    6225             :         Real64 PartLoadRatio;        // Part load ratio of furnace
    6226             :         Real64 HeatErrorToler;       // Error tolerance in heating mode
    6227             :         Real64 IterRelax;            // Relaxation factor for iterations
    6228             :         Real64 ActualSensibleOutput; // Actual furnace sensible capacity
    6229             :         Real64 ActualLatentOutput;   // Actual furnace latent capacity = 0
    6230             :         Real64 deltaT;               // Heater outlet temp minus design heater outlet temp
    6231             : 
    6232       24444 :         auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    6233             :         // Retrieve the load on the controlled zone
    6234       24444 :         auto &furnaceInNode = state.dataLoopNodes->Node(thisFurnace.FurnaceInletNodeNum);
    6235       24444 :         auto const &furnaceOutNode = state.dataLoopNodes->Node(thisFurnace.FurnaceOutletNodeNum);
    6236       24444 :         int ControlZoneNode = thisFurnace.NodeNumOfControlledZone;
    6237       24444 :         HVAC::FanOp fanOp = thisFurnace.fanOp; // fan operating mode
    6238       24444 :         thisFurnace.MdotFurnace = thisFurnace.DesignMassFlowRate;
    6239       24444 :         thisFurnace.CoolPartLoadRatio = 0.0;
    6240             : 
    6241             :         // Calculate the Cp Air of zone
    6242       24444 :         Real64 cpair = Psychrometrics::PsyCpAirFnW(state.dataLoopNodes->Node(ControlZoneNode).HumRat);
    6243             : 
    6244       24444 :         if (FirstHVACIteration) {
    6245       10592 :             HeatCoilLoad = ZoneLoad;
    6246       10592 :             state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
    6247             :         } else {
    6248             :             // If Furnace runs then set HeatCoilLoad on Heating Coil and the Mass Flow
    6249       26034 :             if ((ScheduleManager::GetCurrentScheduleValue(state, thisFurnace.SchedPtr) > 0.0) && (furnaceInNode.MassFlowRate > 0.0) &&
    6250       12182 :                 (state.dataFurnaces->HeatingLoad)) {
    6251             : 
    6252        5599 :                 furnaceInNode.MassFlowRate = thisFurnace.MdotFurnace;
    6253        5599 :                 HeatCoilLoad = thisFurnace.DesignHeatingCapacity;
    6254        5599 :                 SystemSensibleLoad = ZoneLoad;
    6255             : 
    6256             :                 // Get no load result
    6257        5599 :                 if (fanOp == HVAC::FanOp::Cycling) {
    6258        5599 :                     furnaceInNode.MassFlowRate = 0.0;
    6259             :                 }
    6260        5599 :                 if (fanOp == HVAC::FanOp::Continuous) {
    6261           0 :                     state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0; // The on/off fan will not cycle, so set part-load fraction = 1
    6262             :                 }
    6263             : 
    6264             :                 //     Set the inlet mass flow rate based on user specified coil OFF flow rate
    6265        5599 :                 PartLoadRatio = 0.0;
    6266        5599 :                 SetAverageAirFlow(state, FurnaceNum, PartLoadRatio, OnOffAirFlowRatio);
    6267             : 
    6268        5599 :                 CalcFurnaceOutput(state,
    6269             :                                   FurnaceNum,
    6270             :                                   FirstHVACIteration,
    6271             :                                   fanOp,
    6272             :                                   HVAC::CompressorOp::On,
    6273             :                                   0.0,
    6274             :                                   0.0,
    6275             :                                   0.0,
    6276             :                                   0.0,
    6277             :                                   NoSensibleOutput,
    6278             :                                   NoLatentOutput,
    6279             :                                   OnOffAirFlowRatio,
    6280             :                                   false);
    6281             : 
    6282        5599 :                 furnaceInNode.MassFlowRate = thisFurnace.MdotFurnace;
    6283             : 
    6284             :                 // Set fan part-load fraction equal to 1 while getting full load result
    6285        5599 :                 state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
    6286        5599 :                 OnOffAirFlowRatio = 1.0;
    6287             : 
    6288             :                 // Get full load result
    6289        5599 :                 CalcFurnaceOutput(state,
    6290             :                                   FurnaceNum,
    6291             :                                   FirstHVACIteration,
    6292             :                                   fanOp,
    6293             :                                   HVAC::CompressorOp::On,
    6294             :                                   0.0,
    6295             :                                   1.0,
    6296             :                                   HeatCoilLoad,
    6297             :                                   0.0,
    6298             :                                   FullSensibleOutput,
    6299             :                                   FullLatentOutput,
    6300             :                                   OnOffAirFlowRatio,
    6301             :                                   false);
    6302             : 
    6303             :                 // Since we are heating, we expect FullSensibleOutput to be > 0 and FullSensibleOutput > NoSensibleOutput
    6304             :                 // Check that this is the case; if not set PartLoadRatio = 0.0d0 (off) and return
    6305             : 
    6306        5599 :                 if (FullSensibleOutput > NoSensibleOutput) {
    6307             :                     PartLoadRatio =
    6308        5599 :                         max(MinPLR, min(1.0, std::abs(SystemSensibleLoad - NoSensibleOutput) / std::abs(FullSensibleOutput - NoSensibleOutput)));
    6309        5599 :                     if (fanOp == HVAC::FanOp::Cycling) {
    6310        5599 :                         furnaceInNode.MassFlowRate = thisFurnace.MdotFurnace * PartLoadRatio;
    6311        5599 :                         HeatCoilLoad = thisFurnace.DesignHeatingCapacity * PartLoadRatio;
    6312             :                     } else { // FanOp::Continuous
    6313           0 :                         if (furnaceOutNode.Temp > thisFurnace.DesignMaxOutletTemp) {
    6314           0 :                             deltaT = furnaceOutNode.Temp - thisFurnace.DesignMaxOutletTemp;
    6315           0 :                             if (HeatCoilLoad > thisFurnace.DesignHeatingCapacity) HeatCoilLoad = thisFurnace.DesignHeatingCapacity;
    6316           0 :                             HeatCoilLoad -= furnaceInNode.MassFlowRate * cpair * deltaT;
    6317             :                         } else {
    6318           0 :                             HeatCoilLoad = SystemSensibleLoad - NoSensibleOutput;
    6319             :                         }
    6320             :                     }
    6321             : 
    6322             :                     // Calculate the part load ratio through iteration
    6323        5599 :                     HeatErrorToler = thisFurnace.HeatingConvergenceTolerance; // Error tolerance for convergence from input deck
    6324        5599 :                     Error = 1.0;                                              // initialize error value for comparison against tolerance
    6325        5599 :                     state.dataFurnaces->Iter = 0;                             // initialize iteration counter
    6326        5599 :                     IterRelax = 0.9;                                          // relaxation factor for iterations
    6327        6589 :                     while (state.dataFurnaces->Iter <= MaxIter) {
    6328             : 
    6329        6589 :                         if (fanOp == HVAC::FanOp::Cycling) furnaceInNode.MassFlowRate = thisFurnace.MdotFurnace * PartLoadRatio;
    6330        6589 :                         CalcFurnaceOutput(state,
    6331             :                                           FurnaceNum,
    6332             :                                           FirstHVACIteration,
    6333             :                                           fanOp,
    6334             :                                           HVAC::CompressorOp::On,
    6335             :                                           0.0,
    6336             :                                           PartLoadRatio,
    6337             :                                           HeatCoilLoad,
    6338             :                                           0.0,
    6339             :                                           ActualSensibleOutput,
    6340             :                                           ActualLatentOutput,
    6341             :                                           OnOffAirFlowRatio,
    6342             :                                           false);
    6343             : 
    6344        6589 :                         if (SystemSensibleLoad != 0.0) Error = (SystemSensibleLoad - ActualSensibleOutput) / (SystemSensibleLoad);
    6345        6589 :                         if (std::abs(Error) <= HeatErrorToler) break;
    6346        1452 :                         PartLoadRatio = max(
    6347             :                             MinPLR,
    6348             :                             min(1.0,
    6349        1452 :                                 PartLoadRatio + IterRelax * (SystemSensibleLoad - ActualSensibleOutput) / (FullSensibleOutput - NoSensibleOutput)));
    6350             : 
    6351             :                         // limit the heating coil outlet air temperature to DesignMaxOutletTemp
    6352        1452 :                         if (furnaceOutNode.Temp > thisFurnace.DesignMaxOutletTemp) {
    6353           0 :                             deltaT = furnaceOutNode.Temp - thisFurnace.DesignMaxOutletTemp;
    6354           0 :                             if (HeatCoilLoad > thisFurnace.DesignHeatingCapacity) HeatCoilLoad = thisFurnace.DesignHeatingCapacity;
    6355           0 :                             HeatCoilLoad -= furnaceInNode.MassFlowRate * cpair * deltaT;
    6356           0 :                             CalcFurnaceOutput(state,
    6357             :                                               FurnaceNum,
    6358             :                                               FirstHVACIteration,
    6359             :                                               fanOp,
    6360             :                                               HVAC::CompressorOp::On,
    6361             :                                               0.0,
    6362             :                                               PartLoadRatio,
    6363             :                                               HeatCoilLoad,
    6364             :                                               0.0,
    6365             :                                               ActualSensibleOutput,
    6366             :                                               ActualLatentOutput,
    6367             :                                               OnOffAirFlowRatio,
    6368             :                                               false);
    6369             : 
    6370           0 :                             if (SystemSensibleLoad != 0.0) Error = (SystemSensibleLoad - ActualSensibleOutput) / (SystemSensibleLoad);
    6371           0 :                             PartLoadRatio = max(MinPLR,
    6372             :                                                 min(1.0,
    6373           0 :                                                     PartLoadRatio + IterRelax * (SystemSensibleLoad - ActualSensibleOutput) /
    6374           0 :                                                                         (FullSensibleOutput - NoSensibleOutput)));
    6375             :                         } else {
    6376        1452 :                             HeatCoilLoad = thisFurnace.DesignHeatingCapacity * PartLoadRatio;
    6377             :                         }
    6378             : 
    6379        1452 :                         if (PartLoadRatio == MinPLR) break;
    6380        1452 :                         if (PartLoadRatio == 1.0) break;
    6381         990 :                         ++state.dataFurnaces->Iter;
    6382         990 :                         if (state.dataFurnaces->Iter == 7) IterRelax = 0.7;
    6383         990 :                         if (state.dataFurnaces->Iter == 15) IterRelax = 0.4;
    6384             :                     }
    6385             : 
    6386        5599 :                     if (state.dataFurnaces->Iter > MaxIter) {
    6387           0 :                         if (thisFurnace.HeatingMaxIterIndex2 == 0) {
    6388           0 :                             ShowWarningMessage(state,
    6389           0 :                                                format("{} \"{}\" -- Exceeded max heating iterations ({}) while adjusting furnace runtime.",
    6390           0 :                                                       HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    6391           0 :                                                       thisFurnace.Name,
    6392             :                                                       MaxIter));
    6393           0 :                             ShowContinueErrorTimeStamp(state, "");
    6394             :                         }
    6395           0 :                         ShowRecurringWarningErrorAtEnd(state,
    6396           0 :                                                        format("{} \"{}\" -- Exceeded max heating iterations error continues...",
    6397           0 :                                                               HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    6398           0 :                                                               thisFurnace.Name),
    6399           0 :                                                        thisFurnace.HeatingMaxIterIndex2);
    6400             :                     }
    6401             : 
    6402             :                 } else { // ELSE from IF(FullSensibleOutput.GT.NoSensibleOutput)THEN above
    6403             :                     // Set part load ratio to 1 and run heater at design heating capacity
    6404           0 :                     PartLoadRatio = 1.0;
    6405           0 :                     HeatCoilLoad = thisFurnace.DesignHeatingCapacity;
    6406             :                 }
    6407             :                 // Set the final results
    6408             :                 //      IF (fanOp .EQ. FanOp::Cycling) THEN
    6409             :                 //        Furnace(FurnaceNum)%MdotFurnace = Furnace(FurnaceNum)%MdotFurnace * PartLoadRatio
    6410             :                 //      END IF
    6411        5599 :                 thisFurnace.MdotFurnace = furnaceInNode.MassFlowRate;
    6412             : 
    6413        8253 :             } else if ((ScheduleManager::GetCurrentScheduleValue(state, thisFurnace.SchedPtr) > 0.0) && (furnaceInNode.MassFlowRate > 0.0) &&
    6414             :                        (fanOp == HVAC::FanOp::Continuous)) {
    6415           0 :                 HeatCoilLoad = 0.0;
    6416             :             } else { // no heating and no flow
    6417        8253 :                 thisFurnace.MdotFurnace = 0.0;
    6418        8253 :                 HeatCoilLoad = 0.0;
    6419             :             } // End of the Scheduled Furnace If block
    6420             : 
    6421             :         } // End of the FirstHVACIteration control of the mass flow If block
    6422             : 
    6423             :         // Set the fan inlet node flow rates
    6424       24444 :         furnaceInNode.MassFlowRateMaxAvail = thisFurnace.MdotFurnace;
    6425       24444 :         furnaceInNode.MassFlowRate = thisFurnace.MdotFurnace;
    6426       24444 :     }
    6427             : 
    6428     4597475 :     void CalcNewZoneHeatCoolFlowRates(EnergyPlusData &state,
    6429             :                                       int const FurnaceNum,
    6430             :                                       bool const FirstHVACIteration,
    6431             :                                       HVAC::CompressorOp const compressorOp, // compressor operation flag (1=On, 0=Off)
    6432             :                                       Real64 const ZoneLoad,                 // the control zone load (watts)
    6433             :                                       Real64 const MoistureLoad,             // the control zone latent load (watts)
    6434             :                                       Real64 &HeatCoilLoad,                  // Heating load to be met by heating coil ( excluding heat pump DX coil)
    6435             :                                       Real64 &ReheatCoilLoad,    // Heating load to be met by reheat coil using hstat (excluding HP DX coil)
    6436             :                                       Real64 &OnOffAirFlowRatio, // Ratio of compressor ON air flow to AVERAGE air flow over time step
    6437             :                                       bool &HXUnitOn             // flag to control HX based on zone moisture load
    6438             :     )
    6439             :     {
    6440             :         // SUBROUTINE INFORMATION:
    6441             :         //       AUTHOR         Richard Liesen
    6442             :         //       DATE WRITTEN   Feb 2001
    6443             :         //       MODIFIED       R. Raustad and D. Shirey, Feb/Mar/Sept/Oct/Dec 2001, Jan/Oct 2002
    6444             :         //       RE-ENGINEERED  R. Raustad, Feb. 2005 (added RegulaFalsi for iteration technique)
    6445             : 
    6446             :         // PURPOSE OF THIS SUBROUTINE:
    6447             :         // This subroutine updates the coil outlet nodes.
    6448             : 
    6449             :         // METHODOLOGY EMPLOYED:
    6450             :         // Determine the operating PLR to meet the zone sensible load. If a humidistat is specified, determine
    6451             :         // the operating PLR (greater of the sensible and latent PLR) to meet the zone SENSIBLE load
    6452             :         // (Multimode dehumidification control) or zone LATENT load (CoolReheat dehumidification control).
    6453             :         // For dehumidification control type COOLREHEAT, both a sensible and latent PLR may exist for a
    6454             :         // single time step (heating and dehumidificaiton can occur). For all other sytem types,
    6455             :         // only a single PLR is allowed for any given time step.
    6456             :         // Order of simulation depends on dehumidification control option as described below.
    6457             :         // Dehumidificaiton control options:
    6458             :         // Dehumidification Control NONE:   Cooling performance is simulated first and then heating performance. If a HX
    6459             :         //                                  assisted cooling coil is selected, the HX is always active.
    6460             :         // Dehumidification Control COOLREHEAT: Continuous Fan Operation:
    6461             :         //                                      For cooling operation, the sensible and latent capacities are calculated to
    6462             :         //                                      meet the thermostat setpoint. If a HX assisted cooling coil is selected,
    6463             :         //                                      the HX is always active. If the latent load is not met by operating the
    6464             :         //                                      system at the sensible PLR, a new PLR is calculated to meet the humidistat
    6465             :         //                                      setpoint. The reheat coil load is then calculated to meet the HEATING
    6466             :         //                                      setpoint temperature.
    6467             :         //                                      Cycling Fan Operation:
    6468             :         //                                      The heating part-load ratio is calculated first. Since the fan will be
    6469             :         //                                      controlled at the higher of the heating or cooling PLR's, a ratio of the
    6470             :         //                                      cooling to heating PLR is used to pass to the cooling coil (MAX=1). This allows
    6471             :         //                                      the cooling coil to operate at the heating PLR when the heating PLR is
    6472             :         //                                      higher than the cooling PLR. The sensible and latent capacities are then
    6473             :         //                                      calculated to meet the thermostat setpoint.
    6474             :         //                                      If a HX assisted cooling coil is selected, the HX is always active.
    6475             :         //                                      If the latent load is not met by operating the system at the sensible PLR,
    6476             :         //                                      a new PLR is calculated to meet the humidistat setpoint.
    6477             :         //                                      The reheat coil load is then calculated to meet the HEATING setpoint temperature.
    6478             :         // Dehumidification Control MULTIMODE: For cooling operation, the sensible and latent capacities are calculated to
    6479             :         //                                     meet the thermostat setpoint. If a HX assisted cooling coil is selected,
    6480             :         //                                     the HX is off for this calculation. If the latent load is not met by operating
    6481             :         //                                     the system at the sensible PLR, a new PLR is calculated with the HX operating
    6482             :         //                                     and the target is the thermostat setpoint. Humidity is not controlled in this
    6483             :         //                                     mode. No reheat coil is used in this configuration.
    6484             :         //  Note: A supplemental heater augments the heating capacity for air-to-air heat pumps.
    6485             :         //        A reheat coil is used for the HeatCool furnace/unitarysystem to offset the sensible cooling when the
    6486             :         //        dehumidification control type is COOLREHEAT. Both the supplemental and reheat heating coil load is calculated
    6487             :         //        in the Calc routines. The actual simulation of these coils is performed in the SimFurnace routine (i.e. the
    6488             :         //        supplemental and reheat coil loads are passed as 0 to CalcFurnaceOutput).
    6489             : 
    6490             :         // SUBROUTINE PARAMETER DEFINITIONS:
    6491     4597475 :         int constexpr MaxIter(100);   // maximum number of iterations
    6492     4597475 :         Real64 constexpr MinPLR(0.0); // minimum part load ratio allowed
    6493             : 
    6494             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    6495             :         Real64 SystemMoistureLoad;   // Total latent load to be removed by furnace/unitary system
    6496             :         Real64 deltaT;               // Temperature rise across heating coil (C)
    6497             :         Real64 TempOutHeatingCoil;   // Temperature leaving heating coil (C)
    6498             :         Real64 FullSensibleOutput;   // Full sensible output of AC (W)
    6499             :         Real64 FullLatentOutput;     // Full latent output of AC (W)
    6500             :         Real64 NoCoolOutput;         // Sensible output of AC with no cooling allowed (W)
    6501             :         Real64 NoHeatOutput;         // Sensible output of heater with no heating allowed (W)
    6502             :         Real64 NoLatentOutput;       // Latent output of AC with no cooling allowed (W)
    6503             :         Real64 CoolErrorToler;       // Error tolerance in cooling mode
    6504             :         Real64 HeatErrorToler;       // Error tolerance in heating mode
    6505             :         Real64 ActualSensibleOutput; // Actual furnace sensible capacity
    6506             :         Real64 ActualLatentOutput;   // Actual furnace latent capacity
    6507             :         Real64 PartLoadRatio;        // Part load ratio (greater of sensible or latent part load ratio for cooling,
    6508             :         // or heating PLR)
    6509             :         Real64 LatentPartLoadRatio; // Part load ratio to meet dehumidification load
    6510             :         Real64 TempCoolOutput;      // Temporary Sensible output of AC while iterating on PLR (W)
    6511             :         Real64 TempHeatOutput;      // Temporary Sensible output of heating coil while iterating on PLR (W)
    6512             :         Real64 TempLatentOutput;    // Temporary Latent output of AC at increasing PLR (W)
    6513             :         //                                           ! (Temp variables are used to find min PLR for positive latent removal)
    6514             :         Real64 TempMinPLR;             // Temporary min latent PLR when hum control is required and iter is exceeded
    6515             :         Real64 TempMinPLR2;            // Temporary min latent PLR when cyc fan hum control is required and iter is exceeded
    6516             :         Real64 TempMaxPLR;             // Temporary max latent PLR when hum control is required and iter is exceeded
    6517             :         Real64 QToHeatSetPt;           // Load required to meet heating setpoint temp (>0 is a heating load)
    6518             :         Real64 CoolingHeatingPLRRatio; // ratio of cooling to heating PLR (MAX=1). Used in heating mode.
    6519             :         Real64 HeatingSensibleOutput;
    6520             :         Real64 HeatingLatentOutput;
    6521             :         Real64 OutdoorDryBulbTemp; // secondary coil (condenser) entering dry bulb temperature
    6522             : 
    6523     4597475 :         Real64 &SystemSensibleLoad = state.dataFurnaces->SystemSensibleLoad;
    6524     4597475 :         auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    6525             :         // Set local variables
    6526     4597475 :         int FurnaceOutletNode = thisFurnace.FurnaceOutletNodeNum;
    6527     4597475 :         int FurnaceInletNode = thisFurnace.FurnaceInletNodeNum;
    6528     4597475 :         int ControlZoneNode = thisFurnace.NodeNumOfControlledZone;
    6529     4597475 :         HVAC::FanOp fanOp = thisFurnace.fanOp; // fan operating mode
    6530     4597475 :         bool HumControl = false;
    6531             :         // Calculate the Cp Air of zone
    6532     4597475 :         Real64 cpair = Psychrometrics::PsyCpAirFnW(state.dataLoopNodes->Node(ControlZoneNode).HumRat);
    6533     4597475 :         NoHeatOutput = 0.0;
    6534     4597475 :         SystemSensibleLoad = 0.0;
    6535     4597475 :         ReheatCoilLoad = 0.0;
    6536     4597475 :         HeatCoilLoad = 0.0;
    6537     4597475 :         ReheatCoilLoad = 0.0;
    6538     4597475 :         PartLoadRatio = 0.0;
    6539             : 
    6540     4597475 :         if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_AirToAir) {
    6541      391662 :             if (state.dataDXCoils->DXCoil(thisFurnace.HeatingCoilIndex)
    6542      391662 :                     .IsSecondaryDXCoilInZone) { // assumes compressor is in same location as secondary coil
    6543       16288 :                 OutdoorDryBulbTemp =
    6544       16288 :                     state.dataZoneTempPredictorCorrector->zoneHeatBalance(state.dataDXCoils->DXCoil(thisFurnace.HeatingCoilIndex).SecZonePtr).ZT;
    6545      375374 :             } else if (state.dataDXCoils->DXCoil(thisFurnace.CoolingCoilIndex).IsSecondaryDXCoilInZone) {
    6546           0 :                 OutdoorDryBulbTemp =
    6547           0 :                     state.dataZoneTempPredictorCorrector->zoneHeatBalance(state.dataDXCoils->DXCoil(thisFurnace.CoolingCoilIndex).SecZonePtr).ZT;
    6548             :             } else {
    6549      375374 :                 if (thisFurnace.CondenserNodeNum > 0) {
    6550       63402 :                     OutdoorDryBulbTemp = state.dataLoopNodes->Node(thisFurnace.CondenserNodeNum).Temp;
    6551             :                 } else {
    6552      311972 :                     OutdoorDryBulbTemp = state.dataEnvrn->OutDryBulbTemp;
    6553             :                 }
    6554             :             }
    6555             :         } else {
    6556     4205813 :             OutdoorDryBulbTemp = state.dataEnvrn->OutDryBulbTemp;
    6557             :         }
    6558     4597475 :         if (FirstHVACIteration) {
    6559             :             // Set selected values during first HVAC iteration
    6560             : 
    6561             :             // Init for heating
    6562     1595035 :             if (state.dataFurnaces->HeatingLoad) {
    6563      572012 :                 if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_AirToAir ||
    6564      515602 :                     (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir && thisFurnace.WatertoAirHPType == WAHPCoilType::Simple)) {
    6565      170850 :                     thisFurnace.HeatPartLoadRatio = 1.0;
    6566      170850 :                     HeatCoilLoad = 0.0;
    6567      170850 :                     thisFurnace.HeatingCoilSensDemand = 0.0;
    6568      170850 :                     thisFurnace.CoolingCoilSensDemand = 0.0;
    6569      170850 :                     thisFurnace.CoolingCoilLatentDemand = 0.0;
    6570             :                 } else { // for furnaces
    6571      401162 :                     thisFurnace.HeatPartLoadRatio = 0.0;
    6572      401162 :                     HeatCoilLoad = ZoneLoad;
    6573      401162 :                     state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = thisFurnace.MdotFurnace;
    6574      401162 :                     thisFurnace.HeatingCoilSensDemand = 0.0;
    6575      401162 :                     thisFurnace.CoolingCoilSensDemand = 0.0;
    6576      401162 :                     thisFurnace.CoolingCoilLatentDemand = 0.0;
    6577             :                 }
    6578      572012 :                 ReheatCoilLoad = 0.0;
    6579      572012 :                 thisFurnace.CoolPartLoadRatio = 0.0;
    6580             : 
    6581             :                 // Init for cooling
    6582     1023023 :             } else if (state.dataFurnaces->CoolingLoad) {
    6583             :                 // air to air heat pumps
    6584      555293 :                 thisFurnace.CoolPartLoadRatio = 1.0;
    6585      555293 :                 thisFurnace.HeatPartLoadRatio = 0.0;
    6586      555293 :                 HeatCoilLoad = 0.0;
    6587      555293 :                 ReheatCoilLoad = 0.0;
    6588             : 
    6589             :                 // Init for moisture load only
    6590             :             } else {
    6591      467730 :                 thisFurnace.CoolPartLoadRatio = 0.0;
    6592      467730 :                 thisFurnace.HeatPartLoadRatio = 0.0;
    6593      467730 :                 HeatCoilLoad = 0.0;
    6594      467730 :                 ReheatCoilLoad = 0.0;
    6595      467730 :                 thisFurnace.HeatingCoilSensDemand = 0.0;
    6596      467730 :                 thisFurnace.CoolingCoilSensDemand = 0.0;
    6597      467730 :                 thisFurnace.CoolingCoilLatentDemand = 0.0;
    6598             :             }
    6599             : 
    6600     1595035 :             SetAverageAirFlow(state, FurnaceNum, max(thisFurnace.HeatPartLoadRatio, thisFurnace.CoolPartLoadRatio), OnOffAirFlowRatio);
    6601             :             //  if dehumidification load exists (for heat pumps) turn on the supplmental heater
    6602     1595035 :             if (state.dataFurnaces->HPDehumidificationLoadFlag) HumControl = true;
    6603             :         } else { // not FirstHVACIteration
    6604             :             // Init for heating
    6605     3002440 :             Real64 &CoolCoilLoad = state.dataFurnaces->CoolCoilLoad;
    6606     3002440 :             if (state.dataFurnaces->HeatingLoad) {
    6607     1230288 :                 CoolCoilLoad = 0.0;
    6608     1230288 :                 if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_AirToAir ||
    6609     1138478 :                     (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir && thisFurnace.WatertoAirHPType == WAHPCoilType::Simple)) {
    6610      630470 :                     SystemSensibleLoad = ZoneLoad;
    6611      630470 :                     SystemMoistureLoad = 0.0;
    6612      630470 :                     HeatCoilLoad = 0.0;
    6613      630470 :                     thisFurnace.HeatingCoilSensDemand = SystemSensibleLoad;
    6614      630470 :                     thisFurnace.CoolingCoilSensDemand = 0.0;
    6615      630470 :                     thisFurnace.CoolingCoilLatentDemand = 0.0;
    6616             :                 } else {
    6617      599818 :                     SystemMoistureLoad = MoistureLoad;
    6618      599818 :                     HeatCoilLoad = ZoneLoad;
    6619             :                 }
    6620             : 
    6621             :                 // Init for cooling
    6622     1772152 :             } else if (state.dataFurnaces->CoolingLoad) {
    6623     1248779 :                 CoolCoilLoad = ZoneLoad;
    6624     1248779 :                 SystemMoistureLoad = MoistureLoad;
    6625     1248779 :                 HeatCoilLoad = 0.0;
    6626     1248779 :                 thisFurnace.CoolingCoilSensDemand = std::abs(CoolCoilLoad);
    6627     1248779 :                 thisFurnace.CoolingCoilLatentDemand = std::abs(SystemMoistureLoad);
    6628     1248779 :                 thisFurnace.HeatingCoilSensDemand = 0.0;
    6629             : 
    6630             :                 // Init for latent
    6631             :             } else {
    6632      523373 :                 SystemMoistureLoad = MoistureLoad;
    6633      523373 :                 CoolCoilLoad = 0.0;
    6634      523373 :                 HeatCoilLoad = 0.0;
    6635             :                 // set report variables
    6636      523373 :                 thisFurnace.CoolingCoilSensDemand = 0.0;
    6637      523373 :                 thisFurnace.CoolingCoilLatentDemand = SystemMoistureLoad;
    6638      523373 :                 thisFurnace.HeatingCoilSensDemand = 0.0;
    6639             :             }
    6640     3002440 :             HeatingSensibleOutput = 0.0;
    6641     3002440 :             HeatingLatentOutput = 0.0;
    6642     3002440 :             ReheatCoilLoad = 0.0;
    6643     3002440 :             thisFurnace.CoolPartLoadRatio = 0.0;
    6644     3002440 :             thisFurnace.HeatPartLoadRatio = 0.0;
    6645     3002440 :             thisFurnace.CompPartLoadRatio = 0.0;
    6646     3002440 :             thisFurnace.DehumidInducedHeatingDemandRate = 0.0;
    6647             : 
    6648             :             // When humidity control is used with cycling fan control and a heating load exists, if a moisture load
    6649             :             // also exists, the heating PLR must be available for the cooling coil calculations.
    6650             :             //*********** Heating Section ************
    6651             :             // If Furnace runs with a heating load then set HeatCoilLoad on Heating Coil and the Mass Flow
    6652             :             //         (Node(FurnaceInletNode)%MassFlowRate .gt. 0.0d0) .and. &
    6653     3002440 :             if ((ScheduleManager::GetCurrentScheduleValue(state, thisFurnace.SchedPtr) > 0.0) && (state.dataFurnaces->HeatingLoad)) {
    6654             : 
    6655             :                 //    Heat pumps only calculate a single PLR each time step (i.e. only cooling or heating allowed in a single time step)
    6656     1219760 :                 if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_AirToAir ||
    6657     1127950 :                     (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir && thisFurnace.WatertoAirHPType == WAHPCoilType::Simple)) {
    6658             : 
    6659      630470 :                     state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = thisFurnace.MdotFurnace;
    6660             : 
    6661             :                     // Get no load result
    6662      630470 :                     if (fanOp == HVAC::FanOp::Cycling) {
    6663      593322 :                         state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = 0.0;
    6664             :                     }
    6665             : 
    6666             :                     //     Set the inlet mass flow rate based on user specified coil OFF flow rate
    6667      630470 :                     PartLoadRatio = 0.0;
    6668             : 
    6669      630470 :                     SetAverageAirFlow(state, FurnaceNum, PartLoadRatio, OnOffAirFlowRatio);
    6670             : 
    6671             :                     // Set the input parameters for CalcFurnaceOutput
    6672      630470 :                     thisFurnace.CompPartLoadRatio = 0.0; // compressor off
    6673             : 
    6674      630470 :                     CalcFurnaceOutput(state,
    6675             :                                       FurnaceNum,
    6676             :                                       FirstHVACIteration,
    6677             :                                       fanOp,
    6678             :                                       compressorOp,
    6679             :                                       0.0,
    6680             :                                       MinPLR,
    6681             :                                       0.0,
    6682             :                                       0.0,
    6683             :                                       NoHeatOutput,
    6684             :                                       NoLatentOutput,
    6685             :                                       OnOffAirFlowRatio,
    6686             :                                       false);
    6687             : 
    6688      630470 :                     PartLoadRatio = 1.0;
    6689      630470 :                     state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = thisFurnace.MdotFurnace;
    6690             : 
    6691      630470 :                     thisFurnace.CompPartLoadRatio = 1.0; // compressor ON
    6692             : 
    6693             :                     // Set fan part-load fraction equal to 1 while getting full load result
    6694      630470 :                     state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
    6695      630470 :                     OnOffAirFlowRatio = 1.0;
    6696             : 
    6697             :                     // Get full load result
    6698      630470 :                     CalcFurnaceOutput(state,
    6699             :                                       FurnaceNum,
    6700             :                                       FirstHVACIteration,
    6701             :                                       fanOp,
    6702             :                                       compressorOp,
    6703             :                                       0.0,
    6704             :                                       PartLoadRatio,
    6705             :                                       0.0,
    6706             :                                       0.0,
    6707             :                                       FullSensibleOutput,
    6708             :                                       FullLatentOutput,
    6709             :                                       OnOffAirFlowRatio,
    6710             :                                       false);
    6711             : 
    6712             :                     // Check that SystemSensibleLoad is between FullSensibleOutput and NoHeatOutput
    6713             :                     // If so then calculate PartLoadRatio for the DX Heating coil
    6714      630470 :                     if (SystemSensibleLoad < FullSensibleOutput && SystemSensibleLoad > NoHeatOutput) {
    6715             : 
    6716             :                         // Calculate the part load ratio through iteration
    6717      544890 :                         HeatErrorToler = thisFurnace.HeatingConvergenceTolerance; // Error tolerance for convergence from input deck
    6718             : 
    6719      544890 :                         int SolFlag = 0; // # of iterations if positive, -1 means failed to converge, -2 means bounds are incorrect
    6720             :                         // HeatErrorToler is in fraction of load, MaxIter = 30, SolFalg = # of iterations or error as appropriate
    6721     2700486 :                         auto f = [&state, FurnaceNum, FirstHVACIteration, fanOp, compressorOp, SystemSensibleLoad](Real64 const PartLoadRatio) {
    6722     2155596 :                             return CalcFurnaceResidual(state,
    6723             :                                                        PartLoadRatio,
    6724             :                                                        FurnaceNum,
    6725             :                                                        FirstHVACIteration,
    6726             :                                                        fanOp,
    6727             :                                                        compressorOp,
    6728             :                                                        SystemSensibleLoad,
    6729             :                                                        0.0,  // par6_loadFlag,
    6730             :                                                        1.0,  // par7_sensLatentFlag,
    6731             :                                                        0.0,  // par9_HXOnFlag,
    6732     2155596 :                                                        0.0); // par10_HeatingCoilPLR);
    6733      544890 :                         };
    6734      544890 :                         General::SolveRoot(state, HeatErrorToler, MaxIter, SolFlag, PartLoadRatio, f, 0.0, 1.0);
    6735             :                         //         OnOffAirFlowRatio is updated during the above iteration. Reset to correct value based on PLR.
    6736      544890 :                         OnOffAirFlowRatio = state.dataFurnaces->OnOffAirFlowRatioSave;
    6737      544890 :                         if (SolFlag < 0) {
    6738           0 :                             if (SolFlag == -1) {
    6739           0 :                                 CalcFurnaceOutput(state,
    6740             :                                                   FurnaceNum,
    6741             :                                                   FirstHVACIteration,
    6742             :                                                   fanOp,
    6743             :                                                   compressorOp,
    6744             :                                                   0.0,
    6745             :                                                   PartLoadRatio,
    6746             :                                                   0.0,
    6747             :                                                   0.0,
    6748             :                                                   TempHeatOutput,
    6749             :                                                   TempLatentOutput,
    6750             :                                                   OnOffAirFlowRatio,
    6751             :                                                   false);
    6752           0 :                                 if (std::abs(SystemSensibleLoad - TempHeatOutput) > HVAC::SmallLoad) {
    6753           0 :                                     if (thisFurnace.DXHeatingMaxIterIndex == 0) {
    6754           0 :                                         ShowWarningMessage(state,
    6755           0 :                                                            format("Heating coil control failed to converge for {}:{}",
    6756           0 :                                                                   HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    6757           0 :                                                                   thisFurnace.Name));
    6758           0 :                                         ShowContinueError(state,
    6759             :                                                           "  Iteration limit exceeded in calculating DX heating coil sensible part-load ratio.");
    6760           0 :                                         ShowContinueErrorTimeStamp(
    6761             :                                             state,
    6762           0 :                                             format("Sensible load to be met by DX heating coil = {:.2T} (watts), sensible output of DX heating "
    6763             :                                                    "coil = {:.2T} (watts), and the simulation continues.",
    6764             :                                                    SystemSensibleLoad,
    6765             :                                                    TempHeatOutput));
    6766             :                                     }
    6767           0 :                                     ShowRecurringWarningErrorAtEnd(state,
    6768           0 :                                                                    format("{} \"{}\" - Iteration limit exceeded in calculating DX sensible heating "
    6769             :                                                                           "part-load ratio error continues. "
    6770             :                                                                           "Sensible load statistics:",
    6771           0 :                                                                           HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    6772           0 :                                                                           thisFurnace.Name),
    6773           0 :                                                                    thisFurnace.DXHeatingMaxIterIndex,
    6774             :                                                                    SystemSensibleLoad,
    6775             :                                                                    SystemSensibleLoad);
    6776             :                                 }
    6777           0 :                             } else if (SolFlag == -2) {
    6778           0 :                                 if (thisFurnace.DXHeatingRegulaFalsiFailedIndex == 0) {
    6779           0 :                                     ShowWarningMessage(state,
    6780           0 :                                                        format("Heating coil control failed for {}:{}",
    6781           0 :                                                               HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    6782           0 :                                                               thisFurnace.Name));
    6783           0 :                                     ShowContinueError(state, "  DX sensible heating part-load ratio determined to be outside the range of 0-1.");
    6784           0 :                                     ShowContinueErrorTimeStamp(
    6785             :                                         state,
    6786           0 :                                         format("Sensible load to be met by DX heating coil = {:.2T} (watts), and the simulation continues.",
    6787             :                                                SystemSensibleLoad));
    6788             :                                 }
    6789           0 :                                 ShowRecurringWarningErrorAtEnd(
    6790             :                                     state,
    6791           0 :                                     format("{} \"{}\" -  DX sensible heating part-load ratio out of range error continues. Sensible load statistics:",
    6792           0 :                                            HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    6793           0 :                                            thisFurnace.Name),
    6794           0 :                                     thisFurnace.DXHeatingRegulaFalsiFailedIndex,
    6795             :                                     SystemSensibleLoad,
    6796             :                                     SystemSensibleLoad);
    6797             :                             }
    6798             :                         }
    6799             : 
    6800      544890 :                         thisFurnace.HeatPartLoadRatio = PartLoadRatio;
    6801             :                         //       Check if Heat Pump compressor is allowed to run based on outdoor temperature
    6802      544890 :                         if (OutdoorDryBulbTemp > thisFurnace.MinOATCompressorHeating) {
    6803      544872 :                             thisFurnace.CompPartLoadRatio = PartLoadRatio;
    6804             :                         } else {
    6805          18 :                             thisFurnace.CompPartLoadRatio = 0.0;
    6806             :                         }
    6807      630470 :                     } else if (SystemSensibleLoad > FullSensibleOutput) {
    6808             :                         //       SystemSensibleLoad is greater than full DX Heating coil output so heat pump runs entire
    6809             :                         //       timestep and additional supplemental heating is required
    6810       85580 :                         thisFurnace.HeatPartLoadRatio = 1.0;
    6811       85580 :                         if (OutdoorDryBulbTemp > thisFurnace.MinOATCompressorHeating) {
    6812             :                             //       Check to see if Heat Pump compressor was allowed to run based on outdoor temperature
    6813        4142 :                             thisFurnace.CompPartLoadRatio = 1.0;
    6814             :                         } else {
    6815       81438 :                             thisFurnace.CompPartLoadRatio = 0.0;
    6816             :                         }
    6817           0 :                     } else if (SystemSensibleLoad < NoHeatOutput) {
    6818             :                         //       SystemSensibleLoad is less than minimum DX Heating coil output so heat pump does not run and
    6819             :                         //       the load will be met by the supplemental heater
    6820           0 :                         thisFurnace.CompPartLoadRatio = 0.0;
    6821           0 :                         thisFurnace.HeatPartLoadRatio = 1.0;
    6822             :                     }
    6823      630470 :                     if (thisFurnace.HeatPartLoadRatio == 1.0) {
    6824             :                         //       Determine the load on the supplemental heating coil
    6825       85580 :                         if ((SystemSensibleLoad - FullSensibleOutput) > thisFurnace.DesignSuppHeatingCapacity) {
    6826       24992 :                             HeatCoilLoad = thisFurnace.DesignSuppHeatingCapacity;
    6827       24992 :                             TempOutHeatingCoil = state.dataLoopNodes->Node(FurnaceOutletNode).Temp + HeatCoilLoad / (cpair * thisFurnace.MdotFurnace);
    6828       60588 :                         } else if (SystemSensibleLoad < NoHeatOutput) {
    6829           0 :                             HeatCoilLoad = max(0.0, SystemSensibleLoad); // BG 10/22/2008 need a case for when its all suppl heat
    6830           0 :                             TempOutHeatingCoil = state.dataLoopNodes->Node(FurnaceInletNode).Temp + HeatCoilLoad / (cpair * thisFurnace.MdotFurnace);
    6831             :                         } else {
    6832       60588 :                             HeatCoilLoad = max(0.0, (SystemSensibleLoad - FullSensibleOutput));
    6833       60588 :                             TempOutHeatingCoil = state.dataLoopNodes->Node(FurnaceOutletNode).Temp + HeatCoilLoad / (cpair * thisFurnace.MdotFurnace);
    6834             :                         }
    6835       85580 :                         if (OutdoorDryBulbTemp > thisFurnace.MaxOATSuppHeat) {
    6836           0 :                             HeatCoilLoad = 0.0;
    6837           0 :                             if (SystemSensibleLoad < NoHeatOutput) {
    6838           0 :                                 TempOutHeatingCoil = state.dataLoopNodes->Node(FurnaceInletNode).Temp;
    6839             :                             } else {
    6840           0 :                                 TempOutHeatingCoil = state.dataLoopNodes->Node(FurnaceOutletNode).Temp;
    6841             :                             }
    6842             :                         }
    6843       85580 :                         if ((TempOutHeatingCoil > thisFurnace.DesignMaxOutletTemp) && (HeatCoilLoad > 0.0)) {
    6844             :                             // deltaT = Furnace(FurnaceNum)%DesignMaxOutletTemp - Node(FurnaceOutletNode)%Temp
    6845             :                             // BG 10/22/2008 above made no sense if DX heat is off and its all supplemental,
    6846             :                             //  because Node(FurnaceOutletNode)%Temp will have been calc'd with full DX heat in last faux call to CalcFurnaceOutput
    6847             : 
    6848        1374 :                             Real64 cpairSupply = Psychrometrics::PsyCpAirFnW(state.dataLoopNodes->Node(FurnaceInletNode).HumRat);
    6849        1374 :                             deltaT = (thisFurnace.DesignMaxOutletTemp - TempOutHeatingCoil);
    6850        1374 :                             HeatCoilLoad += (state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate * cpairSupply * deltaT);
    6851        1374 :                             HeatCoilLoad = max(0.0, HeatCoilLoad);
    6852             :                         }
    6853             :                     } else {
    6854      544890 :                         HeatCoilLoad = 0.0;
    6855             :                     }
    6856      630470 :                     PartLoadRatio = 0.0;
    6857             : 
    6858             :                     //   HeatCool systems can have both a sensible and latent PLR in a single time step
    6859             :                     //   (i.e. both cooling and heating can occur in a single time step)
    6860      630470 :                 } else { // else not a heatpump DX coil ** non-HP heating coils are not DX so testing if OutdoorDryBulbTemp < MinOATCompressorHeating
    6861             :                          // is not necessary **
    6862             : 
    6863      589290 :                     state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = thisFurnace.MdotFurnace;
    6864      589290 :                     HeatCoilLoad = thisFurnace.DesignHeatingCapacity;
    6865      589290 :                     SystemSensibleLoad = ZoneLoad;
    6866             : 
    6867             :                     // Get no load result
    6868      589290 :                     if (fanOp == HVAC::FanOp::Cycling) {
    6869      443811 :                         state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = 0.0;
    6870             :                     }
    6871      589290 :                     if (fanOp == HVAC::FanOp::Continuous) {
    6872      145479 :                         state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0; // The on/off fan will not cycle, so set part-load fraction = 1
    6873             :                     }
    6874             : 
    6875             :                     //     Set the inlet mass flow rate based on user specified coil OFF flow rate
    6876      589290 :                     PartLoadRatio = 0.0;
    6877      589290 :                     SetAverageAirFlow(state, FurnaceNum, PartLoadRatio, OnOffAirFlowRatio);
    6878             : 
    6879      589290 :                     CalcFurnaceOutput(state,
    6880             :                                       FurnaceNum,
    6881             :                                       FirstHVACIteration,
    6882             :                                       fanOp,
    6883             :                                       compressorOp,
    6884             :                                       0.0,
    6885             :                                       MinPLR,
    6886             :                                       0.0,
    6887             :                                       0.0,
    6888             :                                       NoHeatOutput,
    6889             :                                       NoLatentOutput,
    6890             :                                       OnOffAirFlowRatio,
    6891             :                                       false);
    6892             : 
    6893      589290 :                     if (NoHeatOutput < SystemSensibleLoad) {
    6894      589290 :                         state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = thisFurnace.MdotFurnace;
    6895             : 
    6896             :                         // Set fan part-load fraction equal to 1 while getting full load result
    6897      589290 :                         state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
    6898      589290 :                         OnOffAirFlowRatio = 1.0;
    6899             : 
    6900             :                         // Get full load result
    6901      589290 :                         CalcFurnaceOutput(state,
    6902             :                                           FurnaceNum,
    6903             :                                           FirstHVACIteration,
    6904             :                                           fanOp,
    6905             :                                           compressorOp,
    6906             :                                           0.0,
    6907             :                                           1.0,
    6908             :                                           HeatCoilLoad,
    6909             :                                           0.0,
    6910             :                                           FullSensibleOutput,
    6911             :                                           FullLatentOutput,
    6912             :                                           OnOffAirFlowRatio,
    6913             :                                           false);
    6914             :                     } else {
    6915           0 :                         FullSensibleOutput = NoHeatOutput + 0.000000001;
    6916             :                     }
    6917             : 
    6918             :                     // Since we are heating, we expect FullSensibleOutput to be > 0 and FullSensibleOutput > NoSensibleOutput
    6919             :                     // Check that this is the case; if not set PartLoadRatio = 0.0 (off) and return
    6920             : 
    6921      589290 :                     if (FullSensibleOutput > NoHeatOutput) {
    6922             : 
    6923             :                         // check bounds on sensible output prior to iteration using RegulaFalsi
    6924      534244 :                         if (FullSensibleOutput <= SystemSensibleLoad) {
    6925       96967 :                             PartLoadRatio = 1.0;
    6926             :                             //         save modified HeatCoilLoad in case it was reset because outlet temp > DesignMaxOutletTemp
    6927       96967 :                             if (state.dataFurnaces->ModifiedHeatCoilLoad > 0.0) {
    6928       14808 :                                 HeatCoilLoad = state.dataFurnaces->ModifiedHeatCoilLoad;
    6929             :                             } else {
    6930       82159 :                                 HeatCoilLoad = thisFurnace.DesignHeatingCapacity;
    6931             :                             }
    6932      437277 :                         } else if (NoHeatOutput >= SystemSensibleLoad) {
    6933           0 :                             PartLoadRatio = 0.0;
    6934           0 :                             HeatCoilLoad = 0.0;
    6935             :                         } else {
    6936             : 
    6937             :                             // Calculate the part load ratio through iteration
    6938      437277 :                             HeatErrorToler = thisFurnace.HeatingConvergenceTolerance; // Error tolerance for convergence from input deck
    6939             : 
    6940      437277 :                             int SolFlag = 0; // # of iterations if positive, -1 means failed to converge, -2 means bounds are incorrect
    6941             :                             // HeatErrorToler is in fraction load, MaxIter = 30, SolFalg = # of iterations or error as appropriate
    6942     1753894 :                             auto f = [&state, FurnaceNum, FirstHVACIteration, fanOp, compressorOp, SystemSensibleLoad](Real64 const PartLoadRatio) {
    6943     1316617 :                                 return CalcFurnaceResidual(state,
    6944             :                                                            PartLoadRatio,
    6945             :                                                            FurnaceNum,
    6946             :                                                            FirstHVACIteration,
    6947             :                                                            fanOp,
    6948             :                                                            compressorOp,
    6949             :                                                            SystemSensibleLoad,
    6950             :                                                            0.0,  // par6_loadFlag,
    6951             :                                                            1.0,  // par7_sensLatentFlag,
    6952             :                                                            0.0,  // par9_HXOnFlag,
    6953     1316617 :                                                            0.0); // par10_HeatingCoilPLR);
    6954      437277 :                             };
    6955      437277 :                             General::SolveRoot(state, HeatErrorToler, MaxIter, SolFlag, PartLoadRatio, f, 0.0, 1.0);
    6956             :                             //         OnOffAirFlowRatio is updated during the above iteration. Reset to correct value based on PLR.
    6957      437277 :                             OnOffAirFlowRatio = state.dataFurnaces->OnOffAirFlowRatioSave;
    6958             :                             //         Reset HeatCoilLoad calculated in CalcFurnaceResidual (in case it was reset because output temp >
    6959             :                             //         DesignMaxOutletTemp)
    6960      437277 :                             if (state.dataFurnaces->ModifiedHeatCoilLoad > 0.0) {
    6961       62506 :                                 HeatCoilLoad = state.dataFurnaces->ModifiedHeatCoilLoad;
    6962             :                             } else {
    6963      374771 :                                 HeatCoilLoad = thisFurnace.DesignHeatingCapacity * PartLoadRatio;
    6964             :                             }
    6965      437277 :                             if (SolFlag == -1) {
    6966             : 
    6967             :                                 //           RegulaFalsi may not find heating PLR when the maximum supply air temperature is exceeded.
    6968             :                                 //           If iteration limit is exceeded, find tighter boundary of solution and repeat RegulaFalsi
    6969           0 :                                 TempMaxPLR = -0.1;
    6970           0 :                                 TempHeatOutput = NoHeatOutput;
    6971           0 :                                 while ((TempHeatOutput - SystemSensibleLoad) < 0.0 && TempMaxPLR < 1.0) {
    6972             :                                     //             find upper limit of HeatingPLR
    6973           0 :                                     TempMaxPLR += 0.1;
    6974           0 :                                     HeatCoilLoad = thisFurnace.DesignHeatingCapacity * TempMaxPLR;
    6975           0 :                                     CalcFurnaceOutput(state,
    6976             :                                                       FurnaceNum,
    6977             :                                                       FirstHVACIteration,
    6978             :                                                       fanOp,
    6979             :                                                       compressorOp,
    6980             :                                                       0.0,
    6981             :                                                       TempMaxPLR,
    6982             :                                                       HeatCoilLoad,
    6983             :                                                       0.0,
    6984             :                                                       TempHeatOutput,
    6985             :                                                       TempLatentOutput,
    6986             :                                                       OnOffAirFlowRatio,
    6987             :                                                       false);
    6988             :                                 }
    6989           0 :                                 TempMinPLR = TempMaxPLR;
    6990           0 :                                 while ((TempHeatOutput - SystemSensibleLoad) > 0.0 && TempMinPLR > 0.0) {
    6991             :                                     //             pull upper limit of HeatingPLR down to last valid limit (i.e. heat output still exceeds
    6992             :                                     //             SystemSensibleLoad)
    6993           0 :                                     TempMaxPLR = TempMinPLR;
    6994             :                                     //             find minimum limit of HeatingPLR
    6995           0 :                                     TempMinPLR -= 0.01;
    6996             : 
    6997           0 :                                     HeatCoilLoad = thisFurnace.DesignHeatingCapacity * TempMinPLR;
    6998           0 :                                     CalcFurnaceOutput(state,
    6999             :                                                       FurnaceNum,
    7000             :                                                       FirstHVACIteration,
    7001             :                                                       fanOp,
    7002             :                                                       compressorOp,
    7003             :                                                       0.0,
    7004             :                                                       TempMinPLR,
    7005             :                                                       HeatCoilLoad,
    7006             :                                                       0.0,
    7007             :                                                       TempHeatOutput,
    7008             :                                                       TempLatentOutput,
    7009             :                                                       OnOffAirFlowRatio,
    7010             :                                                       false);
    7011             :                                 }
    7012             :                                 //           Now solve again with tighter PLR limits
    7013             :                                 auto f2 = // (AUTO_OK_LAMBDA)
    7014           0 :                                     [&state, FurnaceNum, FirstHVACIteration, fanOp, compressorOp, SystemSensibleLoad](Real64 const PartLoadRatio) {
    7015           0 :                                         return CalcFurnaceResidual(state,
    7016             :                                                                    PartLoadRatio,
    7017             :                                                                    FurnaceNum,
    7018             :                                                                    FirstHVACIteration,
    7019             :                                                                    fanOp,
    7020             :                                                                    compressorOp,
    7021             :                                                                    SystemSensibleLoad,
    7022             :                                                                    0.0,  // par6_loadFlag,
    7023             :                                                                    1.0,  // par7_sensLatentFlag,
    7024             :                                                                    0.0,  // par9_HXOnFlag,
    7025           0 :                                                                    0.0); // par10_HeatingCoilPLR);
    7026           0 :                                     };
    7027           0 :                                 General::SolveRoot(state, HeatErrorToler, MaxIter, SolFlag, PartLoadRatio, f2, TempMinPLR, TempMaxPLR);
    7028           0 :                                 if (state.dataFurnaces->ModifiedHeatCoilLoad > 0.0) {
    7029           0 :                                     HeatCoilLoad = state.dataFurnaces->ModifiedHeatCoilLoad;
    7030             :                                 } else {
    7031           0 :                                     HeatCoilLoad = thisFurnace.DesignHeatingCapacity * PartLoadRatio;
    7032             :                                 }
    7033           0 :                                 CalcFurnaceOutput(state,
    7034             :                                                   FurnaceNum,
    7035             :                                                   FirstHVACIteration,
    7036             :                                                   fanOp,
    7037             :                                                   compressorOp,
    7038             :                                                   0.0,
    7039             :                                                   PartLoadRatio,
    7040             :                                                   HeatCoilLoad,
    7041             :                                                   0.0,
    7042             :                                                   TempHeatOutput,
    7043             :                                                   TempLatentOutput,
    7044             :                                                   OnOffAirFlowRatio,
    7045             :                                                   false);
    7046             : 
    7047             :                                 //           After iterating with tighter boundaries, if still out of tolerance, show warning.
    7048           0 :                                 if (SolFlag == -1 && std::abs(SystemSensibleLoad - TempHeatOutput) > HVAC::SmallLoad) {
    7049           0 :                                     if (thisFurnace.HeatingMaxIterIndex == 0) {
    7050           0 :                                         ShowWarningMessage(state,
    7051           0 :                                                            format("Heating coil control failed to converge for {}:{}",
    7052           0 :                                                                   HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    7053           0 :                                                                   thisFurnace.Name));
    7054           0 :                                         ShowContinueError(state, "  Iteration limit exceeded in calculating heating coil sensible part-load ratio.");
    7055           0 :                                         ShowContinueErrorTimeStamp(state,
    7056           0 :                                                                    format("Sensible load to be met by heating coil = {:.2T} (watts), sensible output "
    7057             :                                                                           "of heating coil = {:.2T} (watts), and the simulation continues.",
    7058             :                                                                           SystemSensibleLoad,
    7059             :                                                                           TempHeatOutput));
    7060             :                                     }
    7061           0 :                                     ShowRecurringWarningErrorAtEnd(
    7062             :                                         state,
    7063           0 :                                         format("{} \"{}\" - Iteration limit exceeded in calculating sensible heating part-load "
    7064             :                                                "ratio error continues. Sensible load statistics:",
    7065           0 :                                                HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    7066           0 :                                                thisFurnace.Name),
    7067           0 :                                         thisFurnace.HeatingMaxIterIndex,
    7068             :                                         SystemSensibleLoad,
    7069             :                                         SystemSensibleLoad);
    7070             :                                 }
    7071      437277 :                             } else if (SolFlag == -2) {
    7072           0 :                                 if (thisFurnace.HeatingRegulaFalsiFailedIndex == 0) {
    7073           0 :                                     ShowWarningMessage(state,
    7074           0 :                                                        format("Heating coil control failed for {}:{}",
    7075           0 :                                                               HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    7076           0 :                                                               thisFurnace.Name));
    7077           0 :                                     ShowContinueError(state, "  Sensible heating part-load ratio determined to be outside the range of 0-1.");
    7078           0 :                                     ShowContinueErrorTimeStamp(
    7079             :                                         state,
    7080           0 :                                         format("Sensible load to be met by heating coil = {:.2T} (watts), and the simulation continues.",
    7081             :                                                SystemSensibleLoad));
    7082             :                                 }
    7083           0 :                                 ShowRecurringWarningErrorAtEnd(
    7084             :                                     state,
    7085           0 :                                     format("{} \"{}\" -  Sensible heating part-load ratio out of range error continues. Sensible load statistics:",
    7086           0 :                                            HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    7087           0 :                                            thisFurnace.Name),
    7088           0 :                                     thisFurnace.HeatingRegulaFalsiFailedIndex,
    7089             :                                     SystemSensibleLoad,
    7090             :                                     SystemSensibleLoad);
    7091             :                             }
    7092             :                         }
    7093             : 
    7094             :                     } else { // ELSE from IF(FullSensibleOutput.GT.NoSensibleOutput)THEN above
    7095             :                         // Set part load ratio to 1 and run heater at design heating capacity
    7096       55046 :                         PartLoadRatio = 1.0;
    7097       55046 :                         HeatCoilLoad = thisFurnace.DesignHeatingCapacity;
    7098             :                     }
    7099             : 
    7100             :                 } // End of IF HeatPump
    7101             : 
    7102             :             } // End of IF for heating
    7103             : 
    7104             :             // Non-heat pump systems do not set a heating PLR, set it here for use with the DX cooling coil calculations.
    7105             :             // Set this variable back to 0 for non-heat pump systems at the end of this routine.
    7106     3002440 :             thisFurnace.HeatPartLoadRatio = max(PartLoadRatio, thisFurnace.HeatPartLoadRatio);
    7107     3002440 :             CalcFurnaceOutput(state,
    7108             :                               FurnaceNum,
    7109             :                               FirstHVACIteration,
    7110             :                               fanOp,
    7111             :                               compressorOp,
    7112             :                               0.0,
    7113             :                               thisFurnace.HeatPartLoadRatio,
    7114             :                               HeatCoilLoad,
    7115             :                               0.0,
    7116             :                               HeatingSensibleOutput,
    7117             :                               HeatingLatentOutput,
    7118             :                               OnOffAirFlowRatio,
    7119             :                               false);
    7120             : 
    7121     5756598 :             if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_AirToAir ||
    7122     2754158 :                 (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir && thisFurnace.WatertoAirHPType == WAHPCoilType::Simple &&
    7123     1352600 :                  state.dataFurnaces->CoolingLoad)) {
    7124      938770 :                 HeatingSensibleOutput = 0.0;
    7125      938770 :                 HeatingLatentOutput = 0.0;
    7126             :             }
    7127             :             //***********Cooling Section*****************
    7128             :             // Simulate if scheduled ON and cooling load or if a moisture load exists when using a humidistat
    7129             :             // Check of HeatingLatentOutput is used to reduce overshoot during simultaneous heating and cooling
    7130             :             // Setback flag is used to avoid continued RH control when Tstat is setback (RH should float down)
    7131     4763470 :             if ((ScheduleManager::GetCurrentScheduleValue(state, thisFurnace.SchedPtr) > 0.0 && state.dataFurnaces->CoolingLoad) ||
    7132     1761030 :                 (thisFurnace.Humidistat && thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat &&
    7133      335771 :                  (SystemMoistureLoad < 0.0 || (SystemMoistureLoad >= 0.0 && HeatingLatentOutput > SystemMoistureLoad &&
    7134       10847 :                                                !state.dataZoneEnergyDemand->Setback(thisFurnace.ControlZoneNum))))) {
    7135             : 
    7136             :                 //     For cooling operation, the first step is to set the HX operation flag in case a HX assisted coil is used.
    7137             :                 //      (if a HX assisted coil is not used, this flag is not used. It's only used in the CALL to SimHXAssistedCoolingCoil)
    7138             :                 //     Check the dehumidification control type:
    7139             :                 //           For dehumidification control options CoolReheat and None, the HX is always active (locked ON).
    7140             :                 //           For dehumidification control option Multimode, the system is operated first with the HX off.
    7141             :                 //           If the moisture load is not met, the HX will then be turned on and the system is re-simulated.
    7142             : 
    7143     1402258 :                 if (thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat ||
    7144     1142919 :                     thisFurnace.DehumidControlType_Num == DehumidificationControlMode::None) {
    7145     1393818 :                     HXUnitOn = true;
    7146             :                 } else {
    7147        8440 :                     HXUnitOn = false;
    7148             :                 }
    7149             : 
    7150             :                 //     The next step is to determine the system output at no load (PLR=0) and full load (PLR=1)
    7151             : 
    7152             :                 //     Set the inlet mass flow rate based on user specified coil OFF flow rate
    7153     1402258 :                 PartLoadRatio = 0.0;
    7154             : 
    7155     1402258 :                 thisFurnace.CompPartLoadRatio = 0.0; // compressor off
    7156             : 
    7157             :                 //     SetAverageAirFlow calculates the operating mass flow rate based on PLR and the user specified inputs
    7158             :                 //     for MaxCoolAirMassFlow and MaxNoCoolHeatAirMassFlow.
    7159             :                 //     Air flow rate is set according to max of cooling and heating PLR if heating and latent load exists.
    7160      787692 :                 if (fanOp == HVAC::FanOp::Cycling && thisFurnace.HeatPartLoadRatio > 0.0 && thisFurnace.Humidistat &&
    7161     2189952 :                     thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat &&
    7162           2 :                     (SystemMoistureLoad < 0.0 || (SystemMoistureLoad >= 0.0 && HeatingLatentOutput > SystemMoistureLoad &&
    7163           0 :                                                   !state.dataZoneEnergyDemand->Setback(thisFurnace.ControlZoneNum)))) {
    7164           2 :                     CoolingHeatingPLRRatio = min(1.0, PartLoadRatio / thisFurnace.HeatPartLoadRatio);
    7165           2 :                     SetAverageAirFlow(state, FurnaceNum, max(PartLoadRatio, thisFurnace.HeatPartLoadRatio), OnOffAirFlowRatio);
    7166             : 
    7167             :                 } else {
    7168     1402256 :                     CoolingHeatingPLRRatio = 1.0;
    7169     1402256 :                     SetAverageAirFlow(state, FurnaceNum, PartLoadRatio, OnOffAirFlowRatio);
    7170             :                 }
    7171             : 
    7172             :                 // Get no load result (coils simulated OFF)
    7173     1402258 :                 CalcFurnaceOutput(state,
    7174             :                                   FurnaceNum,
    7175             :                                   FirstHVACIteration,
    7176             :                                   fanOp,
    7177             :                                   compressorOp,
    7178             :                                   MinPLR,
    7179             :                                   PartLoadRatio,
    7180             :                                   0.0,
    7181             :                                   0.0,
    7182             :                                   NoCoolOutput,
    7183             :                                   NoLatentOutput,
    7184             :                                   OnOffAirFlowRatio,
    7185     1402258 :                                   HXUnitOn,
    7186             :                                   CoolingHeatingPLRRatio);
    7187             : 
    7188             :                 //     Don't calculate full load output if no load output can meet sensible load
    7189     1402258 :                 if (NoCoolOutput >= CoolCoilLoad && (CoolCoilLoad != 0.0 || state.dataFurnaces->HPDehumidificationLoadFlag)) {
    7190             :                     //       Set full mass flow rate for full load calculation
    7191     1254656 :                     state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = thisFurnace.MdotFurnace;
    7192             : 
    7193             :                     // Set fan part-load fraction equal to 1 while getting full load result
    7194     1254656 :                     state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
    7195     1254656 :                     OnOffAirFlowRatio = 1.0;
    7196     1254656 :                     PartLoadRatio = 1.0;
    7197     1254656 :                     thisFurnace.CompPartLoadRatio = 1.0; // compressor ON
    7198             : 
    7199             :                     // Get full load result (coils simulated full ON)
    7200     1254656 :                     CalcFurnaceOutput(state,
    7201             :                                       FurnaceNum,
    7202             :                                       FirstHVACIteration,
    7203             :                                       fanOp,
    7204             :                                       compressorOp,
    7205             :                                       PartLoadRatio,
    7206             :                                       0.0,
    7207             :                                       0.0,
    7208             :                                       0.0,
    7209             :                                       FullSensibleOutput,
    7210             :                                       FullLatentOutput,
    7211             :                                       OnOffAirFlowRatio,
    7212     1254656 :                                       HXUnitOn);
    7213             :                 } else {
    7214      147602 :                     FullSensibleOutput = NoCoolOutput - 0.00000001;
    7215             :                 }
    7216             : 
    7217             :                 //     The next step is to compare the results of the full load and no load results
    7218             :                 //     1) Since we are cooling, we expect FullSensibleOutput < NoCoolOutput
    7219             :                 //        Check that this is the case; if not set PartLoadRatio = 0.0 (off)
    7220             :                 //     2) Verify that the load to be met is within the range of available output
    7221             :                 //        (i.e. between FullSensibleOutput and NoCoolOutput)
    7222             :                 //     3) Set PLR if load is out of range or RegulaFalsi on PLR if system can meet the load
    7223     1402258 :                 if (FullSensibleOutput < NoCoolOutput) {
    7224     1397548 :                     if (CoolCoilLoad != 0.0 || state.dataFurnaces->HPDehumidificationLoadFlag) {
    7225             : 
    7226             :                         // check bounds on sensible output prior to iteration using RegulaFalsi
    7227             :                         // Negative value represents cooling load, IF FullSensibleOutput .GT. CoolCoilLoad, load is greater than capacity
    7228     1252012 :                         if (FullSensibleOutput >= CoolCoilLoad) {
    7229      113274 :                             PartLoadRatio = 1.0;
    7230             :                             //           Likewise IF NoCoolOutput .LT. CoolCoilLoad, then load can be met using only the fan (constant fan mode only)
    7231     1138738 :                         } else if (NoCoolOutput <= CoolCoilLoad) {
    7232        2066 :                             PartLoadRatio = 0.0;
    7233             :                             //           ELSE load is between NoCoolOutput and FullSensibleOuput, find PLR required to meet load
    7234             :                         } else {
    7235             : 
    7236             :                             // Calculate the sensible part load ratio through iteration
    7237     1136672 :                             CoolErrorToler = thisFurnace.CoolingConvergenceTolerance; // Error tolerance for convergence from input deck
    7238     1136672 :                             int SolFlag = 0; // # of iterations if positive, -1 means failed to converge, -2 means bounds are incorrect
    7239     1136672 :                             Real64 par8_HXFlag = HXUnitOn ? 1.0 : 0.0;
    7240             :                             // CoolErrorToler is in fraction of load, MaxIter = 30, SolFalg = # of iterations or error as appropriate
    7241             :                             auto f =
    7242     5451712 :                                 [&state, FurnaceNum, FirstHVACIteration, fanOp, compressorOp, CoolCoilLoad, par8_HXFlag](Real64 const PartLoadRatio) {
    7243     4315040 :                                     return CalcFurnaceResidual(state,
    7244             :                                                                PartLoadRatio,
    7245             :                                                                FurnaceNum,
    7246             :                                                                FirstHVACIteration,
    7247             :                                                                fanOp,
    7248             :                                                                compressorOp,
    7249             :                                                                CoolCoilLoad,
    7250             :                                                                1.0,         // par6_loadFlag,
    7251             :                                                                1.0,         // par7_sensLatentFlag,
    7252             :                                                                par8_HXFlag, // par9_HXOnFlag,
    7253     4315040 :                                                                0.0);        // par10_HeatingCoilPLR);
    7254     1136672 :                                 };
    7255     1136672 :                             General::SolveRoot(state, CoolErrorToler, MaxIter, SolFlag, PartLoadRatio, f, 0.0, 1.0);
    7256             :                             //             OnOffAirFlowRatio is updated during the above iteration. Reset to correct value based on PLR.
    7257     1136672 :                             OnOffAirFlowRatio = state.dataFurnaces->OnOffAirFlowRatioSave;
    7258     1136672 :                             if (SolFlag < 0) {
    7259           0 :                                 if (SolFlag == -1) {
    7260           0 :                                     CalcFurnaceOutput(state,
    7261             :                                                       FurnaceNum,
    7262             :                                                       FirstHVACIteration,
    7263             :                                                       fanOp,
    7264             :                                                       compressorOp,
    7265             :                                                       PartLoadRatio,
    7266             :                                                       0.0,
    7267             :                                                       0.0,
    7268             :                                                       0.0,
    7269             :                                                       TempCoolOutput,
    7270             :                                                       TempLatentOutput,
    7271             :                                                       OnOffAirFlowRatio,
    7272           0 :                                                       HXUnitOn);
    7273           0 :                                     if (!state.dataGlobal->WarmupFlag) {
    7274           0 :                                         if (std::abs(CoolCoilLoad - TempCoolOutput) > HVAC::SmallLoad) {
    7275           0 :                                             if (thisFurnace.SensibleMaxIterIndex == 0) {
    7276           0 :                                                 ShowWarningMessage(state,
    7277           0 :                                                                    format("Cooling coil control failed to converge for {}:{}",
    7278           0 :                                                                           HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    7279           0 :                                                                           thisFurnace.Name));
    7280           0 :                                                 ShowContinueError(
    7281             :                                                     state, "  Iteration limit exceeded in calculating DX cooling coil sensible part-load ratio.");
    7282           0 :                                                 ShowContinueErrorTimeStamp(state,
    7283           0 :                                                                            format("Sensible load to be met by DX coil = {:.2T} (watts), sensible "
    7284             :                                                                                   "output of DX coil = {:.2T} (watts), and the simulation continues.",
    7285             :                                                                                   CoolCoilLoad,
    7286             :                                                                                   TempCoolOutput));
    7287             :                                             }
    7288           0 :                                             ShowRecurringWarningErrorAtEnd(
    7289             :                                                 state,
    7290           0 :                                                 format("{} \"{}\" - Iteration limit exceeded in calculating sensible cooling "
    7291             :                                                        "part-load ratio error continues. Sensible load statistics:",
    7292           0 :                                                        HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    7293           0 :                                                        thisFurnace.Name),
    7294           0 :                                                 thisFurnace.SensibleMaxIterIndex,
    7295             :                                                 CoolCoilLoad,
    7296             :                                                 CoolCoilLoad);
    7297             :                                         }
    7298             :                                     }
    7299           0 :                                 } else if (SolFlag == -2) {
    7300           0 :                                     if (!state.dataGlobal->WarmupFlag) {
    7301           0 :                                         if (thisFurnace.SensibleRegulaFalsiFailedIndex == 0) {
    7302           0 :                                             ShowWarningMessage(state,
    7303           0 :                                                                format("Cooling coil control failed for {}:{}",
    7304           0 :                                                                       HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    7305           0 :                                                                       thisFurnace.Name));
    7306           0 :                                             ShowContinueError(state, "  Cooling sensible part-load ratio determined to be outside the range of 0-1.");
    7307           0 :                                             ShowContinueErrorTimeStamp(state, format("  Cooling sensible load = {:.2T}", CoolCoilLoad));
    7308             :                                         }
    7309           0 :                                         ShowRecurringWarningErrorAtEnd(
    7310             :                                             state,
    7311           0 :                                             format("{} \"{}\" - Cooling sensible part-load ratio out of range error continues. Sensible cooling load "
    7312             :                                                    "statistics:",
    7313           0 :                                                    HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    7314           0 :                                                    thisFurnace.Name),
    7315           0 :                                             thisFurnace.SensibleRegulaFalsiFailedIndex,
    7316             :                                             CoolCoilLoad,
    7317             :                                             CoolCoilLoad);
    7318             :                                     }
    7319             :                                 }
    7320             :                             }
    7321             :                         }
    7322             : 
    7323             :                     } else {
    7324      145536 :                         PartLoadRatio = 0.0;
    7325             :                     } // EndIf for IF(CoolCoilLoad.NE.0.0)
    7326             : 
    7327             :                     //       Calculate the delivered capacity from the PLR caculated above
    7328     1397548 :                     CalcFurnaceOutput(state,
    7329             :                                       FurnaceNum,
    7330             :                                       FirstHVACIteration,
    7331             :                                       fanOp,
    7332             :                                       compressorOp,
    7333             :                                       PartLoadRatio,
    7334             :                                       thisFurnace.HeatPartLoadRatio,
    7335             :                                       0.0,
    7336             :                                       0.0,
    7337             :                                       TempCoolOutput,
    7338             :                                       TempLatentOutput,
    7339             :                                       OnOffAirFlowRatio,
    7340     1397548 :                                       HXUnitOn);
    7341             : 
    7342             :                     //       Calculate the latent part load ratio through iteration
    7343             :                     //       Negative SystemMoistureLoad means dehumidification load is present
    7344             :                     //       IF this furnace uses MultiMode control AND there is a moisture load AND the moisture load met by the furnace in
    7345             :                     //       cooling only mode above is sufficient to meet the moisture demand OR there is no sensible load (PLR=0 from above)
    7346             :                     //       then set LatentPartLoadRatio to 0 (no additional dehumidification is required).
    7347     1397548 :                     if (thisFurnace.DehumidControlType_Num == DehumidificationControlMode::Multimode &&
    7348        8440 :                         ((SystemMoistureLoad < 0.0 && TempLatentOutput < SystemMoistureLoad) || PartLoadRatio == 0.0)) {
    7349         634 :                         LatentPartLoadRatio = 0.0;
    7350             :                         //       ELSE calculate a new PLR for valid dehumidification control types if a moisture load exists.
    7351     1664029 :                     } else if (thisFurnace.DehumidControlType_Num != DehumidificationControlMode::None &&
    7352      267115 :                                (SystemMoistureLoad < 0.0 || (SystemMoistureLoad >= 0.0 && TempLatentOutput > SystemMoistureLoad &&
    7353        8816 :                                                              !state.dataZoneEnergyDemand->Setback(thisFurnace.ControlZoneNum)))) {
    7354             : 
    7355             :                         //         IF the furnace uses dehumidification control MultiMode, turn on the HX and calculate the latent output with
    7356             :                         //         the HX ON to compare to the moisture load predicted by the humidistat.
    7357      188058 :                         if (thisFurnace.DehumidControlType_Num == DehumidificationControlMode::Multimode) {
    7358        7580 :                             HXUnitOn = true;
    7359        7580 :                             state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = thisFurnace.MdotFurnace;
    7360             :                             // Set fan part-load fraction equal to 1 while getting full load result
    7361        7580 :                             state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
    7362        7580 :                             OnOffAirFlowRatio = 1.0;
    7363             :                             // Get full load result
    7364        7580 :                             CalcFurnaceOutput(state,
    7365             :                                               FurnaceNum,
    7366             :                                               FirstHVACIteration,
    7367             :                                               fanOp,
    7368             :                                               compressorOp,
    7369             :                                               1.0,
    7370             :                                               0.0,
    7371             :                                               0.0,
    7372             :                                               0.0,
    7373             :                                               TempCoolOutput,
    7374             :                                               TempLatentOutput,
    7375             :                                               OnOffAirFlowRatio,
    7376        7580 :                                               HXUnitOn);
    7377             :                         }
    7378             : 
    7379             :                         //         Set the global cooling to heating PLR ratio. CoolHeatPLRRat = MIN(1,CoolingPLR/HeatingPLR)
    7380      188058 :                         state.dataFurnaces->CoolHeatPLRRat = 1.0; // means cooling dominated operation (applies to cycling fan mode)
    7381             : 
    7382      188058 :                         if (TempLatentOutput > SystemMoistureLoad) {
    7383             :                             //           Set full mass flow rate for full load calculation
    7384      184495 :                             state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = thisFurnace.MdotFurnace;
    7385             : 
    7386             :                             // Set fan part-load fraction equal to 1 while getting full load result
    7387      184495 :                             state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
    7388      184495 :                             OnOffAirFlowRatio = 1.0;
    7389      184495 :                             thisFurnace.CompPartLoadRatio = 1.0; // compressor ON
    7390             : 
    7391             :                             // Get full load result (coils simulated full ON)
    7392      184495 :                             CalcFurnaceOutput(state,
    7393             :                                               FurnaceNum,
    7394             :                                               FirstHVACIteration,
    7395             :                                               fanOp,
    7396             :                                               compressorOp,
    7397             :                                               1.0,
    7398             :                                               0.0,
    7399             :                                               0.0,
    7400             :                                               0.0,
    7401             :                                               TempCoolOutput,
    7402             :                                               TempLatentOutput,
    7403             :                                               OnOffAirFlowRatio,
    7404      184495 :                                               HXUnitOn);
    7405             :                         }
    7406             : 
    7407             :                         // check bounds on latent output prior to iteration using RegulaFalsi
    7408      188058 :                         if (TempLatentOutput > SystemMoistureLoad ||
    7409       55180 :                             (thisFurnace.DehumidControlType_Num == DehumidificationControlMode::Multimode && TempCoolOutput > CoolCoilLoad)) {
    7410      132878 :                             LatentPartLoadRatio = 1.0;
    7411       55180 :                         } else if (NoLatentOutput < SystemMoistureLoad || HeatingLatentOutput < SystemMoistureLoad) {
    7412          94 :                             LatentPartLoadRatio = 0.0;
    7413             :                         } else {
    7414             : 
    7415       55086 :                             CoolErrorToler = thisFurnace.CoolingConvergenceTolerance; // Error tolerance for convergence
    7416             : 
    7417       55086 :                             int SolFlag = 0; // # of iterations if positive, -1 means failed to converge, -2 means bounds are incorrect
    7418             :                             // Multimode always controls to meet the SENSIBLE load (however, HXUnitOn is now TRUE)
    7419             :                             Real64 par4_load;
    7420       55086 :                             if (thisFurnace.DehumidControlType_Num == DehumidificationControlMode::Multimode) {
    7421         772 :                                 par4_load = CoolCoilLoad;
    7422             :                             } else {
    7423       54314 :                                 par4_load = SystemMoistureLoad;
    7424             :                             }
    7425             :                             // Multimode always controls to meet the SENSIBLE load (however, HXUnitOn is now TRUE)
    7426             :                             Real64 par6_LatentSens;
    7427       55086 :                             if (thisFurnace.DehumidControlType_Num == DehumidificationControlMode::Multimode) {
    7428         772 :                                 par6_LatentSens = 1.0;
    7429             :                             } else {
    7430       54314 :                                 par6_LatentSens = 0.0;
    7431             :                             }
    7432       55086 :                             Real64 par8_HXUnit = HXUnitOn ? 1.0 : 0.0;
    7433             :                             Real64 par9_HtgCoilPLR;
    7434       55086 :                             if (fanOp == HVAC::FanOp::Cycling && thisFurnace.HeatPartLoadRatio > 0.0 && par6_LatentSens == 0.0) {
    7435           0 :                                 par9_HtgCoilPLR = thisFurnace.HeatPartLoadRatio;
    7436             :                             } else {
    7437       55086 :                                 par9_HtgCoilPLR = 0.0;
    7438             :                             }
    7439      448688 :                             auto f = [&state,
    7440             :                                       FurnaceNum,
    7441             :                                       FirstHVACIteration,
    7442             :                                       fanOp,
    7443             :                                       compressorOp,
    7444             :                                       par4_load,
    7445             :                                       par6_LatentSens,
    7446             :                                       par8_HXUnit,
    7447      448688 :                                       par9_HtgCoilPLR](Real64 const PartLoadRatio) {
    7448      448688 :                                 return CalcFurnaceResidual(state,
    7449             :                                                            PartLoadRatio,
    7450             :                                                            FurnaceNum,
    7451             :                                                            FirstHVACIteration,
    7452             :                                                            fanOp,
    7453             :                                                            compressorOp,
    7454             :                                                            par4_load,
    7455             :                                                            1.0,              // par6_loadFlag,
    7456             :                                                            par6_LatentSens,  // par7_sensLatentFlag,
    7457             :                                                            par8_HXUnit,      // par9_HXOnFlag,
    7458      448688 :                                                            par9_HtgCoilPLR); // par10_HeatingCoilPLR);
    7459       55086 :                             };
    7460             :                             //           CoolErrorToler is in fraction of load, MaxIter = 30, SolFalg = # of iterations or error as appropriate
    7461       55086 :                             General::SolveRoot(state, CoolErrorToler, MaxIter, SolFlag, LatentPartLoadRatio, f, 0.0, 1.0);
    7462             :                             //           OnOffAirFlowRatio is updated during the above iteration. Reset to correct value based on PLR.
    7463       55086 :                             OnOffAirFlowRatio = state.dataFurnaces->OnOffAirFlowRatioSave;
    7464       55086 :                             if (SolFlag == -1) {
    7465             :                                 //             RegulaFalsi may not find latent PLR when the latent degradation model is used.
    7466             :                                 //             If iteration limit is exceeded, find tighter boundary of solution and repeat RegulaFalsi
    7467          98 :                                 TempMaxPLR = -0.1;
    7468          98 :                                 TempLatentOutput = NoLatentOutput;
    7469         498 :                                 while ((TempLatentOutput - SystemMoistureLoad) > 0.0 && TempMaxPLR < 1.0) {
    7470             :                                     //               find upper limit of LatentPLR
    7471         400 :                                     TempMaxPLR += 0.1;
    7472             : 
    7473             :                                     //               Same calculation as is done in Function CalcFurnaceResidual for latent PLR calculation.
    7474             :                                     //               Set cooling to heating PLR for use with Subroutine CalcFurnaceOutput. IF Par(10) = 0,
    7475             :                                     //               heating PLR = 0 so set the CoolingHeatingPLRRatio to 1 so the cooling PLR is used in the
    7476             :                                     //               DX cooling coil calculations.
    7477         400 :                                     if (par9_HtgCoilPLR > 0.0) {
    7478             :                                         //                 Par(10) = Furnace(FurnaceNum)%HeatPartLoadRatio
    7479             :                                         //                 fanOp = CycFan and Furnace(FurnaceNum)%HeatPartLoadRatio must be > 0 for Part(10) to be
    7480             :                                         //                 greater than 0
    7481           0 :                                         CoolingHeatingPLRRatio = min(1.0, TempMaxPLR / thisFurnace.HeatPartLoadRatio);
    7482             :                                     } else {
    7483         400 :                                         CoolingHeatingPLRRatio = 1.0;
    7484             :                                     }
    7485             : 
    7486         400 :                                     CalcFurnaceOutput(state,
    7487             :                                                       FurnaceNum,
    7488             :                                                       FirstHVACIteration,
    7489             :                                                       fanOp,
    7490             :                                                       compressorOp,
    7491             :                                                       TempMaxPLR,
    7492             :                                                       0.0,
    7493             :                                                       0.0,
    7494             :                                                       0.0,
    7495             :                                                       TempCoolOutput,
    7496             :                                                       TempLatentOutput,
    7497             :                                                       OnOffAirFlowRatio,
    7498         400 :                                                       HXUnitOn,
    7499             :                                                       CoolingHeatingPLRRatio);
    7500             :                                 }
    7501          98 :                                 TempMinPLR = TempMaxPLR;
    7502         876 :                                 while ((TempLatentOutput - SystemMoistureLoad) < 0.0 && TempMinPLR > 0.0) {
    7503             :                                     //               pull upper limit of LatentPLR down to last valid limit (i.e. latent output still exceeds
    7504             :                                     //               SystemMoisuterLoad) CR7558 - relax final limits to allow HX assisted coils to converge
    7505         778 :                                     TempMaxPLR = TempMinPLR + 0.001;
    7506             :                                     //               find minimum limit of Latent PLR
    7507         778 :                                     TempMinPLR -= 0.001;
    7508             : 
    7509             :                                     //               Set cooling to heating PLR for use with Subroutine CalcFurnaceOutput.
    7510         778 :                                     if (par9_HtgCoilPLR > 0.0) {
    7511             :                                         //                 Par(10) = Furnace(FurnaceNum)%HeatPartLoadRatio
    7512             :                                         //                 fanOp = CycFan and Furnace(FurnaceNum)%HeatPartLoadRatio must be > 0 for Part(10) to be
    7513             :                                         //                 greater than 0 Since the latent output of cycling fan systems is 0 at PLR=0, do not allow
    7514             :                                         //                 the PLR to be 0, otherwise RegulaFalsi can fail when a heating and moisture load exists and
    7515             :                                         //                 heating PLR > latent PLR.
    7516           0 :                                         TempMinPLR2 = max(0.0000000001, TempMinPLR);
    7517           0 :                                         CoolingHeatingPLRRatio = min(1.0, TempMinPLR2 / thisFurnace.HeatPartLoadRatio);
    7518             :                                     } else {
    7519         778 :                                         TempMinPLR2 = TempMinPLR;
    7520         778 :                                         CoolingHeatingPLRRatio = 1.0;
    7521             :                                     }
    7522             : 
    7523         778 :                                     CalcFurnaceOutput(state,
    7524             :                                                       FurnaceNum,
    7525             :                                                       FirstHVACIteration,
    7526             :                                                       fanOp,
    7527             :                                                       compressorOp,
    7528             :                                                       TempMinPLR2,
    7529             :                                                       0.0,
    7530             :                                                       0.0,
    7531             :                                                       0.0,
    7532             :                                                       TempCoolOutput,
    7533             :                                                       TempLatentOutput,
    7534             :                                                       OnOffAirFlowRatio,
    7535         778 :                                                       HXUnitOn,
    7536             :                                                       CoolingHeatingPLRRatio);
    7537             :                                 }
    7538             :                                 //             tighter boundary of solution has been found, call RegulaFalsi a second time
    7539         494 :                                 auto f2 = [&state,
    7540             :                                            FurnaceNum,
    7541             :                                            FirstHVACIteration,
    7542             :                                            fanOp,
    7543             :                                            compressorOp,
    7544             :                                            par4_load,
    7545             :                                            par6_LatentSens,
    7546             :                                            par8_HXUnit,
    7547         494 :                                            par9_HtgCoilPLR](Real64 const PartLoadRatio) {
    7548         494 :                                     return CalcFurnaceResidual(state,
    7549             :                                                                PartLoadRatio,
    7550             :                                                                FurnaceNum,
    7551             :                                                                FirstHVACIteration,
    7552             :                                                                fanOp,
    7553             :                                                                compressorOp,
    7554             :                                                                par4_load,
    7555             :                                                                1.0,              // par6_loadFlag,
    7556             :                                                                par6_LatentSens,  // par7_sensLatentFlag,
    7557             :                                                                par8_HXUnit,      // par9_HXOnFlag,
    7558         494 :                                                                par9_HtgCoilPLR); // par10_HeatingCoilPLR);
    7559          98 :                                 };
    7560          98 :                                 General::SolveRoot(state, CoolErrorToler, MaxIter, SolFlag, LatentPartLoadRatio, f2, TempMinPLR2, TempMaxPLR);
    7561             :                                 //             OnOffAirFlowRatio is updated during the above iteration. Reset to correct value based on PLR.
    7562          98 :                                 OnOffAirFlowRatio = state.dataFurnaces->OnOffAirFlowRatioSave;
    7563          98 :                                 if (SolFlag == -1) {
    7564             : 
    7565             :                                     //               Set cooling to heating PLR for use with Subroutine CalcFurnaceOutput.
    7566          48 :                                     if (par9_HtgCoilPLR > 0.0) {
    7567             :                                         //                 Par(10) = Furnace(FurnaceNum)%HeatPartLoadRatio
    7568             :                                         //                 fanOp = CycFan and Furnace(FurnaceNum)%HeatPartLoadRatio must be > 0 for Part(10) to be
    7569             :                                         //                 greater than 0
    7570           0 :                                         CoolingHeatingPLRRatio = min(1.0, LatentPartLoadRatio / thisFurnace.HeatPartLoadRatio);
    7571             :                                     } else {
    7572          48 :                                         CoolingHeatingPLRRatio = 1.0;
    7573             :                                     }
    7574             : 
    7575          48 :                                     CalcFurnaceOutput(state,
    7576             :                                                       FurnaceNum,
    7577             :                                                       FirstHVACIteration,
    7578             :                                                       fanOp,
    7579             :                                                       compressorOp,
    7580             :                                                       LatentPartLoadRatio,
    7581             :                                                       0.0,
    7582             :                                                       0.0,
    7583             :                                                       0.0,
    7584             :                                                       TempCoolOutput,
    7585             :                                                       TempLatentOutput,
    7586             :                                                       OnOffAirFlowRatio,
    7587          48 :                                                       HXUnitOn,
    7588             :                                                       CoolingHeatingPLRRatio);
    7589          96 :                                     if (std::abs((SystemMoistureLoad - TempLatentOutput) / SystemMoistureLoad) > CoolErrorToler &&
    7590          48 :                                         std::abs(SystemMoistureLoad - TempLatentOutput) > 10.0) {
    7591           0 :                                         if (!state.dataGlobal->WarmupFlag) {
    7592           0 :                                             if (thisFurnace.LatentMaxIterIndex == 0) {
    7593           0 :                                                 ShowWarningMessage(state,
    7594           0 :                                                                    format("Cooling coil control failed to converge for {}:{}",
    7595           0 :                                                                           HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    7596           0 :                                                                           thisFurnace.Name));
    7597           0 :                                                 ShowContinueError(state,
    7598             :                                                                   "  Iteration limit exceeded in calculating cooling coil latent part-load ratio.");
    7599           0 :                                                 ShowContinueError(
    7600             :                                                     state,
    7601           0 :                                                     format("  Latent load convergence error (percent) = {:.2T}",
    7602           0 :                                                            100.0 * std::abs((SystemMoistureLoad - TempLatentOutput) / SystemMoistureLoad)));
    7603           0 :                                                 ShowContinueErrorTimeStamp(state,
    7604           0 :                                                                            format("Moisture load to be met by DX coil = {:.2T} (watts), Latent "
    7605             :                                                                                   "output of DX coil = {:.2T} (watts), and the simulation continues.",
    7606             :                                                                                   SystemMoistureLoad,
    7607             :                                                                                   TempLatentOutput));
    7608             :                                             }
    7609           0 :                                             ShowRecurringWarningErrorAtEnd(
    7610             :                                                 state,
    7611           0 :                                                 format("{} \"{}\" - Iteration limit exceeded in calculating latent part-load ratio error continues. "
    7612             :                                                        "Latent "
    7613             :                                                        "load convergence error (percent) statistics follow.",
    7614           0 :                                                        HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    7615           0 :                                                        thisFurnace.Name),
    7616           0 :                                                 thisFurnace.LatentMaxIterIndex,
    7617           0 :                                                 100.0 * std::abs((SystemMoistureLoad - TempLatentOutput) / SystemMoistureLoad),
    7618           0 :                                                 100.0 * std::abs((SystemMoistureLoad - TempLatentOutput) / SystemMoistureLoad));
    7619             :                                         }
    7620             :                                     }
    7621          50 :                                 } else if (SolFlag == -2) {
    7622           0 :                                     if (thisFurnace.LatentRegulaFalsiFailedIndex2 == 0) {
    7623           0 :                                         ShowWarningMessage(state,
    7624           0 :                                                            format("Cooling coil control failed for {}:{}",
    7625           0 :                                                                   HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    7626           0 :                                                                   thisFurnace.Name));
    7627           0 :                                         ShowContinueError(state,
    7628           0 :                                                           format("  Latent part-load ratio determined to be outside the range of {:.3T} to {:.3T}.",
    7629             :                                                                  TempMinPLR,
    7630             :                                                                  TempMaxPLR));
    7631           0 :                                         ShowContinueErrorTimeStamp(state,
    7632           0 :                                                                    format("A PLR of {:.3T} will be used and the simulation continues.", TempMinPLR));
    7633             :                                     }
    7634           0 :                                     ShowRecurringWarningErrorAtEnd(state,
    7635           0 :                                                                    format("{} \"{}\" - Cooling sensible part-load ratio out of range error "
    7636             :                                                                           "continues. System moisture load statistics:",
    7637           0 :                                                                           HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    7638           0 :                                                                           thisFurnace.Name),
    7639           0 :                                                                    thisFurnace.LatentRegulaFalsiFailedIndex2,
    7640             :                                                                    SystemMoistureLoad,
    7641             :                                                                    SystemMoistureLoad);
    7642           0 :                                     LatentPartLoadRatio = TempMinPLR;
    7643             :                                 }
    7644       54988 :                             } else if (SolFlag == -2) {
    7645           0 :                                 if (thisFurnace.LatentRegulaFalsiFailedIndex == 0) {
    7646           0 :                                     ShowWarningMessage(state,
    7647           0 :                                                        format("Cooling coil control failed for {}:{}",
    7648           0 :                                                               HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    7649           0 :                                                               thisFurnace.Name));
    7650           0 :                                     ShowContinueError(state, "  Latent part-load ratio determined to be outside the range of 0-1.");
    7651           0 :                                     ShowContinueErrorTimeStamp(state, "A PLR of 0 will be used and the simulation continues.");
    7652             :                                 }
    7653           0 :                                 ShowRecurringWarningErrorAtEnd(
    7654             :                                     state,
    7655           0 :                                     format("{} \"{}\" - Latent part-load ratio out of range or 0-1 error continues. System moisture load statistics:",
    7656           0 :                                            HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    7657           0 :                                            thisFurnace.Name),
    7658           0 :                                     thisFurnace.LatentRegulaFalsiFailedIndex,
    7659             :                                     SystemMoistureLoad,
    7660             :                                     SystemMoistureLoad);
    7661           0 :                                 LatentPartLoadRatio = 0.0;
    7662             :                             }
    7663             :                         }
    7664             : 
    7665             :                         //         Cooling to heating PLR ratio is now known as CoolHeatPLRRat (Module level global set in CalcFurnaceOutput
    7666             :                         //         This same variable is use in Subroutine SimFurnace for final calculations.
    7667             :                         //         Get the actual output in case reheat needs to be calculated (HumControl=TRUE [latent PLR > sensible PLR])
    7668      188058 :                         CalcFurnaceOutput(state,
    7669             :                                           FurnaceNum,
    7670             :                                           FirstHVACIteration,
    7671             :                                           fanOp,
    7672             :                                           compressorOp,
    7673             :                                           LatentPartLoadRatio,
    7674             :                                           0.0,
    7675             :                                           0.0,
    7676             :                                           0.0,
    7677             :                                           ActualSensibleOutput,
    7678             :                                           ActualLatentOutput,
    7679             :                                           OnOffAirFlowRatio,
    7680      188058 :                                           HXUnitOn,
    7681      188058 :                                           state.dataFurnaces->CoolHeatPLRRat);
    7682             : 
    7683             :                     } else {
    7684     1208856 :                         LatentPartLoadRatio = 0.0;
    7685             :                     } // ENDIF for valid dehumidification control types
    7686             : 
    7687             :                     //       IF a humidistat is used and there is a moisture load, check if the latent PLR is greater than the (sensible) PLR
    7688             :                     //        IF(LatentPartLoadRatio .GT. PartLoadRatio .and. SystemMoistureLoad .lt. 0.0 .and. Furnace(FurnaceNum)%Humidistat) THEN
    7689     1397548 :                     if (LatentPartLoadRatio > PartLoadRatio && thisFurnace.Humidistat) {
    7690             :                         // For dehumidification mode CoolReheat, compare the Sensible and Latent PLR values, if latentPLR is greater
    7691             :                         // than PLR (sensible), then overcooling is required and reheat will be activated using the HumControl flag.
    7692      185083 :                         if (thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat) {
    7693      177589 :                             PartLoadRatio = LatentPartLoadRatio;
    7694      177589 :                             HumControl = true;
    7695             :                         }
    7696             :                         // For dehumidification mode MultiMode, compare the Sensible and Latent PLR values, if latentPLR is
    7697             :                         // greater than PLR (sensible), then use the latent PLR to control the unit.
    7698             :                         // For MultiMode control, the latent PLR is found by enabling the HX and calculating a PLR required to meet the
    7699             :                         // sensible load. Overcooling is not required, and reheat will not be activated using the HumControl flag.
    7700      185083 :                         if (thisFurnace.DehumidControlType_Num == DehumidificationControlMode::Multimode) {
    7701        7494 :                             PartLoadRatio = LatentPartLoadRatio;
    7702             :                         }
    7703             :                     }
    7704             : 
    7705     1397548 :                     thisFurnace.CoolPartLoadRatio = PartLoadRatio;
    7706     1397548 :                     if (compressorOp == HVAC::CompressorOp::Off) {
    7707        4090 :                         thisFurnace.CompPartLoadRatio = 0.0;
    7708             :                     } else {
    7709     1393458 :                         thisFurnace.CompPartLoadRatio = PartLoadRatio;
    7710             :                     }
    7711             : 
    7712             :                 } else { // ELSE from IF(FullSensibleOutput.LT.NoCoolOutput)THEN above
    7713             :                     // CR8679 - Unitary Heat Cool control problem, will not run to meeting cooling load
    7714             :                     // underlying problem is that FullSensibleOutput is greater than 0 due to very high inlet temp, so the system should be on
    7715             :                     // NoCoolOutput was 0 since the defect file is a cycling fan system and the system was turned off
    7716             : 
    7717             :                     // if FullSensibleOutput > NoCoolOutput, it means the system cannot meet the load and will run full out
    7718             :                     // this same logic for WSHP does not seem to work (only the Unitary Heat Pump Compressor Part-Load Ratio report
    7719             :                     // variable was affected in the HeatPumpWaterToAirRHControl.idf file while other variables showed very small diffs).
    7720             :                     // The defect files meter.csv showed 2% diffs so this IF test is used to keep the results the same in that file.
    7721             :                     // Additional logic is used here to make sure the coil actually turned on, e.g., if DX coil PLR > 0 then set to 1,
    7722             :                     // otherwise 0 (to make sure coil is actually ON and not off due to schedule, OAT, or other reason).
    7723             :                     // The global variable DXCoilPartLoadRatio(DXCoilNum) is not yet used for the WSHP to make the same check.
    7724        4710 :                     if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir) {
    7725         230 :                         thisFurnace.CoolPartLoadRatio = 0.0;
    7726         230 :                         thisFurnace.CompPartLoadRatio = 0.0;
    7727             :                     } else {
    7728        4480 :                         if (thisFurnace.CoolingCoilType_Num == HVAC::CoilDX_CoolingHXAssisted) {
    7729             : 
    7730             :                             // VS coil issue here...
    7731           0 :                             if (state.dataDXCoils->DXCoilPartLoadRatio(thisFurnace.ActualDXCoilIndexForHXAssisted) > 0.0) {
    7732           0 :                                 thisFurnace.CoolPartLoadRatio = 1.0;
    7733           0 :                                 thisFurnace.CompPartLoadRatio = 1.0;
    7734             :                             } else {
    7735           0 :                                 thisFurnace.CoolPartLoadRatio = 0.0;
    7736           0 :                                 thisFurnace.CompPartLoadRatio = 0.0;
    7737             :                             }
    7738             :                         } else {
    7739        4480 :                             if (state.dataDXCoils->DXCoilPartLoadRatio(thisFurnace.CoolingCoilIndex) > 0.0) {
    7740           0 :                                 thisFurnace.CoolPartLoadRatio = 1.0;
    7741           0 :                                 thisFurnace.CompPartLoadRatio = 1.0;
    7742             :                             } else {
    7743        4480 :                                 thisFurnace.CoolPartLoadRatio = 0.0;
    7744        4480 :                                 thisFurnace.CompPartLoadRatio = 0.0;
    7745             :                             }
    7746             :                         }
    7747             :                     }
    7748             :                 }
    7749             : 
    7750             :                 //     Calculate the reheat coil output
    7751     1402258 :                 if (HumControl) { // HumControl = .TRUE. if a Humidistat is installed and dehumdification control type is CoolReheat
    7752      177589 :                     if (thisFurnace.ZoneSequenceHeatingNum > 0) {
    7753      177589 :                         QToHeatSetPt = (state.dataZoneEnergyDemand->ZoneSysEnergyDemand(thisFurnace.ControlZoneNum)
    7754      177589 :                                             .SequencedOutputRequiredToHeatingSP(thisFurnace.ZoneSequenceHeatingNum) /
    7755      177589 :                                         thisFurnace.ControlZoneMassFlowFrac);
    7756             :                     } else {
    7757           0 :                         QToHeatSetPt = (state.dataZoneEnergyDemand->ZoneSysEnergyDemand(thisFurnace.ControlZoneNum).OutputRequiredToHeatingSP /
    7758           0 :                                         thisFurnace.ControlZoneMassFlowFrac);
    7759             :                     }
    7760             :                     //       Cooling mode or floating condition and dehumidification is required
    7761      177589 :                     if (QToHeatSetPt < 0.0) {
    7762             :                         //         Calculate the reheat coil load wrt the heating setpoint temperature. Reheat coil picks up
    7763             :                         //         the entire excess sensible cooling (DX cooling coil and impact of outdoor air).
    7764      165238 :                         ReheatCoilLoad = max(0.0, (QToHeatSetPt - ActualSensibleOutput));
    7765      165238 :                         thisFurnace.DehumidInducedHeatingDemandRate = ReheatCoilLoad;
    7766             :                         //       Heating mode and dehumidification is required
    7767             :                     } else {
    7768             :                         //         Calculate the reheat coil load as the sensible capacity of the DX cooling coil only. Let
    7769             :                         //         the heating coil pick up the load due to outdoor air.
    7770       12351 :                         ReheatCoilLoad = max(0.0, (ActualSensibleOutput - NoCoolOutput) * (-1.0));
    7771             :                         //         Dehumidification is not required
    7772       12351 :                         if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_AirToAir ||
    7773       10293 :                             (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir &&
    7774        7122 :                              thisFurnace.WatertoAirHPType == WAHPCoilType::Simple)) {
    7775        9180 :                             ReheatCoilLoad = max(QToHeatSetPt, QToHeatSetPt - ActualSensibleOutput);
    7776             :                         }
    7777       12351 :                         thisFurnace.DehumidInducedHeatingDemandRate = max(0.0, ActualSensibleOutput * (-1.0));
    7778             :                     }
    7779             :                 } else {
    7780             :                     //       No humidistat installed
    7781     1224669 :                     ReheatCoilLoad = 0.0;
    7782             :                 }
    7783             :             } // End of cooling section IF statement
    7784             : 
    7785     3002440 :             if (NoHeatOutput > SystemSensibleLoad && ReheatCoilLoad > 0.0) {
    7786             :                 // Reduce reheat coil load if you are controlling high humidity but outside air
    7787             :                 // and/or the supply air fan is providing enough heat to meet the system sensible load.
    7788             :                 // This will bring the zone temp closer to the heating setpoint temp.
    7789           0 :                 ReheatCoilLoad = max(0.0, ReheatCoilLoad - (NoHeatOutput - SystemSensibleLoad));
    7790             :             }
    7791             : 
    7792             :             // Set the final air flow. MdotFurnace will be used to set the fan part-load ratio in ReportFurnace
    7793     3002440 :             if (HumControl && SystemMoistureLoad < 0.0) {
    7794      169165 :                 if (fanOp == HVAC::FanOp::Cycling) {
    7795             :                     //       set the flow rate at the maximum of the cooling and heating PLR's
    7796         420 :                     SetAverageAirFlow(state, FurnaceNum, max(thisFurnace.CoolPartLoadRatio, thisFurnace.HeatPartLoadRatio), OnOffAirFlowRatio);
    7797             :                 } else {
    7798             :                     //       ELSE set the flow rate at the cooling PLR
    7799      168745 :                     SetAverageAirFlow(state, FurnaceNum, thisFurnace.CoolPartLoadRatio, OnOffAirFlowRatio);
    7800             :                 }
    7801             :             } else {
    7802     2833275 :                 SetAverageAirFlow(state, FurnaceNum, max(thisFurnace.CoolPartLoadRatio, thisFurnace.HeatPartLoadRatio), OnOffAirFlowRatio);
    7803             :             }
    7804     3002440 :             thisFurnace.MdotFurnace = state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate;
    7805             : 
    7806     3002440 :             if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_AirToAir ||
    7807     2754158 :                 (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir && thisFurnace.WatertoAirHPType == WAHPCoilType::Simple)) {
    7808             :             } else {
    7809             :                 // Non-HeatPump (non-DX) heating coils do not set PLR, reset to 0 here. This variable was set for non-DX
    7810             :                 // coils to allow the SetAverageAirFlow CALL above to set the correct air mass flow rate. See this
    7811             :                 // IF block above in heating section. HeatPLR is not set in the ELSE part of the IF (only HeatCoilLoad is set).
    7812     1401558 :                 thisFurnace.HeatPartLoadRatio = 0.0;
    7813             :             }
    7814             : 
    7815             :             //*********HVAC Scheduled OFF*************
    7816             :             // No heating or cooling or dehumidification
    7817             :             //!!LKL discrepancy with < 0?
    7818     5927599 :             if (ScheduleManager::GetCurrentScheduleValue(state, thisFurnace.SchedPtr) == 0.0 ||
    7819     2925159 :                 state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate == 0.0) {
    7820      248712 :                 thisFurnace.MdotFurnace = 0.0;
    7821      248712 :                 CoolCoilLoad = 0.0;
    7822      248712 :                 HeatCoilLoad = 0.0;
    7823      248712 :                 ReheatCoilLoad = 0.0;
    7824      248712 :                 state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0; // System off, so set on/off fan part-load fraction = 1
    7825      248712 :                 thisFurnace.CoolPartLoadRatio = 0.0;
    7826      248712 :                 thisFurnace.HeatPartLoadRatio = 0.0;
    7827      248712 :                 thisFurnace.CompPartLoadRatio = 0.0;
    7828             :                 // set report variables
    7829      248712 :                 thisFurnace.CoolingCoilSensDemand = 0.0;
    7830      248712 :                 thisFurnace.CoolingCoilLatentDemand = 0.0;
    7831      248712 :                 thisFurnace.HeatingCoilSensDemand = 0.0;
    7832             :             }
    7833             : 
    7834             :         } // End of the FirstHVACIteration control of the mass flow If block
    7835             : 
    7836             :         // Set the fan inlet node flow rates
    7837     4597475 :         state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRateMaxAvail = thisFurnace.MdotFurnace;
    7838     4597475 :         state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = thisFurnace.MdotFurnace;
    7839     4597475 :     }
    7840             : 
    7841      119270 :     void CalcWaterToAirHeatPump(EnergyPlusData &state,
    7842             :                                 int const FurnaceNum,                  // index to Furnace
    7843             :                                 bool const FirstHVACIteration,         // TRUE on first HVAC iteration
    7844             :                                 HVAC::CompressorOp const compressorOp, // compressor operation flag (1=On, 0=Off)
    7845             :                                 Real64 const ZoneLoad,                 // the control zone load (watts)
    7846             :                                 Real64 const MoistureLoad              // the control zone latent load (watts)
    7847             :     )
    7848             :     {
    7849             : 
    7850             :         // SUBROUTINE INFORMATION:
    7851             :         //       AUTHOR         Dan Fisher
    7852             :         //       DATE WRITTEN   Feb 2004
    7853             :         //       MODIFIED       R. Raustad (Oct 2006) Revised iteration technique
    7854             : 
    7855             :         // PURPOSE OF THIS SUBROUTINE:
    7856             :         // This subroutine manages the heat pump simulation
    7857             : 
    7858             :         // METHODOLOGY EMPLOYED:
    7859             :         // Calculate the part-load ratio required to meet the zone sensible load.
    7860             : 
    7861             :         // SUBROUTINE PARAMETER DEFINITIONS:
    7862      119270 :         int constexpr MaxIter(600);   // maximum number of iterations
    7863      119270 :         Real64 constexpr MinPLR(0.0); // minimum part load ratio allowed
    7864             : 
    7865             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    7866             :         Real64 ZoneSensLoadMet;             // Actual zone sensible load met by heat pump (W)
    7867             :         Real64 ZoneLatLoadMet;              // Actual zone latent load met by heat pump (W)
    7868             :         Real64 ZoneSensLoadMetFanONCompON;  // Max Zone sensible load heat pump can meet (W)
    7869             :         Real64 ZoneLatLoadMetFanONCompON;   // Max Zone latentload heat pump can meet (W)
    7870             :         Real64 ZoneSensLoadMetFanONCompOFF; // control zone sensible load met using only outside air
    7871             :         // and fan heat (no coil output) (W)
    7872             :         Real64 ZoneLatLoadMetFanONCompOFF; // control zone Latent   load met using only outside air
    7873             :         // and fan heat (no coil output) (W)
    7874             :         Real64 HPCoilSensDemand;   // Heat pump sensible demand
    7875             :         Real64 HPCoilSensCapacity; // Heat pump sensible capacity
    7876             : 
    7877             :         Real64 SuppHeatCoilLoad; // Load passed to supplemental heater (W)
    7878             :         Real64 CoolErrorToler;   // convergence tolerance used in cooling mode
    7879             :         Real64 HeatErrorToler;   // convergence tolerance used in heating mode
    7880             :         int SolFlag;             // flag returned from iteration routine to denote problems
    7881             : 
    7882      119270 :         Real64 &TotalZoneLatentLoad = state.dataFurnaces->TotalZoneLatentLoad;
    7883      119270 :         Real64 &TotalZoneSensLoad = state.dataFurnaces->TotalZoneSensLoad;
    7884      119270 :         Real64 &CoolPartLoadRatio = state.dataFurnaces->CoolPartLoadRatio;
    7885      119270 :         Real64 &HeatPartLoadRatio = state.dataFurnaces->HeatPartLoadRatio;
    7886      119270 :         auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    7887             : 
    7888             :         // Set local variables
    7889      119270 :         Real64 Dummy2 = 0.0;            // used as dummy heat and reheat coil load
    7890      119270 :         Real64 OnOffAirFlowRatio = 1.0; // Ratio of compressor ON air mass flow to AVERAGE air mass flow over time step
    7891      119270 :         int FurnaceInletNode = thisFurnace.FurnaceInletNodeNum;
    7892      119270 :         HVAC::FanOp fanOp = thisFurnace.fanOp; // fan operting mode
    7893      119270 :         thisFurnace.MdotFurnace = thisFurnace.DesignMassFlowRate;
    7894             : 
    7895             :         //*********INITIAL CALCULATIONS****************
    7896             :         // set the fan part load fraction
    7897             :         // Note: OnOffFanPartLoadFraction is passed to the
    7898             :         //       fan module by DataHVACGlobals.  It should be
    7899             :         //     set =1 for all cases except cycling fan/cycling
    7900             :         //     coil. For this case it is set to the part load
    7901             :         //     factor.  In SimOnOffFan, the part load ratio is
    7902             :         //     divided by the part load factor (OnOffFanPartLoadFraction)
    7903             :         //     in order to match the run time fraction of the cycling
    7904             :         //     fan with the run time fraction of the cycling compressor
    7905      119270 :         if (FirstHVACIteration) state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
    7906             : 
    7907             :         // Calc Zone sensible loads for heating (+) and cooling (-)
    7908      119270 :         TotalZoneSensLoad = ZoneLoad;
    7909             : 
    7910      119270 :         if (state.dataFurnaces->HeatingLoad) {
    7911       55271 :             TotalZoneLatentLoad = 0.0; // Set latent load for heating
    7912             :         } else {
    7913       63999 :             TotalZoneLatentLoad = MoistureLoad; // Set latent load for cooling and no sensible load condition
    7914             :         }
    7915             : 
    7916             :         //*********COOLING CALCULATIONS****************
    7917             :         // IF scheduled on...
    7918             :         // AND air flow rate is greater than zero...
    7919             :         // AND the air system has a cooling load and is not set back or in the deadband...
    7920             :         // OR the system is controlled by a humidistat and there is a latent load
    7921      119270 :         if ((ScheduleManager::GetCurrentScheduleValue(state, thisFurnace.SchedPtr) > 0.0 &&
    7922      212252 :              state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate > 0.0) &&
    7923       92982 :             ((state.dataFurnaces->CoolingLoad) || (thisFurnace.Humidistat && thisFurnace.CoolingCoilLatentDemand < 0.0))) {
    7924             : 
    7925             :             // Set the air flow rate to the design flow rate and set the fan operation fraction to 1 (continuous operation)
    7926       37711 :             state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = thisFurnace.DesignMassFlowRate;
    7927       37711 :             state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0; // see 'Note' under INITIAL CALCULATIONS
    7928             : 
    7929             :             //         !Set the operation flag to run the fan continuously
    7930             :             //         fanOp = FanOp::Continuous
    7931             : 
    7932             :             // Set the input parameters for CalcFurnaceOutput
    7933       37711 :             thisFurnace.HeatingCoilSensDemand = 0.0;
    7934       37711 :             thisFurnace.CoolingCoilLatentDemand = 0.0;
    7935       37711 :             thisFurnace.CoolingCoilSensDemand = 0.0;
    7936       37711 :             thisFurnace.CompPartLoadRatio = 0.0; // compressor off
    7937       37711 :             thisFurnace.InitHeatPump = true;     // initialization call to Calc Furnace
    7938       37711 :             CoolPartLoadRatio = 0.0;
    7939             : 
    7940             :             // Get no load result in order to calculate the effect of the fan and the mixed air equipment
    7941       37711 :             CalcFurnaceOutput(state,
    7942             :                               FurnaceNum,
    7943             :                               FirstHVACIteration,
    7944             :                               fanOp,
    7945             :                               compressorOp,
    7946             :                               CoolPartLoadRatio,
    7947             :                               HeatPartLoadRatio,
    7948             :                               Dummy2,
    7949             :                               Dummy2,
    7950             :                               ZoneSensLoadMetFanONCompOFF,
    7951             :                               ZoneLatLoadMetFanONCompOFF,
    7952             :                               OnOffAirFlowRatio,
    7953             :                               false);
    7954             : 
    7955             :             // Set the input parameters for CalcFurnaceOutput
    7956       37711 :             thisFurnace.CoolingCoilSensDemand = 1.0;
    7957       37711 :             thisFurnace.CompPartLoadRatio = 1.0; // compressor ON
    7958       37711 :             CoolPartLoadRatio = 1.0;
    7959             : 
    7960             :             // Get full load result in order to estimate the operating part load ratio for continuous fan operation
    7961       37711 :             CalcFurnaceOutput(state,
    7962             :                               FurnaceNum,
    7963             :                               FirstHVACIteration,
    7964             :                               fanOp,
    7965             :                               compressorOp,
    7966             :                               CoolPartLoadRatio,
    7967             :                               HeatPartLoadRatio,
    7968             :                               Dummy2,
    7969             :                               Dummy2,
    7970             :                               ZoneSensLoadMetFanONCompON,
    7971             :                               ZoneLatLoadMetFanONCompON,
    7972             :                               OnOffAirFlowRatio,
    7973             :                               false);
    7974             : 
    7975             :             // Calculate the heating coil demand for continuous fan operation as:
    7976             :             //    (the zone sensible load - the zone sensible load met by fan heat and mixed air)
    7977             :             // Note; The sensible zone load met by fan heat and mixed air is calculated as:
    7978             :             //     mdotsys(control zone inlet enthalpy - control zone outlet enthalpy)
    7979             :             // This accounts for the negative sign in the equation.
    7980       37711 :             HPCoilSensDemand = TotalZoneSensLoad - ZoneSensLoadMetFanONCompOFF;
    7981             : 
    7982             :             // Calculate the heating coil capacity for continuous fan operation as:
    7983             :             //    (the zone sensible load met by fan heat and mixed air and coil
    7984             :             //   - the zone sensible load met by fan heat and mixed air)
    7985       37711 :             HPCoilSensCapacity = ZoneSensLoadMetFanONCompON - ZoneSensLoadMetFanONCompOFF;
    7986             : 
    7987             :             // Calculate the part load ratio for continuous fan operation with cycling coil
    7988       37711 :             if (HPCoilSensCapacity == 0.0) {
    7989           0 :                 CoolPartLoadRatio = 0.0;
    7990             :             } else {
    7991       37711 :                 CoolPartLoadRatio = max(MinPLR, min(1.0, std::abs(HPCoilSensDemand) / std::abs(HPCoilSensCapacity)));
    7992             :             }
    7993             : 
    7994       37711 :             thisFurnace.InitHeatPump = false;
    7995             : 
    7996             :             // check bounds on sensible output prior to iteration using RegulaFalsi
    7997       37711 :             if (ZoneSensLoadMetFanONCompON > TotalZoneSensLoad) {
    7998        2160 :                 CoolPartLoadRatio = 1.0;
    7999        2160 :                 HPCoilSensDemand = std::abs(ZoneSensLoadMetFanONCompON - ZoneSensLoadMetFanONCompOFF);
    8000        2160 :                 thisFurnace.CoolingCoilSensDemand = HPCoilSensDemand;
    8001       35551 :             } else if (ZoneSensLoadMetFanONCompOFF < TotalZoneSensLoad) {
    8002           0 :                 CoolPartLoadRatio = 0.0;
    8003           0 :                 thisFurnace.CompPartLoadRatio = 0.0; // compressor OFF
    8004           0 :                 thisFurnace.CoolingCoilSensDemand = 0.0;
    8005           0 :                 CalcFurnaceOutput(state,
    8006             :                                   FurnaceNum,
    8007             :                                   FirstHVACIteration,
    8008             :                                   fanOp,
    8009             :                                   compressorOp,
    8010             :                                   CoolPartLoadRatio,
    8011             :                                   HeatPartLoadRatio,
    8012             :                                   Dummy2,
    8013             :                                   Dummy2,
    8014             :                                   ZoneSensLoadMetFanONCompOFF,
    8015             :                                   ZoneLatLoadMetFanONCompOFF,
    8016             :                                   OnOffAirFlowRatio,
    8017             :                                   false);
    8018             :             } else {
    8019             :                 //         Calculate the sensible part load ratio through iteration
    8020       35551 :                 CoolErrorToler = thisFurnace.CoolingConvergenceTolerance;
    8021       35551 :                 SolFlag = 0; // # of iterations if positive, -1 means failed to converge, -2 means bounds are incorrect
    8022             :                 // CoolErrorToler is in fraction of load, MaxIter = 600, SolFalg = # of iterations or error as appropriate
    8023      143703 :                 auto f = [&state, FurnaceNum, FirstHVACIteration, fanOp, compressorOp, TotalZoneSensLoad, ZoneSensLoadMetFanONCompOFF](
    8024      108152 :                              Real64 const PartLoadRatio) {
    8025      108152 :                     return CalcWaterToAirResidual(state,
    8026             :                                                   PartLoadRatio,
    8027             :                                                   FurnaceNum,
    8028             :                                                   FirstHVACIteration,
    8029             :                                                   fanOp,
    8030             :                                                   compressorOp,
    8031             :                                                   TotalZoneSensLoad,
    8032             :                                                   1.0,
    8033             :                                                   1.0,
    8034             :                                                   ZoneSensLoadMetFanONCompOFF,
    8035      108152 :                                                   0.0);
    8036       35551 :                 };
    8037       35551 :                 General::SolveRoot(state, CoolErrorToler, MaxIter, SolFlag, CoolPartLoadRatio, f, 0.0, 1.0);
    8038       35551 :                 if (SolFlag == -1 && !state.dataGlobal->WarmupFlag && !FirstHVACIteration) {
    8039          13 :                     state.dataHVACGlobal->OnOffFanPartLoadFraction = state.dataFurnaces->OnOffFanPartLoadFractionSave;
    8040          13 :                     CalcFurnaceOutput(state,
    8041             :                                       FurnaceNum,
    8042             :                                       FirstHVACIteration,
    8043             :                                       fanOp,
    8044             :                                       compressorOp,
    8045             :                                       CoolPartLoadRatio,
    8046             :                                       0.0,
    8047             :                                       0.0,
    8048             :                                       0.0,
    8049             :                                       ZoneSensLoadMet,
    8050             :                                       ZoneLatLoadMet,
    8051             :                                       OnOffAirFlowRatio,
    8052             :                                       false);
    8053          13 :                     if (std::abs(ZoneSensLoadMet - TotalZoneSensLoad) / TotalZoneSensLoad > CoolErrorToler) {
    8054           0 :                         if (thisFurnace.SensibleMaxIterIndex == 0) {
    8055           0 :                             ShowWarningMessage(state,
    8056           0 :                                                format("Cooling coil control failed to converge for {}:{}",
    8057           0 :                                                       HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    8058           0 :                                                       thisFurnace.Name));
    8059           0 :                             ShowContinueError(state, "  Iteration limit exceeded in calculating DX cooling coil sensible part-load ratio.");
    8060           0 :                             ShowContinueErrorTimeStamp(state,
    8061           0 :                                                        format("Sensible load to be met by DX coil = {:.2T} (watts), sensible output of DX coil = "
    8062             :                                                               "{:.2T} (watts), and the simulation continues.",
    8063             :                                                               TotalZoneSensLoad,
    8064             :                                                               ZoneSensLoadMet));
    8065             :                         }
    8066           0 :                         ShowRecurringWarningErrorAtEnd(
    8067             :                             state,
    8068           0 :                             format("{} \"{}\" - Iteration limit exceeded in calculating sensible cooling part-load ratio error "
    8069             :                                    "continues. Sensible load statistics:",
    8070           0 :                                    HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    8071           0 :                                    thisFurnace.Name),
    8072           0 :                             thisFurnace.SensibleMaxIterIndex,
    8073             :                             TotalZoneSensLoad,
    8074             :                             TotalZoneSensLoad);
    8075             :                     }
    8076       35538 :                 } else if (SolFlag == -2 && !state.dataGlobal->WarmupFlag && !FirstHVACIteration) {
    8077           0 :                     CoolPartLoadRatio = max(MinPLR, min(1.0, std::abs(HPCoilSensDemand) / std::abs(HPCoilSensCapacity)));
    8078           0 :                     state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
    8079           0 :                     CalcFurnaceOutput(state,
    8080             :                                       FurnaceNum,
    8081             :                                       FirstHVACIteration,
    8082             :                                       fanOp,
    8083             :                                       compressorOp,
    8084             :                                       CoolPartLoadRatio,
    8085             :                                       0.0,
    8086             :                                       0.0,
    8087             :                                       0.0,
    8088             :                                       ZoneSensLoadMet,
    8089             :                                       ZoneLatLoadMet,
    8090             :                                       OnOffAirFlowRatio,
    8091             :                                       false);
    8092           0 :                     if ((ZoneSensLoadMet - TotalZoneSensLoad) / TotalZoneSensLoad > CoolErrorToler) {
    8093           0 :                         if (thisFurnace.SensibleRegulaFalsiFailedIndex == 0) {
    8094           0 :                             ShowWarningMessage(
    8095             :                                 state,
    8096           0 :                                 format("Cooling coil control failed for {}:{}", HVAC::unitarySysTypeNames[(int)thisFurnace.type], thisFurnace.Name));
    8097           0 :                             ShowContinueError(state, "  Cooling sensible part-load ratio determined to be outside the range of 0-1.");
    8098           0 :                             ShowContinueError(
    8099             :                                 state,
    8100           0 :                                 format("  An estimated part-load ratio = {:.2T} will be used and the simulation continues.", CoolPartLoadRatio));
    8101           0 :                             ShowContinueError(
    8102           0 :                                 state, format("  The estimated part-load ratio provides a cooling sensible capacity = {:.2T}", ZoneSensLoadMet));
    8103           0 :                             ShowContinueErrorTimeStamp(state, format("  Cooling sensible load required = {:.2T}", TotalZoneSensLoad));
    8104             :                         }
    8105           0 :                         ShowRecurringWarningErrorAtEnd(
    8106             :                             state,
    8107           0 :                             format("{} \"{}\" - Cooling sensible part-load ratio out of range error continues. Sensible cooling load statistics:",
    8108           0 :                                    HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    8109           0 :                                    thisFurnace.Name),
    8110           0 :                             thisFurnace.SensibleRegulaFalsiFailedIndex,
    8111             :                             TotalZoneSensLoad,
    8112             :                             TotalZoneSensLoad);
    8113             :                     }
    8114             :                 }
    8115             :             }
    8116             : 
    8117       37711 :             if (fanOp == HVAC::FanOp::Cycling) {
    8118       37711 :                 thisFurnace.MdotFurnace *= CoolPartLoadRatio;
    8119             :             }
    8120             : 
    8121             :             //*********HEATING CALCULATIONS****************
    8122             :             // If Furnace runs with a heating load then set HeatCoilLoad on Heating Coil and the Mass Flow
    8123       81559 :         } else if ((ScheduleManager::GetCurrentScheduleValue(state, thisFurnace.SchedPtr) > 0.0) &&
    8124       81559 :                    (state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate > 0.0) && state.dataFurnaces->HeatingLoad) {
    8125             : 
    8126             :             // Set the air flow rate to the design flow rate and set the fan operation fraction to 1 (continuous operation)
    8127       55271 :             state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = thisFurnace.DesignMassFlowRate;
    8128       55271 :             state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0; // see 'Note' under INITIAL CALCULATIONS
    8129             : 
    8130             :             //         !Set the operation flag to run the fan continuously
    8131             :             //         fanOp = FanOp::Continuous
    8132             : 
    8133             :             // Set the input parameters for CalcFurnaceOutput
    8134       55271 :             thisFurnace.HeatingCoilSensDemand = 0.0;
    8135       55271 :             thisFurnace.CoolingCoilLatentDemand = 0.0;
    8136       55271 :             thisFurnace.CoolingCoilSensDemand = 0.0;
    8137       55271 :             thisFurnace.CompPartLoadRatio = 0.0; // compressor off
    8138       55271 :             thisFurnace.InitHeatPump = true;     // initialization call to Calc Furnace
    8139       55271 :             HeatPartLoadRatio = 0.0;
    8140             : 
    8141             :             // Get no load result in order to calculate the effect of the fan and the mixed air equipment
    8142       55271 :             CalcFurnaceOutput(state,
    8143             :                               FurnaceNum,
    8144             :                               FirstHVACIteration,
    8145             :                               fanOp,
    8146             :                               compressorOp,
    8147             :                               CoolPartLoadRatio,
    8148             :                               HeatPartLoadRatio,
    8149             :                               Dummy2,
    8150             :                               Dummy2,
    8151             :                               ZoneSensLoadMetFanONCompOFF,
    8152             :                               ZoneLatLoadMetFanONCompOFF,
    8153             :                               OnOffAirFlowRatio,
    8154             :                               false);
    8155             : 
    8156             :             // Set the input parameters for CalcFurnaceOutput
    8157       55271 :             thisFurnace.HeatingCoilSensDemand = 1.0;
    8158       55271 :             thisFurnace.CompPartLoadRatio = 1.0; // compressor ON
    8159       55271 :             HeatPartLoadRatio = 1.0;
    8160             : 
    8161             :             // Get full load result in order to estimate the operating part load ratio for continuous fan operation
    8162             : 
    8163       55271 :             CalcFurnaceOutput(state,
    8164             :                               FurnaceNum,
    8165             :                               FirstHVACIteration,
    8166             :                               fanOp,
    8167             :                               compressorOp,
    8168             :                               CoolPartLoadRatio,
    8169             :                               HeatPartLoadRatio,
    8170             :                               Dummy2,
    8171             :                               Dummy2,
    8172             :                               ZoneSensLoadMetFanONCompON,
    8173             :                               ZoneLatLoadMetFanONCompON,
    8174             :                               OnOffAirFlowRatio,
    8175             :                               false);
    8176             : 
    8177             :             // Calculate the heating coil demand for continuous fan operation as:
    8178             :             //    (the zone sensible load - the zone sensible load met by fan heat and mixed air)
    8179             :             // Note; The sensible zone load met by fan heat and mixed air is calculated as:
    8180             :             //     mdotsys(control zone inlet enthalpy - control zone outlet enthalpy)
    8181             :             // This accounts for the negative sign in the equation.
    8182       55271 :             HPCoilSensDemand = TotalZoneSensLoad - ZoneSensLoadMetFanONCompOFF;
    8183             : 
    8184             :             // Calculate the heating coil capacity for continuous fan operation as:
    8185             :             //    (the zone sensible load met by fan heat and mixed air and coil
    8186             :             //   - the zone sensible load met by fan heat and mixed air)
    8187       55271 :             HPCoilSensCapacity = ZoneSensLoadMetFanONCompON - ZoneSensLoadMetFanONCompOFF;
    8188             : 
    8189             :             // Calculate the part load ratio for continuous fan operation with cycling coil
    8190       55271 :             if (HPCoilSensCapacity == 0.0) {
    8191           0 :                 HeatPartLoadRatio = 0.0;
    8192             :             } else {
    8193       55271 :                 HeatPartLoadRatio = max(MinPLR, min(1.0, std::abs(HPCoilSensDemand) / std::abs(HPCoilSensCapacity)));
    8194             :             }
    8195             : 
    8196       55271 :             thisFurnace.InitHeatPump = false;
    8197             : 
    8198             :             // check bounds on sensible output prior to iteration using RegulaFalsi
    8199       55271 :             if (ZoneSensLoadMetFanONCompON < TotalZoneSensLoad) {
    8200        4228 :                 HeatPartLoadRatio = 1.0;
    8201        4228 :                 ZoneSensLoadMet = ZoneSensLoadMetFanONCompON;
    8202        4228 :                 HPCoilSensDemand = std::abs(ZoneSensLoadMetFanONCompON - ZoneSensLoadMetFanONCompOFF);
    8203        4228 :                 thisFurnace.HeatingCoilSensDemand = HPCoilSensDemand;
    8204       51043 :             } else if (ZoneSensLoadMetFanONCompOFF > TotalZoneSensLoad) {
    8205           0 :                 HeatPartLoadRatio = 0.0;
    8206           0 :                 ZoneSensLoadMet = ZoneSensLoadMetFanONCompOFF;
    8207           0 :                 thisFurnace.CompPartLoadRatio = 0.0; // compressor ON
    8208           0 :                 CalcFurnaceOutput(state,
    8209             :                                   FurnaceNum,
    8210             :                                   FirstHVACIteration,
    8211             :                                   fanOp,
    8212             :                                   compressorOp,
    8213             :                                   CoolPartLoadRatio,
    8214             :                                   HeatPartLoadRatio,
    8215             :                                   Dummy2,
    8216             :                                   Dummy2,
    8217             :                                   ZoneSensLoadMet,
    8218             :                                   ZoneLatLoadMet,
    8219             :                                   OnOffAirFlowRatio,
    8220             :                                   false);
    8221             :             } else {
    8222             :                 //         Calculate the sensible part load ratio through iteration
    8223       51043 :                 HeatErrorToler = thisFurnace.HeatingConvergenceTolerance;
    8224       51043 :                 SolFlag = 0; // # of iterations if positive, -1 means failed to converge, -2 means bounds are incorrect
    8225             :                 // HeatErrorToler is in fraction of load, MaxIter = 600, SolFalg = # of iterations or error as appropriate
    8226      204172 :                 auto f = [&state, FurnaceNum, FirstHVACIteration, fanOp, compressorOp, TotalZoneSensLoad, ZoneSensLoadMetFanONCompOFF](
    8227      153129 :                              Real64 const PartLoadRatio) {
    8228      153129 :                     return CalcWaterToAirResidual(state,
    8229             :                                                   PartLoadRatio,
    8230             :                                                   FurnaceNum,
    8231             :                                                   FirstHVACIteration,
    8232             :                                                   fanOp,
    8233             :                                                   compressorOp,
    8234             :                                                   TotalZoneSensLoad,
    8235             :                                                   0.0,
    8236             :                                                   1.0,
    8237             :                                                   ZoneSensLoadMetFanONCompOFF,
    8238      153129 :                                                   0.0);
    8239       51043 :                 };
    8240       51043 :                 General::SolveRoot(state, HeatErrorToler, MaxIter, SolFlag, HeatPartLoadRatio, f, 0.0, 1.0);
    8241       51043 :                 state.dataHVACGlobal->OnOffFanPartLoadFraction = state.dataFurnaces->OnOffFanPartLoadFractionSave;
    8242       51043 :                 CalcFurnaceOutput(state,
    8243             :                                   FurnaceNum,
    8244             :                                   FirstHVACIteration,
    8245             :                                   fanOp,
    8246             :                                   compressorOp,
    8247             :                                   CoolPartLoadRatio,
    8248             :                                   HeatPartLoadRatio,
    8249             :                                   Dummy2,
    8250             :                                   Dummy2,
    8251             :                                   ZoneSensLoadMet,
    8252             :                                   ZoneLatLoadMet,
    8253             :                                   OnOffAirFlowRatio,
    8254             :                                   false);
    8255       51043 :                 if (SolFlag == -1 && !state.dataGlobal->WarmupFlag && !FirstHVACIteration) {
    8256           0 :                     if (std::abs(ZoneSensLoadMet - TotalZoneSensLoad) / TotalZoneSensLoad > HeatErrorToler) {
    8257           0 :                         if (thisFurnace.WSHPHeatMaxIterIndex == 0) {
    8258           0 :                             ShowWarningMessage(state,
    8259           0 :                                                format("Heating coil control failed to converge for {}:{}",
    8260           0 :                                                       HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    8261           0 :                                                       thisFurnace.Name));
    8262           0 :                             ShowContinueError(state, "  Iteration limit exceeded in calculating DX heating coil sensible part-load ratio.");
    8263           0 :                             ShowContinueErrorTimeStamp(state,
    8264           0 :                                                        format("Sensible load to be met by DX coil = {:.2T} (watts), sensible output of DX coil = "
    8265             :                                                               "{:.2T} (watts), and the simulation continues.",
    8266             :                                                               TotalZoneSensLoad,
    8267             :                                                               ZoneSensLoadMet));
    8268             :                         }
    8269           0 :                         ShowRecurringWarningErrorAtEnd(
    8270             :                             state,
    8271           0 :                             format("{} \"{}\" - Iteration limit exceeded in calculating sensible heating part-load ratio error continues.",
    8272           0 :                                    HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    8273           0 :                                    thisFurnace.Name),
    8274           0 :                             thisFurnace.WSHPHeatMaxIterIndex,
    8275             :                             TotalZoneSensLoad,
    8276             :                             TotalZoneSensLoad);
    8277             :                     }
    8278       51043 :                 } else if (SolFlag == -2) {
    8279           0 :                     HeatPartLoadRatio = max(MinPLR, min(1.0, std::abs(HPCoilSensDemand) / std::abs(HPCoilSensCapacity)));
    8280           0 :                     CalcFurnaceOutput(state,
    8281             :                                       FurnaceNum,
    8282             :                                       FirstHVACIteration,
    8283             :                                       fanOp,
    8284             :                                       compressorOp,
    8285             :                                       0.0,
    8286             :                                       HeatPartLoadRatio,
    8287             :                                       0.0,
    8288             :                                       0.0,
    8289             :                                       ZoneSensLoadMet,
    8290             :                                       ZoneLatLoadMet,
    8291             :                                       OnOffAirFlowRatio,
    8292             :                                       false);
    8293           0 :                     if ((ZoneSensLoadMet - TotalZoneSensLoad) / TotalZoneSensLoad > HeatErrorToler) {
    8294           0 :                         if (thisFurnace.WSHPHeatRegulaFalsiFailedIndex == 0) {
    8295           0 :                             ShowWarningError(
    8296             :                                 state,
    8297           0 :                                 format("Heating coil control failed for {}:{}", HVAC::unitarySysTypeNames[(int)thisFurnace.type], thisFurnace.Name));
    8298           0 :                             ShowContinueError(state, "  Heating sensible part-load ratio determined to be outside the range of 0-1.");
    8299           0 :                             ShowContinueError(
    8300             :                                 state,
    8301           0 :                                 format("  An estimated part-load ratio = {:.2T} will be used and the simulation continues.", HeatPartLoadRatio));
    8302           0 :                             ShowContinueError(
    8303           0 :                                 state, format("  The estimated part-load ratio provides a heating sensible capacity = {:.2T}", ZoneSensLoadMet));
    8304           0 :                             ShowContinueErrorTimeStamp(state, format("  Heating sensible load required = {:.2T}", TotalZoneSensLoad));
    8305             :                         }
    8306           0 :                         ShowRecurringWarningErrorAtEnd(state,
    8307           0 :                                                        format("{} \"{}\" - Heating sensible part-load ratio out of range error continues.",
    8308           0 :                                                               HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    8309           0 :                                                               thisFurnace.Name),
    8310           0 :                                                        thisFurnace.WSHPHeatRegulaFalsiFailedIndex,
    8311             :                                                        TotalZoneSensLoad,
    8312             :                                                        TotalZoneSensLoad);
    8313             :                     }
    8314             :                 }
    8315             :             }
    8316             : 
    8317             :             //       CALL supplemental heater if required
    8318       55271 :             if ((TotalZoneSensLoad - ZoneSensLoadMet) > HVAC::SmallLoad && HeatPartLoadRatio >= 1.0) {
    8319        4228 :                 SuppHeatCoilLoad = TotalZoneSensLoad - ZoneSensLoadMet;
    8320        4228 :                 CalcFurnaceOutput(state,
    8321             :                                   FurnaceNum,
    8322             :                                   FirstHVACIteration,
    8323             :                                   fanOp,
    8324             :                                   compressorOp,
    8325             :                                   CoolPartLoadRatio,
    8326             :                                   HeatPartLoadRatio,
    8327             :                                   SuppHeatCoilLoad,
    8328             :                                   Dummy2,
    8329             :                                   ZoneSensLoadMet,
    8330             :                                   ZoneLatLoadMet,
    8331             :                                   OnOffAirFlowRatio,
    8332             :                                   false);
    8333             :             }
    8334             : 
    8335       55271 :             if (fanOp == HVAC::FanOp::Cycling) {
    8336       55271 :                 thisFurnace.MdotFurnace *= HeatPartLoadRatio;
    8337             :             }
    8338             : 
    8339             :             //**********HVAC Scheduled ON, but no cooling, dehumidification or heating load*********
    8340       26288 :         } else if (ScheduleManager::GetCurrentScheduleValue(state, thisFurnace.SchedPtr) > 0.0) {
    8341       12252 :             thisFurnace.InitHeatPump = true; // initialization call to Calc Furnace
    8342       12252 :             HeatPartLoadRatio = 0.0;
    8343       12252 :             CoolPartLoadRatio = 0.0;
    8344       12252 :             state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0; //! see 'Note' under INITIAL CALCULATIONS
    8345             :             // set report variables
    8346       12252 :             thisFurnace.CompPartLoadRatio = 0.0;
    8347       12252 :             thisFurnace.CoolingCoilSensDemand = 0.0;
    8348       12252 :             thisFurnace.CoolingCoilLatentDemand = 0.0;
    8349       12252 :             thisFurnace.HeatingCoilSensDemand = 0.0;
    8350       12252 :             if (fanOp == HVAC::FanOp::Cycling) {
    8351       12252 :                 thisFurnace.MdotFurnace = 0.0;
    8352       12252 :                 state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0; // see 'Note' under INITIAL CALCULATIONS
    8353       12252 :                 CalcFurnaceOutput(state,
    8354             :                                   FurnaceNum,
    8355             :                                   FirstHVACIteration,
    8356             :                                   fanOp,
    8357             :                                   compressorOp,
    8358             :                                   CoolPartLoadRatio,
    8359             :                                   HeatPartLoadRatio,
    8360             :                                   Dummy2,
    8361             :                                   Dummy2,
    8362             :                                   ZoneSensLoadMet,
    8363             :                                   ZoneLatLoadMet,
    8364             :                                   OnOffAirFlowRatio,
    8365             :                                   false);
    8366       12252 :                 thisFurnace.MdotFurnace = 0.0;
    8367             :             } else { // continuous fan, cycling coil
    8368           0 :                 CalcFurnaceOutput(state,
    8369             :                                   FurnaceNum,
    8370             :                                   FirstHVACIteration,
    8371             :                                   fanOp,
    8372             :                                   compressorOp,
    8373             :                                   CoolPartLoadRatio,
    8374             :                                   HeatPartLoadRatio,
    8375             :                                   Dummy2,
    8376             :                                   Dummy2,
    8377             :                                   ZoneSensLoadMet,
    8378             :                                   ZoneLatLoadMet,
    8379             :                                   OnOffAirFlowRatio,
    8380             :                                   false);
    8381             :             }
    8382             :             //*********No heating or cooling or dehumidification*********
    8383             :         } else {
    8384       14036 :             thisFurnace.InitHeatPump = true; // initialization call to Calc Furnace
    8385       14036 :             thisFurnace.MdotFurnace = 0.0;
    8386       14036 :             HeatPartLoadRatio = 0.0;
    8387       14036 :             CoolPartLoadRatio = 0.0;
    8388       14036 :             state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0; // see 'Note' under INITIAL CALCULATIONS
    8389       14036 :             thisFurnace.CompPartLoadRatio = 0.0;
    8390       14036 :             thisFurnace.CoolingCoilSensDemand = 0.0;
    8391       14036 :             thisFurnace.CoolingCoilLatentDemand = 0.0;
    8392       14036 :             thisFurnace.HeatingCoilSensDemand = 0.0;
    8393       14036 :             CalcFurnaceOutput(state,
    8394             :                               FurnaceNum,
    8395             :                               FirstHVACIteration,
    8396             :                               fanOp,
    8397             :                               compressorOp,
    8398             :                               CoolPartLoadRatio,
    8399             :                               HeatPartLoadRatio,
    8400             :                               Dummy2,
    8401             :                               Dummy2,
    8402             :                               ZoneSensLoadMet,
    8403             :                               ZoneLatLoadMet,
    8404             :                               OnOffAirFlowRatio,
    8405             :                               false);
    8406       14036 :             thisFurnace.MdotFurnace = 0.0;
    8407             :         }
    8408             : 
    8409             :         // Set the fan inlet node flow rates
    8410      119270 :         state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRateMaxAvail = thisFurnace.MdotFurnace;
    8411      119270 :         state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = thisFurnace.MdotFurnace;
    8412      119270 :     }
    8413             : 
    8414    20453647 :     void CalcFurnaceOutput(EnergyPlusData &state,
    8415             :                            int const FurnaceNum,
    8416             :                            bool const FirstHVACIteration,
    8417             :                            HVAC::FanOp const fanOp,               // Cycling fan or constant fan
    8418             :                            HVAC::CompressorOp const compressorOp, // Compressor on/off; 1=on, 0=off
    8419             :                            Real64 const CoolPartLoadRatio,        // DX cooling coil part load ratio
    8420             :                            Real64 const HeatPartLoadRatio,        // DX heating coil part load ratio (0 for other heating coil types)
    8421             :                            Real64 const HeatCoilLoad,             // Heating coil load for gas heater
    8422             :                            Real64 const ReheatCoilLoad,           // Reheating coil load for gas heater
    8423             :                            Real64 &SensibleLoadMet,               // Sensible cooling load met (furnace outlet with respect to control zone temp)
    8424             :                            Real64 &LatentLoadMet,              // Latent cooling load met (furnace outlet with respect to control zone humidity ratio)
    8425             :                            Real64 &OnOffAirFlowRatio,          // Ratio of compressor ON mass flow rate to AVERAGE
    8426             :                            bool const HXUnitOn,                // flag to enable HX based on zone moisture load
    8427             :                            Real64 const CoolingHeatingPLRRatio // cooling PLR to heating PLR ratio, used for cycling fan RH control
    8428             :     )
    8429             :     {
    8430             : 
    8431             :         // SUBROUTINE INFORMATION:
    8432             :         //       AUTHOR         Richard Raustad
    8433             :         //       DATE WRITTEN   Sept 2001
    8434             :         //       MODIFIED       Dec 2001
    8435             : 
    8436             :         // PURPOSE OF THIS SUBROUTINE:
    8437             :         // This subroutine calculates to sensible and latent loads met by the DX coils
    8438             :         // specified.  Load met is the outlet node with respect to the control zone's
    8439             :         // temperature and humidity ratio.
    8440             : 
    8441             :         // METHODOLOGY EMPLOYED:
    8442             :         // Simulate each child object in the correct order for each system type. This routine is used in the
    8443             :         // RegulaFalsi function CALL. Air mass flow rate is set each iteration based on PLR.
    8444             : 
    8445    20453647 :         auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    8446    20453647 :         auto &inletNode = state.dataLoopNodes->Node(thisFurnace.FurnaceInletNodeNum);
    8447    20453647 :         int CoolingCoilType_Num = thisFurnace.CoolingCoilType_Num;
    8448    20453647 :         Real64 QActual = 0.0; // heating coil load met or delivered
    8449    20453647 :         state.dataFurnaces->ModifiedHeatCoilLoad = 0.0;
    8450             : 
    8451    20453647 :         state.dataFurnaces->CoolHeatPLRRat = CoolingHeatingPLRRatio;
    8452             : 
    8453             :         // Cooling to Heating PLR Ratio (CoolHeatPLRRat) is used to track the air mass flow rate of both the heating
    8454             :         // and cooling coils when RH control is used and the heating coil operates longer than the cooling coil.
    8455             :         // When CoolPartLoadRatio/CoolHeatPLRRat is used, the PLR calculated is acutally the PLR for the heating
    8456             :         // coil (heating PLR is greater than cooling PLR), it is this PLR that determines the air mass flow rate.
    8457             :         // When MAX(HeatPartLoadRatio,CoolPartLoadRatio) is used, only one of these values is non-zero.
    8458    20453647 :         if (fanOp == HVAC::FanOp::Cycling) {
    8459    12941008 :             if (state.dataFurnaces->CoolHeatPLRRat < 1.0) {
    8460           2 :                 if (state.dataFurnaces->CoolHeatPLRRat > 0.0) {
    8461           0 :                     inletNode.MassFlowRate = state.dataFurnaces->CompOnMassFlow * CoolPartLoadRatio / state.dataFurnaces->CoolHeatPLRRat;
    8462           0 :                     if (thisFurnace.type != HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir) {
    8463           0 :                         SetAverageAirFlow(state, FurnaceNum, CoolPartLoadRatio / state.dataFurnaces->CoolHeatPLRRat, OnOffAirFlowRatio);
    8464             :                     }
    8465             :                 } else {
    8466           2 :                     inletNode.MassFlowRate = state.dataFurnaces->CompOnMassFlow * CoolPartLoadRatio;
    8467           2 :                     if (thisFurnace.type != HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir) {
    8468           2 :                         SetAverageAirFlow(state, FurnaceNum, max(HeatPartLoadRatio, CoolPartLoadRatio), OnOffAirFlowRatio);
    8469             :                     }
    8470             :                 }
    8471             :             } else {
    8472    12941006 :                 inletNode.MassFlowRate = state.dataFurnaces->CompOnMassFlow * max(HeatPartLoadRatio, CoolPartLoadRatio);
    8473    12941006 :                 if (thisFurnace.type != HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir) {
    8474     5308941 :                     SetAverageAirFlow(state, FurnaceNum, max(HeatPartLoadRatio, CoolPartLoadRatio), OnOffAirFlowRatio);
    8475             :                 }
    8476             :             }
    8477             :         } else {
    8478     7512639 :             if (thisFurnace.type != HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir) {
    8479     4981695 :                 SetAverageAirFlow(state, FurnaceNum, max(HeatPartLoadRatio, CoolPartLoadRatio), OnOffAirFlowRatio);
    8480             :             }
    8481             :         }
    8482             : 
    8483    20453647 :         inletNode.MassFlowRateMaxAvail = inletNode.MassFlowRate;
    8484             : 
    8485             :         // Simulate the air-to-air heat pump
    8486    20453647 :         if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_AirToAir) {
    8487             :             //   Simulate blow-thru fan and non-linear coils twice to update PLF used by the ONOFF Fan
    8488     1635454 :             if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
    8489     1635454 :                 state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
    8490     1635454 :                 if (CoolingCoilType_Num == HVAC::CoilDX_CoolingHXAssisted) {
    8491           0 :                     HVACHXAssistedCoolingCoil::SimHXAssistedCoolingCoil(state,
    8492             :                                                                         BlankString,
    8493             :                                                                         FirstHVACIteration,
    8494             :                                                                         compressorOp,
    8495             :                                                                         CoolPartLoadRatio,
    8496           0 :                                                                         thisFurnace.CoolingCoilIndex,
    8497             :                                                                         fanOp,
    8498             :                                                                         HXUnitOn,
    8499             :                                                                         OnOffAirFlowRatio,
    8500           0 :                                                                         state.dataFurnaces->EconomizerFlag);
    8501             :                 } else {
    8502     3270908 :                     DXCoils::SimDXCoil(state,
    8503             :                                        BlankString,
    8504             :                                        compressorOp,
    8505             :                                        FirstHVACIteration,
    8506     1635454 :                                        thisFurnace.CoolingCoilIndex,
    8507             :                                        fanOp,
    8508             :                                        CoolPartLoadRatio,
    8509             :                                        OnOffAirFlowRatio);
    8510             :                 }
    8511     3270908 :                 DXCoils::SimDXCoil(
    8512     1635454 :                     state, BlankString, compressorOp, FirstHVACIteration, thisFurnace.HeatingCoilIndex, fanOp, HeatPartLoadRatio, OnOffAirFlowRatio);
    8513     1635454 :                 state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
    8514             :             }
    8515             :             //   Simulate cooling and heating coils
    8516     1635454 :             if (CoolingCoilType_Num == HVAC::CoilDX_CoolingHXAssisted) {
    8517           0 :                 HVACHXAssistedCoolingCoil::SimHXAssistedCoolingCoil(state,
    8518             :                                                                     BlankString,
    8519             :                                                                     FirstHVACIteration,
    8520             :                                                                     compressorOp,
    8521             :                                                                     CoolPartLoadRatio,
    8522           0 :                                                                     thisFurnace.CoolingCoilIndex,
    8523             :                                                                     fanOp,
    8524             :                                                                     HXUnitOn,
    8525             :                                                                     OnOffAirFlowRatio,
    8526           0 :                                                                     state.dataFurnaces->EconomizerFlag);
    8527             :             } else {
    8528     3270908 :                 DXCoils::SimDXCoil(
    8529     1635454 :                     state, BlankString, compressorOp, FirstHVACIteration, thisFurnace.CoolingCoilIndex, fanOp, CoolPartLoadRatio, OnOffAirFlowRatio);
    8530             :             }
    8531     3270908 :             DXCoils::SimDXCoil(
    8532     1635454 :                 state, BlankString, compressorOp, FirstHVACIteration, thisFurnace.HeatingCoilIndex, fanOp, HeatPartLoadRatio, OnOffAirFlowRatio);
    8533             :             //   Simulate the draw-thru fan
    8534     1635454 :             if (thisFurnace.fanPlace == HVAC::FanPlace::DrawThru) {
    8535           0 :                 state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
    8536             :             }
    8537             :             //   Simulate the supplemental heating coil
    8538     1635454 :             if (thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat && ReheatCoilLoad > 0.0) {
    8539           0 :                 bool SuppHeatingCoilFlag = true;
    8540           0 :                 CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, ReheatCoilLoad, fanOp, QActual);
    8541           0 :             } else {
    8542             :                 // equivalent to QCoilReq=0.0d0 or ReHeatCoilLoad = 0.0d0
    8543     1635454 :                 bool SuppHeatingCoilFlag = true;
    8544     1635454 :                 CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, ReheatCoilLoad, fanOp, QActual);
    8545             :             }
    8546             :             // Simulate the parameter estimate water-to-air heat pump
    8547    18818193 :         } else if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir && thisFurnace.WatertoAirHPType == WAHPCoilType::Simple) {
    8548             :             //    Simulate blow-thru fan and non-linear coils twice to update PLF used by the ONOFF Fan
    8549     9634192 :             if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
    8550     9634192 :                 state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
    8551             :                 // COIL:WATERTOAIRHPSIMPLE:COOLING
    8552     9634192 :                 WaterToAirHeatPumpSimple::SimWatertoAirHPSimple(state,
    8553             :                                                                 BlankString,
    8554     9634192 :                                                                 thisFurnace.CoolingCoilIndex,
    8555             :                                                                 thisFurnace.CoolingCoilSensDemand,
    8556             :                                                                 thisFurnace.CoolingCoilLatentDemand,
    8557             :                                                                 fanOp,
    8558             :                                                                 compressorOp,
    8559             :                                                                 CoolPartLoadRatio,
    8560             :                                                                 FirstHVACIteration); // CoolPartLoadRatio
    8561     9634192 :                 Real64 Dummy = 0.0;
    8562             :                 // COIL:WATERTOAIRHPSIMPLE:HEATING
    8563     9634192 :                 WaterToAirHeatPumpSimple::SimWatertoAirHPSimple(state,
    8564             :                                                                 BlankString,
    8565     9634192 :                                                                 thisFurnace.HeatingCoilIndex,
    8566             :                                                                 thisFurnace.HeatingCoilSensDemand,
    8567             :                                                                 Dummy,
    8568             :                                                                 fanOp,
    8569             :                                                                 compressorOp,
    8570             :                                                                 HeatPartLoadRatio,
    8571             :                                                                 FirstHVACIteration); // HeatPartLoadRatio
    8572             :                 //      Simulate the whole thing a second time so that the correct PLF required by the coils is used by the Fan. *******
    8573     9634192 :                 state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
    8574             :             }
    8575             :             //    Simulate the cooling and heating coils
    8576             :             // COIL:WATERTOAIRHPSIMPLE:COOLING
    8577     9634192 :             WaterToAirHeatPumpSimple::SimWatertoAirHPSimple(state,
    8578             :                                                             BlankString,
    8579     9634192 :                                                             thisFurnace.CoolingCoilIndex,
    8580             :                                                             thisFurnace.CoolingCoilSensDemand,
    8581             :                                                             thisFurnace.CoolingCoilLatentDemand,
    8582             :                                                             fanOp,
    8583             :                                                             compressorOp,
    8584             :                                                             CoolPartLoadRatio,
    8585             :                                                             FirstHVACIteration); // CoolPartLoadRatio
    8586     9634192 :             Real64 Dummy = 0.0;
    8587             :             // COIL:WATERTOAIRHPSIMPLE:HEATING
    8588     9634192 :             WaterToAirHeatPumpSimple::SimWatertoAirHPSimple(state,
    8589             :                                                             BlankString,
    8590     9634192 :                                                             thisFurnace.HeatingCoilIndex,
    8591             :                                                             thisFurnace.HeatingCoilSensDemand,
    8592             :                                                             Dummy,
    8593             :                                                             fanOp,
    8594             :                                                             compressorOp,
    8595             :                                                             HeatPartLoadRatio,
    8596             :                                                             FirstHVACIteration); // HeatPartLoadRatio
    8597             :             //     Simulate the draw-thru fan
    8598     9634192 :             if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
    8599     9634192 :                 state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
    8600             :             }
    8601             :             //     Simulate the supplemental heating coil
    8602     9634192 :             if (thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat && ReheatCoilLoad > 0.0) {
    8603           0 :                 bool SuppHeatingCoilFlag = true; // if true simulates supplemental heating coil
    8604           0 :                 CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, ReheatCoilLoad, fanOp, QActual);
    8605           0 :             } else {
    8606     9634192 :                 bool SuppHeatingCoilFlag = true; // if true simulates supplemental heating coil
    8607     9634192 :                 CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, fanOp, QActual);
    8608             :             }
    8609             :             // Simulate the detailed water-to-air heat pump
    8610    18818193 :         } else if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir && thisFurnace.WatertoAirHPType == WAHPCoilType::ParEst) {
    8611             :             //    Simulate the draw-thru fan
    8612      528817 :             if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
    8613      528817 :                 state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
    8614             :             }
    8615             :             //    Simulate the cooling and heating coils
    8616      528817 :             WaterToAirHeatPump::SimWatertoAirHP(state,
    8617             :                                                 BlankString,
    8618      528817 :                                                 thisFurnace.CoolingCoilIndex,
    8619             :                                                 thisFurnace.DesignMassFlowRate,
    8620             :                                                 fanOp,
    8621             :                                                 FirstHVACIteration,
    8622      528817 :                                                 thisFurnace.InitHeatPump,
    8623             :                                                 thisFurnace.CoolingCoilSensDemand,
    8624             :                                                 thisFurnace.CoolingCoilLatentDemand,
    8625             :                                                 compressorOp,
    8626             :                                                 CoolPartLoadRatio);
    8627      528817 :             Real64 Dummy = 0.0;
    8628      528817 :             WaterToAirHeatPump::SimWatertoAirHP(state,
    8629             :                                                 BlankString,
    8630      528817 :                                                 thisFurnace.HeatingCoilIndex,
    8631             :                                                 thisFurnace.DesignMassFlowRate,
    8632             :                                                 fanOp,
    8633             :                                                 FirstHVACIteration,
    8634      528817 :                                                 thisFurnace.InitHeatPump,
    8635             :                                                 thisFurnace.HeatingCoilSensDemand,
    8636             :                                                 Dummy,
    8637             :                                                 compressorOp,
    8638             :                                                 HeatPartLoadRatio);
    8639             :             //    Simulate the draw-thru fan
    8640      528817 :             if (thisFurnace.fanPlace == HVAC::FanPlace::DrawThru) {
    8641           0 :                 state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
    8642             :             }
    8643             :             //    Simulate the supplemental heating coil
    8644     2115268 :             HeatingCoils::SimulateHeatingCoilComponents(
    8645     1586451 :                 state, BlankString, FirstHVACIteration, HeatCoilLoad, thisFurnace.SuppHeatCoilIndex, _, true, fanOp);
    8646             : 
    8647      528817 :         } else { // ELSE it's not a heat pump
    8648             :             //   Simulate blow-thru fan
    8649     8655184 :             if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
    8650             : 
    8651     8455786 :                 state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
    8652             : 
    8653             :                 //     For non-linear coils, simulate coil to update PLF used by the ONOFF Fan
    8654     8455786 :                 if (thisFurnace.fanType == HVAC::FanType::OnOff) {
    8655     6463895 :                     if (thisFurnace.type != HVAC::UnitarySysType::Unitary_HeatOnly && thisFurnace.type != HVAC::UnitarySysType::Furnace_HeatOnly) {
    8656             : 
    8657     6446108 :                         if (!thisFurnace.CoolingCoilUpstream) {
    8658     4244823 :                             bool SuppHeatingCoilFlag = false; // if false simulates heating coil
    8659     4244823 :                             CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, fanOp, QActual);
    8660             :                         }
    8661             : 
    8662     6446108 :                         if (CoolingCoilType_Num == HVAC::CoilDX_CoolingHXAssisted) {
    8663       69930 :                             HVACHXAssistedCoolingCoil::SimHXAssistedCoolingCoil(state,
    8664             :                                                                                 BlankString,
    8665             :                                                                                 FirstHVACIteration,
    8666             :                                                                                 compressorOp,
    8667             :                                                                                 CoolPartLoadRatio,
    8668       23310 :                                                                                 thisFurnace.CoolingCoilIndex,
    8669             :                                                                                 fanOp,
    8670             :                                                                                 HXUnitOn,
    8671             :                                                                                 OnOffAirFlowRatio,
    8672       23310 :                                                                                 state.dataFurnaces->EconomizerFlag);
    8673             :                         } else {
    8674    19268394 :                             DXCoils::SimDXCoil(state,
    8675             :                                                BlankString,
    8676             :                                                compressorOp,
    8677             :                                                FirstHVACIteration,
    8678     6422798 :                                                thisFurnace.CoolingCoilIndex,
    8679             :                                                fanOp,
    8680             :                                                CoolPartLoadRatio,
    8681             :                                                OnOffAirFlowRatio,
    8682     6422798 :                                                state.dataFurnaces->CoolHeatPLRRat);
    8683             :                         }
    8684             :                     }
    8685             : 
    8686     6463895 :                     if (thisFurnace.CoolingCoilUpstream) {
    8687     2219072 :                         bool SuppHeatingCoilFlag = false; // if false simulates heating coil
    8688     2219072 :                         CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, fanOp, QActual);
    8689             :                     }
    8690     6463895 :                     state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
    8691             :                 } // Simple OnOff fan
    8692             : 
    8693             :             } // Blow thru fan
    8694             : 
    8695             :             //   Simulate the cooling and heating coils
    8696     8655184 :             if (thisFurnace.type != HVAC::UnitarySysType::Unitary_HeatOnly && thisFurnace.type != HVAC::UnitarySysType::Furnace_HeatOnly) {
    8697             : 
    8698     8637397 :                 if (!thisFurnace.CoolingCoilUpstream) {
    8699     4307625 :                     bool SuppHeatingCoilFlag = false; // if false simulates heating coil
    8700     4307625 :                     CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, fanOp, QActual);
    8701             :                 }
    8702             : 
    8703     8637397 :                 if (CoolingCoilType_Num == HVAC::CoilDX_CoolingHXAssisted) {
    8704      461826 :                     HVACHXAssistedCoolingCoil::SimHXAssistedCoolingCoil(state,
    8705             :                                                                         BlankString,
    8706             :                                                                         FirstHVACIteration,
    8707             :                                                                         compressorOp,
    8708             :                                                                         CoolPartLoadRatio,
    8709      153942 :                                                                         thisFurnace.CoolingCoilIndex,
    8710             :                                                                         fanOp,
    8711             :                                                                         HXUnitOn,
    8712             :                                                                         OnOffAirFlowRatio,
    8713      153942 :                                                                         state.dataFurnaces->EconomizerFlag);
    8714             :                 } else {
    8715    25450365 :                     DXCoils::SimDXCoil(state,
    8716             :                                        BlankString,
    8717             :                                        compressorOp,
    8718             :                                        FirstHVACIteration,
    8719     8483455 :                                        thisFurnace.CoolingCoilIndex,
    8720             :                                        fanOp,
    8721             :                                        CoolPartLoadRatio,
    8722             :                                        OnOffAirFlowRatio,
    8723     8483455 :                                        state.dataFurnaces->CoolHeatPLRRat);
    8724             :                 }
    8725             :             }
    8726             : 
    8727     8655184 :             if (thisFurnace.CoolingCoilUpstream) {
    8728     4347559 :                 bool SuppHeatingCoilFlag = false; // if false simulates heating coil
    8729     4347559 :                 CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, fanOp, QActual);
    8730             :             }
    8731             :             //   Simulate the draw-thru fan
    8732     8655184 :             if (thisFurnace.fanPlace == HVAC::FanPlace::DrawThru) {
    8733      199398 :                 state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
    8734             :             }
    8735     8655184 :             if (thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat || thisFurnace.SuppHeatCoilIndex > 0) {
    8736     2712851 :                 bool SuppHeatingCoilFlag = true; // if truee simulates supplemental heating coil
    8737     2712851 :                 CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, ReheatCoilLoad, fanOp, QActual);
    8738             :             }
    8739             :         } // IF(Furnace(FurnaceNum)%type == UnitarySys_HeatPump_AirToAir)THEN
    8740             : 
    8741             :         // Get mass flow rate after components are simulated
    8742    20453647 :         auto &outletNode = state.dataLoopNodes->Node(thisFurnace.FurnaceOutletNodeNum);
    8743    20453647 :         Real64 AirMassFlow = inletNode.MassFlowRate; // this should be outlet node as in 9897?
    8744             : 
    8745             :         // check the DesignMaxOutletTemp and reset if necessary (for Coil:Gas:Heating or Coil:Electric:Heating only)
    8746    20453647 :         if (outletNode.Temp > thisFurnace.DesignMaxOutletTemp) {
    8747      215214 :             Real64 Wout = outletNode.HumRat;
    8748      215214 :             Real64 Tout = thisFurnace.DesignMaxOutletTemp;
    8749      215214 :             state.dataFurnaces->ModifiedHeatCoilLoad = HeatCoilLoad - (AirMassFlow * Psychrometrics::PsyCpAirFnW(Wout) * (outletNode.Temp - Tout));
    8750      215214 :             outletNode.Temp = Tout;
    8751             :         }
    8752             : 
    8753             :         // If the fan runs continually do not allow coils to set OnOffFanPartLoadRatio.
    8754    20453647 :         if (fanOp == HVAC::FanOp::Continuous) state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
    8755             : 
    8756    20453647 :         Real64 SensibleOutput = 0.0; // sensible output rate, {W}
    8757    20453647 :         Real64 LatentOutput = 0.0;   // latent output rate, {W}
    8758    20453647 :         Real64 TotalOutput = 0.0;    // total output rate, {W}
    8759    40907294 :         CalcZoneSensibleLatentOutput(AirMassFlow,
    8760             :                                      outletNode.Temp,
    8761             :                                      outletNode.HumRat,
    8762    20453647 :                                      state.dataLoopNodes->Node(thisFurnace.NodeNumOfControlledZone).Temp,
    8763    20453647 :                                      state.dataLoopNodes->Node(thisFurnace.NodeNumOfControlledZone).HumRat,
    8764             :                                      SensibleOutput,
    8765             :                                      LatentOutput,
    8766             :                                      TotalOutput);
    8767    20453647 :         SensibleLoadMet = SensibleOutput - thisFurnace.SenLoadLoss;
    8768    20453647 :         thisFurnace.SensibleLoadMet = SensibleLoadMet;
    8769             : 
    8770    20453647 :         if (thisFurnace.Humidistat) {
    8771     3388605 :             LatentLoadMet = LatentOutput - thisFurnace.LatLoadLoss;
    8772             :         } else {
    8773    17065042 :             LatentLoadMet = 0.0;
    8774             :         }
    8775    20453647 :         thisFurnace.LatentLoadMet = LatentLoadMet;
    8776    20453647 :     }
    8777             : 
    8778             :     //        End of Update subroutines for the Furnace Module
    8779             :     // *****************************************************************************
    8780             : 
    8781     8236435 :     Real64 CalcFurnaceResidual(EnergyPlusData &state,
    8782             :                                Real64 const PartLoadRatio, // DX cooling coil part load ratio
    8783             :                                int FurnaceNum,
    8784             :                                bool FirstHVACIteration,
    8785             :                                HVAC::FanOp const fanOp,
    8786             :                                HVAC::CompressorOp compressorOp,
    8787             :                                Real64 LoadToBeMet,
    8788             :                                Real64 par6_loadFlag,
    8789             :                                Real64 par7_sensLatentFlag,
    8790             :                                Real64 par9_HXOnFlag,
    8791             :                                Real64 par10_HeatingCoilPLR)
    8792             :     {
    8793             : 
    8794             :         // FUNCTION INFORMATION:
    8795             :         //       AUTHOR         Richard Raustad
    8796             :         //       DATE WRITTEN   Feb 2005
    8797             : 
    8798             :         // PURPOSE OF THIS SUBROUTINE:
    8799             :         // To calculate the part-load ratio for cooling and heating coils
    8800             : 
    8801             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    8802             :         Real64 CoolPartLoadRatio;      // DX cooling coil part load ratio
    8803             :         Real64 HeatPartLoadRatio;      // DX heating coil part load ratio (0 for other heating coil types)
    8804             :         Real64 HeatCoilLoad;           // Heating coil load for gas heater
    8805             :         Real64 SensibleLoadMet;        // Sensible cooling load met (furnace outlet with respect to control zone temp)
    8806             :         Real64 LatentLoadMet;          // Latent cooling load met (furnace outlet with respect to control zone humidity ratio)
    8807             :         Real64 OnOffAirFlowRatio;      // Ratio of compressor ON air mass flow to AVERAGE air mass flow over time step
    8808             :         Real64 CoolingHeatingPLRRatio; // ratio of cooling PLR to heating PLR, used for cycling fan RH control
    8809             :         bool HXUnitOn;                 // flag to enable HX based on zone moisture load
    8810             : 
    8811             :         //        // Convert parameters to usable variables
    8812             :         //        int FurnaceNum = int(Par(1));
    8813             :         //        bool FirstHVACIteration = Par(2) == 1.0;
    8814             :         //        int FanfanOp = int(Par(3));
    8815             :         //        CompressorOperation CompressorOp = static_cast<CompressorOperation>(Par(4));
    8816             :         //        Real64 LoadToBeMet = Par(5);
    8817             :         //        Real64 par6_loadFlag = Par(6);
    8818             :         //        Real64 par7_sensLatentFlag = Par(7);
    8819             :         //        Real64 par9_HXOnFlag = Par(9);
    8820             :         //        Real64 par10_HeatingCoilPLR = Par(10);
    8821             : 
    8822     8236435 :         if (par6_loadFlag == 1.0) {
    8823     4764222 :             CoolPartLoadRatio = PartLoadRatio;
    8824     4764222 :             HeatPartLoadRatio = 0.0;
    8825     4764222 :             HeatCoilLoad = 0.0;
    8826             :         } else {
    8827     3472213 :             CoolPartLoadRatio = 0.0;
    8828     3472213 :             HeatPartLoadRatio = PartLoadRatio;
    8829             : 
    8830     3472213 :             int const HeatingCoilType_Num(state.dataFurnaces->Furnace(FurnaceNum).HeatingCoilType_Num);
    8831     3472213 :             if (HeatingCoilType_Num == HVAC::Coil_HeatingGasOrOtherFuel || HeatingCoilType_Num == HVAC::Coil_HeatingElectric ||
    8832     2155596 :                 HeatingCoilType_Num == HVAC::Coil_HeatingWater || HeatingCoilType_Num == HVAC::Coil_HeatingSteam) {
    8833     1316617 :                 HeatCoilLoad = state.dataFurnaces->Furnace(FurnaceNum).DesignHeatingCapacity * PartLoadRatio;
    8834             :             } else {
    8835     2155596 :                 HeatCoilLoad = 0.0;
    8836             :             }
    8837             :         }
    8838             : 
    8839             :         //  OnOffAirFlowRatio = Par(8)
    8840     8236435 :         if (state.dataFurnaces->Furnace(FurnaceNum).type == HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir) {
    8841     4509204 :             state.dataFurnaces->Furnace(FurnaceNum).CompPartLoadRatio = PartLoadRatio;
    8842             :         }
    8843             : 
    8844     8236435 :         if (par9_HXOnFlag == 1.0) {
    8845     4731402 :             HXUnitOn = true;
    8846             :         } else {
    8847     3505033 :             HXUnitOn = false;
    8848             :         }
    8849             : 
    8850     8236435 :         if (par10_HeatingCoilPLR > 0.0) {
    8851             :             //    Par(10) = Furnace(FurnaceNum)%HeatPartLoadRatio
    8852             :             //    FanOp = CycFan and Furnace(FurnaceNum)%HeatPartLoadRatio must be > 0 for Part(10) to be greater than 0
    8853             :             //    This variable used when in heating mode and dehumidification (cooling) is required.
    8854           0 :             CoolingHeatingPLRRatio = min(1.0, CoolPartLoadRatio / state.dataFurnaces->Furnace(FurnaceNum).HeatPartLoadRatio);
    8855             :         } else {
    8856     8236435 :             CoolingHeatingPLRRatio = 1.0;
    8857             :         }
    8858             : 
    8859             :         // Subroutine arguments
    8860     8236435 :         CalcFurnaceOutput(state,
    8861             :                           FurnaceNum,
    8862             :                           FirstHVACIteration,
    8863             :                           fanOp,
    8864             :                           compressorOp,
    8865             :                           CoolPartLoadRatio,
    8866             :                           HeatPartLoadRatio,
    8867             :                           HeatCoilLoad,
    8868             :                           0.0,
    8869             :                           SensibleLoadMet,
    8870             :                           LatentLoadMet,
    8871             :                           OnOffAirFlowRatio,
    8872             :                           HXUnitOn,
    8873             :                           CoolingHeatingPLRRatio);
    8874             : 
    8875             :         // Calculate residual based on output calculation flag
    8876     8236435 :         if (par7_sensLatentFlag == 1.0) {
    8877     7791655 :             if (LoadToBeMet == 0.0) {
    8878       65344 :                 return (SensibleLoadMet - LoadToBeMet) / 100.0;
    8879             :             } else {
    8880     7726311 :                 return (SensibleLoadMet - LoadToBeMet) / LoadToBeMet;
    8881             :             }
    8882             :         } else {
    8883      444780 :             if (LoadToBeMet == 0.0) {
    8884           0 :                 return (LatentLoadMet - LoadToBeMet) / 100.0;
    8885             :             } else {
    8886      444780 :                 return (LatentLoadMet - LoadToBeMet) / LoadToBeMet;
    8887             :             }
    8888             :         }
    8889             :     }
    8890             : 
    8891      261281 :     Real64 CalcWaterToAirResidual(EnergyPlusData &state,
    8892             :                                   Real64 const PartLoadRatio, // DX cooling coil part load ratio
    8893             :                                   int FurnaceNum,
    8894             :                                   bool FirstHVACIteration,
    8895             :                                   HVAC::FanOp const fanOp,
    8896             :                                   HVAC::CompressorOp compressorOp,
    8897             :                                   Real64 LoadToBeMet,
    8898             :                                   Real64 par6_loadTypeFlag,
    8899             :                                   Real64 par7_latentOrSensible,
    8900             :                                   Real64 ZoneSensLoadMetFanONCompOFF,
    8901             :                                   Real64 par9_HXUnitOne)
    8902             :     {
    8903             : 
    8904             :         // FUNCTION INFORMATION:
    8905             :         //       AUTHOR         Richard Raustad
    8906             :         //       DATE WRITTEN   October 2006
    8907             : 
    8908             :         // PURPOSE OF THIS SUBROUTINE:
    8909             :         // To calculate the part-load ratio for water to air HP's
    8910             :         // this is used for parameter estimation WAHPs but not equation fit WAHPs
    8911             : 
    8912             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    8913             :         Real64 CoolPartLoadRatio; // DX cooling coil part load ratio
    8914             :         Real64 HeatPartLoadRatio; // DX heating coil part load ratio (0 for other heating coil types)
    8915             :         Real64 HeatCoilLoad;      // Heating coil load for gas heater
    8916             :         Real64 ZoneSensLoadMet;   // Sensible cooling load met (furnace outlet with respect to control zone temp)
    8917             :         Real64 ZoneLatLoadMet;    // Latent cooling load met (furnace outlet with respect to control zone humidity ratio)
    8918             :         Real64 Dummy;
    8919             :         Real64 HPCoilSensDemand;
    8920             :         Real64 OnOffAirFlowRatio;
    8921             :         bool HXUnitOn; // flag to enable HX based on zone moisture load (not valid for water-to-air HP's
    8922             : 
    8923             :         // Convert parameters to usable variables
    8924             :         //        int FurnaceNum = int(Par[0]);
    8925             :         //        bool FirstHVACIteration = Par[1] == 1.0;
    8926             :         //        int FanOp = int(Par[2]);
    8927             :         //        CompressorOperation CompressorOp = static_cast<CompressorOperation>(Par[3]);
    8928             :         //        Real64 LoadToBeMet = Par[4];
    8929             :         //        Real64 par6_loadTypeFlag = Par[5];
    8930             :         //        Real64 par7_latentOrSensible = Par[6];
    8931             :         //        Real64 ZoneSensLoadMetFanONCompOFF = Par[7];
    8932             :         //        Real64 par9_HXUnitOne = Par[8];
    8933             : 
    8934             :         int CoilIndex;
    8935      261281 :         if (par6_loadTypeFlag == 1.0) {
    8936      108152 :             CoolPartLoadRatio = PartLoadRatio;
    8937      108152 :             HeatPartLoadRatio = 0.0;
    8938      108152 :             HeatCoilLoad = 0.0;
    8939      108152 :             CoilIndex = state.dataFurnaces->Furnace(FurnaceNum).CoolingCoilIndex;
    8940             :         } else {
    8941      153129 :             CoolPartLoadRatio = 0.0;
    8942      153129 :             HeatPartLoadRatio = PartLoadRatio;
    8943      153129 :             CoilIndex = state.dataFurnaces->Furnace(FurnaceNum).HeatingCoilIndex;
    8944             :         }
    8945             : 
    8946             :         // Get child component RuntimeFrac
    8947             :         Real64 RuntimeFrac;
    8948      261281 :         switch (state.dataFurnaces->Furnace(FurnaceNum).WatertoAirHPType) {
    8949           0 :         case WAHPCoilType::Simple: {
    8950           0 :             RuntimeFrac = state.dataWaterToAirHeatPumpSimple->SimpleWatertoAirHP(CoilIndex).RunFrac;
    8951           0 :             break;
    8952             :         }
    8953      261281 :         case WAHPCoilType::ParEst: {
    8954      261281 :             RuntimeFrac = state.dataWaterToAirHeatPump->WatertoAirHP(CoilIndex).RunFrac;
    8955      261281 :             break;
    8956             :         }
    8957           0 :         case WAHPCoilType::VarSpeedEquationFit: {
    8958           0 :             RuntimeFrac = state.dataVariableSpeedCoils->VarSpeedCoil(CoilIndex).RunFrac;
    8959           0 :             break;
    8960             :         }
    8961           0 :         default:
    8962           0 :             RuntimeFrac = 1.0; // Programming error. Assert failure?
    8963             :         }
    8964             : 
    8965      261281 :         state.dataFurnaces->OnOffFanPartLoadFractionSave = state.dataHVACGlobal->OnOffFanPartLoadFraction;
    8966             :         // update fan and compressor run times
    8967      261281 :         state.dataFurnaces->Furnace(FurnaceNum).CompPartLoadRatio = PartLoadRatio;
    8968             : 
    8969             :         // Calculate the heating coil demand as (the zone sensible load - load met by fan heat and mixed air)
    8970             :         // Note; The load met by fan heat and mixed air is calculated as mdot(zoneinletenthalpy-zoneoutletenthalpy)
    8971             :         // This accounts for the negative sign in the equation.
    8972             : 
    8973             :         // Calculate the heat coil sensible capacity as the load met by the system with the fan and compressor on less
    8974             :         // the load met by the system with the compressor off.
    8975             :         //  HPCoilSensCapacity = ZoneSensLoadMetFanONCompON - ZoneSensLoadMetFanONCompOFF
    8976             : 
    8977             :         // Set input parameters for heat pump coil model
    8978      261281 :         HPCoilSensDemand = LoadToBeMet - RuntimeFrac * ZoneSensLoadMetFanONCompOFF;
    8979             :         //  HPCoilSensDemand = LoadToBeMet  - PartLoadRatio*ZoneSensLoadMetFanONCompOFF
    8980      261281 :         if (par6_loadTypeFlag == 1.0) {
    8981      108152 :             state.dataFurnaces->Furnace(FurnaceNum).HeatingCoilSensDemand = 0.0;
    8982      108152 :             state.dataFurnaces->Furnace(FurnaceNum).CoolingCoilSensDemand = std::abs(HPCoilSensDemand);
    8983             :         } else {
    8984      153129 :             state.dataFurnaces->Furnace(FurnaceNum).HeatingCoilSensDemand = HPCoilSensDemand;
    8985      153129 :             state.dataFurnaces->Furnace(FurnaceNum).CoolingCoilSensDemand = 0.0;
    8986             :         }
    8987      261281 :         state.dataFurnaces->Furnace(FurnaceNum).InitHeatPump = false; // initialization call to Calc Furnace
    8988             : 
    8989             :         // Calculate the zone loads met and the new part load ratio and for the specified run time
    8990      261281 :         Dummy = 0.0;
    8991      261281 :         OnOffAirFlowRatio = 1.0;
    8992      261281 :         if (par9_HXUnitOne == 1.0) {
    8993           0 :             HXUnitOn = true;
    8994             :         } else {
    8995      261281 :             HXUnitOn = false;
    8996             :         }
    8997             : 
    8998             :         //  Subroutine arguments
    8999             :         //  CALL CalcFurnaceOutput(FurnaceNum,FirstHVACIteration,FanOp,compressorOp,CoolPartLoadRatio,&
    9000             :         //                         HeatPartLoadRatio, HeatCoilLoad, ReHeatCoilLoad, SensibleLoadMet, LatentLoadMet, HXUnitOn)
    9001      261281 :         CalcFurnaceOutput(state,
    9002             :                           FurnaceNum,
    9003             :                           FirstHVACIteration,
    9004             :                           fanOp,
    9005             :                           compressorOp,
    9006             :                           CoolPartLoadRatio,
    9007             :                           HeatPartLoadRatio,
    9008             :                           Dummy,
    9009             :                           Dummy,
    9010             :                           ZoneSensLoadMet,
    9011             :                           ZoneLatLoadMet,
    9012             :                           OnOffAirFlowRatio,
    9013             :                           HXUnitOn);
    9014             : 
    9015             :         // Calculate residual based on output calculation flag
    9016      261281 :         if (par7_latentOrSensible == 1.0) {
    9017      261281 :             return (ZoneSensLoadMet - LoadToBeMet) / LoadToBeMet;
    9018             :         } else {
    9019           0 :             return (ZoneLatLoadMet - LoadToBeMet) / LoadToBeMet;
    9020             :         }
    9021             :     }
    9022             : 
    9023    24581377 :     void SetAverageAirFlow(EnergyPlusData &state,
    9024             :                            int const FurnaceNum,       // Unit index
    9025             :                            Real64 const PartLoadRatio, // unit part load ratio
    9026             :                            Real64 &OnOffAirFlowRatio   // ratio of compressor ON airflow to AVERAGE airflow over timestep
    9027             :     )
    9028             :     {
    9029             : 
    9030             :         // SUBROUTINE INFORMATION:
    9031             :         //       AUTHOR         Richard Raustad
    9032             :         //       DATE WRITTEN   July 2005
    9033             : 
    9034             :         // PURPOSE OF THIS SUBROUTINE:
    9035             :         // Set the average air mass flow rates using the part-load fraction of the HVAC system for this time step
    9036             :         // Set OnOffAirFlowRatio to be used by DX coils
    9037             : 
    9038             :         // METHODOLOGY EMPLOYED:
    9039             :         // The air flow rate in cooling, heating, and no cooling or heating can be different.
    9040             :         // Calculate the air flow rate based on initializations made in InitFurnace.
    9041             : 
    9042    24581377 :         int InletNode = state.dataFurnaces->Furnace(FurnaceNum).FurnaceInletNodeNum;
    9043             :         Real64 AverageUnitMassFlow =
    9044    24581377 :             (PartLoadRatio * state.dataFurnaces->CompOnMassFlow) + ((1 - PartLoadRatio) * state.dataFurnaces->CompOffMassFlow);
    9045    24581377 :         if (state.dataFurnaces->CompOffFlowRatio > 0.0) {
    9046    11892234 :             state.dataFurnaces->FanSpeedRatio =
    9047    11892234 :                 (PartLoadRatio * state.dataFurnaces->CompOnFlowRatio) + ((1 - PartLoadRatio) * state.dataFurnaces->CompOffFlowRatio);
    9048             :         } else {
    9049    12689143 :             state.dataFurnaces->FanSpeedRatio = state.dataFurnaces->CompOnFlowRatio;
    9050             :         }
    9051             :         // IF the furnace is scheduled on or nightime cycle overrides fan schedule. Uses same logic as fan.
    9052    48471899 :         if (ScheduleManager::GetCurrentScheduleValue(state, state.dataFurnaces->Furnace(FurnaceNum).SchedPtr) > 0.0 &&
    9053    23890522 :             ((ScheduleManager::GetCurrentScheduleValue(state, state.dataFurnaces->Furnace(FurnaceNum).FanAvailSchedPtr) > 0.0 ||
    9054     1638986 :               state.dataHVACGlobal->TurnFansOn) &&
    9055    23216522 :              !state.dataHVACGlobal->TurnFansOff)) {
    9056    23216522 :             state.dataLoopNodes->Node(InletNode).MassFlowRate = AverageUnitMassFlow;
    9057    23216522 :             state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail = AverageUnitMassFlow;
    9058    23216522 :             if (AverageUnitMassFlow > 0.0) {
    9059    19156275 :                 OnOffAirFlowRatio = state.dataFurnaces->CompOnMassFlow / AverageUnitMassFlow;
    9060             :             } else {
    9061     4060247 :                 OnOffAirFlowRatio = 0.0;
    9062             :             }
    9063             :         } else {
    9064     1364855 :             state.dataLoopNodes->Node(InletNode).MassFlowRate = 0.0;
    9065     1364855 :             OnOffAirFlowRatio = 1.0;
    9066             :         }
    9067             : 
    9068    24581377 :         state.dataFurnaces->Furnace(FurnaceNum).MdotFurnace = state.dataFurnaces->CompOnMassFlow;
    9069    24581377 :         state.dataFurnaces->OnOffAirFlowRatioSave = OnOffAirFlowRatio;
    9070    24581377 :     }
    9071             : 
    9072             :     // Beginning of Reporting subroutines for the Furnace Module
    9073             :     // *****************************************************************************
    9074             : 
    9075     6243009 :     void ReportFurnace(EnergyPlusData &state, int const FurnaceNum, int const AirLoopNum)
    9076             :     {
    9077             : 
    9078             :         // SUBROUTINE INFORMATION:
    9079             :         //       AUTHOR         Richard Liesen
    9080             :         //       DATE WRITTEN   Feb 2001
    9081             : 
    9082             :         // PURPOSE OF THIS SUBROUTINE:
    9083             :         // This subroutine updates the report variable for the coils.
    9084             : 
    9085             :         // METHODOLOGY EMPLOYED:
    9086             :         // Update fan part-load ratio based on mass flow rate ratio.
    9087             :         // Update global variables used by AirflowNetwork module.
    9088             : 
    9089             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    9090             :         Real64 ratio;
    9091             :         Real64 OnOffRatio;
    9092     6243009 :         auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    9093             : 
    9094             :         // Report the Furnace Fan Part Load Ratio
    9095     6243009 :         if (thisFurnace.NumOfSpeedCooling < 1) {
    9096     4735385 :             if (thisFurnace.DesignMassFlowRate > 0.0) {
    9097     4735385 :                 thisFurnace.FanPartLoadRatio = thisFurnace.MdotFurnace / thisFurnace.DesignMassFlowRate;
    9098             :             } else {
    9099           0 :                 thisFurnace.FanPartLoadRatio = 0.0;
    9100             :             }
    9101             :         }
    9102             : 
    9103             :         // Set mass flow rates during on and off cylce using an OnOff fan
    9104     6243009 :         if (state.afn->distribution_simulated) {
    9105      214495 :             state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopSystemOnMassFlowrate = state.dataFurnaces->CompOnMassFlow;
    9106      214495 :             state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopSystemOffMassFlowrate = state.dataFurnaces->CompOffMassFlow;
    9107      214495 :             state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopFanOperationMode = thisFurnace.fanOp;
    9108      214495 :             state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopOnOffFanPartLoadRatio = thisFurnace.FanPartLoadRatio;
    9109      214495 :             OnOffRatio = state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopOnOffFanPartLoadRatio;
    9110      214495 :             if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_AirToAir) {
    9111      150922 :                 state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopOnOffFanPartLoadRatio =
    9112      150922 :                     max(thisFurnace.FanPartLoadRatio, thisFurnace.HeatPartLoadRatio, thisFurnace.CoolPartLoadRatio);
    9113      150922 :                 state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopOnOffFanPartLoadRatio =
    9114      150922 :                     min(1.0, state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopOnOffFanPartLoadRatio);
    9115             :             }
    9116      214495 :             if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatCool) {
    9117       24774 :                 if (thisFurnace.HeatPartLoadRatio == 0.0 && thisFurnace.CoolPartLoadRatio == 0.0 && thisFurnace.FanPartLoadRatio > 0.0) {
    9118        7424 :                     if (state.dataFurnaces->CompOnMassFlow < max(thisFurnace.MaxCoolAirMassFlow, thisFurnace.MaxHeatAirMassFlow) &&
    9119           0 :                         state.dataFurnaces->CompOnMassFlow > 0.0) {
    9120           0 :                         ratio = max(thisFurnace.MaxCoolAirMassFlow, thisFurnace.MaxHeatAirMassFlow) / state.dataFurnaces->CompOnMassFlow;
    9121           0 :                         state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopOnOffFanPartLoadRatio =
    9122           0 :                             state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopOnOffFanPartLoadRatio * ratio;
    9123             :                     }
    9124             :                 }
    9125             :             }
    9126             :         }
    9127     6243009 :         if (thisFurnace.FirstPass) {
    9128         359 :             if (!state.dataGlobal->SysSizingCalc) {
    9129         359 :                 DataSizing::resetHVACSizingGlobals(state, 0, state.dataSize->CurSysNum, thisFurnace.FirstPass);
    9130             :             }
    9131             :         }
    9132     6243009 :         state.dataHVACGlobal->OnOffFanPartLoadFraction =
    9133             :             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)
    9134     6243009 :     }
    9135             : 
    9136    67595255 :     void CalcNonDXHeatingCoils(EnergyPlusData &state,
    9137             :                                int const FurnaceNum,           // Furnace Index
    9138             :                                bool const SuppHeatingCoilFlag, // .TRUE. if supplemental heating coil
    9139             :                                bool const FirstHVACIteration,  // flag for first HVAC iteration in the time step
    9140             :                                Real64 const QCoilLoad,         // load met by unit (watts)
    9141             :                                HVAC::FanOp const fanOp,        // fan operation mode
    9142             :                                Real64 &HeatCoilLoadmet         // Heating Load Met
    9143             :     )
    9144             :     {
    9145             :         // SUBROUTINE INFORMATION:
    9146             :         //       AUTHOR         Bereket Nigusse, FSEC/UCF
    9147             :         //       DATE WRITTEN   January 2012
    9148             : 
    9149             :         // PURPOSE OF THIS SUBROUTINE:
    9150             :         // This subroutine simulates the four non dx heating coil types: Gas, Electric, hot water and steam.
    9151             : 
    9152             :         // METHODOLOGY EMPLOYED:
    9153             :         // Simply calls the different heating coil component.  The hot water flow rate matching the coil load
    9154             :         // is calculated iteratively.
    9155             : 
    9156             :         // SUBROUTINE PARAMETER DEFINITIONS:
    9157    67595255 :         Real64 constexpr ErrTolerance(0.001); // convergence limit for hotwater coil
    9158    67595255 :         int constexpr SolveMaxIter(50);
    9159             : 
    9160             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    9161             :         Real64 mdot;              // heating coil steam or hot water mass flow rate
    9162             :         Real64 MinWaterFlow;      // coil minimum hot water mass flow rate, kg/s
    9163             :         Real64 MaxHotWaterFlow;   // coil maximum hot water mass flow rate, kg/s
    9164             :         Real64 HotWaterMdot;      // actual hot water mass flow rate
    9165    67595255 :         int CoilTypeNum(0);       // heating coil type number
    9166    67595255 :         int HeatingCoilIndex(0);  // heating coil index
    9167    67595255 :         int CoilControlNode(0);   // control node for hot water and steam heating coils
    9168    67595255 :         int CoilOutletNode(0);    // air outlet node of the heatiing coils
    9169    67595255 :         PlantLocation plantLoc{}; // plant loop location
    9170             : 
    9171    67595255 :         Real64 QActual = 0.0;                                               // actual heating load
    9172    67595255 :         std::string &HeatingCoilName = state.dataFurnaces->HeatingCoilName; // name of heating coil
    9173    67595255 :         auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    9174             : 
    9175    67595255 :         if (SuppHeatingCoilFlag) {
    9176    19257203 :             HeatingCoilName = thisFurnace.SuppHeatCoilName;
    9177    19257203 :             HeatingCoilIndex = thisFurnace.SuppHeatCoilIndex;
    9178    19257203 :             CoilControlNode = thisFurnace.SuppCoilControlNode;
    9179    19257203 :             CoilOutletNode = thisFurnace.SuppCoilOutletNode;
    9180    19257203 :             CoilTypeNum = thisFurnace.SuppHeatCoilType_Num;
    9181    19257203 :             plantLoc = thisFurnace.SuppPlantLoc;
    9182    19257203 :             MaxHotWaterFlow = thisFurnace.MaxSuppCoilFluidFlow;
    9183             :         } else {
    9184    48338052 :             HeatingCoilName = thisFurnace.HeatingCoilName;
    9185    48338052 :             HeatingCoilIndex = thisFurnace.HeatingCoilIndex;
    9186    48338052 :             CoilControlNode = thisFurnace.CoilControlNode;
    9187    48338052 :             CoilOutletNode = thisFurnace.CoilOutletNode;
    9188    48338052 :             CoilTypeNum = thisFurnace.HeatingCoilType_Num;
    9189    48338052 :             plantLoc = thisFurnace.plantLoc;
    9190    48338052 :             MaxHotWaterFlow = thisFurnace.MaxHeatCoilFluidFlow;
    9191             :         }
    9192             : 
    9193    67595255 :         switch (CoilTypeNum) {
    9194    67504527 :         case HVAC::Coil_HeatingGasOrOtherFuel:
    9195             :         case HVAC::Coil_HeatingElectric:
    9196             :         case HVAC::Coil_HeatingDesuperheater: {
    9197    67504527 :             HeatingCoils::SimulateHeatingCoilComponents(
    9198             :                 state, HeatingCoilName, FirstHVACIteration, QCoilLoad, HeatingCoilIndex, QActual, SuppHeatingCoilFlag, fanOp);
    9199    67504527 :         } break;
    9200       90728 :         case HVAC::Coil_HeatingWater: {
    9201       90728 :             if (QCoilLoad > HVAC::SmallLoad) {
    9202        1590 :                 PlantUtilities::SetComponentFlowRate(state, MaxHotWaterFlow, CoilControlNode, CoilOutletNode, plantLoc);
    9203        1590 :                 WaterCoils::SimulateWaterCoilComponents(state, HeatingCoilName, FirstHVACIteration, HeatingCoilIndex, QActual, fanOp);
    9204             : 
    9205        1590 :                 if (QActual > (QCoilLoad + HVAC::SmallLoad)) {
    9206             :                     // control water flow to obtain output matching QCoilLoad
    9207        1468 :                     MinWaterFlow = 0.0;
    9208      337740 :                     auto f = [&state, FurnaceNum, FirstHVACIteration, QCoilLoad, SuppHeatingCoilFlag](Real64 const HWFlow) {
    9209       22516 :                         Real64 QCoilRequested = QCoilLoad;
    9210             : 
    9211             :                         // FUNCTION LOCAL VARIABLE DECLARATIONS:
    9212             :                         Real64 QCoilActual;   // delivered coil load, W
    9213       22516 :                         Real64 mdot = HWFlow; // to get non-const argument
    9214       22516 :                         QCoilActual = QCoilRequested;
    9215       22516 :                         if (!SuppHeatingCoilFlag) {
    9216           0 :                             PlantUtilities::SetComponentFlowRate(state,
    9217             :                                                                  mdot,
    9218           0 :                                                                  state.dataFurnaces->Furnace(FurnaceNum).CoilControlNode,
    9219           0 :                                                                  state.dataFurnaces->Furnace(FurnaceNum).CoilOutletNode,
    9220           0 :                                                                  state.dataFurnaces->Furnace(FurnaceNum).plantLoc);
    9221           0 :                             WaterCoils::SimulateWaterCoilComponents(state,
    9222           0 :                                                                     state.dataFurnaces->Furnace(FurnaceNum).HeatingCoilName,
    9223             :                                                                     FirstHVACIteration,
    9224           0 :                                                                     state.dataFurnaces->Furnace(FurnaceNum).HeatingCoilIndex,
    9225             :                                                                     QCoilActual,
    9226           0 :                                                                     state.dataFurnaces->Furnace(FurnaceNum).fanOp);
    9227             :                         } else {
    9228             :                             // supplemental coil
    9229       45032 :                             PlantUtilities::SetComponentFlowRate(state,
    9230             :                                                                  mdot,
    9231       22516 :                                                                  state.dataFurnaces->Furnace(FurnaceNum).SuppCoilControlNode,
    9232       22516 :                                                                  state.dataFurnaces->Furnace(FurnaceNum).SuppCoilOutletNode,
    9233       22516 :                                                                  state.dataFurnaces->Furnace(FurnaceNum).SuppPlantLoc);
    9234             :                             // simulate the hot water supplemental heating coil
    9235       67548 :                             WaterCoils::SimulateWaterCoilComponents(state,
    9236       22516 :                                                                     state.dataFurnaces->Furnace(FurnaceNum).SuppHeatCoilName,
    9237             :                                                                     FirstHVACIteration,
    9238       22516 :                                                                     state.dataFurnaces->Furnace(FurnaceNum).SuppHeatCoilIndex,
    9239             :                                                                     QCoilActual,
    9240       22516 :                                                                     state.dataFurnaces->Furnace(FurnaceNum).fanOp);
    9241             :                         }
    9242       22516 :                         return QCoilRequested != 0.0 ? (QCoilActual - QCoilRequested) / QCoilRequested : 0.0;
    9243        1468 :                     };
    9244        1468 :                     int SolFlag = 0;
    9245        1468 :                     General::SolveRoot(state, ErrTolerance, SolveMaxIter, SolFlag, HotWaterMdot, f, MinWaterFlow, MaxHotWaterFlow);
    9246        1468 :                     if (SolFlag == -1) {
    9247           0 :                         if (thisFurnace.HotWaterCoilMaxIterIndex == 0) {
    9248           0 :                             ShowWarningMessage(state,
    9249           0 :                                                format("CalcNonDXHeatingCoils: Hot water coil control failed for {}=\"{}\"",
    9250           0 :                                                       HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    9251           0 :                                                       thisFurnace.Name));
    9252           0 :                             ShowContinueErrorTimeStamp(state, "");
    9253           0 :                             ShowContinueError(state, format("  Iteration limit [{}] exceeded in calculating hot water mass flow rate", SolveMaxIter));
    9254             :                         }
    9255           0 :                         ShowRecurringWarningErrorAtEnd(
    9256             :                             state,
    9257           0 :                             format("CalcNonDXHeatingCoils: Hot water coil control failed (iteration limit [{}]) for {}=\"{}",
    9258             :                                    SolveMaxIter,
    9259           0 :                                    HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    9260           0 :                                    thisFurnace.Name),
    9261           0 :                             thisFurnace.HotWaterCoilMaxIterIndex);
    9262        1468 :                     } else if (SolFlag == -2) {
    9263           0 :                         if (thisFurnace.HotWaterCoilMaxIterIndex2 == 0) {
    9264           0 :                             ShowWarningMessage(state,
    9265           0 :                                                format("CalcNonDXHeatingCoils: Hot water coil control failed (maximum flow limits) for {}=\"{}\"",
    9266           0 :                                                       HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    9267           0 :                                                       thisFurnace.Name));
    9268           0 :                             ShowContinueErrorTimeStamp(state, "");
    9269           0 :                             ShowContinueError(state, "...Bad hot water maximum flow rate limits");
    9270           0 :                             ShowContinueError(state, format("...Given minimum water flow rate={:.3R} kg/s", MinWaterFlow));
    9271           0 :                             ShowContinueError(state, format("...Given maximum water flow rate={:.3R} kg/s", MaxHotWaterFlow));
    9272             :                         }
    9273           0 :                         ShowRecurringWarningErrorAtEnd(state,
    9274           0 :                                                        format("CalcNonDXHeatingCoils: Hot water coil control failed (flow limits) for {}=\"{}\"",
    9275           0 :                                                               HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    9276           0 :                                                               thisFurnace.Name),
    9277           0 :                                                        thisFurnace.HotWaterCoilMaxIterIndex2,
    9278             :                                                        MaxHotWaterFlow,
    9279             :                                                        MinWaterFlow,
    9280             :                                                        _,
    9281             :                                                        "[kg/s]",
    9282             :                                                        "[kg/s]");
    9283             :                     }
    9284             :                 }
    9285             :             } else {
    9286       89138 :                 mdot = 0.0;
    9287       89138 :                 PlantUtilities::SetComponentFlowRate(state, mdot, CoilControlNode, CoilOutletNode, plantLoc);
    9288             :             }
    9289             :             // simulate the hot water heating coil
    9290       90728 :             WaterCoils::SimulateWaterCoilComponents(state, HeatingCoilName, FirstHVACIteration, HeatingCoilIndex, QActual, fanOp);
    9291       90728 :         } break;
    9292           0 :         case HVAC::Coil_HeatingSteam: {
    9293           0 :             if (QCoilLoad > HVAC::SmallLoad) {
    9294           0 :                 PlantUtilities::SetComponentFlowRate(state, MaxHotWaterFlow, CoilControlNode, CoilOutletNode, plantLoc);
    9295             :                 // simulate the steam heating coil
    9296           0 :                 SteamCoils::SimulateSteamCoilComponents(state, HeatingCoilName, FirstHVACIteration, HeatingCoilIndex, QCoilLoad, QActual, fanOp);
    9297             :             } else {
    9298           0 :                 mdot = 0.0;
    9299           0 :                 PlantUtilities::SetComponentFlowRate(state, mdot, CoilControlNode, CoilOutletNode, plantLoc);
    9300             :                 // simulate the steam heating coil
    9301           0 :                 SteamCoils::SimulateSteamCoilComponents(state, HeatingCoilName, FirstHVACIteration, HeatingCoilIndex, QCoilLoad, QActual, fanOp);
    9302             :             }
    9303           0 :         } break;
    9304           0 :         default:
    9305           0 :             break;
    9306             :         }
    9307             : 
    9308    67595255 :         HeatCoilLoadmet = QActual;
    9309    67595255 :     }
    9310             : 
    9311             :     //        End of Reporting subroutines for the Furnace Module
    9312             : 
    9313             :     //******************************************************************************
    9314             : 
    9315     1507624 :     void SimVariableSpeedHP(EnergyPlusData &state,
    9316             :                             int const FurnaceNum,          // number of the current engine driven Heat Pump being simulated
    9317             :                             bool const FirstHVACIteration, // TRUE if 1st HVAC simulation of system timestep
    9318             :                             int const AirLoopNum,          // index to air loop
    9319             :                             Real64 const QZnReq,           // required zone load
    9320             :                             Real64 const QLatReq,          // required latent load
    9321             :                             Real64 &OnOffAirFlowRatio      // ratio of compressor ON airflow to AVERAGE airflow over timestep
    9322             :     )
    9323             :     {
    9324             : 
    9325             :         // SUBROUTINE INFORMATION:
    9326             :         //       AUTHOR         Bo Shen, based on HVACMultiSpeedHeatPump:CalcMSHeatPump
    9327             :         //       DATE WRITTEN   March, 2012
    9328             : 
    9329             :         // PURPOSE OF THIS SUBROUTINE:
    9330             :         // Simulate a multispeed heat pump; adjust its output to match the
    9331             :         // required system load.
    9332             : 
    9333             :         // METHODOLOGY EMPLOYED:
    9334             :         // Calls ControlMSHPOutput to obtain the desired unit output
    9335             : 
    9336             :         Real64 PartLoadFrac; // compressor part load fraction
    9337             :         Real64 SpeedRatio;   // compressor speed ratio
    9338             :         Real64 QTotUnitOut;  // capacity output
    9339     1507624 :         auto &SpeedNum = state.dataFurnaces->SpeedNum;
    9340     1507624 :         auto &SupHeaterLoad = state.dataFurnaces->SupHeaterLoad;
    9341             :         HVAC::CompressorOp compressorOp; // compressor operation; 1=on, 0=off
    9342             :         Real64 QSensUnitOut;             // sensible capacity output
    9343             :         Real64 QLatUnitOut;              // latent capacity output
    9344             :         Real64 ActualSensibleOutput;     // Actual furnace sensible capacity
    9345             :         Real64 QToHeatSetPt;             // Load required to meet heating setpoint temp (>0 is a heating load)
    9346             :         Real64 NoCompOutput;             // output when no active compressor [W]
    9347             :         bool EconoActive;                // TRUE if Economizer is active
    9348             : 
    9349             :         // zero DX coils, and supplemental electric heater electricity consumption
    9350     1507624 :         state.dataHVACGlobal->DXElecHeatingPower = 0.0;
    9351     1507624 :         state.dataHVACGlobal->DXElecCoolingPower = 0.0;
    9352     1507624 :         state.dataFurnaces->SaveCompressorPLR = 0.0;
    9353     1507624 :         state.dataHVACGlobal->ElecHeatingCoilPower = 0.0;
    9354     1507624 :         state.dataHVACGlobal->SuppHeatingCoilPower = 0.0;
    9355     1507624 :         state.dataHVACGlobal->DefrostElecPower = 0.0;
    9356             : 
    9357     1507624 :         Real64 SystemSensibleLoad = QZnReq; // Positive value means heating required
    9358     1507624 :         Real64 TotalZoneSensibleLoad = QZnReq;
    9359     1507624 :         Real64 TotalZoneLatentLoad = QLatReq;
    9360     1507624 :         auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    9361             :         // initialize local variables
    9362     1507624 :         bool UnitOn = true;
    9363     1507624 :         int OutletNode = thisFurnace.FurnaceOutletNodeNum;
    9364     1507624 :         int InletNode = thisFurnace.FurnaceInletNodeNum;
    9365     1507624 :         Real64 AirMassFlow = thisFurnace.DesignMassFlowRate;
    9366     1507624 :         HVAC::FanOp fanOp = thisFurnace.fanOp; // fan operating mode
    9367     1507624 :         int ZoneNum = thisFurnace.ControlZoneNum;
    9368             : 
    9369             :         // Set latent load for heating
    9370     1507624 :         if (state.dataFurnaces->HeatingLoad) {
    9371      105434 :             thisFurnace.HeatCoolMode = Furnaces::ModeOfOperation::HeatingMode;
    9372             :             // Set latent load for cooling and no sensible load condition
    9373     1402190 :         } else if (state.dataFurnaces->CoolingLoad) {
    9374     1302969 :             thisFurnace.HeatCoolMode = Furnaces::ModeOfOperation::CoolingMode;
    9375             :         } else {
    9376       99221 :             thisFurnace.HeatCoolMode = Furnaces::ModeOfOperation::NoCoolHeat;
    9377             :         }
    9378             : 
    9379             :         // set the on/off flags
    9380     1507624 :         if (thisFurnace.fanOp == HVAC::FanOp::Cycling) {
    9381             :             // cycling unit only runs if there is a cooling or heating load.
    9382       55903 :             if (std::abs(QZnReq) < HVAC::SmallLoad || AirMassFlow < HVAC::SmallMassFlow ||
    9383       25641 :                 state.dataZoneEnergyDemand->CurDeadBandOrSetback(ZoneNum)) {
    9384        4624 :                 UnitOn = false;
    9385             :             }
    9386     1477362 :         } else if (thisFurnace.fanOp == HVAC::FanOp::Continuous) {
    9387             :             // continuous unit: fan runs if scheduled on; coil runs only if there is a cooling or heating load
    9388     1477362 :             if (AirMassFlow < HVAC::SmallMassFlow) {
    9389           0 :                 UnitOn = false;
    9390             :             }
    9391             :         }
    9392             : 
    9393     1507624 :         state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
    9394     1507624 :         EconoActive = (AirLoopNum != 0) ? state.dataAirLoop->AirLoopControlInfo(AirLoopNum).EconoActive : false;
    9395             : 
    9396     1507624 :         Real64 SaveMassFlowRate = state.dataLoopNodes->Node(InletNode).MassFlowRate;
    9397             :         // decide current working mode for IHP
    9398     1507624 :         if ((FirstHVACIteration) && (thisFurnace.bIsIHP))
    9399        5024 :             IntegratedHeatPump::DecideWorkMode(state, thisFurnace.CoolingCoilIndex, TotalZoneSensibleLoad, TotalZoneLatentLoad);
    9400             : 
    9401     1507624 :         if (!FirstHVACIteration && thisFurnace.fanOp == HVAC::FanOp::Cycling &&
    9402       15160 :             (QZnReq < (-1.0 * HVAC::SmallLoad) || TotalZoneLatentLoad < (-HVAC::SmallLoad)) && EconoActive) {
    9403             :             // for cycling fan, cooling load, check whether furnace can meet load with compressor off
    9404           0 :             compressorOp = HVAC::CompressorOp::Off;
    9405           0 :             ControlVSHPOutput(state,
    9406             :                               FurnaceNum,
    9407             :                               FirstHVACIteration,
    9408             :                               compressorOp,
    9409             :                               fanOp,
    9410             :                               TotalZoneSensibleLoad,
    9411             :                               TotalZoneLatentLoad,
    9412             :                               SpeedNum,
    9413             :                               SpeedRatio,
    9414             :                               PartLoadFrac,
    9415             :                               OnOffAirFlowRatio,
    9416             :                               SupHeaterLoad);
    9417             : 
    9418           0 :             TotalZoneSensibleLoad = QZnReq;
    9419           0 :             TotalZoneLatentLoad = QLatReq;
    9420             : 
    9421           0 :             if (SpeedNum == thisFurnace.NumOfSpeedCooling && SpeedRatio == 1.0) {
    9422             :                 // compressor on (reset inlet air mass flow rate to starting value)
    9423           0 :                 state.dataLoopNodes->Node(InletNode).MassFlowRate = SaveMassFlowRate;
    9424           0 :                 compressorOp = HVAC::CompressorOp::On;
    9425           0 :                 ControlVSHPOutput(state,
    9426             :                                   FurnaceNum,
    9427             :                                   FirstHVACIteration,
    9428             :                                   compressorOp,
    9429             :                                   fanOp,
    9430             :                                   TotalZoneSensibleLoad,
    9431             :                                   TotalZoneLatentLoad,
    9432             :                                   SpeedNum,
    9433             :                                   SpeedRatio,
    9434             :                                   PartLoadFrac,
    9435             :                                   OnOffAirFlowRatio,
    9436             :                                   SupHeaterLoad);
    9437             :             }
    9438             :         } else {
    9439             :             // compressor on
    9440     1507624 :             compressorOp = HVAC::CompressorOp::On;
    9441             : 
    9442     1507624 :             ControlVSHPOutput(state,
    9443             :                               FurnaceNum,
    9444             :                               FirstHVACIteration,
    9445             :                               compressorOp,
    9446             :                               fanOp,
    9447             :                               TotalZoneSensibleLoad,
    9448             :                               TotalZoneLatentLoad,
    9449             :                               SpeedNum,
    9450             :                               SpeedRatio,
    9451             :                               PartLoadFrac,
    9452             :                               OnOffAirFlowRatio,
    9453             :                               SupHeaterLoad);
    9454             :         }
    9455             : 
    9456     1507624 :         if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatCool) {
    9457     1247320 :             state.dataFurnaces->SaveCompressorPLR = PartLoadFrac;
    9458             :         } else {
    9459      260304 :             if (SpeedNum > 1) {
    9460      110053 :                 state.dataFurnaces->SaveCompressorPLR = 1.0;
    9461             :             }
    9462             : 
    9463      260304 :             if (PartLoadFrac == 1.0 && state.dataFurnaces->SaveCompressorPLR < 1.0) {
    9464          10 :                 PartLoadFrac = state.dataFurnaces->SaveCompressorPLR;
    9465             :             }
    9466             :         }
    9467             : 
    9468     1507624 :         Real64 ReheatCoilLoad = 0.0;
    9469     1507624 :         TotalZoneSensibleLoad = QZnReq;
    9470     1507624 :         TotalZoneLatentLoad = QLatReq;
    9471             :         //     Calculate the reheat coil output
    9472     3003668 :         if ((ScheduleManager::GetCurrentScheduleValue(state, thisFurnace.SchedPtr) > 0.0) &&
    9473     1496044 :             (thisFurnace.Humidistat && thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat &&
    9474             :              (QLatReq < 0.0))) { // if a Humidistat is installed and dehumdification control type is CoolReheat
    9475       74584 :             CalcVarSpeedHeatPump(state,
    9476             :                                  FurnaceNum,
    9477             :                                  FirstHVACIteration,
    9478             :                                  compressorOp,
    9479             :                                  SpeedNum,
    9480             :                                  SpeedRatio,
    9481             :                                  PartLoadFrac,
    9482             :                                  ActualSensibleOutput,
    9483             :                                  QLatUnitOut,
    9484             :                                  TotalZoneSensibleLoad,
    9485             :                                  TotalZoneLatentLoad,
    9486             :                                  OnOffAirFlowRatio,
    9487             :                                  ReheatCoilLoad);
    9488       74584 :             if (thisFurnace.ZoneSequenceHeatingNum > 0) {
    9489       74584 :                 QToHeatSetPt = (state.dataZoneEnergyDemand->ZoneSysEnergyDemand(thisFurnace.ControlZoneNum)
    9490       74584 :                                     .SequencedOutputRequiredToHeatingSP(thisFurnace.ZoneSequenceHeatingNum) /
    9491       74584 :                                 thisFurnace.ControlZoneMassFlowFrac);
    9492             :             } else {
    9493           0 :                 QToHeatSetPt = (state.dataZoneEnergyDemand->ZoneSysEnergyDemand(thisFurnace.ControlZoneNum).OutputRequiredToHeatingSP /
    9494           0 :                                 thisFurnace.ControlZoneMassFlowFrac);
    9495             :             }
    9496             :             //       Cooling mode or floating condition and dehumidification is required
    9497       74584 :             if (QToHeatSetPt < 0.0) {
    9498             :                 //         Calculate the reheat coil load wrt the heating setpoint temperature. Reheat coil picks up
    9499             :                 //         the entire excess sensible cooling (DX cooling coil and impact of outdoor air).
    9500       52682 :                 ReheatCoilLoad = max(0.0, (QToHeatSetPt - ActualSensibleOutput));
    9501       52682 :                 thisFurnace.DehumidInducedHeatingDemandRate = ReheatCoilLoad;
    9502             :                 //       Heating mode and dehumidification is required
    9503             :             } else {
    9504       21902 :                 ReheatCoilLoad = max(QToHeatSetPt, QToHeatSetPt - ActualSensibleOutput);
    9505       21902 :                 thisFurnace.DehumidInducedHeatingDemandRate = max(0.0, ActualSensibleOutput * (-1.0));
    9506             :             }
    9507             : 
    9508       74584 :             SupHeaterLoad = 0.0;
    9509       74584 :             CalcVarSpeedHeatPump(state,
    9510             :                                  FurnaceNum,
    9511             :                                  FirstHVACIteration,
    9512             :                                  compressorOp,
    9513             :                                  1,
    9514             :                                  0.0,
    9515             :                                  0.0,
    9516             :                                  NoCompOutput,
    9517             :                                  QLatUnitOut,
    9518             :                                  0.0,
    9519             :                                  0.0,
    9520             :                                  OnOffAirFlowRatio,
    9521             :                                  SupHeaterLoad);
    9522             : 
    9523       74584 :             if (NoCompOutput > SystemSensibleLoad && SystemSensibleLoad > 0.0 && ReheatCoilLoad > 0.0) {
    9524             :                 // Reduce reheat coil load if you are controlling high humidity but outside air
    9525             :                 // and/or the supply air fan is providing enough heat to meet the system sensible load.
    9526             :                 // This will bring the zone temp closer to the heating setpoint temp.
    9527        4561 :                 ReheatCoilLoad = max(0.0, ReheatCoilLoad - (NoCompOutput - SystemSensibleLoad));
    9528             :             }
    9529             :         } else {
    9530             :             //       No humidistat installed
    9531     1433040 :             ReheatCoilLoad = 0.0;
    9532             :         }
    9533             : 
    9534     1507624 :         TotalZoneSensibleLoad = QZnReq;
    9535     1507624 :         TotalZoneLatentLoad = QLatReq;
    9536     1507624 :         if (ReheatCoilLoad > 0.0) {
    9537       65311 :             CalcVarSpeedHeatPump(state,
    9538             :                                  FurnaceNum,
    9539             :                                  FirstHVACIteration,
    9540             :                                  compressorOp,
    9541             :                                  SpeedNum,
    9542             :                                  SpeedRatio,
    9543             :                                  PartLoadFrac,
    9544             :                                  QSensUnitOut,
    9545             :                                  QLatUnitOut,
    9546             :                                  TotalZoneSensibleLoad,
    9547             :                                  TotalZoneLatentLoad,
    9548             :                                  OnOffAirFlowRatio,
    9549             :                                  ReheatCoilLoad);
    9550             :         } else {
    9551     1442313 :             CalcVarSpeedHeatPump(state,
    9552             :                                  FurnaceNum,
    9553             :                                  FirstHVACIteration,
    9554             :                                  compressorOp,
    9555             :                                  SpeedNum,
    9556             :                                  SpeedRatio,
    9557             :                                  PartLoadFrac,
    9558             :                                  QSensUnitOut,
    9559             :                                  QLatUnitOut,
    9560             :                                  TotalZoneSensibleLoad,
    9561             :                                  TotalZoneLatentLoad,
    9562             :                                  OnOffAirFlowRatio,
    9563             :                                  SupHeaterLoad);
    9564             :         }
    9565             : 
    9566             :         // calculate delivered capacity
    9567     1507624 :         AirMassFlow = state.dataLoopNodes->Node(InletNode).MassFlowRate;
    9568             : 
    9569     1507624 :         thisFurnace.MdotFurnace = AirMassFlow;
    9570             : 
    9571     1507624 :         QTotUnitOut =
    9572     1507624 :             AirMassFlow * (state.dataLoopNodes->Node(OutletNode).Enthalpy - state.dataLoopNodes->Node(thisFurnace.NodeNumOfControlledZone).Enthalpy);
    9573             : 
    9574     1507624 :         state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail = AirMassFlow;
    9575     1507624 :         state.dataLoopNodes->Node(OutletNode).MassFlowRateMaxAvail = AirMassFlow;
    9576             : 
    9577     1507624 :         if (!FirstHVACIteration && AirMassFlow > 0.0 && AirLoopNum > 0) {
    9578     1408368 :             int TotBranchNum = state.dataAirSystemsData->PrimaryAirSystems(AirLoopNum).NumOutletBranches;
    9579     1408368 :             if (TotBranchNum == 1) {
    9580     1408368 :                 int ZoneSideNodeNum = state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).ZoneEquipSupplyNodeNum(1);
    9581             :                 // THE MASS FLOW PRECISION of the system solver is not enough for some small air flow rate iterations , BY DEBUGGING
    9582             :                 // it may cause mass flow rate occilations between airloop and zoneequip
    9583             :                 // specify the air flow rate directly for one-to-one system, when the iteration deviation is closing the solver precision level
    9584             :                 // 0.02 is 2 * HVACFlowRateToler, in order to accomodate the system solver precision level
    9585     1408368 :                 if (std::abs(AirMassFlow - state.dataLoopNodes->Node(ZoneSideNodeNum).MassFlowRate) < 0.02)
    9586      797935 :                     state.dataLoopNodes->Node(ZoneSideNodeNum).MassFlowRateMaxAvail = AirMassFlow;
    9587     1408368 :                 state.dataLoopNodes->Node(ZoneSideNodeNum).MassFlowRate = AirMassFlow;
    9588             :             }
    9589             : 
    9590             :             // the below might be useful if more divergences occur
    9591             :             // Node(PrimaryAirSystem(AirLoopNumber)%Branch(1)%NodeNumIn)%MassFlowRateMaxAvail = AirMassFlow
    9592             :             // Node(PrimaryAirSystem(AirLoopNumber)%Branch(1)%NodeNumIn)%MassFlowRate = AirMassFlow
    9593             :         }
    9594             : 
    9595             :         // report variables
    9596     1507624 :         thisFurnace.DehumidInducedHeatingDemandRate = ReheatCoilLoad;
    9597     1507624 :         if (QZnReq > HVAC::SmallLoad) { // HEATING LOAD
    9598      123543 :             thisFurnace.CoolingCoilSensDemand = 0.0;
    9599      123543 :             thisFurnace.HeatingCoilSensDemand = QZnReq;
    9600             :         } else {
    9601     1384081 :             thisFurnace.CoolingCoilSensDemand = std::abs(QZnReq);
    9602     1384081 :             thisFurnace.HeatingCoilSensDemand = 0.0;
    9603             :         }
    9604             : 
    9605     1507624 :         thisFurnace.CompPartLoadRatio = state.dataFurnaces->SaveCompressorPLR;
    9606     1507624 :         if (thisFurnace.fanOp == HVAC::FanOp::Cycling) {
    9607       30262 :             if (SupHeaterLoad > 0.0) {
    9608       13986 :                 thisFurnace.FanPartLoadRatio = 1.0;
    9609             :             } else {
    9610       16276 :                 if (SpeedNum < 2) {
    9611        8962 :                     thisFurnace.FanPartLoadRatio = PartLoadFrac;
    9612             :                 } else {
    9613        7314 :                     thisFurnace.FanPartLoadRatio = 1.0;
    9614             :                 }
    9615             :             }
    9616             :         } else {
    9617     1477362 :             if (UnitOn) {
    9618     1477362 :                 thisFurnace.FanPartLoadRatio = 1.0;
    9619             :             } else {
    9620           0 :                 if (SpeedNum < 2) {
    9621           0 :                     thisFurnace.FanPartLoadRatio = PartLoadFrac;
    9622             :                 } else {
    9623           0 :                     thisFurnace.FanPartLoadRatio = 1.0;
    9624             :                 }
    9625             :             }
    9626             :         }
    9627     1507624 :     }
    9628             : 
    9629             :     //******************************************************************************
    9630             : 
    9631     1507624 :     void ControlVSHPOutput(EnergyPlusData &state,
    9632             :                            int const FurnaceNum,                  // Unit index of engine driven heat pump
    9633             :                            bool const FirstHVACIteration,         // flag for 1st HVAC iteration in the time step
    9634             :                            HVAC::CompressorOp const compressorOp, // compressor operation; 1=on, 0=off
    9635             :                            HVAC::FanOp const fanOp,               // operating mode: FanOp::Cycling | FanOp::Continuous
    9636             :                            Real64 &QZnReq,                        // cooling or heating output needed by zone [W]
    9637             :                            Real64 QLatReq,                        // latent cooling output needed by zone [W]
    9638             :                            int &SpeedNum,                         // Speed number
    9639             :                            Real64 &SpeedRatio,                    // unit speed ratio for DX coils
    9640             :                            Real64 &PartLoadFrac,                  // unit part load fraction
    9641             :                            Real64 &OnOffAirFlowRatio,             // ratio of compressor ON airflow to AVERAGE airflow over timestep
    9642             :                            Real64 &SupHeaterLoad                  // Supplemental heater load [W]
    9643             :     )
    9644             :     {
    9645             : 
    9646             :         // SUBROUTINE INFORMATION:
    9647             :         //       AUTHOR         Bo Shen, based on HVACMultiSpeedHeatPump:ControlMSHPOutput
    9648             :         //       DATE WRITTEN   March,  2012
    9649             : 
    9650             :         // PURPOSE OF THIS SUBROUTINE:
    9651             :         // Determine the part load fraction at low speed, and speed ratio at high speed for this time step.
    9652             : 
    9653             :         // METHODOLOGY EMPLOYED:
    9654             :         // Use RegulaFalsi technique to iterate on part-load ratio until convergence is achieved.
    9655             : 
    9656             :         // SUBROUTINE PARAMETER DEFINITIONS:
    9657     1507624 :         int constexpr MaxIte(500); // maximum number of iterations
    9658             : 
    9659             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    9660             :         Real64 FullOutput;   // unit full output when compressor is operating [W]
    9661             :         Real64 LowOutput;    // unit full output at low speed [W]
    9662             :         Real64 TempOutput;   // unit output when iteration limit exceeded [W]
    9663             :         Real64 NoCompOutput; // output when no active compressor [W]
    9664             :         int SolFla;          // Flag of RegulaFalsi solver
    9665             :         Real64 QCoilActual;  // coil load actually delivered returned to calling component
    9666             :         int i;               // Speed index
    9667     1507624 :         IntegratedHeatPump::IHPOperationMode IHPMode(IntegratedHeatPump::IHPOperationMode::Idle);
    9668             : 
    9669     1507624 :         SupHeaterLoad = 0.0;
    9670     1507624 :         PartLoadFrac = 0.0;
    9671     1507624 :         SpeedRatio = 0.0;
    9672     1507624 :         SpeedNum = 1;
    9673     1507624 :         Real64 LatOutput = 0.0;
    9674     1507624 :         Real64 noLatOutput = 0.0;
    9675     1507624 :         Real64 ErrorToler = 0.001; // Error tolerance for convergence from input deck
    9676             : 
    9677     1507624 :         auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    9678     1544558 :         if (ScheduleManager::GetCurrentScheduleValue(state, thisFurnace.SchedPtr) == 0.0) return;
    9679             : 
    9680             :         // Get result when DX coil is off
    9681     1496044 :         SupHeaterLoad = 0.0;
    9682     1496044 :         CalcVarSpeedHeatPump(state,
    9683             :                              FurnaceNum,
    9684             :                              FirstHVACIteration,
    9685             :                              compressorOp,
    9686             :                              SpeedNum,
    9687             :                              SpeedRatio,
    9688             :                              PartLoadFrac,
    9689             :                              NoCompOutput,
    9690             :                              noLatOutput,
    9691             :                              0.0,
    9692             :                              0.0,
    9693             :                              OnOffAirFlowRatio,
    9694             :                              SupHeaterLoad);
    9695             : 
    9696     1496044 :         if (thisFurnace.bIsIHP) {
    9697       10094 :             IHPMode = IntegratedHeatPump::GetCurWorkMode(state, thisFurnace.CoolingCoilIndex);
    9698       10094 :             if ((IntegratedHeatPump::IHPOperationMode::DedicatedWaterHtg == IHPMode) ||
    9699             :                 (IntegratedHeatPump::IHPOperationMode::SCWHMatchWH == IHPMode)) { // cooling capacity is a resultant
    9700         280 :                 return;
    9701             :             }
    9702             :         }
    9703             : 
    9704             :         // If cooling and NoCompOutput < QZnReq, the coil needs to be off
    9705             :         // If heating and NoCompOutput > QZnReq, the coil needs to be off
    9706             :         // If no cooling or heating and no latent load, the coil needs to be off
    9707     1495764 :         if (QZnReq < -HVAC::SmallLoad) {
    9708     1285333 :             if (NoCompOutput < QZnReq && QLatReq >= -HVAC::SmallLoad) return;
    9709      210431 :         } else if (QZnReq > HVAC::SmallLoad) {
    9710      123543 :             if (NoCompOutput > QZnReq && QLatReq >= -HVAC::SmallLoad) return;
    9711      122174 :             if (QLatReq <= -HVAC::SmallLoad) QZnReq = 0.0; // Zero heating load to allow dehumidification
    9712             :         } else {
    9713       86888 :             if (QLatReq >= -HVAC::SmallLoad) return;
    9714             :         }
    9715             : 
    9716             :         // Get full load result
    9717     1461601 :         PartLoadFrac = 1.0;
    9718     1461601 :         SpeedRatio = 1.0;
    9719     1461601 :         if (thisFurnace.HeatCoolMode == Furnaces::ModeOfOperation::HeatingMode) {
    9720      105096 :             SpeedNum = thisFurnace.NumOfSpeedHeating;
    9721     1356505 :         } else if (thisFurnace.HeatCoolMode == Furnaces::ModeOfOperation::CoolingMode) {
    9722     1301628 :             SpeedNum = thisFurnace.NumOfSpeedCooling;
    9723       54877 :         } else if (QLatReq < -HVAC::SmallLoad) {
    9724       54476 :             SpeedNum = thisFurnace.NumOfSpeedCooling;
    9725             :         } else {
    9726         401 :             SpeedNum = 1;
    9727         401 :             PartLoadFrac = 0.0;
    9728             :         }
    9729             : 
    9730     1461601 :         if (thisFurnace.bIsIHP) SpeedNum = IntegratedHeatPump::GetMaxSpeedNumIHP(state, thisFurnace.CoolingCoilIndex);
    9731             : 
    9732     1461601 :         CalcVarSpeedHeatPump(state,
    9733             :                              FurnaceNum,
    9734             :                              FirstHVACIteration,
    9735             :                              compressorOp,
    9736             :                              SpeedNum,
    9737             :                              SpeedRatio,
    9738             :                              PartLoadFrac,
    9739             :                              FullOutput,
    9740             :                              LatOutput,
    9741             :                              QZnReq,
    9742             :                              QLatReq,
    9743             :                              OnOffAirFlowRatio,
    9744             :                              SupHeaterLoad);
    9745             : 
    9746     1461601 :         if (QLatReq < (-1.0 * HVAC::SmallLoad)) { // dehumidification mode
    9747       74584 :             if (QLatReq <= LatOutput || (QZnReq < -HVAC::SmallLoad && QZnReq <= FullOutput) || (QZnReq > HVAC::SmallLoad && QZnReq >= FullOutput)) {
    9748         138 :                 PartLoadFrac = 1.0;
    9749         138 :                 SpeedRatio = 1.0;
    9750         138 :                 thisFurnace.CompPartLoadRatio = PartLoadFrac;
    9751         138 :                 thisFurnace.CompSpeedRatio = SpeedRatio;
    9752         138 :                 thisFurnace.CompSpeedNum = SpeedNum;
    9753         138 :                 return;
    9754             :             }
    9755     1387017 :         } else if (QZnReq < -HVAC::SmallLoad) {
    9756     1281851 :             if (QZnReq <= FullOutput) {
    9757        2353 :                 PartLoadFrac = 1.0;
    9758        2353 :                 SpeedRatio = 1.0;
    9759        2353 :                 thisFurnace.CompPartLoadRatio = PartLoadFrac;
    9760        2353 :                 thisFurnace.CompSpeedRatio = SpeedRatio;
    9761        2353 :                 thisFurnace.CompSpeedNum = SpeedNum;
    9762        2353 :                 return;
    9763             :             }
    9764             :         } else {
    9765      105166 :             if (QZnReq >= FullOutput) {
    9766       46302 :                 PartLoadFrac = 1.0;
    9767       46302 :                 SpeedRatio = 1.0;
    9768             :                 // may need supplemental heating so don't return in heating mode
    9769             :             }
    9770             :         }
    9771             : 
    9772     1459110 :         if ((QZnReq < -HVAC::SmallLoad && NoCompOutput - QZnReq > HVAC::SmallLoad) ||
    9773      176512 :             (QZnReq > HVAC::SmallLoad && QZnReq - NoCompOutput > HVAC::SmallLoad)) {
    9774     1387744 :             if ((QZnReq > HVAC::SmallLoad && QZnReq < FullOutput) || (QZnReq < (-1.0 * HVAC::SmallLoad) && QZnReq > FullOutput)) {
    9775             :                 // Check whether the low speed coil can meet the load or not
    9776     1341462 :                 CalcVarSpeedHeatPump(state,
    9777             :                                      FurnaceNum,
    9778             :                                      FirstHVACIteration,
    9779             :                                      compressorOp,
    9780             :                                      1,
    9781             :                                      0.0,
    9782             :                                      1.0,
    9783             :                                      LowOutput,
    9784             :                                      LatOutput,
    9785             :                                      QZnReq,
    9786             :                                      QLatReq,
    9787             :                                      OnOffAirFlowRatio,
    9788             :                                      SupHeaterLoad);
    9789     1341462 :                 if ((QZnReq > HVAC::SmallLoad && QZnReq <= LowOutput) || (QZnReq < (-HVAC::SmallLoad) && QZnReq >= LowOutput)) {
    9790             :                     // Calculate the part load fraction
    9791      335879 :                     SpeedRatio = 0.0;
    9792      335879 :                     SpeedNum = 1;
    9793             :                     auto f = // (AUTO_OK_LAMBDA)
    9794     2031213 :                         [&state, FurnaceNum, FirstHVACIteration, QZnReq, OnOffAirFlowRatio, SupHeaterLoad, compressorOp](Real64 const PartLoadFrac) {
    9795     1695334 :                             return VSHPCyclingResidual(
    9796     1695334 :                                 state, PartLoadFrac, FurnaceNum, FirstHVACIteration, QZnReq, OnOffAirFlowRatio, SupHeaterLoad, compressorOp, 1.0);
    9797      335879 :                         };
    9798      335879 :                     General::SolveRoot(state, ErrorToler, MaxIte, SolFla, PartLoadFrac, f, 0.0, 1.0);
    9799      335879 :                     if (SolFla == -1) {
    9800           0 :                         if (!state.dataGlobal->WarmupFlag) {
    9801           0 :                             if (thisFurnace.ErrCountCyc == 0) {
    9802           0 :                                 ++thisFurnace.ErrCountCyc;
    9803           0 :                                 ShowWarningError(
    9804           0 :                                     state, format("Iteration limit exceeded calculating VS WSHP unit cycling ratio, for unit={}", thisFurnace.Name));
    9805           0 :                                 ShowContinueErrorTimeStamp(state, format("Cycling ratio returned={:.2R}", PartLoadFrac));
    9806             :                             } else {
    9807           0 :                                 ShowRecurringWarningErrorAtEnd(
    9808             :                                     state,
    9809           0 :                                     thisFurnace.Name + "\": Iteration limit warning exceeding calculating DX unit cycling ratio  continues...",
    9810           0 :                                     thisFurnace.ErrIndexCyc,
    9811             :                                     PartLoadFrac,
    9812             :                                     PartLoadFrac);
    9813             :                             }
    9814             :                         }
    9815      335879 :                     } else if (SolFla == -2) {
    9816           0 :                         ShowFatalError(
    9817           0 :                             state, format("VS WSHP unit cycling ratio calculation failed: cycling limits exceeded, for unit={}", thisFurnace.Name));
    9818             :                     }
    9819      335879 :                 } else {
    9820             :                     // Check to see which speed to meet the load
    9821     1005583 :                     PartLoadFrac = 1.0;
    9822     1005583 :                     SpeedRatio = 1.0;
    9823     1005583 :                     if (QZnReq < -HVAC::SmallLoad) { // Cooling
    9824     4429293 :                         for (i = 2; i <= thisFurnace.NumOfSpeedCooling; ++i) {
    9825     4429293 :                             CalcVarSpeedHeatPump(state,
    9826             :                                                  FurnaceNum,
    9827             :                                                  FirstHVACIteration,
    9828             :                                                  compressorOp,
    9829             :                                                  i,
    9830             :                                                  SpeedRatio,
    9831             :                                                  PartLoadFrac,
    9832             :                                                  TempOutput,
    9833             :                                                  LatOutput,
    9834             :                                                  QZnReq,
    9835             :                                                  QLatReq,
    9836             :                                                  OnOffAirFlowRatio,
    9837             :                                                  SupHeaterLoad);
    9838             : 
    9839     4429293 :                             if (QZnReq >= TempOutput) {
    9840      965495 :                                 SpeedNum = i;
    9841      965495 :                                 break;
    9842             :                             }
    9843             :                         }
    9844             :                     } else {
    9845      190721 :                         for (i = 2; i <= thisFurnace.NumOfSpeedHeating; ++i) {
    9846      190721 :                             CalcVarSpeedHeatPump(state,
    9847             :                                                  FurnaceNum,
    9848             :                                                  FirstHVACIteration,
    9849             :                                                  compressorOp,
    9850             :                                                  i,
    9851             :                                                  SpeedRatio,
    9852             :                                                  PartLoadFrac,
    9853             :                                                  TempOutput,
    9854             :                                                  LatOutput,
    9855             :                                                  QZnReq,
    9856             :                                                  QLatReq,
    9857             :                                                  OnOffAirFlowRatio,
    9858             :                                                  SupHeaterLoad);
    9859      190721 :                             if (QZnReq <= TempOutput) {
    9860       40088 :                                 SpeedNum = i;
    9861       40088 :                                 break;
    9862             :                             }
    9863             :                         }
    9864             :                     }
    9865     4433648 :                     auto f = [&state, FurnaceNum, FirstHVACIteration, QZnReq, OnOffAirFlowRatio, SupHeaterLoad, SpeedNum, compressorOp](
    9866     3428065 :                                  Real64 const SpeedRatio) {
    9867     3428065 :                         return VSHPSpeedResidual(
    9868     3428065 :                             state, SpeedRatio, FurnaceNum, FirstHVACIteration, QZnReq, OnOffAirFlowRatio, SupHeaterLoad, SpeedNum, compressorOp, 1.0);
    9869     1005583 :                     };
    9870     1005583 :                     General::SolveRoot(state, ErrorToler, MaxIte, SolFla, SpeedRatio, f, 1.0e-10, 1.0);
    9871     1005583 :                     if (SolFla == -1) {
    9872           0 :                         if (!state.dataGlobal->WarmupFlag) {
    9873           0 :                             if (thisFurnace.ErrCountVar == 0) {
    9874           0 :                                 ++thisFurnace.ErrCountVar;
    9875           0 :                                 ShowWarningError(
    9876           0 :                                     state, format("Iteration limit exceeded calculating VS WSHP unit speed ratio, for unit={}", thisFurnace.Name));
    9877           0 :                                 ShowContinueErrorTimeStamp(state, format("Speed ratio returned=[{:.2R}], Speed number ={}", SpeedRatio, SpeedNum));
    9878             :                             } else {
    9879           0 :                                 ShowRecurringWarningErrorAtEnd(
    9880             :                                     state,
    9881           0 :                                     thisFurnace.Name + "\": Iteration limit warning exceeding calculating DX unit speed ratio continues...",
    9882           0 :                                     thisFurnace.ErrIndexVar,
    9883             :                                     SpeedRatio,
    9884             :                                     SpeedRatio);
    9885             :                             }
    9886             :                         }
    9887     1005583 :                     } else if (SolFla == -2) {
    9888           0 :                         ShowFatalError(
    9889           0 :                             state, format("VS WSHP unit compressor speed calculation failed: speed limits exceeded, for unit={}", thisFurnace.Name));
    9890             :                     }
    9891             :                 }
    9892     1341462 :             } else {
    9893       46282 :                 LatOutput = noLatOutput; // reset full output if not needed for sensible load
    9894       46282 :                 SpeedNum = 1;            // reset speed from full output test
    9895             :             }
    9896     1387744 :         } else {
    9897       71366 :             LatOutput = noLatOutput; // reset full output if not needed for sensible load
    9898       71366 :             SpeedNum = 1;            // reset speed from full output test
    9899             :         }
    9900             :         // meet the latent load
    9901     1459110 :         if (QLatReq < -HVAC::SmallLoad && QLatReq < LatOutput) {
    9902       71282 :             PartLoadFrac = 1.0;
    9903       71282 :             SpeedRatio = 1.0;
    9904      113772 :             for (i = SpeedNum; i <= thisFurnace.NumOfSpeedCooling; ++i) {
    9905      113772 :                 CalcVarSpeedHeatPump(state,
    9906             :                                      FurnaceNum,
    9907             :                                      FirstHVACIteration,
    9908             :                                      compressorOp,
    9909             :                                      i,
    9910             :                                      SpeedRatio,
    9911             :                                      PartLoadFrac,
    9912             :                                      TempOutput,
    9913             :                                      LatOutput,
    9914             :                                      QZnReq,
    9915             :                                      QLatReq,
    9916             :                                      OnOffAirFlowRatio,
    9917             :                                      SupHeaterLoad);
    9918             : 
    9919      113772 :                 if (QLatReq > LatOutput) {
    9920       71282 :                     SpeedNum = i;
    9921       71282 :                     break;
    9922             :                 }
    9923             :             }
    9924       71282 :             if (QLatReq - LatOutput > HVAC::SmallLoad) {
    9925       71227 :                 if (SpeedNum < 2) {
    9926             :                     auto f = // (AUTO_OK_LAMBDA)
    9927      316336 :                         [&state, FurnaceNum, FirstHVACIteration, QLatReq, OnOffAirFlowRatio, SupHeaterLoad, compressorOp](Real64 const PartLoadFrac) {
    9928      269407 :                             return VSHPCyclingResidual(
    9929      269407 :                                 state, PartLoadFrac, FurnaceNum, FirstHVACIteration, QLatReq, OnOffAirFlowRatio, SupHeaterLoad, compressorOp, 0.0);
    9930       46929 :                         };
    9931       46929 :                     General::SolveRoot(state, ErrorToler, MaxIte, SolFla, PartLoadFrac, f, 0.0, 1.0);
    9932             :                 } else {
    9933      130582 :                     auto f = [&state, FurnaceNum, FirstHVACIteration, QLatReq, OnOffAirFlowRatio, SupHeaterLoad, SpeedNum, compressorOp](
    9934      106284 :                                  Real64 const SpeedRatio) {
    9935      106284 :                         return VSHPSpeedResidual(state,
    9936             :                                                  SpeedRatio,
    9937             :                                                  FurnaceNum,
    9938             :                                                  FirstHVACIteration,
    9939             :                                                  QLatReq,
    9940             :                                                  OnOffAirFlowRatio,
    9941             :                                                  SupHeaterLoad,
    9942             :                                                  SpeedNum,
    9943             :                                                  compressorOp,
    9944      106284 :                                                  0.0);
    9945       24298 :                     };
    9946       24298 :                     General::SolveRoot(state, ErrorToler, MaxIte, SolFla, SpeedRatio, f, 1.0e-10, 1.0);
    9947             :                 }
    9948       71227 :                 if (SolFla == -1) {
    9949           0 :                     if (!state.dataGlobal->WarmupFlag) {
    9950           0 :                         if (thisFurnace.ErrCountVar2 == 0) {
    9951           0 :                             ++thisFurnace.ErrCountVar2;
    9952           0 :                             ShowWarningError(state,
    9953           0 :                                              format("Iteration limit exceeded calculating VS WSHP unit speed ratio, for unit={}", thisFurnace.Name));
    9954           0 :                             ShowContinueErrorTimeStamp(state, format("Speed ratio returned=[{:.2R}], Speed number ={}", SpeedRatio, SpeedNum));
    9955             :                         } else {
    9956           0 :                             ShowRecurringWarningErrorAtEnd(state,
    9957           0 :                                                            thisFurnace.Name +
    9958             :                                                                "\": Iteration limit warning exceeding calculating DX unit speed ratio continues...",
    9959           0 :                                                            thisFurnace.ErrIndexVar,
    9960             :                                                            SpeedRatio,
    9961             :                                                            SpeedRatio);
    9962             :                         }
    9963             :                     }
    9964       71227 :                 } else if (SolFla == -2) {
    9965           0 :                     ShowFatalError(state,
    9966           0 :                                    format("VS WSHP unit compressor speed calculation failed: speed limits exceeded, for unit={}", thisFurnace.Name));
    9967             :                 }
    9968             :             }
    9969             :         }
    9970             :         // end meet the latent load
    9971             : 
    9972             :         // if the heating coil cannot meet the load, trim with supplemental heater
    9973             :         // occurs with constant fan mode when compressor is on or off
    9974             :         // occurs with cycling fan mode when compressor PLR is equal to 1
    9975     1459110 :         if ((QZnReq > HVAC::SmallLoad && QZnReq > FullOutput) && (thisFurnace.SuppHeatCoilIndex != 0)) {
    9976       25968 :             PartLoadFrac = 1.0;
    9977       25968 :             SpeedRatio = 1.0;
    9978       25968 :             if (thisFurnace.NumOfSpeedHeating > 0)
    9979       25968 :                 SpeedNum = thisFurnace.NumOfSpeedHeating; // maximum heating speed, avoid zero for cooling only mode
    9980             : 
    9981       25968 :             if (state.dataEnvrn->OutDryBulbTemp <= thisFurnace.MaxOATSuppHeat) {
    9982       25968 :                 SupHeaterLoad = QZnReq - FullOutput;
    9983             :             } else {
    9984           0 :                 SupHeaterLoad = 0.0;
    9985             :             }
    9986       25968 :             CalcVarSpeedHeatPump(state,
    9987             :                                  FurnaceNum,
    9988             :                                  FirstHVACIteration,
    9989             :                                  compressorOp,
    9990             :                                  SpeedNum,
    9991             :                                  SpeedRatio,
    9992             :                                  PartLoadFrac,
    9993             :                                  TempOutput,
    9994             :                                  LatOutput,
    9995             :                                  QZnReq,
    9996             :                                  QLatReq,
    9997             :                                  OnOffAirFlowRatio,
    9998             :                                  SupHeaterLoad);
    9999             :         }
   10000             : 
   10001             :         // check the outlet of the supplemental heater to be lower than the maximum supplemental heater supply air temperature
   10002     1459110 :         if (state.dataLoopNodes->Node(thisFurnace.FurnaceOutletNodeNum).Temp > thisFurnace.DesignMaxOutletTemp && SupHeaterLoad > 0.0) {
   10003             : 
   10004             :             //   If the supply air temperature is to high, turn off the supplemental heater to recalculate the outlet temperature
   10005          96 :             CalcNonDXHeatingCoils(state, FurnaceNum, true, FirstHVACIteration, 0.0, fanOp, QCoilActual);
   10006             :             //   If the outlet temperature is below the maximum supplemental heater supply air temperature, reduce the load passed to
   10007             :             //   the supplemental heater, otherwise leave the supplemental heater off. If the supplemental heater is to be turned on,
   10008             :             //   use the outlet conditions when the supplemental heater was off (CALL above) as the inlet conditions for the calculation
   10009             :             //   of supplemental heater load to just meet the maximum supply air temperature from the supplemental heater.
   10010          96 :             if (state.dataLoopNodes->Node(thisFurnace.FurnaceOutletNodeNum).Temp < thisFurnace.DesignMaxOutletTemp) {
   10011          96 :                 Real64 CpAir = Psychrometrics::PsyCpAirFnW(state.dataLoopNodes->Node(thisFurnace.FurnaceOutletNodeNum).HumRat);
   10012          96 :                 SupHeaterLoad = state.dataLoopNodes->Node(thisFurnace.FurnaceInletNodeNum).MassFlowRate * CpAir *
   10013          96 :                                 (thisFurnace.DesignMaxOutletTemp - state.dataLoopNodes->Node(thisFurnace.FurnaceOutletNodeNum).Temp);
   10014             : 
   10015             :             } else {
   10016           0 :                 SupHeaterLoad = 0.0;
   10017             :             }
   10018             :         }
   10019             : 
   10020             :         // prepare module level output
   10021     1459110 :         thisFurnace.CompPartLoadRatio = PartLoadFrac;
   10022     1459110 :         thisFurnace.CompSpeedRatio = SpeedRatio;
   10023     1459110 :         thisFurnace.CompSpeedNum = SpeedNum;
   10024     1459110 :         thisFurnace.CoolingCoilLatentDemand = std::abs(QLatReq);
   10025             : 
   10026     1459110 :         if (thisFurnace.fanOp == HVAC::FanOp::Continuous) {
   10027     1433624 :             thisFurnace.FanPartLoadRatio = 1.0;
   10028             :         } else {
   10029       25486 :             thisFurnace.FanPartLoadRatio = PartLoadFrac;
   10030             :         }
   10031             :     }
   10032             : 
   10033             :     //******************************************************************************
   10034             : 
   10035    17687782 :     void CalcVarSpeedHeatPump(EnergyPlusData &state,
   10036             :                               int const FurnaceNum,                  // Variable speed heat pump number
   10037             :                               bool const FirstHVACIteration,         // Flag for 1st HVAC iteration
   10038             :                               HVAC::CompressorOp const compressorOp, // Compressor on/off; 1=on, 0=off
   10039             :                               int const SpeedNum,                    // Speed number
   10040             :                               Real64 const SpeedRatio,               // Compressor speed ratio
   10041             :                               Real64 const PartLoadFrac,             // Compressor part load fraction
   10042             :                               Real64 &SensibleLoadMet,               // Sensible cooling load met (furnace outlet with respect to control zone temp)
   10043             :                               Real64 &LatentLoadMet,     // Latent cooling load met (furnace outlet with respect to control zone humidity ratio)
   10044             :                               Real64 const QZnReq,       // Zone load (W)
   10045             :                               Real64 const QLatReq,      // Zone latent load []
   10046             :                               Real64 &OnOffAirFlowRatio, // Ratio of compressor ON airflow to AVERAGE airflow over timestep
   10047             :                               Real64 const SupHeaterLoad // supplemental heater load (W)
   10048             :     )
   10049             :     {
   10050             :         // SUBROUTINE INFORMATION:
   10051             :         //       AUTHOR:          Bo Shen, based on HVACMultiSpeedHeatPump:CalcMSHeatPump
   10052             :         //       DATE WRITTEN:    March 2012
   10053             : 
   10054             :         // PURPOSE OF THIS SUBROUTINE:
   10055             :         //  This routine will calcultes MSHP performance based on given system load
   10056             : 
   10057    17687782 :         Real64 SavePartloadRatio = 0.0; // part-load ratio
   10058    17687782 :         Real64 SaveSpeedRatio = 0.0;    // speed ratio
   10059    17687782 :         Real64 QCoilActual = 0.0;       // coil load actually delivered returned to calling component
   10060    17687782 :         Real64 HeatCoilLoad = 0.0;      // required heating coil load
   10061             : 
   10062    17687782 :         state.dataFurnaces->SaveCompressorPLR = 0.0;
   10063             : 
   10064             :         // Set inlet air mass flow rate based on PLR and compressor on/off air flow rates
   10065    17687782 :         SetVSHPAirFlow(state, FurnaceNum, PartLoadFrac, OnOffAirFlowRatio, SpeedNum, SpeedRatio);
   10066             : 
   10067    17687782 :         auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
   10068             : 
   10069    17687782 :         if ((SupHeaterLoad > 1.0e-10) && (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatCool) && (thisFurnace.SuppHeatCoilIndex == 0)) {
   10070             :             // ONLY HEATING COIL, NO SUPPLEMENTAL COIL, USED FOR REHEAT DURING DUHMI
   10071           0 :             HeatCoilLoad = thisFurnace.DesignHeatingCapacity * PartLoadFrac; // REHEAT IN FAN ON TIME
   10072             : 
   10073           0 :             if (HeatCoilLoad > SupHeaterLoad) HeatCoilLoad = SupHeaterLoad; // HEATING COIL RUN TIME < FAN ON TIME
   10074             : 
   10075    17687782 :         } else if ((QZnReq > HVAC::SmallLoad) && (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatCool)) {
   10076       63320 :             HeatCoilLoad = thisFurnace.DesignHeatingCapacity * PartLoadFrac;
   10077             :         } else {
   10078    17624462 :             HeatCoilLoad = 0.0;
   10079             :         }
   10080             : 
   10081    17687782 :         Real64 AirMassFlow = state.dataLoopNodes->Node(thisFurnace.FurnaceInletNodeNum).MassFlowRate;
   10082             :         // if blow through, simulate fan then coils
   10083    17687782 :         if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
   10084    17687782 :             state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
   10085             : 
   10086    17687782 :             if ((!thisFurnace.CoolingCoilUpstream) && (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatCool)) {
   10087             :                 // simulate thisFurnace heating coil
   10088           0 :                 bool SuppHeatingCoilFlag = false; // if true simulates supplemental heating coil
   10089           0 :                 CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, thisFurnace.fanOp, QCoilActual);
   10090             :             }
   10091             : 
   10092    31623779 :             if ((QZnReq < -HVAC::SmallLoad || (QLatReq < -HVAC::SmallLoad)) &&
   10093    13935997 :                 (state.dataEnvrn->OutDryBulbTemp >= thisFurnace.MinOATCompressorCooling)) { // COOLING MODE or dehumidification mode
   10094             : 
   10095    13935997 :                 if (thisFurnace.bIsIHP) {
   10096       73294 :                     IntegratedHeatPump::SimIHP(state,
   10097             :                                                BlankString,
   10098       36647 :                                                thisFurnace.CoolingCoilIndex,
   10099             :                                                thisFurnace.fanOp,
   10100             :                                                compressorOp,
   10101             :                                                PartLoadFrac,
   10102             :                                                SpeedNum,
   10103             :                                                SpeedRatio,
   10104             :                                                QZnReq,
   10105             :                                                QLatReq,
   10106             :                                                false,
   10107             :                                                false,
   10108             :                                                OnOffAirFlowRatio);
   10109             :                 } else {
   10110    13899350 :                     VariableSpeedCoils::SimVariableSpeedCoils(state,
   10111             :                                                               BlankString,
   10112    13899350 :                                                               thisFurnace.CoolingCoilIndex,
   10113             :                                                               thisFurnace.fanOp,
   10114             :                                                               compressorOp,
   10115             :                                                               PartLoadFrac,
   10116             :                                                               SpeedNum,
   10117             :                                                               SpeedRatio,
   10118             :                                                               QZnReq,
   10119             :                                                               QLatReq,
   10120             :                                                               OnOffAirFlowRatio);
   10121             :                 }
   10122             : 
   10123    13935997 :                 SavePartloadRatio = PartLoadFrac;
   10124    13935997 :                 SaveSpeedRatio = SpeedRatio;
   10125             : 
   10126    13935997 :                 state.dataFurnaces->SaveCompressorPLR = state.dataVariableSpeedCoils->VarSpeedCoil(thisFurnace.CoolingCoilIndex).PartLoadRatio;
   10127             :             } else {
   10128     3751785 :                 if (thisFurnace.bIsIHP) {
   10129       51358 :                     IntegratedHeatPump::SimIHP(state,
   10130             :                                                BlankString,
   10131       25679 :                                                thisFurnace.CoolingCoilIndex,
   10132             :                                                thisFurnace.fanOp,
   10133             :                                                compressorOp,
   10134             :                                                PartLoadFrac,
   10135             :                                                SpeedNum,
   10136             :                                                SpeedRatio,
   10137             :                                                QZnReq,
   10138             :                                                QLatReq,
   10139             :                                                false,
   10140             :                                                false,
   10141             :                                                OnOffAirFlowRatio);
   10142             :                 } else {
   10143     3726106 :                     VariableSpeedCoils::SimVariableSpeedCoils(
   10144     3726106 :                         state, BlankString, thisFurnace.CoolingCoilIndex, thisFurnace.fanOp, compressorOp, 0.0, 1, 0.0, 0.0, 0.0, OnOffAirFlowRatio);
   10145             :                 }
   10146             :             }
   10147             : 
   10148    17687782 :             if (thisFurnace.type != HVAC::UnitarySysType::Unitary_HeatCool) {
   10149     2335958 :                 if ((QZnReq > HVAC::SmallLoad) && state.dataFurnaces->HeatingLoad) {
   10150      598955 :                     if (thisFurnace.bIsIHP) {
   10151       27964 :                         IntegratedHeatPump::SimIHP(state,
   10152             :                                                    BlankString,
   10153       13982 :                                                    thisFurnace.HeatingCoilIndex,
   10154             :                                                    thisFurnace.fanOp,
   10155             :                                                    compressorOp,
   10156             :                                                    PartLoadFrac,
   10157             :                                                    SpeedNum,
   10158             :                                                    SpeedRatio,
   10159             :                                                    QZnReq,
   10160             :                                                    QLatReq,
   10161             :                                                    false,
   10162             :                                                    false,
   10163             :                                                    OnOffAirFlowRatio);
   10164             :                     } else {
   10165      584973 :                         VariableSpeedCoils::SimVariableSpeedCoils(state,
   10166             :                                                                   BlankString,
   10167      584973 :                                                                   thisFurnace.HeatingCoilIndex,
   10168             :                                                                   thisFurnace.fanOp,
   10169             :                                                                   compressorOp,
   10170             :                                                                   PartLoadFrac,
   10171             :                                                                   SpeedNum,
   10172             :                                                                   SpeedRatio,
   10173             :                                                                   QZnReq,
   10174             :                                                                   QLatReq,
   10175             :                                                                   OnOffAirFlowRatio);
   10176             :                     }
   10177             : 
   10178      598955 :                     SavePartloadRatio = PartLoadFrac;
   10179      598955 :                     SaveSpeedRatio = SpeedRatio;
   10180             : 
   10181      598955 :                     state.dataFurnaces->SaveCompressorPLR = state.dataVariableSpeedCoils->VarSpeedCoil(thisFurnace.HeatingCoilIndex).PartLoadRatio;
   10182             :                 } else {
   10183     1737003 :                     if (thisFurnace.bIsIHP) {
   10184       96688 :                         IntegratedHeatPump::SimIHP(state,
   10185             :                                                    BlankString,
   10186       48344 :                                                    thisFurnace.CoolingCoilIndex,
   10187             :                                                    thisFurnace.fanOp,
   10188             :                                                    compressorOp,
   10189             :                                                    PartLoadFrac,
   10190             :                                                    SpeedNum,
   10191             :                                                    SpeedRatio,
   10192             :                                                    QZnReq,
   10193             :                                                    QLatReq,
   10194             :                                                    false,
   10195             :                                                    false,
   10196             :                                                    OnOffAirFlowRatio);
   10197             :                     } else {
   10198     1688659 :                         VariableSpeedCoils::SimVariableSpeedCoils(state,
   10199             :                                                                   BlankString,
   10200     1688659 :                                                                   thisFurnace.HeatingCoilIndex,
   10201             :                                                                   thisFurnace.fanOp,
   10202             :                                                                   compressorOp,
   10203             :                                                                   0.0,
   10204             :                                                                   1,
   10205             :                                                                   0.0,
   10206             :                                                                   0.0,
   10207             :                                                                   0.0,
   10208             :                                                                   OnOffAirFlowRatio);
   10209             :                     }
   10210             :                 }
   10211    15351824 :             } else if (thisFurnace.CoolingCoilUpstream && (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatCool)) {
   10212             :                 // simulate thisFurnace heating coil
   10213    15351824 :                 bool SuppHeatingCoilFlag = false; // if true simulates supplemental heating coil
   10214    15351824 :                 CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, thisFurnace.fanOp, QCoilActual);
   10215             :             }
   10216             : 
   10217             :             // Call twice to ensure the fan outlet conditions are updated
   10218    17687782 :             state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
   10219             : 
   10220    17687782 :             if ((!thisFurnace.CoolingCoilUpstream) && (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatCool)) {
   10221             :                 // simulate thisFurnace heating coil
   10222           0 :                 bool SuppHeatingCoilFlag = false; // if true simulates supplemental heating coil
   10223           0 :                 CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, thisFurnace.fanOp, QCoilActual);
   10224             :             }
   10225             : 
   10226    31623779 :             if ((QZnReq < -HVAC::SmallLoad || (QLatReq < -HVAC::SmallLoad)) &&
   10227    13935997 :                 (state.dataEnvrn->OutDryBulbTemp >= thisFurnace.MinOATCompressorCooling)) {
   10228             : 
   10229    13935997 :                 if (thisFurnace.bIsIHP) {
   10230       73294 :                     IntegratedHeatPump::SimIHP(state,
   10231             :                                                BlankString,
   10232       36647 :                                                thisFurnace.CoolingCoilIndex,
   10233             :                                                thisFurnace.fanOp,
   10234             :                                                compressorOp,
   10235             :                                                PartLoadFrac,
   10236             :                                                SpeedNum,
   10237             :                                                SpeedRatio,
   10238             :                                                QZnReq,
   10239             :                                                QLatReq,
   10240             :                                                false,
   10241             :                                                false,
   10242             :                                                OnOffAirFlowRatio);
   10243             :                 } else {
   10244    13899350 :                     VariableSpeedCoils::SimVariableSpeedCoils(state,
   10245             :                                                               BlankString,
   10246    13899350 :                                                               thisFurnace.CoolingCoilIndex,
   10247             :                                                               thisFurnace.fanOp,
   10248             :                                                               compressorOp,
   10249             :                                                               PartLoadFrac,
   10250             :                                                               SpeedNum,
   10251             :                                                               SpeedRatio,
   10252             :                                                               QZnReq,
   10253             :                                                               QLatReq,
   10254             :                                                               OnOffAirFlowRatio);
   10255             :                 }
   10256             : 
   10257    13935997 :                 SavePartloadRatio = PartLoadFrac;
   10258    13935997 :                 SaveSpeedRatio = SpeedRatio;
   10259    13935997 :                 state.dataFurnaces->SaveCompressorPLR = state.dataVariableSpeedCoils->VarSpeedCoil(thisFurnace.CoolingCoilIndex).PartLoadRatio;
   10260             :             } else {
   10261             : 
   10262     3751785 :                 if (thisFurnace.bIsIHP) {
   10263       51358 :                     IntegratedHeatPump::SimIHP(state,
   10264             :                                                BlankString,
   10265       25679 :                                                thisFurnace.CoolingCoilIndex,
   10266             :                                                thisFurnace.fanOp,
   10267             :                                                compressorOp,
   10268             :                                                PartLoadFrac,
   10269             :                                                SpeedNum,
   10270             :                                                SpeedRatio,
   10271             :                                                QZnReq,
   10272             :                                                QLatReq,
   10273             :                                                false,
   10274             :                                                false,
   10275             :                                                OnOffAirFlowRatio);
   10276             :                 } else {
   10277     3726106 :                     VariableSpeedCoils::SimVariableSpeedCoils(
   10278     3726106 :                         state, BlankString, thisFurnace.CoolingCoilIndex, thisFurnace.fanOp, compressorOp, 0.0, 1, 0.0, 0.0, 0.0, OnOffAirFlowRatio);
   10279             :                 }
   10280             :             }
   10281             : 
   10282    17687782 :             if (thisFurnace.type != HVAC::UnitarySysType::Unitary_HeatCool) {
   10283     2335958 :                 if ((QZnReq > HVAC::SmallLoad) && state.dataFurnaces->HeatingLoad) {
   10284      598955 :                     if (thisFurnace.bIsIHP) {
   10285       27964 :                         IntegratedHeatPump::SimIHP(state,
   10286             :                                                    BlankString,
   10287       13982 :                                                    thisFurnace.HeatingCoilIndex,
   10288             :                                                    thisFurnace.fanOp,
   10289             :                                                    compressorOp,
   10290             :                                                    PartLoadFrac,
   10291             :                                                    SpeedNum,
   10292             :                                                    SpeedRatio,
   10293             :                                                    QZnReq,
   10294             :                                                    QLatReq,
   10295             :                                                    false,
   10296             :                                                    false,
   10297             :                                                    OnOffAirFlowRatio);
   10298             :                     } else {
   10299      584973 :                         VariableSpeedCoils::SimVariableSpeedCoils(state,
   10300             :                                                                   BlankString,
   10301      584973 :                                                                   thisFurnace.HeatingCoilIndex,
   10302             :                                                                   thisFurnace.fanOp,
   10303             :                                                                   compressorOp,
   10304             :                                                                   PartLoadFrac,
   10305             :                                                                   SpeedNum,
   10306             :                                                                   SpeedRatio,
   10307             :                                                                   QZnReq,
   10308             :                                                                   QLatReq,
   10309             :                                                                   OnOffAirFlowRatio);
   10310             :                     }
   10311             : 
   10312      598955 :                     SavePartloadRatio = PartLoadFrac;
   10313      598955 :                     SaveSpeedRatio = SpeedRatio;
   10314      598955 :                     state.dataFurnaces->SaveCompressorPLR = state.dataVariableSpeedCoils->VarSpeedCoil(thisFurnace.HeatingCoilIndex).PartLoadRatio;
   10315             :                 } else {
   10316     1737003 :                     if (thisFurnace.bIsIHP) {
   10317       96688 :                         IntegratedHeatPump::SimIHP(state,
   10318             :                                                    BlankString,
   10319       48344 :                                                    thisFurnace.CoolingCoilIndex,
   10320             :                                                    thisFurnace.fanOp,
   10321             :                                                    compressorOp,
   10322             :                                                    PartLoadFrac,
   10323             :                                                    SpeedNum,
   10324             :                                                    SpeedRatio,
   10325             :                                                    QZnReq,
   10326             :                                                    QLatReq,
   10327             :                                                    false,
   10328             :                                                    false,
   10329             :                                                    OnOffAirFlowRatio);
   10330             :                     } else {
   10331     1688659 :                         VariableSpeedCoils::SimVariableSpeedCoils(state,
   10332             :                                                                   BlankString,
   10333     1688659 :                                                                   thisFurnace.HeatingCoilIndex,
   10334             :                                                                   thisFurnace.fanOp,
   10335             :                                                                   compressorOp,
   10336             :                                                                   0.0,
   10337             :                                                                   1,
   10338             :                                                                   0.0,
   10339             :                                                                   0.0,
   10340             :                                                                   0.0,
   10341             :                                                                   OnOffAirFlowRatio);
   10342             :                     }
   10343             :                 }
   10344    15351824 :             } else if (thisFurnace.CoolingCoilUpstream && (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatCool)) {
   10345             :                 // simulate thisFurnace heating coil
   10346    15351824 :                 bool SuppHeatingCoilFlag = false; // if true simulates supplemental heating coil
   10347    15351824 :                 CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, thisFurnace.fanOp, QCoilActual);
   10348             :             }
   10349             : 
   10350             :             //  Simulate supplemental heating coil for blow through fan
   10351    17687782 :             if (thisFurnace.SuppHeatCoilIndex > 0) {
   10352     2335958 :                 bool SuppHeatingCoilFlag = true; // if true simulates supplemental heating coil
   10353     2335958 :                 CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, SupHeaterLoad, thisFurnace.fanOp, QCoilActual);
   10354             :             }
   10355             :         } else { // otherwise simulate DX coils then fan then supplemental heater
   10356             : 
   10357           0 :             if ((!thisFurnace.CoolingCoilUpstream) && (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatCool)) {
   10358             :                 // simulate thisFurnace heating coil
   10359           0 :                 bool SuppHeatingCoilFlag = false; // if true simulates supplemental heating coil
   10360           0 :                 CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, thisFurnace.fanOp, QCoilActual);
   10361             :             }
   10362             : 
   10363           0 :             if ((QZnReq < -HVAC::SmallLoad || (QLatReq < -HVAC::SmallLoad)) &&
   10364           0 :                 (state.dataEnvrn->OutDryBulbTemp >= thisFurnace.MinOATCompressorCooling)) {
   10365             : 
   10366           0 :                 if (thisFurnace.bIsIHP) {
   10367           0 :                     IntegratedHeatPump::SimIHP(state,
   10368             :                                                BlankString,
   10369           0 :                                                thisFurnace.CoolingCoilIndex,
   10370             :                                                thisFurnace.fanOp,
   10371             :                                                compressorOp,
   10372             :                                                PartLoadFrac,
   10373             :                                                SpeedNum,
   10374             :                                                SpeedRatio,
   10375             :                                                QZnReq,
   10376             :                                                QLatReq,
   10377             :                                                false,
   10378             :                                                false,
   10379             :                                                OnOffAirFlowRatio);
   10380             :                 } else {
   10381           0 :                     VariableSpeedCoils::SimVariableSpeedCoils(state,
   10382             :                                                               BlankString,
   10383           0 :                                                               thisFurnace.CoolingCoilIndex,
   10384             :                                                               thisFurnace.fanOp,
   10385             :                                                               compressorOp,
   10386             :                                                               PartLoadFrac,
   10387             :                                                               SpeedNum,
   10388             :                                                               SpeedRatio,
   10389             :                                                               QZnReq,
   10390             :                                                               QLatReq,
   10391             :                                                               OnOffAirFlowRatio);
   10392             :                 }
   10393             : 
   10394           0 :                 SavePartloadRatio = PartLoadFrac;
   10395           0 :                 SaveSpeedRatio = SpeedRatio;
   10396             : 
   10397           0 :                 state.dataFurnaces->SaveCompressorPLR = state.dataVariableSpeedCoils->VarSpeedCoil(thisFurnace.CoolingCoilIndex).PartLoadRatio;
   10398             :             } else {
   10399           0 :                 if (thisFurnace.bIsIHP) {
   10400           0 :                     IntegratedHeatPump::SimIHP(state,
   10401             :                                                BlankString,
   10402           0 :                                                thisFurnace.CoolingCoilIndex,
   10403             :                                                thisFurnace.fanOp,
   10404             :                                                compressorOp,
   10405             :                                                PartLoadFrac,
   10406             :                                                SpeedNum,
   10407             :                                                SpeedRatio,
   10408             :                                                QZnReq,
   10409             :                                                QLatReq,
   10410             :                                                false,
   10411             :                                                false,
   10412             :                                                OnOffAirFlowRatio);
   10413             :                 } else {
   10414           0 :                     VariableSpeedCoils::SimVariableSpeedCoils(
   10415           0 :                         state, BlankString, thisFurnace.CoolingCoilIndex, thisFurnace.fanOp, compressorOp, 0.0, 1, 0.0, 0.0, 0.0, OnOffAirFlowRatio);
   10416             :                 }
   10417             :             }
   10418             : 
   10419           0 :             if (thisFurnace.type != HVAC::UnitarySysType::Unitary_HeatCool) {
   10420           0 :                 if (QZnReq > HVAC::SmallLoad && (state.dataEnvrn->OutDryBulbTemp >= thisFurnace.MinOATCompressorCooling)) {
   10421             : 
   10422           0 :                     if (thisFurnace.bIsIHP) {
   10423           0 :                         IntegratedHeatPump::SimIHP(state,
   10424             :                                                    BlankString,
   10425           0 :                                                    thisFurnace.HeatingCoilIndex,
   10426             :                                                    thisFurnace.fanOp,
   10427             :                                                    compressorOp,
   10428             :                                                    PartLoadFrac,
   10429             :                                                    SpeedNum,
   10430             :                                                    SpeedRatio,
   10431             :                                                    QZnReq,
   10432             :                                                    QLatReq,
   10433             :                                                    false,
   10434             :                                                    false,
   10435             :                                                    OnOffAirFlowRatio);
   10436             :                     } else {
   10437           0 :                         VariableSpeedCoils::SimVariableSpeedCoils(state,
   10438             :                                                                   BlankString,
   10439           0 :                                                                   thisFurnace.HeatingCoilIndex,
   10440             :                                                                   thisFurnace.fanOp,
   10441             :                                                                   compressorOp,
   10442             :                                                                   PartLoadFrac,
   10443             :                                                                   SpeedNum,
   10444             :                                                                   SpeedRatio,
   10445             :                                                                   QZnReq,
   10446             :                                                                   QLatReq,
   10447             :                                                                   OnOffAirFlowRatio);
   10448             :                     }
   10449             : 
   10450           0 :                     SavePartloadRatio = PartLoadFrac;
   10451           0 :                     SaveSpeedRatio = SpeedRatio;
   10452           0 :                     state.dataFurnaces->SaveCompressorPLR = state.dataVariableSpeedCoils->VarSpeedCoil(thisFurnace.HeatingCoilIndex).PartLoadRatio;
   10453             :                 } else {
   10454           0 :                     if (thisFurnace.bIsIHP) {
   10455           0 :                         IntegratedHeatPump::SimIHP(state,
   10456             :                                                    BlankString,
   10457           0 :                                                    thisFurnace.CoolingCoilIndex,
   10458             :                                                    thisFurnace.fanOp,
   10459             :                                                    compressorOp,
   10460             :                                                    PartLoadFrac,
   10461             :                                                    SpeedNum,
   10462             :                                                    SpeedRatio,
   10463             :                                                    QZnReq,
   10464             :                                                    QLatReq,
   10465             :                                                    false,
   10466             :                                                    false,
   10467             :                                                    OnOffAirFlowRatio);
   10468             :                     } else {
   10469           0 :                         VariableSpeedCoils::SimVariableSpeedCoils(state,
   10470             :                                                                   BlankString,
   10471           0 :                                                                   thisFurnace.HeatingCoilIndex,
   10472             :                                                                   thisFurnace.fanOp,
   10473             :                                                                   compressorOp,
   10474             :                                                                   0.0,
   10475             :                                                                   1,
   10476             :                                                                   0.0,
   10477             :                                                                   0.0,
   10478             :                                                                   0.0,
   10479             :                                                                   OnOffAirFlowRatio);
   10480             :                     }
   10481             :                 }
   10482           0 :             } else if (thisFurnace.CoolingCoilUpstream && (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatCool)) {
   10483             :                 // simulate thisFurnace heating coil
   10484           0 :                 bool SuppHeatingCoilFlag = false; // if true simulates supplemental heating coil
   10485           0 :                 CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, thisFurnace.fanOp, QCoilActual);
   10486             :             }
   10487             : 
   10488           0 :             state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
   10489             :             //  Simulate supplemental heating coil for draw through fan
   10490           0 :             if (thisFurnace.SuppHeatCoilIndex > 0) {
   10491           0 :                 bool SuppHeatingCoilFlag = true; // if true simulates supplemental heating coil
   10492           0 :                 CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, SupHeaterLoad, thisFurnace.fanOp, QCoilActual);
   10493             :             }
   10494             :         }
   10495             : 
   10496             :         // If the fan runs continually do not allow coils to set OnOffFanPartLoadRatio.
   10497    17687782 :         if (thisFurnace.fanOp == HVAC::FanOp::Continuous) state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
   10498             : 
   10499    17687782 :         auto &outNode = state.dataLoopNodes->Node(thisFurnace.FurnaceOutletNodeNum);
   10500    17687782 :         auto &zoneNode = state.dataLoopNodes->Node(thisFurnace.NodeNumOfControlledZone);
   10501    17687782 :         Real64 zoneEnthalpy = Psychrometrics::PsyHFnTdbW(zoneNode.Temp, zoneNode.HumRat);
   10502    17687782 :         Real64 outletEnthalpy = Psychrometrics::PsyHFnTdbW(outNode.Temp, outNode.HumRat);
   10503    17687782 :         Real64 totalLoadMet = AirMassFlow * (outletEnthalpy - zoneEnthalpy);
   10504    17687782 :         SensibleLoadMet =
   10505    17687782 :             AirMassFlow * Psychrometrics::PsyDeltaHSenFnTdb2W2Tdb1W1(outNode.Temp, outNode.HumRat, zoneNode.Temp, zoneNode.HumRat); // sensible {W};
   10506    17687782 :         LatentLoadMet = totalLoadMet - SensibleLoadMet;
   10507    17687782 :         thisFurnace.LatentLoadMet = LatentLoadMet;
   10508    17687782 :     }
   10509             : 
   10510             :     //******************************************************************************
   10511             : 
   10512     1964741 :     Real64 VSHPCyclingResidual(EnergyPlusData &state,
   10513             :                                Real64 const PartLoadFrac, // compressor cycling ratio (1.0 is continuous, 0.0 is off)
   10514             :                                int FurnaceNum,
   10515             :                                // int ZoneNum,
   10516             :                                bool FirstHVACIteration,
   10517             :                                // int fanOp,
   10518             :                                Real64 LoadToBeMet,
   10519             :                                Real64 OnOffAirFlowRatio,
   10520             :                                Real64 SupHeaterLoad,
   10521             :                                HVAC::CompressorOp compressorOp,
   10522             :                                Real64 par9_SensLatFlag)
   10523             :     {
   10524             :         // FUNCTION INFORMATION:
   10525             :         //       AUTHOR         Bo Shen, based on HVACMultiSpeedHeatPump:MSHPCyclingResidual
   10526             :         //       DATE WRITTEN   March, 2012
   10527             : 
   10528             :         // PURPOSE OF THIS FUNCTION:
   10529             :         //  Calculates residual function ((ActualOutput - QZnReq)/QZnReq)
   10530             :         //  MSHP output depends on the part load ratio which is being varied to zero the residual.
   10531             : 
   10532             :         // METHODOLOGY EMPLOYED:
   10533             :         //  Calls CalcMSHeatPump to get ActualOutput at the given part load ratio
   10534             :         //  and calculates the residual as defined above
   10535             : 
   10536             :         // int FurnaceNum = int(Par[0]);
   10537             :         // int ZoneNum = int(Par[1]);
   10538             :         // bool FirstHVACIteration = (Par[2] == 1.0);
   10539             :         // int fanOp = int(Par[3]);
   10540             :         // Real64 LoadToBeMet = Par[4];
   10541             :         // Real64 OnOffAirFlowRatio = Par[5];
   10542             :         // Real64 SupHeaterLoad = Par[6];
   10543             :         // CompressorOperation CompressorOp = static_cast<CompressorOperation>(Par[8]);
   10544             :         // Real64 par9_SensLatFlag = Par[9];
   10545             : 
   10546             :         // FUNCTION LOCAL VARIABLE DECLARATIONS:
   10547             :         Real64 ZoneSensLoadMet; // delivered sensible capacity of MSHP
   10548             :         Real64 ZoneLatLoadMet;  // delivered latent capacity of MSHP
   10549             : 
   10550     1964741 :         Real64 QZnReq = 0.0;
   10551     1964741 :         Real64 QZnLat = 0.0;
   10552     1964741 :         if (par9_SensLatFlag == 1.0) {
   10553     1695334 :             QZnReq = LoadToBeMet;
   10554             :         } else {
   10555      269407 :             QZnLat = LoadToBeMet;
   10556             :         }
   10557             : 
   10558     1964741 :         CalcVarSpeedHeatPump(state,
   10559             :                              FurnaceNum,
   10560             :                              FirstHVACIteration,
   10561             :                              compressorOp,
   10562             :                              1,
   10563             :                              0.0,
   10564             :                              PartLoadFrac,
   10565             :                              ZoneSensLoadMet,
   10566             :                              ZoneLatLoadMet,
   10567             :                              QZnReq,
   10568             :                              QZnLat,
   10569             :                              OnOffAirFlowRatio,
   10570             :                              SupHeaterLoad);
   10571             : 
   10572     1964741 :         Real64 ResScale = std::abs(LoadToBeMet);
   10573     1964741 :         if (ResScale < 100.0) {
   10574        7954 :             ResScale = 100.0;
   10575             :         } else {
   10576     1956787 :             ResScale = LoadToBeMet;
   10577             :         }
   10578             : 
   10579             :         // Calculate residual based on output calculation flag
   10580     1964741 :         if (par9_SensLatFlag == 1.0) {
   10581     1695334 :             return (ZoneSensLoadMet - LoadToBeMet) / ResScale;
   10582             :         } else {
   10583      269407 :             return (ZoneLatLoadMet - LoadToBeMet) / ResScale;
   10584             :         }
   10585             :     }
   10586             : 
   10587             :     //******************************************************************************
   10588             : 
   10589     3534349 :     Real64 VSHPSpeedResidual(EnergyPlusData &state,
   10590             :                              Real64 const SpeedRatio, // compressor cycling ratio (1.0 is continuous, 0.0 is off)
   10591             :                              int FurnaceNum,
   10592             :                              // int ZoneNum,
   10593             :                              bool FirstHVACIteration,
   10594             :                              // int fanOp
   10595             :                              Real64 LoadToBeMet,
   10596             :                              Real64 OnOffAirFlowRatio,
   10597             :                              Real64 SupHeaterLoad,
   10598             :                              int SpeedNum,
   10599             :                              HVAC::CompressorOp compressorOp,
   10600             :                              Real64 par9_SensLatFlag)
   10601             :     {
   10602             :         // FUNCTION INFORMATION:
   10603             :         //       AUTHOR         Bo Shen, , based on HVACMultiSpeedHeatPump:MSHPVarSpeedgResidual
   10604             :         //       DATE WRITTEN   March, 2012
   10605             : 
   10606             :         // PURPOSE OF THIS FUNCTION:
   10607             :         //  Calculates residual function ((ActualOutput - QZnReq)/QZnReq)
   10608             :         //  MSHP output depends on the part load ratio which is being varied to zero the residual.
   10609             : 
   10610             :         // METHODOLOGY EMPLOYED:
   10611             :         //  Calls CalcMSHeatPump to get ActualOutput at the given speed ratio (partload ratio for high speed)
   10612             :         //  and calculates the residual as defined above
   10613             : 
   10614     3534349 :         Real64 QZnReq = 0.0;
   10615     3534349 :         Real64 QZnLat = 0.0;
   10616     3534349 :         if (par9_SensLatFlag == 1.0) {
   10617     3428065 :             QZnReq = LoadToBeMet;
   10618             :         } else {
   10619      106284 :             QZnLat = LoadToBeMet;
   10620             :         }
   10621             : 
   10622             :         Real64 ZoneSensLoadMet; // delivered sensible capacity of MSHP
   10623             :         Real64 ZoneLatLoadMet;  // delivered latent capacity of MSHP
   10624     3534349 :         CalcVarSpeedHeatPump(state,
   10625             :                              FurnaceNum,
   10626             :                              FirstHVACIteration,
   10627             :                              compressorOp,
   10628             :                              SpeedNum,
   10629             :                              SpeedRatio,
   10630             :                              1.0,
   10631             :                              ZoneSensLoadMet,
   10632             :                              ZoneLatLoadMet,
   10633             :                              QZnReq,
   10634             :                              QZnLat,
   10635             :                              OnOffAirFlowRatio,
   10636             :                              SupHeaterLoad);
   10637             : 
   10638     3534349 :         Real64 ResScale = std::abs(LoadToBeMet);
   10639     3534349 :         if (ResScale < 100.0) {
   10640           0 :             ResScale = 100.0;
   10641             :         } else {
   10642     3534349 :             ResScale = LoadToBeMet;
   10643             :         }
   10644             : 
   10645             :         // Calculate residual based on output calculation flag
   10646     3534349 :         if (par9_SensLatFlag == 1.0) {
   10647     3428065 :             return (ZoneSensLoadMet - LoadToBeMet) / ResScale;
   10648             :         } else {
   10649      106284 :             return (ZoneLatLoadMet - LoadToBeMet) / ResScale;
   10650             :         }
   10651             :     }
   10652             : 
   10653    17687782 :     void SetVSHPAirFlow(EnergyPlusData &state,
   10654             :                         int const FurnaceNum,                        // Unit index
   10655             :                         Real64 const PartLoadRatio,                  // unit part load ratio
   10656             :                         Real64 &OnOffAirFlowRatio,                   // ratio of compressor ON airflow to average airflow over timestep
   10657             :                         ObjexxFCL::Optional_int_const SpeedNum,      // Speed number
   10658             :                         ObjexxFCL::Optional<Real64 const> SpeedRatio // Speed ratio
   10659             :     )
   10660             :     {
   10661             : 
   10662             :         // SUBROUTINE INFORMATION:
   10663             :         //       AUTHOR         Bo Shen, based on HVACMultiSpeedHeatPump:SetAverageAirFlow
   10664             :         //       DATE WRITTEN   March, 2012
   10665             : 
   10666             :         // PURPOSE OF THIS SUBROUTINE:
   10667             :         // Set the average air mass flow rates using the part load fraction of the heat pump for this time step
   10668             :         // Set OnOffAirFlowRatio to be used by DX coils
   10669             : 
   10670             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
   10671             :         Real64 AverageUnitMassFlow; // average supply air mass flow rate over time step
   10672             : 
   10673    17687782 :         auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
   10674             : 
   10675    17687782 :         state.dataHVACGlobal->MSHPMassFlowRateLow = 0.0;  // Mass flow rate at low speed
   10676    17687782 :         state.dataHVACGlobal->MSHPMassFlowRateHigh = 0.0; // Mass flow rate at high speed
   10677             : 
   10678    17687782 :         if (thisFurnace.fanOp == HVAC::FanOp::Continuous) {
   10679    17499846 :             state.dataFurnaces->CompOffMassFlow = thisFurnace.IdleMassFlowRate;
   10680    17499846 :             state.dataFurnaces->CompOffFlowRatio = thisFurnace.IdleSpeedRatio;
   10681             :         } else {
   10682      187936 :             state.dataFurnaces->CompOffMassFlow = 0.0;
   10683      187936 :             state.dataFurnaces->CompOffFlowRatio = 0.0;
   10684             :         }
   10685             : 
   10686    17687782 :         if (state.dataFurnaces->CoolingLoad && (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatCool)) {
   10687    15238427 :             if (thisFurnace.NumOfSpeedCooling > 0) {
   10688    15238427 :                 state.dataFurnaces->CompOnMassFlow = thisFurnace.CoolMassFlowRate(thisFurnace.NumOfSpeedCooling);
   10689    15238427 :                 state.dataFurnaces->CompOnFlowRatio = thisFurnace.MSCoolingSpeedRatio(thisFurnace.NumOfSpeedCooling);
   10690    15238427 :                 state.dataHVACGlobal->MSHPMassFlowRateLow = thisFurnace.CoolMassFlowRate(thisFurnace.NumOfSpeedCooling);
   10691    15238427 :                 state.dataHVACGlobal->MSHPMassFlowRateHigh = thisFurnace.CoolMassFlowRate(thisFurnace.NumOfSpeedCooling);
   10692             :             } else {
   10693           0 :                 state.dataFurnaces->CompOnMassFlow = thisFurnace.MaxCoolAirMassFlow;
   10694           0 :                 state.dataFurnaces->CompOnFlowRatio = thisFurnace.CoolingSpeedRatio;
   10695             :             }
   10696    15238427 :             AverageUnitMassFlow = (PartLoadRatio * state.dataFurnaces->CompOnMassFlow) + ((1 - PartLoadRatio) * state.dataFurnaces->CompOffMassFlow);
   10697    15238427 :             if (state.dataFurnaces->CompOffFlowRatio > 0.0) {
   10698    15238427 :                 state.dataFurnaces->FanSpeedRatio =
   10699    15238427 :                     (PartLoadRatio * state.dataFurnaces->CompOnFlowRatio) + ((1 - PartLoadRatio) * state.dataFurnaces->CompOffFlowRatio);
   10700             :             } else {
   10701           0 :                 state.dataFurnaces->FanSpeedRatio = state.dataFurnaces->CompOnFlowRatio;
   10702             :             }
   10703     2449355 :         } else if (state.dataFurnaces->HeatingLoad && (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatCool)) {
   10704      111753 :             if (thisFurnace.NumOfSpeedHeating > 0) {
   10705           0 :                 state.dataFurnaces->CompOnMassFlow = thisFurnace.HeatMassFlowRate(thisFurnace.NumOfSpeedHeating);
   10706           0 :                 state.dataFurnaces->CompOnFlowRatio = thisFurnace.MSHeatingSpeedRatio(thisFurnace.NumOfSpeedHeating);
   10707           0 :                 state.dataHVACGlobal->MSHPMassFlowRateLow = thisFurnace.HeatMassFlowRate(thisFurnace.NumOfSpeedHeating);
   10708           0 :                 state.dataHVACGlobal->MSHPMassFlowRateHigh = thisFurnace.HeatMassFlowRate(thisFurnace.NumOfSpeedHeating);
   10709             :             } else {
   10710      111753 :                 state.dataFurnaces->CompOnMassFlow = thisFurnace.MaxHeatAirMassFlow;
   10711      111753 :                 state.dataFurnaces->CompOnFlowRatio = thisFurnace.HeatingSpeedRatio;
   10712             :             }
   10713      111753 :             AverageUnitMassFlow = (PartLoadRatio * state.dataFurnaces->CompOnMassFlow) + ((1 - PartLoadRatio) * state.dataFurnaces->CompOffMassFlow);
   10714      111753 :             if (state.dataFurnaces->CompOffFlowRatio > 0.0) {
   10715      111753 :                 state.dataFurnaces->FanSpeedRatio =
   10716      111753 :                     (PartLoadRatio * state.dataFurnaces->CompOnFlowRatio) + ((1 - PartLoadRatio) * state.dataFurnaces->CompOffFlowRatio);
   10717             :             } else {
   10718           0 :                 state.dataFurnaces->FanSpeedRatio = state.dataFurnaces->CompOnFlowRatio;
   10719             :             }
   10720     2337602 :         } else if (thisFurnace.bIsIHP) {
   10721       62326 :             if (!state.dataZoneEnergyDemand->CurDeadBandOrSetback(thisFurnace.ControlZoneNum) && present(SpeedNum)) {
   10722             :                 // if(present(SpeedNum)) {
   10723      118274 :                 state.dataFurnaces->CompOnMassFlow =
   10724       59137 :                     IntegratedHeatPump::GetAirMassFlowRateIHP(state, thisFurnace.CoolingCoilIndex, SpeedNum, SpeedRatio, false);
   10725      118274 :                 state.dataFurnaces->CompOnFlowRatio =
   10726       59137 :                     state.dataFurnaces->CompOnMassFlow /
   10727       59137 :                     IntegratedHeatPump::GetAirMassFlowRateIHP(
   10728             :                         state, thisFurnace.CoolingCoilIndex, IntegratedHeatPump::GetMaxSpeedNumIHP(state, thisFurnace.CoolingCoilIndex), 1.0, false);
   10729      118274 :                 state.dataHVACGlobal->MSHPMassFlowRateLow =
   10730       59137 :                     IntegratedHeatPump::GetAirMassFlowRateIHP(state, thisFurnace.CoolingCoilIndex, SpeedNum, 0.0, false);
   10731       59137 :                 state.dataHVACGlobal->MSHPMassFlowRateHigh =
   10732       59137 :                     IntegratedHeatPump::GetAirMassFlowRateIHP(state, thisFurnace.CoolingCoilIndex, SpeedNum, 1.0, false);
   10733             :             }
   10734             : 
   10735             :             // Set up fan flow rate during compressor off time
   10736       62326 :             if (thisFurnace.fanOp == HVAC::FanOp::Continuous && present(SpeedNum)) {
   10737           0 :                 if (thisFurnace.AirFlowControl == AirFlowControlConstFan::UseCompressorOnFlow && state.dataFurnaces->CompOnMassFlow > 0.0) {
   10738           0 :                     state.dataFurnaces->CompOffMassFlow =
   10739           0 :                         IntegratedHeatPump::GetAirMassFlowRateIHP(state, thisFurnace.CoolingCoilIndex, SpeedNum, 1.0, false);
   10740           0 :                     state.dataFurnaces->CompOffFlowRatio =
   10741           0 :                         state.dataFurnaces->CompOffMassFlow /
   10742           0 :                         IntegratedHeatPump::GetAirMassFlowRateIHP(state,
   10743             :                                                                   thisFurnace.CoolingCoilIndex,
   10744             :                                                                   IntegratedHeatPump::GetMaxSpeedNumIHP(state, thisFurnace.CoolingCoilIndex),
   10745             :                                                                   1.0,
   10746             :                                                                   false);
   10747             :                 }
   10748             :             }
   10749             : 
   10750       62326 :             if (present(SpeedNum)) {
   10751       62326 :                 if (SpeedNum > 1) {
   10752       39843 :                     AverageUnitMassFlow = state.dataFurnaces->CompOnMassFlow;
   10753       39843 :                     state.dataFurnaces->FanSpeedRatio = state.dataFurnaces->CompOnFlowRatio;
   10754             :                 } else {
   10755       22483 :                     AverageUnitMassFlow =
   10756       22483 :                         (PartLoadRatio * state.dataFurnaces->CompOnMassFlow) + ((1 - PartLoadRatio) * state.dataFurnaces->CompOffMassFlow);
   10757       22483 :                     if (state.dataFurnaces->CompOffFlowRatio > 0.0) {
   10758           0 :                         state.dataFurnaces->FanSpeedRatio =
   10759           0 :                             (PartLoadRatio * state.dataFurnaces->CompOnFlowRatio) + ((1 - PartLoadRatio) * state.dataFurnaces->CompOffFlowRatio);
   10760             :                     } else {
   10761       22483 :                         state.dataFurnaces->FanSpeedRatio = state.dataFurnaces->CompOnFlowRatio;
   10762             :                     }
   10763             :                 }
   10764             :             } else {
   10765           0 :                 AverageUnitMassFlow =
   10766           0 :                     (PartLoadRatio * state.dataFurnaces->CompOnMassFlow) + ((1 - PartLoadRatio) * state.dataFurnaces->CompOffMassFlow);
   10767           0 :                 if (state.dataFurnaces->CompOffFlowRatio > 0.0) {
   10768           0 :                     state.dataFurnaces->FanSpeedRatio =
   10769           0 :                         (PartLoadRatio * state.dataFurnaces->CompOnFlowRatio) + ((1 - PartLoadRatio) * state.dataFurnaces->CompOffFlowRatio);
   10770             :                 } else {
   10771           0 :                     state.dataFurnaces->FanSpeedRatio = state.dataFurnaces->CompOnFlowRatio;
   10772             :                 }
   10773             :             }
   10774             : 
   10775       62326 :             if (IntegratedHeatPump::IHPOperationMode::SCWHMatchWH ==
   10776       62326 :                 state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).CurMode) {
   10777         672 :                 state.dataFurnaces->CompOnMassFlow =
   10778         336 :                     IntegratedHeatPump::GetAirMassFlowRateIHP(state, thisFurnace.CoolingCoilIndex, SpeedNum, SpeedRatio, false);
   10779         336 :                 AverageUnitMassFlow = state.dataFurnaces->CompOnMassFlow;
   10780             :             }
   10781             :         } else {
   10782     2275276 :             if (!state.dataZoneEnergyDemand->CurDeadBandOrSetback(thisFurnace.ControlZoneNum) && present(SpeedNum)) {
   10783     1503373 :                 if (thisFurnace.HeatCoolMode == Furnaces::ModeOfOperation::HeatingMode) {
   10784      728218 :                     if (SpeedNum == 1) {
   10785      258337 :                         state.dataFurnaces->CompOnMassFlow = thisFurnace.HeatMassFlowRate(SpeedNum);
   10786      258337 :                         state.dataFurnaces->CompOnFlowRatio = thisFurnace.MSHeatingSpeedRatio(SpeedNum);
   10787      258337 :                         state.dataHVACGlobal->MSHPMassFlowRateLow = thisFurnace.HeatMassFlowRate(1);
   10788      258337 :                         state.dataHVACGlobal->MSHPMassFlowRateHigh = thisFurnace.HeatMassFlowRate(1);
   10789      469881 :                     } else if (SpeedNum > 1) {
   10790      939762 :                         state.dataFurnaces->CompOnMassFlow =
   10791      469881 :                             SpeedRatio * thisFurnace.HeatMassFlowRate(SpeedNum) + (1.0 - SpeedRatio) * thisFurnace.HeatMassFlowRate(SpeedNum - 1);
   10792      469881 :                         state.dataFurnaces->CompOnFlowRatio = SpeedRatio * thisFurnace.MSHeatingSpeedRatio(SpeedNum) +
   10793      469881 :                                                               (1.0 - SpeedRatio) * thisFurnace.MSHeatingSpeedRatio(SpeedNum - 1);
   10794      469881 :                         state.dataHVACGlobal->MSHPMassFlowRateLow = thisFurnace.HeatMassFlowRate(SpeedNum - 1);
   10795      469881 :                         state.dataHVACGlobal->MSHPMassFlowRateHigh = thisFurnace.HeatMassFlowRate(SpeedNum);
   10796             :                     }
   10797      775155 :                 } else if (thisFurnace.HeatCoolMode == Furnaces::ModeOfOperation::CoolingMode) {
   10798      629651 :                     if (SpeedNum == 1) {
   10799      445955 :                         state.dataFurnaces->CompOnMassFlow = thisFurnace.CoolMassFlowRate(SpeedNum);
   10800      445955 :                         state.dataFurnaces->CompOnFlowRatio = thisFurnace.MSCoolingSpeedRatio(SpeedNum);
   10801      445955 :                         state.dataHVACGlobal->MSHPMassFlowRateLow = thisFurnace.CoolMassFlowRate(1);
   10802      445955 :                         state.dataHVACGlobal->MSHPMassFlowRateHigh = thisFurnace.CoolMassFlowRate(1);
   10803      183696 :                     } else if (SpeedNum > 1) {
   10804      367392 :                         state.dataFurnaces->CompOnMassFlow =
   10805      183696 :                             SpeedRatio * thisFurnace.CoolMassFlowRate(SpeedNum) + (1.0 - SpeedRatio) * thisFurnace.CoolMassFlowRate(SpeedNum - 1);
   10806      183696 :                         state.dataFurnaces->CompOnFlowRatio = SpeedRatio * thisFurnace.MSCoolingSpeedRatio(SpeedNum) +
   10807      183696 :                                                               (1.0 - SpeedRatio) * thisFurnace.MSCoolingSpeedRatio(SpeedNum - 1);
   10808      183696 :                         state.dataHVACGlobal->MSHPMassFlowRateLow = thisFurnace.CoolMassFlowRate(SpeedNum - 1);
   10809      183696 :                         state.dataHVACGlobal->MSHPMassFlowRateHigh = thisFurnace.CoolMassFlowRate(SpeedNum);
   10810             :                     }
   10811             :                 }
   10812             :             }
   10813             : 
   10814             :             // Set up fan flow rate during compressor off time
   10815     2275276 :             if (thisFurnace.fanOp == HVAC::FanOp::Continuous && present(SpeedNum)) {
   10816     2149666 :                 if (thisFurnace.AirFlowControl == AirFlowControlConstFan::UseCompressorOnFlow && state.dataFurnaces->CompOnMassFlow > 0.0) {
   10817     2148022 :                     if (SpeedNum == 1) { // LOWEST SPEED USE IDLE FLOW
   10818     1318263 :                         state.dataFurnaces->CompOffMassFlow = thisFurnace.IdleMassFlowRate;
   10819     1318263 :                         state.dataFurnaces->CompOffFlowRatio = thisFurnace.IdleSpeedRatio;
   10820      829759 :                     } else if (thisFurnace.LastMode == Furnaces::ModeOfOperation::HeatingMode) {
   10821      441861 :                         state.dataFurnaces->CompOffMassFlow = thisFurnace.HeatMassFlowRate(SpeedNum);
   10822      441861 :                         state.dataFurnaces->CompOffFlowRatio = thisFurnace.MSHeatingSpeedRatio(SpeedNum);
   10823             :                     } else {
   10824      387898 :                         state.dataFurnaces->CompOffMassFlow = thisFurnace.CoolMassFlowRate(SpeedNum);
   10825      387898 :                         state.dataFurnaces->CompOffFlowRatio = thisFurnace.MSCoolingSpeedRatio(SpeedNum);
   10826             :                     }
   10827             :                 }
   10828             :             }
   10829             : 
   10830     2275276 :             if (present(SpeedNum)) {
   10831     2275276 :                 if (SpeedNum > 1) {
   10832      910227 :                     AverageUnitMassFlow = state.dataFurnaces->CompOnMassFlow;
   10833      910227 :                     state.dataFurnaces->FanSpeedRatio = state.dataFurnaces->CompOnFlowRatio;
   10834             :                 } else {
   10835     1365049 :                     AverageUnitMassFlow =
   10836     1365049 :                         (PartLoadRatio * state.dataFurnaces->CompOnMassFlow) + ((1 - PartLoadRatio) * state.dataFurnaces->CompOffMassFlow);
   10837     1365049 :                     if (state.dataFurnaces->CompOffFlowRatio > 0.0) {
   10838     1319907 :                         state.dataFurnaces->FanSpeedRatio =
   10839     1319907 :                             (PartLoadRatio * state.dataFurnaces->CompOnFlowRatio) + ((1 - PartLoadRatio) * state.dataFurnaces->CompOffFlowRatio);
   10840             :                     } else {
   10841       45142 :                         state.dataFurnaces->FanSpeedRatio = state.dataFurnaces->CompOnFlowRatio;
   10842             :                     }
   10843             :                 }
   10844             :             } else {
   10845           0 :                 AverageUnitMassFlow =
   10846           0 :                     (PartLoadRatio * state.dataFurnaces->CompOnMassFlow) + ((1 - PartLoadRatio) * state.dataFurnaces->CompOffMassFlow);
   10847           0 :                 if (state.dataFurnaces->CompOffFlowRatio > 0.0) {
   10848           0 :                     state.dataFurnaces->FanSpeedRatio =
   10849           0 :                         (PartLoadRatio * state.dataFurnaces->CompOnFlowRatio) + ((1 - PartLoadRatio) * state.dataFurnaces->CompOffFlowRatio);
   10850             :                 } else {
   10851           0 :                     state.dataFurnaces->FanSpeedRatio = state.dataFurnaces->CompOnFlowRatio;
   10852             :                 }
   10853             :             }
   10854             :         }
   10855             : 
   10856    35363984 :         if ((ScheduleManager::GetCurrentScheduleValue(state, thisFurnace.SchedPtr) == 0.0) || state.dataHVACGlobal->TurnFansOff ||
   10857    17676202 :             (ScheduleManager::GetCurrentScheduleValue(state, thisFurnace.FanAvailSchedPtr) == 0.0 && !state.dataHVACGlobal->TurnFansOn)) {
   10858       11580 :             state.dataLoopNodes->Node(thisFurnace.FurnaceInletNodeNum).MassFlowRate = 0.0;
   10859       11580 :             OnOffAirFlowRatio = 0.0;
   10860             :         } else {
   10861    17676202 :             state.dataLoopNodes->Node(thisFurnace.FurnaceInletNodeNum).MassFlowRate = AverageUnitMassFlow;
   10862    17676202 :             state.dataLoopNodes->Node(thisFurnace.FurnaceInletNodeNum).MassFlowRateMaxAvail = AverageUnitMassFlow;
   10863    17676202 :             if (AverageUnitMassFlow > 0.0) {
   10864    17637342 :                 OnOffAirFlowRatio = state.dataFurnaces->CompOnMassFlow / AverageUnitMassFlow;
   10865             :             } else {
   10866       38860 :                 OnOffAirFlowRatio = 0.0;
   10867             :             }
   10868             :         }
   10869             : 
   10870    17687782 :         state.dataLoopNodes->Node(thisFurnace.FurnaceOutletNodeNum).MassFlowRate =
   10871    17687782 :             state.dataLoopNodes->Node(thisFurnace.FurnaceInletNodeNum).MassFlowRate;
   10872    17687782 :     }
   10873             : 
   10874         359 :     void SetMinOATCompressor(EnergyPlusData &state,
   10875             :                              int const FurnaceNum,                    // index to furnace
   10876             :                              std::string const &cCurrentModuleObject, // type of furnace
   10877             :                              bool &ErrorsFound                        // GetInput logical that errors were found
   10878             :     )
   10879             :     {
   10880         359 :         bool errFlag = false;
   10881         359 :         auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
   10882             : 
   10883             :         // Set minimum OAT for heat pump compressor operation in heating mode
   10884         359 :         if (thisFurnace.CoolingCoilType_Num == HVAC::CoilDX_CoolingSingleSpeed) {
   10885         206 :             thisFurnace.MinOATCompressorCooling = DXCoils::GetMinOATCompressor(state, thisFurnace.CoolingCoilIndex, errFlag);
   10886         153 :         } else if (thisFurnace.CoolingCoilType_Num == HVAC::CoilDX_CoolingHXAssisted) {
   10887           3 :             std::string ChildCoolingCoilType = state.dataHVACAssistedCC->HXAssistedCoil(thisFurnace.CoolingCoilIndex).CoolingCoilType;
   10888           3 :             std::string ChildCoolingCoilName = state.dataHVACAssistedCC->HXAssistedCoil(thisFurnace.CoolingCoilIndex).CoolingCoilName;
   10889             : 
   10890           3 :             if (Util::SameString(ChildCoolingCoilType, "COIL:COOLING:DX")) {
   10891           1 :                 int childCCIndex_DX = CoilCoolingDX::factory(state, ChildCoolingCoilName);
   10892           1 :                 if (childCCIndex_DX < 0) {
   10893           0 :                     ShowContinueError(state, format("Occurs in {} = {}", cCurrentModuleObject, thisFurnace.Name));
   10894           0 :                     errFlag = true;
   10895           0 :                     ErrorsFound = true;
   10896             :                 }
   10897           1 :                 auto const &newCoil = state.dataCoilCooingDX->coilCoolingDXs[childCCIndex_DX];
   10898           1 :                 thisFurnace.MinOATCompressorCooling = newCoil.performance.minOutdoorDrybulb;
   10899           2 :             } else if (Util::SameString(ChildCoolingCoilType, "Coil:Cooling:DX:VariableSpeed")) {
   10900           0 :                 int childCCIndex_VS = state.dataHVACAssistedCC->HXAssistedCoil(thisFurnace.CoolingCoilIndex).CoolingCoilIndex;
   10901           0 :                 thisFurnace.MinOATCompressorCooling = VariableSpeedCoils::GetVSCoilMinOATCompressor(state, childCCIndex_VS, errFlag);
   10902             :             } else { // Single speed
   10903           2 :                 int childCCIndex_SP = state.dataHVACAssistedCC->HXAssistedCoil(thisFurnace.CoolingCoilIndex).CoolingCoilIndex;
   10904           2 :                 thisFurnace.MinOATCompressorCooling = DXCoils::GetMinOATCompressor(state, childCCIndex_SP, errFlag);
   10905             :             }
   10906         153 :         } else if (thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingAirToAirVariableSpeed) {
   10907           7 :             thisFurnace.MinOATCompressorCooling = VariableSpeedCoils::GetVSCoilMinOATCompressor(state, thisFurnace.CoolingCoilIndex, errFlag);
   10908             :         } else {
   10909         143 :             thisFurnace.MinOATCompressorCooling = -1000.0;
   10910             :         }
   10911         359 :         if (errFlag) {
   10912           0 :             ShowContinueError(state, format("...occurs in {} = {}", cCurrentModuleObject, thisFurnace.Name));
   10913           0 :             ErrorsFound = true;
   10914             :         }
   10915             : 
   10916             :         // Set minimum OAT for heat pump compressor operation in heating mode
   10917         359 :         errFlag = false;
   10918         359 :         if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingAirToAirVariableSpeed) {
   10919           3 :             thisFurnace.MinOATCompressorHeating = VariableSpeedCoils::GetVSCoilMinOATCompressor(state, thisFurnace.HeatingCoilIndex, errFlag);
   10920         356 :         } else if (thisFurnace.HeatingCoilType_Num == HVAC::CoilDX_HeatingEmpirical) {
   10921          32 :             thisFurnace.MinOATCompressorHeating = DXCoils::GetMinOATCompressor(state, thisFurnace.HeatingCoilIndex, errFlag);
   10922             :         } else {
   10923         324 :             thisFurnace.MinOATCompressorHeating = -1000.0;
   10924             :         }
   10925         359 :         if (errFlag) {
   10926           0 :             ShowContinueError(state, format("...occurs in {} = {}", cCurrentModuleObject, thisFurnace.Name));
   10927           0 :             ErrorsFound = true;
   10928             :         }
   10929         359 :     }
   10930             : 
   10931             : } // namespace Furnaces
   10932             : 
   10933             : } // namespace EnergyPlus

Generated by: LCOV version 1.14