LCOV - code coverage report
Current view: top level - EnergyPlus - Furnaces.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 21.0 % 5255 1104
Test Date: 2025-05-22 16:09:37 Functions: 44.1 % 34 15

            Line data    Source code
       1              : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
       2              : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
       3              : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
       4              : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
       5              : // contributors. All rights reserved.
       6              : //
       7              : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
       8              : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
       9              : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
      10              : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
      11              : // derivative works, and perform publicly and display publicly, and to permit others to do so.
      12              : //
      13              : // Redistribution and use in source and binary forms, with or without modification, are permitted
      14              : // provided that the following conditions are met:
      15              : //
      16              : // (1) Redistributions of source code must retain the above copyright notice, this list of
      17              : //     conditions and the following disclaimer.
      18              : //
      19              : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
      20              : //     conditions and the following disclaimer in the documentation and/or other materials
      21              : //     provided with the distribution.
      22              : //
      23              : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
      24              : //     the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
      25              : //     used to endorse or promote products derived from this software without specific prior
      26              : //     written permission.
      27              : //
      28              : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
      29              : //     without changes from the version obtained under this License, or (ii) Licensee makes a
      30              : //     reference solely to the software portion of its product, Licensee must refer to the
      31              : //     software as "EnergyPlus version X" software, where "X" is the version number Licensee
      32              : //     obtained under this License and may not use a different name for the software. Except as
      33              : //     specifically required in this Section (4), Licensee shall not use in a company name, a
      34              : //     product name, in advertising, publicity, or other promotional activities any name, trade
      35              : //     name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
      36              : //     similar designation, without the U.S. Department of Energy's prior written consent.
      37              : //
      38              : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
      39              : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
      40              : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
      41              : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      42              : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      43              : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      44              : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      45              : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      46              : // POSSIBILITY OF SUCH DAMAGE.
      47              : 
      48              : // C++ Headers
      49              : #include <cassert>
      50              : #include <cmath>
      51              : 
      52              : // ObjexxFCL Headers
      53              : #include <ObjexxFCL/Array.functions.hh>
      54              : 
      55              : // EnergyPlus Headers
      56              : #include <AirflowNetwork/Solver.hpp>
      57              : #include <EnergyPlus/Autosizing/Base.hh>
      58              : #include <EnergyPlus/BranchInputManager.hh>
      59              : #include <EnergyPlus/BranchNodeConnections.hh>
      60              : #include <EnergyPlus/Coils/CoilCoolingDX.hh>
      61              : #include <EnergyPlus/DXCoils.hh>
      62              : #include <EnergyPlus/Data/EnergyPlusData.hh>
      63              : #include <EnergyPlus/DataAirSystems.hh>
      64              : #include <EnergyPlus/DataHVACGlobals.hh>
      65              : #include <EnergyPlus/DataHeatBalFanSys.hh>
      66              : #include <EnergyPlus/DataHeatBalance.hh>
      67              : #include <EnergyPlus/DataIPShortCuts.hh>
      68              : #include <EnergyPlus/DataSizing.hh>
      69              : #include <EnergyPlus/DataZoneControls.hh>
      70              : #include <EnergyPlus/DataZoneEnergyDemands.hh>
      71              : #include <EnergyPlus/DataZoneEquipment.hh>
      72              : #include <EnergyPlus/EMSManager.hh>
      73              : #include <EnergyPlus/Fans.hh>
      74              : #include <EnergyPlus/FluidProperties.hh>
      75              : #include <EnergyPlus/Furnaces.hh>
      76              : #include <EnergyPlus/General.hh>
      77              : #include <EnergyPlus/GeneralRoutines.hh>
      78              : #include <EnergyPlus/GlobalNames.hh>
      79              : #include <EnergyPlus/HVACControllers.hh>
      80              : #include <EnergyPlus/HVACHXAssistedCoolingCoil.hh>
      81              : #include <EnergyPlus/HeatingCoils.hh>
      82              : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      83              : #include <EnergyPlus/IntegratedHeatPump.hh>
      84              : #include <EnergyPlus/NodeInputManager.hh>
      85              : #include <EnergyPlus/OutAirNodeManager.hh>
      86              : #include <EnergyPlus/OutputProcessor.hh>
      87              : #include <EnergyPlus/OutputReportPredefined.hh>
      88              : #include <EnergyPlus/PlantUtilities.hh>
      89              : #include <EnergyPlus/Psychrometrics.hh>
      90              : #include <EnergyPlus/ScheduleManager.hh>
      91              : #include <EnergyPlus/SteamCoils.hh>
      92              : #include <EnergyPlus/WaterCoils.hh>
      93              : #include <EnergyPlus/WaterToAirHeatPump.hh>
      94              : #include <EnergyPlus/WaterToAirHeatPumpSimple.hh>
      95              : #include <EnergyPlus/ZoneTempPredictorCorrector.hh>
      96              : 
      97              : namespace EnergyPlus {
      98              : 
      99              : namespace Furnaces {
     100              :     // Module containing the Furnace and Unitary System simulation routines
     101              : 
     102              :     // MODULE INFORMATION:
     103              :     //       AUTHOR         Dan Fisher
     104              :     //       DATE WRITTEN   Jan 2001
     105              :     //       MODIFIED       Richard Liesen, Feb 2001; Don Shirey, Mar/Oct 2001, Oct 2003
     106              :     //                      Richard Raustad, Nov 2006 - allow draw through fan and alternate air flow in cooling,
     107              :     //                      heating, and when no cooling or heating is required.
     108              :     //                      Bereket Nigusse, FSEC, June 2010 - deprecated supply air flow fraction through controlled
     109              :     //                      zone from the furnace object input field. Now, the flow fraction is calculated internally
     110              :     //                      B. Nigusse, FSEC, Jan 2012 - added steam and hot water heating coils as an option
     111              :     //                      Bo Shen, ORNL, March 2012 - added variable-speed water source heat pump cooling and heating coils, using curve-fits
     112              :     //                      Bo Shen, ORNL, July 2012 - added variable-speed air source heat pump cooling and heating coils, using curve-fits
     113              : 
     114              :     // PURPOSE OF THIS MODULE:
     115              :     // To encapsulate the data and algorithms required to
     116              :     // manage the Furnace/Unitary System Compound Component
     117              : 
     118              :     // METHODOLOGY EMPLOYED:
     119              :     // Calculates the part-load ratio of the HVAC system to meet the zone sensible load. For non-heat pump HVAC systems,
     120              :     // if humidity control is specified and the latent capacity at the sensible PLR is insufficient to meet the latent load,
     121              :     // calculate a latent part-load ratio to meet the zone sensible load (MultiMode dehumidification control) or the zone
     122              :     // latent load (CoolReheat dehumidification control). Use the greater of the sensible PLR and latent PLR to control
     123              :     // the HVAC system.
     124              :     // Subroutines:
     125              :     // SimFurnace - Top level simulate routine CALLed by other modules. Each child object is simulated a final time after
     126              :     //              the part-load ratio for child components has been determined.
     127              :     //  Note: A supplemental heater augments the heating capacity for both air-to-air and water-to-air heat pump systems.
     128              :     //        A reheat coil is used for the HeatCool furnace/unitarysystem to offset the sensible cooling when the
     129              :     //        dehumidification control type is COOLREHEAT. Both the supplemental and reheat heating coil load is calculated
     130              :     //        in the Calc routines. The actual simulation of these coils is performed in the SimFurnace routine (i.e. the
     131              :     //        supplemental and reheat coil loads are passed as 0 to CalcFurnaceOutput).
     132              :     // CalcNewZoneHeatOnlyFlowRates - HeatOnly furnace/unitarysystem routine.
     133              :     //                                Calculates a part-load ratio to meet the sensible load.
     134              :     // CalcNewZoneHeatCoolFlowRates - HeatCool furnace/unitarysystem and air-to-air HeatPump routine.
     135              :     //                                Calculates a part-load ratio for the system (sensible and/or latent).
     136              :     //                                For dehumidification control type COOLREHEAT, both a sensible and latent PLR
     137              :     //                                may exist for a single time step (heating and dehumidification can occur). For all
     138              :     //                                other system types, only a single PLR is allowed for any given time step.
     139              :     //                                Order of simulation depends on dehumidification control option as described below.
     140              :     // Dehumidification control options (non-heat pump versions):
     141              :     // Dehumidification Control NONE:   Cooling performance is simulated first and then heating performance. If a HX
     142              :     //                                  assisted cooling coil is selected, the HX is always active (cooling).
     143              :     // Dehumidification Control COOLREHEAT: For cooling operation, the sensible capacity is calculated to
     144              :     //                                      meet the thermostat setpoint. If a HX assisted cooling coil is selected,
     145              :     //                                      the HX is always active. If the latent load is not met by operating the
     146              :     //                                      system at the sensible PLR, a new PLR is calculated to meet the humidistat
     147              :     //                                      setpoint. The reheat coil load is then calculated to meet the HEATING
     148              :     //                                      setpoint temperature.
     149              :     // Dehumidification Control MULTIMODE: For cooling operation, the sensible capacity is calculated to
     150              :     //                                     meet the thermostat setpoint. If a HX assisted cooling coil is selected,
     151              :     //                                     the HX is off for this calculation. If the latent load is not met by operating
     152              :     //                                     the system at the sensible PLR, a new PLR is calculated with the HX operating
     153              :     //                                     and the target is the zone SENSIBLE load (thermostat setpoint). Humidity is not
     154              :     //                                     controlled in this mode. No reheat coil is used in this configuration.
     155              :     // CalcWaterToAirHeatPump - Water-to-air HeatPump routine.
     156              :     //                          Calculates a part-load ratio to meet the sensible load.
     157              :     // CalcFurnaceOutput - Simulates each child component in order.
     158              :     //                     For cooling operation, the heating coil is off.
     159              :     //                     For heating operation, the cooling coil is off.
     160              :     //                     Reheat or supplemental heating coil is simulated here just to pass the inlet node conditions
     161              :     //                     to the output node (actual simulation of these coils is done on the final simulation of the
     162              :     //                     child components in SimFurnace).
     163              :     //                     Fan is simulated based on placement (drawthru or blowthru).
     164              : 
     165              :     // MODULE PARAMETER DEFINITIONS
     166              :     static constexpr std::string_view BlankString;
     167              : 
     168              :     // Functions
     169              : 
     170        15222 :     void SimFurnace(EnergyPlusData &state,
     171              :                     std::string_view FurnaceName,
     172              :                     bool const FirstHVACIteration,
     173              :                     int const AirLoopNum, // Primary air loop number
     174              :                     int &CompIndex        // Pointer to which furnace
     175              :     )
     176              :     {
     177              : 
     178              :         // SUBROUTINE INFORMATION:
     179              :         //       AUTHOR         Dan Fisher
     180              :         //       DATE WRITTEN   Jan 2001
     181              :         //       MODIFIED       Richard Liesen, Oct 2001 - Richard Raustad; Bo Shen, March 2012, for VS WSHP
     182              :         //       RE-ENGINEERED  Feb 2001
     183              : 
     184              :         // PURPOSE OF THIS SUBROUTINE:
     185              :         // This subroutine manages Furnace component simulation.
     186              : 
     187              :         // METHODOLOGY EMPLOYED:
     188              :         // Call the calc routine to determine an operating PLR. Resimulate child components at this PLR.
     189              :         // A supplemental heater augments the heating capacity for both air-to-air and water-to-air heat pump systems.
     190              :         // A reheat coil is used for the HeatCool furnace/unitarysystem to offset the sensible cooling when the
     191              :         // dehumidification control type is COOLREHEAT. Both the supplemental and reheat heating coil load is calculated
     192              :         // in the Calc routines and returned here through subroutine arguments. The actual simulation of these coils is
     193              :         // performed here (i.e. the supplemental and reheat coil loads are passed as 0 to CalcFurnaceOutput).
     194              : 
     195              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     196              :         int FurnaceNum;           // Furnace number
     197        15222 :         Real64 HeatCoilLoad(0.0); // Zone heating coil load
     198              :         Real64 ReheatCoilLoad;    // Load to be met by the reheat coil (if high humidity control)
     199              :         Real64 MoistureLoad;      // Control zone latent load
     200        15222 :         Real64 Dummy(0.0);
     201        15222 :         HVAC::FanOp fanOp = HVAC::FanOp::Invalid; // Fan operating mode (1=FanOp::Cycling, 2=FanOp::Continuous)
     202              : 
     203              :         Real64 QActual;           // actual heating coil output (W)
     204              :         bool SuppHeatingCoilFlag; // true if supplemental heating coil
     205              : 
     206              :         // Obtains and Allocates Furnace related parameters from input file
     207        15222 :         if (state.dataFurnaces->GetFurnaceInputFlag) { // First time subroutine has been entered
     208              :             // Get the furnace input
     209            2 :             GetFurnaceInput(state);
     210            2 :             state.dataFurnaces->GetFurnaceInputFlag = false;
     211              :         }
     212              : 
     213              :         // Find the correct Furnace
     214        15222 :         if (CompIndex == 0) {
     215            3 :             FurnaceNum = Util::FindItemInList(FurnaceName, state.dataFurnaces->Furnace);
     216            3 :             if (FurnaceNum == 0) {
     217            0 :                 ShowFatalError(state, format("SimFurnace: Unit not found={}", FurnaceName));
     218              :             }
     219            3 :             CompIndex = FurnaceNum;
     220              :         } else {
     221        15219 :             FurnaceNum = CompIndex;
     222        15219 :             if (FurnaceNum > state.dataFurnaces->NumFurnaces || FurnaceNum < 1) {
     223            0 :                 ShowFatalError(state,
     224            0 :                                format("SimFurnace:  Invalid CompIndex passed={}, Number of Units={}, Entered Unit name={}",
     225              :                                       FurnaceNum,
     226            0 :                                       state.dataFurnaces->NumFurnaces,
     227              :                                       FurnaceName));
     228              :             }
     229        15219 :             if (state.dataFurnaces->CheckEquipName(FurnaceNum)) {
     230            2 :                 if (FurnaceName != state.dataFurnaces->Furnace(FurnaceNum).Name) {
     231            0 :                     ShowFatalError(state,
     232            0 :                                    format("SimFurnace: Invalid CompIndex passed={}, Unit name={}, stored Unit Name for that index={}",
     233              :                                           FurnaceNum,
     234              :                                           FurnaceName,
     235            0 :                                           state.dataFurnaces->Furnace(FurnaceNum).Name));
     236              :                 }
     237            2 :                 state.dataFurnaces->CheckEquipName(FurnaceNum) = false;
     238              :             }
     239              :         }
     240              : 
     241        15222 :         bool HXUnitOn = false;          // flag to control HX assisted cooling coil
     242        15222 :         Real64 OnOffAirFlowRatio = 0.0; // Ratio of compressor ON air flow to AVERAGE air flow over time step
     243              :         // here we need to deal with sequenced zone equip sensible load in control zone
     244        15222 :         Real64 ZoneLoad = 0.0;
     245              : 
     246        15222 :         auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
     247        15222 :         auto &zoneSysEnergyDemand = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(thisFurnace.ControlZoneNum);
     248        15222 :         if (thisFurnace.ZoneSequenceCoolingNum > 0 && thisFurnace.ZoneSequenceHeatingNum > 0) {
     249        15220 :             Real64 ZoneLoadToCoolSPSequenced = zoneSysEnergyDemand.SequencedOutputRequiredToCoolingSP(thisFurnace.ZoneSequenceCoolingNum);
     250        15220 :             Real64 ZoneLoadToHeatSPSequenced = zoneSysEnergyDemand.SequencedOutputRequiredToHeatingSP(thisFurnace.ZoneSequenceHeatingNum);
     251        15220 :             auto const &tempControlType = state.dataHeatBalFanSys->TempControlType(thisFurnace.ControlZoneNum);
     252        15220 :             if (ZoneLoadToHeatSPSequenced > 0.0 && ZoneLoadToCoolSPSequenced > 0.0 && tempControlType != HVAC::SetptType::SingleCool) {
     253         8360 :                 ZoneLoad = ZoneLoadToHeatSPSequenced;
     254         6860 :             } else if (ZoneLoadToHeatSPSequenced > 0.0 && ZoneLoadToCoolSPSequenced > 0.0 && tempControlType == HVAC::SetptType::SingleCool) {
     255            0 :                 ZoneLoad = 0.0;
     256         6860 :             } else if (ZoneLoadToHeatSPSequenced < 0.0 && ZoneLoadToCoolSPSequenced < 0.0 && tempControlType != HVAC::SetptType::SingleHeat) {
     257         6748 :                 ZoneLoad = ZoneLoadToCoolSPSequenced;
     258          112 :             } else if (ZoneLoadToHeatSPSequenced < 0.0 && ZoneLoadToCoolSPSequenced < 0.0 && tempControlType == HVAC::SetptType::SingleHeat) {
     259            0 :                 ZoneLoad = 0.0;
     260          112 :             } else if (ZoneLoadToHeatSPSequenced <= 0.0 && ZoneLoadToCoolSPSequenced >= 0.0) {
     261          112 :                 ZoneLoad = 0.0;
     262              :             }
     263        15220 :             MoistureLoad = state.dataZoneEnergyDemand->ZoneSysMoistureDemand(thisFurnace.ControlZoneNum)
     264        15220 :                                .SequencedOutputRequiredToDehumidSP(thisFurnace.ZoneSequenceCoolingNum);
     265        15220 :         } else {
     266            2 :             ZoneLoad = zoneSysEnergyDemand.RemainingOutputRequired;
     267            2 :             MoistureLoad = state.dataZoneEnergyDemand->ZoneSysMoistureDemand(thisFurnace.ControlZoneNum).OutputRequiredToDehumidifyingSP;
     268              :         }
     269              : 
     270              :         // H2OHtOfVap
     271        15222 :         MoistureLoad *= Psychrometrics::PsyHfgAirFnWTdb(state.dataLoopNodes->Node(thisFurnace.NodeNumOfControlledZone).HumRat,
     272        15222 :                                                         state.dataLoopNodes->Node(thisFurnace.NodeNumOfControlledZone).Temp);
     273              : 
     274              :         // Initialize Furnace Flows
     275        15222 :         InitFurnace(state, FurnaceNum, AirLoopNum, OnOffAirFlowRatio, fanOp, ZoneLoad, MoistureLoad, FirstHVACIteration);
     276              : 
     277        15222 :         int FurnaceInletNode = thisFurnace.FurnaceInletNodeNum;
     278              : 
     279              :         // MassFlowRateMaxAvail issues are impeding non-VAV air loop equipment by limiting air flow
     280              :         // temporarily open up flow limits while simulating, and then set this same value at the INLET after this parent has simulated
     281        15222 :         Real64 TempMassFlowRateMaxAvail = state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRateMaxAvail;
     282        15222 :         state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRateMaxAvail = thisFurnace.DesignMassFlowRate;
     283              : 
     284        15222 :         Real64 FurnaceSavMdot = state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate;
     285        15222 :         HVAC::CompressorOp compressorOp = HVAC::CompressorOp::On;
     286        15222 :         state.dataFurnaces->CoolHeatPLRRat = 1.0;
     287              : 
     288              :         // Simulate correct system type (1 of 4 choices)
     289        15222 :         switch (thisFurnace.type) {
     290              :             // Simulate HeatOnly systems:
     291            0 :         case HVAC::UnitarySysType::Furnace_HeatOnly:
     292              :         case HVAC::UnitarySysType::Unitary_HeatOnly: {
     293              :             // Update the furnace flow rates
     294            0 :             CalcNewZoneHeatOnlyFlowRates(state, FurnaceNum, FirstHVACIteration, ZoneLoad, HeatCoilLoad, OnOffAirFlowRatio);
     295              : 
     296            0 :             if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
     297              :                 // simulate fan
     298            0 :                 state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
     299              :             }
     300              : 
     301              :             // simulate furnace heating coil
     302            0 :             SuppHeatingCoilFlag = false; // if true simulates supplemental heating coil
     303            0 :             CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, fanOp, QActual);
     304              : 
     305            0 :             if (thisFurnace.fanPlace == HVAC::FanPlace::DrawThru) {
     306              :                 // simulate fan
     307            0 :                 state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
     308              :             }
     309            0 :         } break;
     310              :             // Simulate HeatCool systems:
     311            0 :         case HVAC::UnitarySysType::Furnace_HeatCool:
     312              :         case HVAC::UnitarySysType::Unitary_HeatCool: {
     313            0 :             if (thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingAirToAirVariableSpeed) {
     314              :                 // variable speed cooling coil
     315            0 :                 HeatCoilLoad = 0.0;
     316            0 :                 if (thisFurnace.bIsIHP)
     317            0 :                     state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).ControlledZoneTemp =
     318            0 :                         state.dataLoopNodes->Node(thisFurnace.NodeNumOfControlledZone).Temp;
     319            0 :                 SimVariableSpeedHP(state, FurnaceNum, FirstHVACIteration, AirLoopNum, ZoneLoad, MoistureLoad, OnOffAirFlowRatio);
     320              :             } else {
     321              :                 // calculate the system flow rate
     322            0 :                 if (!FirstHVACIteration && thisFurnace.fanOp == HVAC::FanOp::Cycling && state.dataFurnaces->CoolingLoad &&
     323            0 :                     state.dataAirLoop->AirLoopControlInfo(AirLoopNum).EconoActive) {
     324              :                     // for cycling fan, cooling load, check whether furnace can meet load with compressor off
     325            0 :                     compressorOp = HVAC::CompressorOp::Off;
     326            0 :                     CalcNewZoneHeatCoolFlowRates(state,
     327              :                                                  FurnaceNum,
     328              :                                                  FirstHVACIteration,
     329              :                                                  compressorOp,
     330              :                                                  ZoneLoad,
     331              :                                                  MoistureLoad,
     332              :                                                  HeatCoilLoad,
     333              :                                                  ReheatCoilLoad,
     334              :                                                  OnOffAirFlowRatio,
     335              :                                                  HXUnitOn);
     336            0 :                     if (thisFurnace.CoolPartLoadRatio >= 1.0 || thisFurnace.HeatPartLoadRatio >= 1.0 ||
     337            0 :                         (thisFurnace.CoolPartLoadRatio <= 0.0 && thisFurnace.HeatPartLoadRatio <= 0.0)) {
     338              :                         // compressor on (reset inlet air mass flow rate to starting value)
     339            0 :                         state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = FurnaceSavMdot;
     340            0 :                         compressorOp = HVAC::CompressorOp::On;
     341            0 :                         CalcNewZoneHeatCoolFlowRates(state,
     342              :                                                      FurnaceNum,
     343              :                                                      FirstHVACIteration,
     344              :                                                      compressorOp,
     345              :                                                      ZoneLoad,
     346              :                                                      MoistureLoad,
     347              :                                                      HeatCoilLoad,
     348              :                                                      ReheatCoilLoad,
     349              :                                                      OnOffAirFlowRatio,
     350              :                                                      HXUnitOn);
     351              :                     }
     352              :                 } else {
     353              :                     // compressor on
     354            0 :                     CalcNewZoneHeatCoolFlowRates(state,
     355              :                                                  FurnaceNum,
     356              :                                                  FirstHVACIteration,
     357              :                                                  compressorOp,
     358              :                                                  ZoneLoad,
     359              :                                                  MoistureLoad,
     360              :                                                  HeatCoilLoad,
     361              :                                                  ReheatCoilLoad,
     362              :                                                  OnOffAirFlowRatio,
     363              :                                                  HXUnitOn);
     364              :                 }
     365              : 
     366            0 :                 if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
     367              :                     // simulate fan
     368            0 :                     state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
     369              :                 }
     370              : 
     371            0 :                 if (!thisFurnace.CoolingCoilUpstream) {
     372              :                     // simulate furnace heating coil
     373            0 :                     SuppHeatingCoilFlag = false; // if true simulates supplemental heating coil
     374            0 :                     CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, fanOp, QActual);
     375              :                 }
     376              : 
     377              :                 // simulate furnace DX cooling coil
     378            0 :                 if (thisFurnace.CoolingCoilType_Num == HVAC::CoilDX_CoolingHXAssisted) {
     379            0 :                     HVACHXAssistedCoolingCoil::SimHXAssistedCoolingCoil(state,
     380              :                                                                         BlankString,
     381              :                                                                         FirstHVACIteration,
     382              :                                                                         compressorOp,
     383              :                                                                         thisFurnace.CoolPartLoadRatio,
     384            0 :                                                                         thisFurnace.CoolingCoilIndex,
     385              :                                                                         fanOp,
     386              :                                                                         HXUnitOn,
     387              :                                                                         OnOffAirFlowRatio,
     388            0 :                                                                         state.dataFurnaces->EconomizerFlag);
     389              :                 } else {
     390            0 :                     DXCoils::SimDXCoil(state,
     391              :                                        BlankString,
     392              :                                        compressorOp,
     393              :                                        FirstHVACIteration,
     394            0 :                                        thisFurnace.CoolingCoilIndex,
     395              :                                        fanOp,
     396            0 :                                        thisFurnace.CoolPartLoadRatio,
     397              :                                        OnOffAirFlowRatio,
     398            0 :                                        state.dataFurnaces->CoolHeatPLRRat);
     399              :                 }
     400              : 
     401            0 :                 if (thisFurnace.CoolingCoilUpstream) {
     402              :                     // simulate furnace heating coil
     403            0 :                     SuppHeatingCoilFlag = false; // if true simulates supplemental heating coil
     404            0 :                     CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, fanOp, QActual);
     405              :                 }
     406              : 
     407            0 :                 if (thisFurnace.fanPlace == HVAC::FanPlace::DrawThru) {
     408              :                     // simulate fan
     409            0 :                     state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
     410              :                 }
     411              : 
     412              :                 // Simulate furnace reheat coil if a humidistat is used or if the reheat coil is present
     413            0 :                 if (thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat || thisFurnace.SuppHeatCoilIndex > 0) {
     414            0 :                     SuppHeatingCoilFlag = true; // if true simulates supplemental heating coil
     415            0 :                     CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, ReheatCoilLoad, fanOp, QActual);
     416              :                 }
     417              :             }
     418            0 :         } break;
     419              :             // Simulate air-to-air heat pumps:
     420        15222 :         case HVAC::UnitarySysType::Unitary_HeatPump_AirToAir: {
     421        15222 :             if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingAirToAirVariableSpeed) {
     422              :                 // variable speed heat pump
     423            0 :                 HeatCoilLoad = 0.0;
     424            0 :                 if (thisFurnace.bIsIHP) {
     425            0 :                     auto &integratedHP = state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex);
     426            0 :                     integratedHP.ControlledZoneTemp = state.dataLoopNodes->Node(thisFurnace.NodeNumOfControlledZone).Temp;
     427            0 :                     integratedHP.IDFanID = thisFurnace.FanIndex; // why do this every time?
     428            0 :                     integratedHP.IDFanName = BlankString;
     429            0 :                     integratedHP.fanPlace = thisFurnace.fanPlace;
     430              :                 }
     431              : 
     432            0 :                 SimVariableSpeedHP(state, FurnaceNum, FirstHVACIteration, AirLoopNum, ZoneLoad, MoistureLoad, OnOffAirFlowRatio);
     433              :             } else {
     434              :                 // Update the furnace flow rates
     435        20283 :                 if (!FirstHVACIteration && thisFurnace.fanOp == HVAC::FanOp::Cycling && state.dataFurnaces->CoolingLoad &&
     436         5061 :                     state.dataAirLoop->AirLoopControlInfo(AirLoopNum).EconoActive) {
     437              :                     // for cycling fan, cooling load, check whether furnace can meet load with compressor off
     438            0 :                     compressorOp = HVAC::CompressorOp::Off;
     439            0 :                     CalcNewZoneHeatCoolFlowRates(state,
     440              :                                                  FurnaceNum,
     441              :                                                  FirstHVACIteration,
     442              :                                                  compressorOp,
     443              :                                                  ZoneLoad,
     444              :                                                  MoistureLoad,
     445              :                                                  HeatCoilLoad,
     446              :                                                  ReheatCoilLoad,
     447              :                                                  OnOffAirFlowRatio,
     448              :                                                  HXUnitOn);
     449            0 :                     if (thisFurnace.CoolPartLoadRatio >= 1.0 || thisFurnace.HeatPartLoadRatio >= 1.0 ||
     450            0 :                         (thisFurnace.CoolPartLoadRatio <= 0.0 && thisFurnace.HeatPartLoadRatio <= 0.0)) {
     451              :                         // compressor on (reset inlet air mass flow rate to starting value)
     452            0 :                         compressorOp = HVAC::CompressorOp::On;
     453            0 :                         state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = FurnaceSavMdot;
     454            0 :                         CalcNewZoneHeatCoolFlowRates(state,
     455              :                                                      FurnaceNum,
     456              :                                                      FirstHVACIteration,
     457              :                                                      compressorOp,
     458              :                                                      ZoneLoad,
     459              :                                                      MoistureLoad,
     460              :                                                      HeatCoilLoad,
     461              :                                                      ReheatCoilLoad,
     462              :                                                      OnOffAirFlowRatio,
     463              :                                                      HXUnitOn);
     464              :                     }
     465              :                 } else {
     466              :                     // compressor on
     467        15222 :                     CalcNewZoneHeatCoolFlowRates(state,
     468              :                                                  FurnaceNum,
     469              :                                                  FirstHVACIteration,
     470              :                                                  compressorOp,
     471              :                                                  ZoneLoad,
     472              :                                                  MoistureLoad,
     473              :                                                  HeatCoilLoad,
     474              :                                                  ReheatCoilLoad,
     475              :                                                  OnOffAirFlowRatio,
     476              :                                                  HXUnitOn);
     477              :                 }
     478              : 
     479        15222 :                 if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
     480        15222 :                     state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
     481              :                 }
     482              : 
     483        15222 :                 if (thisFurnace.CoolingCoilType_Num == HVAC::CoilDX_CoolingHXAssisted) {
     484            0 :                     HVACHXAssistedCoolingCoil::SimHXAssistedCoolingCoil(state,
     485              :                                                                         BlankString,
     486              :                                                                         FirstHVACIteration,
     487              :                                                                         compressorOp,
     488              :                                                                         thisFurnace.CoolPartLoadRatio,
     489            0 :                                                                         thisFurnace.CoolingCoilIndex,
     490              :                                                                         fanOp,
     491              :                                                                         HXUnitOn,
     492              :                                                                         OnOffAirFlowRatio,
     493            0 :                                                                         state.dataFurnaces->EconomizerFlag);
     494              :                 } else {
     495        30444 :                     DXCoils::SimDXCoil(state,
     496              :                                        BlankString,
     497              :                                        compressorOp,
     498              :                                        FirstHVACIteration,
     499        15222 :                                        thisFurnace.CoolingCoilIndex,
     500              :                                        fanOp,
     501        15222 :                                        thisFurnace.CoolPartLoadRatio,
     502              :                                        OnOffAirFlowRatio);
     503              :                 }
     504        30444 :                 DXCoils::SimDXCoil(state,
     505              :                                    BlankString,
     506              :                                    compressorOp,
     507              :                                    FirstHVACIteration,
     508        15222 :                                    thisFurnace.HeatingCoilIndex,
     509              :                                    fanOp,
     510        15222 :                                    thisFurnace.HeatPartLoadRatio,
     511              :                                    OnOffAirFlowRatio);
     512        15222 :                 if (thisFurnace.fanPlace == HVAC::FanPlace::DrawThru) {
     513            0 :                     state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
     514              :                 }
     515              : 
     516              :                 // Simulate furnace reheat coil if a humidistat is present, the dehumidification type of coolreheat and
     517              :                 // reheat coil load exists
     518        15222 :                 if (thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat && ReheatCoilLoad > 0.0) {
     519            0 :                     SuppHeatingCoilFlag = true; // if true simulates supplemental heating coil
     520            0 :                     CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, ReheatCoilLoad, fanOp, QActual);
     521              :                 } else {
     522        15222 :                     SuppHeatingCoilFlag = true; // if true simulates supplemental heating coil
     523        15222 :                     CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, fanOp, QActual);
     524              :                 }
     525              :             }
     526        15222 :         } break;
     527              :         // Simulate water-to-air systems:
     528            0 :         case HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir: {
     529            0 :             if (thisFurnace.WatertoAirHPType == WAHPCoilType::Simple) {
     530              :                 // Update the furnace flow rates
     531              :                 //   When CompressorOp logic is added to the child cooling coil (COIL:WaterToAirHP:EquationFit:Cooling), then this logic
     532              :                 //   needs to be reinstated... to align with Unitary/Furnace HeatCool and Unitary Air-to-Air Heat Pump (see above).
     533            0 :                 if (!FirstHVACIteration && thisFurnace.fanOp == HVAC::FanOp::Cycling && state.dataFurnaces->CoolingLoad &&
     534            0 :                     state.dataAirLoop->AirLoopControlInfo(AirLoopNum).EconoActive) {
     535              :                     // for cycling fan, cooling load, check whether furnace can meet load with compressor off
     536            0 :                     compressorOp = HVAC::CompressorOp::Off;
     537            0 :                     CalcNewZoneHeatCoolFlowRates(state,
     538              :                                                  FurnaceNum,
     539              :                                                  FirstHVACIteration,
     540              :                                                  compressorOp,
     541              :                                                  ZoneLoad,
     542              :                                                  MoistureLoad,
     543              :                                                  HeatCoilLoad,
     544              :                                                  ReheatCoilLoad,
     545              :                                                  OnOffAirFlowRatio,
     546              :                                                  HXUnitOn);
     547            0 :                     if (thisFurnace.CoolPartLoadRatio >= 1.0 || thisFurnace.HeatPartLoadRatio >= 1.0 ||
     548            0 :                         (thisFurnace.CoolPartLoadRatio <= 0.0 && thisFurnace.HeatPartLoadRatio <= 0.0)) {
     549              :                         // compressor on (reset inlet air mass flow rate to starting value)
     550            0 :                         compressorOp = HVAC::CompressorOp::On;
     551            0 :                         state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = FurnaceSavMdot;
     552            0 :                         CalcNewZoneHeatCoolFlowRates(state,
     553              :                                                      FurnaceNum,
     554              :                                                      FirstHVACIteration,
     555              :                                                      compressorOp,
     556              :                                                      ZoneLoad,
     557              :                                                      MoistureLoad,
     558              :                                                      HeatCoilLoad,
     559              :                                                      ReheatCoilLoad,
     560              :                                                      OnOffAirFlowRatio,
     561              :                                                      HXUnitOn);
     562              :                     }
     563              :                 } else {
     564              :                     // compressor on
     565            0 :                     CalcNewZoneHeatCoolFlowRates(state,
     566              :                                                  FurnaceNum,
     567              :                                                  FirstHVACIteration,
     568              :                                                  compressorOp,
     569              :                                                  ZoneLoad,
     570              :                                                  MoistureLoad,
     571              :                                                  HeatCoilLoad,
     572              :                                                  ReheatCoilLoad,
     573              :                                                  OnOffAirFlowRatio,
     574              :                                                  HXUnitOn);
     575              :                 }
     576            0 :                 if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
     577            0 :                     state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
     578              :                 }
     579              : 
     580            0 :                 WaterToAirHeatPumpSimple::SimWatertoAirHPSimple(state,
     581              :                                                                 BlankString,
     582            0 :                                                                 thisFurnace.CoolingCoilIndex,
     583              :                                                                 thisFurnace.CoolingCoilSensDemand,
     584              :                                                                 thisFurnace.CoolingCoilLatentDemand,
     585              :                                                                 thisFurnace.fanOp,
     586              :                                                                 compressorOp,
     587              :                                                                 thisFurnace.CoolPartLoadRatio,
     588              :                                                                 FirstHVACIteration);
     589            0 :                 WaterToAirHeatPumpSimple::SimWatertoAirHPSimple(state,
     590              :                                                                 BlankString,
     591            0 :                                                                 thisFurnace.HeatingCoilIndex,
     592              :                                                                 thisFurnace.HeatingCoilSensDemand,
     593              :                                                                 Dummy,
     594              :                                                                 thisFurnace.fanOp,
     595              :                                                                 compressorOp,
     596              :                                                                 thisFurnace.HeatPartLoadRatio,
     597              :                                                                 FirstHVACIteration);
     598              : 
     599            0 :                 if (thisFurnace.fanPlace == HVAC::FanPlace::DrawThru) {
     600            0 :                     state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
     601              :                 }
     602            0 :                 if (thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat && ReheatCoilLoad > 0.0) {
     603            0 :                     SuppHeatingCoilFlag = true; // if true simulates supplemental heating coil
     604            0 :                     CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, ReheatCoilLoad, fanOp, QActual);
     605              :                 } else {
     606            0 :                     SuppHeatingCoilFlag = true; // if true simulates supplemental heating coil
     607            0 :                     CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, fanOp, QActual);
     608              :                 }
     609            0 :             } else if (thisFurnace.WatertoAirHPType == WAHPCoilType::ParEst) {
     610              : 
     611              :                 // simulate the heat pump
     612            0 :                 HeatCoilLoad = 0.0;
     613            0 :                 CalcWaterToAirHeatPump(state, FurnaceNum, FirstHVACIteration, compressorOp, ZoneLoad, MoistureLoad);
     614            0 :             } else if (thisFurnace.WatertoAirHPType == WAHPCoilType::VarSpeedEquationFit) {
     615              :                 // simulate the heat pump
     616            0 :                 HeatCoilLoad = 0.0;
     617            0 :                 if (thisFurnace.bIsIHP)
     618            0 :                     state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).ControlledZoneTemp =
     619            0 :                         state.dataLoopNodes->Node(thisFurnace.NodeNumOfControlledZone).Temp;
     620            0 :                 SimVariableSpeedHP(state, FurnaceNum, FirstHVACIteration, AirLoopNum, ZoneLoad, MoistureLoad, OnOffAirFlowRatio);
     621              : 
     622            0 :             } else if (thisFurnace.WatertoAirHPType == WAHPCoilType::VarSpeedLookupTable) {
     623            0 :                 HeatCoilLoad = 0.0; // Added: Used below
     624              :             } else {
     625            0 :                 assert(false); //? If all possible states covered by if conditions change to HeatCoilLoad = 0.0;
     626              :             }
     627            0 :         } break;
     628            0 :         default: {
     629              :             // will never get here, all system types are simulated above
     630            0 :             assert(false);
     631              :         } break;
     632              :         }
     633              : 
     634              :         // set the econo lockout flags
     635        15222 :         auto &airLoopControlInfo = state.dataAirLoop->AirLoopControlInfo(AirLoopNum);
     636        15222 :         if (thisFurnace.CompPartLoadRatio > 0.0 && airLoopControlInfo.CanLockoutEconoWithCompressor) {
     637            0 :             airLoopControlInfo.ReqstEconoLockoutWithCompressor = true;
     638              :         } else {
     639        15222 :             airLoopControlInfo.ReqstEconoLockoutWithCompressor = false;
     640              :         }
     641              : 
     642        15222 :         if ((HeatCoilLoad > 0.0 || thisFurnace.HeatPartLoadRatio > 0.0) &&
     643         8361 :             (airLoopControlInfo.CanLockoutEconoWithCompressor || airLoopControlInfo.CanLockoutEconoWithHeating)) {
     644            0 :             airLoopControlInfo.ReqstEconoLockoutWithHeating = true;
     645              :         } else {
     646        15222 :             airLoopControlInfo.ReqstEconoLockoutWithHeating = false;
     647              :         }
     648              : 
     649        15222 :         if (thisFurnace.fanOp == HVAC::FanOp::Cycling) {
     650        15222 :             state.dataAirLoop->AirLoopFlow(AirLoopNum).FanPLR = thisFurnace.FanPartLoadRatio;
     651              :         } else {
     652            0 :             state.dataAirLoop->AirLoopFlow(AirLoopNum).FanPLR = 1.0; // 1 means constant fan does not cycle.
     653              :         }
     654              : 
     655              :         // Report the current Furnace output
     656        15222 :         ReportFurnace(state, FurnaceNum, AirLoopNum);
     657              : 
     658              :         // Reset OnOffFanPartLoadFraction to 1 in case another on/off fan is called without a part-load curve
     659        15222 :         state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
     660              : 
     661        15222 :         state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRateMaxAvail = TempMassFlowRateMaxAvail;
     662        15222 :     }
     663              : 
     664              :     // Get Input Section of the Module
     665              :     //******************************************************************************
     666              : 
     667            2 :     void GetFurnaceInput(EnergyPlusData &state)
     668              :     {
     669              : 
     670              :         // SUBROUTINE INFORMATION:
     671              :         //       AUTHOR         Richard Liesen
     672              :         //       DATE WRITTEN   Feb 2001
     673              :         //       MODIFIED       Don Shirey and Rich Raustad, Mar/Oct 2001, Mar 2003
     674              :         //                      Bereket Nigusse, April 2010 - deprecated supply air flow fraction through
     675              :         //                      controlled zone from the input field.
     676              :         //                      Bo Shen, March 2012, add inputs for VS WSHP,
     677              :         //                      Bo Shen, ORNL, July 2012 - added variable-speed air source heat pump cooling and heating coils, using curve-fits
     678              : 
     679              :         // PURPOSE OF THIS SUBROUTINE:
     680              :         // Obtains input data for fans and coils and stores it in the Furnace data structures
     681              : 
     682              :         // METHODOLOGY EMPLOYED:
     683              :         // Uses "Get" routines to read in data.
     684              : 
     685              :         // SUBROUTINE PARAMETER DEFINITIONS:
     686            2 :         std::string_view constexpr getUnitaryHeatOnly("GetUnitaryHeatOnly");
     687            2 :         std::string_view constexpr getAirLoopHVACHeatCoolInput("GetAirLoopHVACHeatCoolInput");
     688            2 :         std::string_view constexpr routineName = "GetFurnaceInput";
     689              : 
     690              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     691              :         int FurnaceNum;                // The Furnace that you are currently loading input into
     692              :         int GetObjectNum;              // The index to each specific object name
     693              :         int NumFields;                 // Total number of fields in object
     694              :         int NumAlphas;                 // Total number of alpha fields in object
     695              :         int NumNumbers;                // Total number of numeric fields in object
     696              :         int IOStatus;                  // Function call status
     697            2 :         Array1D<Real64> Numbers;       // Numeric data
     698            2 :         Array1D_string Alphas;         // Alpha data
     699            2 :         Array1D_string cAlphaFields;   // Alpha field names
     700            2 :         Array1D_string cNumericFields; // Numeric field names
     701            2 :         Array1D_bool lAlphaBlanks;     // Logical array, alpha field input BLANK = .TRUE.
     702            2 :         Array1D_bool lNumericBlanks;   // Logical array, numeric field input BLANK = .TRUE.
     703            2 :         std::string CompSetFanInlet;
     704            2 :         std::string CompSetFanOutlet;
     705            2 :         std::string CompSetCoolInlet;
     706            2 :         std::string CompSetHeatInlet;
     707            2 :         std::string CompSetHeatOutlet;
     708            2 :         bool ErrorsFound(false);       // If errors detected in input
     709              :         bool IsNotOK;                  // Flag to verify name
     710              :         bool AirNodeFound;             // Used to determine if control zone is valid
     711              :         bool AirLoopFound;             // Used to determine if control zone is served by furnace air loop
     712              :         int TstatZoneNum;              // Used to determine if control zone has a thermostat object
     713              :         int HStatZoneNum;              // Used to determine if control zone has a humidistat object
     714              :         bool errFlag;                  // Mining function error flag
     715              :         int FanInletNode;              // Used for node checking warning messages
     716              :         int FanOutletNode;             // Used for node checking warning messages
     717              :         int CoolingCoilInletNode;      // Used for node checking warning messages
     718              :         int CoolingCoilOutletNode;     // Used for node checking warning messages
     719              :         int HeatingCoilInletNode;      // Used for node checking warning messages
     720              :         int HeatingCoilOutletNode;     // Used for node checking warning messages
     721              :         int SupHeatCoilInletNode;      // Used for node checking warning messages
     722              :         int SupHeatCoilOutletNode;     // Used for node checking warning messages
     723            2 :         std::string CoolingCoilType;   // Used in mining function CALLS
     724            2 :         std::string CoolingCoilName;   // Used in mining function CALLS
     725            2 :         std::string HeatingCoilType;   // Used in mining function CALLS
     726            2 :         std::string HeatingCoilName;   // Used in mining function CALLS
     727            2 :         std::string ReheatingCoilType; // Used in mining function CALLS
     728            2 :         std::string ReheatingCoilName; // Used in mining function CALLS
     729            2 :         std::string SuppHeatCoilType;  // Used in mining function CALLS
     730            2 :         std::string SuppHeatCoilName;  // Used in mining function CALLS
     731            2 :         std::string FanName;           // Used in mining function CALLS
     732              :         bool PrintMessage;             // Used in mining function CALLS
     733              :         int HeatingCoilPLFCurveIndex;  // index of heating coil PLF curve
     734              :         Real64 SteamDensity;           // density of steam at 100C
     735              :         int DXCoilIndex;               // Index to DX coil in HXAssited object
     736            2 :         std::string IHPCoilName;       // IHP cooling coil name
     737            2 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
     738              :         DataLoopNode::ConnectionObjectType currentModuleObjectType;
     739              : 
     740            2 :         state.dataFurnaces->GetFurnaceInputFlag = false;
     741            2 :         int MaxNumbers = 0;
     742            2 :         int MaxAlphas = 0;
     743              : 
     744            2 :         std::string_view CurrentModuleObject = "AirLoopHVAC:Unitary:Furnace:HeatOnly";
     745            2 :         int NumHeatOnly = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
     746            2 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NumFields, NumAlphas, NumNumbers);
     747            2 :         MaxNumbers = max(MaxNumbers, NumNumbers);
     748            2 :         MaxAlphas = max(MaxAlphas, NumAlphas);
     749              : 
     750            2 :         CurrentModuleObject = "AirLoopHVAC:Unitary:Furnace:HeatCool";
     751            2 :         int NumHeatCool = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
     752            2 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NumFields, NumAlphas, NumNumbers);
     753            2 :         MaxNumbers = max(MaxNumbers, NumNumbers);
     754            2 :         MaxAlphas = max(MaxAlphas, NumAlphas);
     755              : 
     756            2 :         CurrentModuleObject = "AirLoopHVAC:UnitaryHeatOnly";
     757            2 :         int NumUnitaryHeatOnly = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
     758            2 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NumFields, NumAlphas, NumNumbers);
     759            2 :         MaxNumbers = max(MaxNumbers, NumNumbers);
     760            2 :         MaxAlphas = max(MaxAlphas, NumAlphas);
     761              : 
     762            2 :         CurrentModuleObject = "AirLoopHVAC:UnitaryHeatCool";
     763            2 :         int NumUnitaryHeatCool = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
     764            2 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NumFields, NumAlphas, NumNumbers);
     765            2 :         MaxNumbers = max(MaxNumbers, NumNumbers);
     766            2 :         MaxAlphas = max(MaxAlphas, NumAlphas);
     767              : 
     768            2 :         CurrentModuleObject = "AirLoopHVAC:UnitaryHeatPump:AirToAir";
     769            2 :         int NumHeatPump = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
     770            2 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NumFields, NumAlphas, NumNumbers);
     771            2 :         MaxNumbers = max(MaxNumbers, NumNumbers);
     772            2 :         MaxAlphas = max(MaxAlphas, NumAlphas);
     773              : 
     774            2 :         CurrentModuleObject = "AirLoopHVAC:UnitaryHeatPump:WaterToAir";
     775            2 :         int NumWaterToAirHeatPump = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
     776            2 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NumFields, NumAlphas, NumNumbers);
     777            2 :         MaxNumbers = max(MaxNumbers, NumNumbers);
     778            2 :         MaxAlphas = max(MaxAlphas, NumAlphas);
     779              : 
     780            2 :         Alphas.allocate(MaxAlphas);
     781            2 :         Numbers.dimension(MaxNumbers, 0.0);
     782            2 :         cAlphaFields.allocate(MaxAlphas);
     783            2 :         cNumericFields.allocate(MaxNumbers);
     784            2 :         lAlphaBlanks.dimension(MaxAlphas, true);
     785            2 :         lNumericBlanks.dimension(MaxNumbers, true);
     786              : 
     787            2 :         state.dataFurnaces->NumFurnaces = NumHeatOnly + NumHeatCool + NumUnitaryHeatOnly + NumUnitaryHeatCool + NumHeatPump + NumWaterToAirHeatPump;
     788              : 
     789            2 :         if (state.dataFurnaces->NumFurnaces > 0) {
     790            2 :             state.dataFurnaces->Furnace.allocate(state.dataFurnaces->NumFurnaces);
     791            2 :             state.dataFurnaces->UniqueFurnaceNames.reserve(state.dataFurnaces->NumFurnaces);
     792              :         }
     793            2 :         state.dataFurnaces->CheckEquipName.dimension(state.dataFurnaces->NumFurnaces, true);
     794              : 
     795            2 :         int IHPCoilIndex = 0;
     796              : 
     797              :         // Get the data for the HeatOnly Furnace
     798            2 :         for (int HeatOnlyNum = 1; HeatOnlyNum <= NumHeatOnly + NumUnitaryHeatOnly; ++HeatOnlyNum) {
     799              : 
     800            0 :             FanInletNode = 0;
     801            0 :             FanOutletNode = 0;
     802            0 :             HeatingCoilInletNode = 0;
     803            0 :             HeatingCoilOutletNode = 0;
     804            0 :             CoolingCoilType = ' ';
     805            0 :             CoolingCoilName = ' ';
     806            0 :             HeatingCoilType = ' ';
     807            0 :             HeatingCoilName = ' ';
     808              : 
     809            0 :             FurnaceNum = HeatOnlyNum;
     810            0 :             auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
     811              : 
     812              :             //       Furnace and UnitarySystem objects are both read in here.
     813              :             //       Will still have 2 differently named objects for the user, but read in with 1 DO loop.
     814            0 :             if (HeatOnlyNum <= NumHeatOnly) {
     815            0 :                 CurrentModuleObject = "AirLoopHVAC:Unitary:Furnace:HeatOnly";
     816            0 :                 currentModuleObjectType = DataLoopNode::ConnectionObjectType::AirLoopHVACUnitaryFurnaceHeatOnly;
     817            0 :                 thisFurnace.type = HVAC::UnitarySysType::Furnace_HeatOnly;
     818            0 :                 GetObjectNum = HeatOnlyNum;
     819              :             } else {
     820            0 :                 CurrentModuleObject = "AirLoopHVAC:UnitaryHeatOnly";
     821            0 :                 currentModuleObjectType = DataLoopNode::ConnectionObjectType::AirLoopHVACUnitaryHeatOnly;
     822            0 :                 thisFurnace.type = HVAC::UnitarySysType::Unitary_HeatOnly;
     823            0 :                 GetObjectNum = HeatOnlyNum - NumHeatOnly;
     824              :             }
     825              : 
     826            0 :             thisFurnace.iterationMode.allocate(3);
     827              : 
     828            0 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     829              :                                                                      CurrentModuleObject,
     830              :                                                                      GetObjectNum,
     831              :                                                                      Alphas,
     832              :                                                                      NumAlphas,
     833              :                                                                      Numbers,
     834              :                                                                      NumNumbers,
     835              :                                                                      IOStatus,
     836              :                                                                      lNumericBlanks,
     837              :                                                                      lAlphaBlanks,
     838              :                                                                      cAlphaFields,
     839              :                                                                      cNumericFields);
     840              : 
     841            0 :             GlobalNames::VerifyUniqueInterObjectName(
     842            0 :                 state, state.dataFurnaces->UniqueFurnaceNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
     843              : 
     844            0 :             thisFurnace.Name = Alphas(1);
     845            0 :             ErrorObjectHeader eoh{routineName, cAlphaFields(1), thisFurnace.Name};
     846              : 
     847            0 :             if (lAlphaBlanks(2)) {
     848            0 :                 thisFurnace.availSched = Sched::GetScheduleAlwaysOn(state);
     849            0 :             } else if ((thisFurnace.availSched = Sched::GetSchedule(state, Alphas(2))) == nullptr) {
     850            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(2), Alphas(2));
     851            0 :                 ErrorsFound = true;
     852              :             }
     853              : 
     854            0 :             thisFurnace.FurnaceInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
     855            0 :                                                                                   Alphas(3),
     856              :                                                                                   ErrorsFound,
     857              :                                                                                   currentModuleObjectType,
     858            0 :                                                                                   Alphas(1),
     859              :                                                                                   DataLoopNode::NodeFluidType::Air,
     860              :                                                                                   DataLoopNode::ConnectionType::Inlet,
     861              :                                                                                   NodeInputManager::CompFluidStream::Primary,
     862              :                                                                                   DataLoopNode::ObjectIsParent);
     863            0 :             thisFurnace.FurnaceOutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
     864            0 :                                                                                    Alphas(4),
     865              :                                                                                    ErrorsFound,
     866              :                                                                                    currentModuleObjectType,
     867            0 :                                                                                    Alphas(1),
     868              :                                                                                    DataLoopNode::NodeFluidType::Air,
     869              :                                                                                    DataLoopNode::ConnectionType::Outlet,
     870              :                                                                                    NodeInputManager::CompFluidStream::Primary,
     871              :                                                                                    DataLoopNode::ObjectIsParent);
     872              : 
     873            0 :             BranchNodeConnections::TestCompSet(state, CurrentModuleObject, Alphas(1), Alphas(3), Alphas(4), "Air Nodes");
     874              : 
     875            0 :             if (lAlphaBlanks(5)) {
     876            0 :                 thisFurnace.fanOp = HVAC::FanOp::Cycling;
     877            0 :             } else if ((thisFurnace.fanOpModeSched = Sched::GetSchedule(state, Alphas(5))) == nullptr) {
     878            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(5), Alphas(5));
     879            0 :                 ErrorsFound = true;
     880              :             }
     881              : 
     882              :             // Get the Controlling Zone or Location of the Furnace Thermostat
     883              : 
     884            0 :             thisFurnace.ControlZoneNum = Util::FindItemInList(Alphas(6), state.dataHeatBal->Zone);
     885            0 :             if (thisFurnace.ControlZoneNum == 0) {
     886            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
     887            0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(6), Alphas(6)));
     888            0 :                 ErrorsFound = true;
     889              :             }
     890              : 
     891              :             // Get the node number for the zone with the thermostat
     892            0 :             if (thisFurnace.ControlZoneNum > 0) {
     893            0 :                 AirNodeFound = false;
     894            0 :                 AirLoopFound = false;
     895            0 :                 int ControlledZoneNum = thisFurnace.ControlZoneNum;
     896              :                 //             Find the controlled zone number for the specified thermostat location
     897            0 :                 thisFurnace.NodeNumOfControlledZone = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).ZoneNode;
     898              :                 //             Determine if furnace is on air loop served by the thermostat location specified
     899            0 :                 for (int zoneInNode = 1; zoneInNode <= state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).NumInletNodes; ++zoneInNode) {
     900            0 :                     int AirLoopNumber = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).InletNodeAirLoopNum(zoneInNode);
     901            0 :                     if (AirLoopNumber > 0) {
     902            0 :                         for (int BranchNum = 1; BranchNum <= state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).NumBranches; ++BranchNum) {
     903            0 :                             for (int CompNum = 1;
     904            0 :                                  CompNum <= state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).Branch(BranchNum).TotalComponents;
     905              :                                  ++CompNum) {
     906            0 :                                 if (!Util::SameString(state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).Branch(BranchNum).Comp(CompNum).Name,
     907            0 :                                                       thisFurnace.Name) ||
     908            0 :                                     !Util::SameString(
     909            0 :                                         state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).Branch(BranchNum).Comp(CompNum).TypeOf,
     910              :                                         CurrentModuleObject))
     911            0 :                                     continue;
     912            0 :                                 AirLoopFound = true;
     913            0 :                                 thisFurnace.ZoneInletNode = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).InletNode(zoneInNode);
     914            0 :                                 break;
     915              :                             }
     916            0 :                             if (AirLoopFound) break;
     917              :                         }
     918            0 :                         for (TstatZoneNum = 1; TstatZoneNum <= state.dataZoneCtrls->NumTempControlledZones; ++TstatZoneNum) {
     919            0 :                             if (state.dataZoneCtrls->TempControlledZone(TstatZoneNum).ActualZoneNum != thisFurnace.ControlZoneNum) continue;
     920            0 :                             AirNodeFound = true;
     921              :                         }
     922            0 :                         for (TstatZoneNum = 1; TstatZoneNum <= state.dataZoneCtrls->NumComfortControlledZones; ++TstatZoneNum) {
     923            0 :                             if (state.dataZoneCtrls->ComfortControlledZone(TstatZoneNum).ActualZoneNum != thisFurnace.ControlZoneNum) continue;
     924            0 :                             AirNodeFound = true;
     925              :                         }
     926              :                     }
     927            0 :                     if (AirLoopFound) break;
     928              :                 }
     929            0 :                 if (!AirNodeFound) {
     930            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
     931            0 :                     ShowContinueError(state, "Did not find Air Node (Zone with Thermostat).");
     932            0 :                     ShowContinueError(state, format("Specified {} = {}", cAlphaFields(6), Alphas(6)));
     933            0 :                     ShowContinueError(
     934              :                         state, "Both a ZoneHVAC:EquipmentConnections object and a ZoneControl:Thermostat object must be specified for this zone.");
     935            0 :                     ErrorsFound = true;
     936              :                 }
     937            0 :                 if (!AirLoopFound) {
     938            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
     939            0 :                     ShowContinueError(state, "Did not find correct Primary Air Loop.");
     940            0 :                     ShowContinueError(state, format("Specified {} = {} is not served by this AirLoopHVAC equipment.", cAlphaFields(6), Alphas(6)));
     941            0 :                     ErrorsFound = true;
     942              :                 }
     943              :             }
     944              : 
     945              :             // Get fan data
     946            0 :             FanName = Alphas(8);
     947            0 :             errFlag = false;
     948              : 
     949            0 :             thisFurnace.fanType = static_cast<HVAC::FanType>(getEnumValue(HVAC::fanTypeNamesUC, Alphas(7)));
     950            0 :             if (thisFurnace.fanType != HVAC::FanType::OnOff && thisFurnace.fanType != HVAC::FanType::Constant) {
     951            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
     952            0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(7), Alphas(7)));
     953            0 :                 ErrorsFound = true;
     954              : 
     955            0 :             } else if ((thisFurnace.FanIndex = Fans::GetFanIndex(state, FanName)) == 0) {
     956            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(8), FanName);
     957            0 :                 ErrorsFound = true;
     958              : 
     959              :             } else {
     960            0 :                 auto *fan = state.dataFans->fans(thisFurnace.FanIndex);
     961            0 :                 thisFurnace.ActualFanVolFlowRate = fan->maxAirFlowRate;
     962            0 :                 FanInletNode = fan->inletNodeNum;
     963            0 :                 FanOutletNode = fan->outletNodeNum;
     964            0 :                 thisFurnace.fanAvailSched = fan->availSched;
     965              : 
     966              :                 // Check fan's schedule for cycling fan operation if constant volume fan is used
     967            0 :                 if (thisFurnace.fanOpModeSched != nullptr && thisFurnace.fanType == HVAC::FanType::Constant) {
     968            0 :                     if (!thisFurnace.fanOpModeSched->checkMinMaxVals(state, Clusive::Ex, 0.0, Clusive::In, 1.0)) {
     969            0 :                         Sched::ShowSevereBadMinMax(
     970              :                             state,
     971              :                             eoh,
     972            0 :                             cAlphaFields(5),
     973            0 :                             Alphas(5),
     974              :                             Clusive::Ex,
     975              :                             0.0,
     976              :                             Clusive::In,
     977              :                             1.0,
     978            0 :                             format("For {} = {}, Fan operating mode must be continuous (schedule values > 0)", cAlphaFields(7), Alphas(7)));
     979            0 :                         ErrorsFound = true;
     980              :                     }
     981            0 :                 } else if (lAlphaBlanks(5) && thisFurnace.fanType != HVAC::FanType::OnOff) {
     982            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, thisFurnace.Name));
     983            0 :                     ShowContinueError(state, format("{} = {}", cAlphaFields(7), Alphas(7)));
     984            0 :                     ShowContinueError(state, format("Fan type must be Fan:OnOff when {} = Blank.", cAlphaFields(5)));
     985            0 :                     ErrorsFound = true;
     986              :                 }
     987              :             }
     988              : 
     989            0 :             thisFurnace.fanPlace = static_cast<HVAC::FanPlace>(getEnumValue(HVAC::fanPlaceNamesUC, Alphas(9)));
     990            0 :             assert(thisFurnace.fanPlace != HVAC::FanPlace::Invalid);
     991              : 
     992              :             // Get coil data
     993            0 :             HeatingCoilType = Alphas(10);
     994            0 :             HeatingCoilName = Alphas(11);
     995            0 :             thisFurnace.HeatingCoilType = HeatingCoilType;
     996            0 :             thisFurnace.HeatingCoilName = HeatingCoilName;
     997            0 :             if (Util::SameString(HeatingCoilType, "Coil:Heating:Fuel") || Util::SameString(HeatingCoilType, "Coil:Heating:Electric")) {
     998            0 :                 errFlag = false;
     999            0 :                 thisFurnace.HeatingCoilType_Num = HeatingCoils::GetHeatingCoilTypeNum(state, HeatingCoilType, HeatingCoilName, errFlag);
    1000            0 :                 if (errFlag) {
    1001            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1002            0 :                     ErrorsFound = true;
    1003              :                 } else {
    1004            0 :                     ValidateComponent(state, HeatingCoilType, HeatingCoilName, IsNotOK, CurrentModuleObject);
    1005            0 :                     if (IsNotOK) {
    1006            0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1007            0 :                         ErrorsFound = true;
    1008              : 
    1009              :                     } else { // mine data from heating coil object
    1010              : 
    1011              :                         // Get index to Heating Coil
    1012            0 :                         errFlag = false;
    1013            0 :                         HeatingCoils::GetCoilIndex(state, HeatingCoilName, thisFurnace.HeatingCoilIndex, errFlag);
    1014            0 :                         if (errFlag) {
    1015            0 :                             ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1016            0 :                             ErrorsFound = true;
    1017              :                         }
    1018              : 
    1019              :                         // Get the furnace design capacity
    1020            0 :                         errFlag = false;
    1021            0 :                         thisFurnace.DesignHeatingCapacity = HeatingCoils::GetCoilCapacity(state, HeatingCoilType, HeatingCoilName, errFlag);
    1022            0 :                         if (errFlag) {
    1023            0 :                             ShowContinueError(state, format("...occurs in {} ={}", CurrentModuleObject, Alphas(1)));
    1024            0 :                             ErrorsFound = true;
    1025              :                         }
    1026              : 
    1027              :                         // Get the Heating Coil Inlet Node
    1028            0 :                         errFlag = false;
    1029            0 :                         HeatingCoilInletNode = HeatingCoils::GetCoilInletNode(state, HeatingCoilType, HeatingCoilName, errFlag);
    1030            0 :                         thisFurnace.HWCoilAirInletNode = HeatingCoilInletNode;
    1031            0 :                         if (errFlag) {
    1032            0 :                             ShowContinueError(state, format("...occurs in {} ={}", CurrentModuleObject, Alphas(1)));
    1033            0 :                             ErrorsFound = true;
    1034              :                         }
    1035              : 
    1036              :                         // Get the Heating Coil Outlet Node
    1037            0 :                         errFlag = false;
    1038            0 :                         HeatingCoilOutletNode = HeatingCoils::GetCoilOutletNode(state, HeatingCoilType, HeatingCoilName, errFlag);
    1039            0 :                         if (errFlag) {
    1040            0 :                             ShowContinueError(state, format("...occurs in {} ={}", CurrentModuleObject, Alphas(1)));
    1041            0 :                             ErrorsFound = true;
    1042              :                         }
    1043              : 
    1044              :                     } // IF (IsNotOK) THEN
    1045              :                 }
    1046              : 
    1047            0 :             } else if (Util::SameString(HeatingCoilType, "Coil:Heating:Water")) {
    1048            0 :                 thisFurnace.HeatingCoilType_Num = HVAC::Coil_HeatingWater;
    1049            0 :                 ValidateComponent(state, HeatingCoilType, HeatingCoilName, IsNotOK, CurrentModuleObject);
    1050            0 :                 if (IsNotOK) {
    1051            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1052            0 :                     ErrorsFound = true;
    1053              :                 } else { // mine data from heating coil object
    1054              : 
    1055              :                     // Get the Heating Coil water Inlet or control Node number
    1056            0 :                     errFlag = false;
    1057            0 :                     thisFurnace.CoilControlNode = WaterCoils::GetCoilWaterInletNode(state, "Coil:Heating:Water", HeatingCoilName, errFlag);
    1058            0 :                     if (errFlag) {
    1059            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1060            0 :                         ErrorsFound = true;
    1061              :                     }
    1062              : 
    1063              :                     // Get the Heating Coil hot water max volume flow rate
    1064            0 :                     errFlag = false;
    1065            0 :                     thisFurnace.MaxHeatCoilFluidFlow = WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", HeatingCoilName, errFlag);
    1066            0 :                     if (errFlag) {
    1067            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1068            0 :                         ErrorsFound = true;
    1069              :                     }
    1070              : 
    1071              :                     // Get the Heating Coil Inlet Node
    1072            0 :                     errFlag = false;
    1073            0 :                     HeatingCoilInletNode = WaterCoils::GetCoilInletNode(state, "Coil:Heating:Water", HeatingCoilName, errFlag);
    1074            0 :                     thisFurnace.HWCoilAirInletNode = HeatingCoilInletNode;
    1075            0 :                     if (errFlag) {
    1076            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1077            0 :                         ErrorsFound = true;
    1078              :                     }
    1079              : 
    1080              :                     // Get the Heating Coil Outlet Node
    1081            0 :                     errFlag = false;
    1082            0 :                     HeatingCoilOutletNode = WaterCoils::GetCoilOutletNode(state, "Coil:Heating:Water", HeatingCoilName, errFlag);
    1083            0 :                     thisFurnace.HWCoilAirOutletNode = HeatingCoilOutletNode;
    1084            0 :                     if (errFlag) {
    1085            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1086            0 :                         ErrorsFound = true;
    1087              :                     }
    1088              : 
    1089              :                     // check if user has also used a water coil controller, which they should not do
    1090            0 :                     errFlag = false;
    1091            0 :                     HVACControllers::CheckCoilWaterInletNode(state, thisFurnace.CoilControlNode, errFlag);
    1092            0 :                     if (!errFlag) { // then did find a controller so that is bad
    1093            0 :                         ShowSevereError(state,
    1094            0 :                                         format("{} = {} has a conflicting Controller:WaterCoil object", CurrentModuleObject, thisFurnace.Name));
    1095            0 :                         ShowContinueError(state, "Hot water coils are controlled directly by unitary and furnace systems.");
    1096            0 :                         ShowContinueError(state, "No water coil controller should be input for the coil.");
    1097            0 :                         ErrorsFound = true;
    1098              :                     }
    1099              :                 }
    1100              : 
    1101            0 :             } else if (Util::SameString(HeatingCoilType, "Coil:Heating:Steam")) {
    1102            0 :                 thisFurnace.HeatingCoilType_Num = HVAC::Coil_HeatingSteam;
    1103            0 :                 ValidateComponent(state, HeatingCoilType, HeatingCoilName, IsNotOK, CurrentModuleObject);
    1104            0 :                 if (IsNotOK) {
    1105            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1106            0 :                     ErrorsFound = true;
    1107              :                 } else { // mine data from heating coil object
    1108              : 
    1109            0 :                     errFlag = false;
    1110            0 :                     thisFurnace.HeatingCoilIndex = SteamCoils::GetSteamCoilIndex(state, "COIL:HEATING:STEAM", HeatingCoilName, errFlag);
    1111            0 :                     if (thisFurnace.HeatingCoilIndex == 0) {
    1112            0 :                         ShowSevereError(state, format("{} illegal {} = {}", CurrentModuleObject, cAlphaFields(11), HeatingCoilName));
    1113            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1114            0 :                         ErrorsFound = true;
    1115              :                     }
    1116              : 
    1117              :                     // Get the Heating Coil steam inlet node number
    1118            0 :                     errFlag = false;
    1119            0 :                     thisFurnace.CoilControlNode = SteamCoils::GetCoilSteamInletNode(state, "COIL:HEATING:STEAM", HeatingCoilName, errFlag);
    1120            0 :                     if (errFlag) {
    1121            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1122            0 :                         ErrorsFound = true;
    1123              :                     }
    1124              : 
    1125              :                     // Get the Heating Coil steam max volume flow rate
    1126            0 :                     thisFurnace.MaxHeatCoilFluidFlow = SteamCoils::GetCoilMaxSteamFlowRate(state, thisFurnace.HeatingCoilIndex, errFlag);
    1127            0 :                     if (thisFurnace.MaxHeatCoilFluidFlow > 0.0) {
    1128            0 :                         SteamDensity = Fluid::GetSteam(state)->getSatDensity(state, state.dataFurnaces->TempSteamIn, 1.0, getUnitaryHeatOnly);
    1129            0 :                         thisFurnace.MaxHeatCoilFluidFlow *= SteamDensity;
    1130              :                     }
    1131              : 
    1132              :                     // Get the Heating Coil Inlet Node
    1133            0 :                     errFlag = false;
    1134            0 :                     HeatingCoilInletNode = SteamCoils::GetCoilAirInletNode(state, thisFurnace.HeatingCoilIndex, HeatingCoilName, errFlag);
    1135            0 :                     thisFurnace.HWCoilAirInletNode = HeatingCoilInletNode;
    1136            0 :                     if (errFlag) {
    1137            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1138            0 :                         ErrorsFound = true;
    1139              :                     }
    1140              : 
    1141              :                     // Get the Heating Coil Outlet Node
    1142            0 :                     errFlag = false;
    1143            0 :                     HeatingCoilOutletNode = SteamCoils::GetCoilAirOutletNode(state, thisFurnace.HeatingCoilIndex, HeatingCoilName, errFlag);
    1144            0 :                     thisFurnace.HWCoilAirOutletNode = HeatingCoilOutletNode;
    1145            0 :                     if (errFlag) {
    1146            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1147            0 :                         ErrorsFound = true;
    1148              :                     }
    1149              :                 }
    1150              : 
    1151              :             } else {
    1152            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1153            0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(11), Alphas(11)));
    1154            0 :                 ErrorsFound = true;
    1155              :             } // IF (Furnace(FurnaceNum)%HeatingCoilType_Num == Coil_HeatingGasOrOtherFuel .OR. &, etc.
    1156              : 
    1157              :             // Add component sets array
    1158            0 :             if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
    1159            0 :                 CompSetFanInlet = Alphas(3);
    1160            0 :                 CompSetFanOutlet = state.dataLoopNodes->NodeID(FanOutletNode);
    1161            0 :                 CompSetHeatInlet = state.dataLoopNodes->NodeID(FanOutletNode);
    1162            0 :                 CompSetHeatOutlet = Alphas(4);
    1163              :                 // Fan inlet node name must not be the same as the furnace inlet node name
    1164            0 :                 if (FanInletNode != thisFurnace.FurnaceInletNodeNum) {
    1165            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1166            0 :                     if (thisFurnace.type == HVAC::UnitarySysType::Furnace_HeatOnly) {
    1167            0 :                         ShowContinueError(
    1168              :                             state, "When a blow through fan is specified, the fan inlet node name must be the same as the furnace inlet node name.");
    1169            0 :                         ShowContinueError(state, format("...Fan inlet node name     = {}", state.dataLoopNodes->NodeID(FanInletNode)));
    1170            0 :                         ShowContinueError(state,
    1171            0 :                                           format("...Furnace inlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceInletNodeNum)));
    1172              :                     } else {
    1173            0 :                         ShowContinueError(
    1174              :                             state,
    1175              :                             "When a blow through fan is specified, the fan inlet node name must be the same as the unitary system inlet node name.");
    1176            0 :                         ShowContinueError(state, format("...Fan inlet node name            = {}", state.dataLoopNodes->NodeID(FanInletNode)));
    1177            0 :                         ShowContinueError(
    1178            0 :                             state, format("...Unitary System inlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceInletNodeNum)));
    1179              :                     }
    1180            0 :                     ErrorsFound = true;
    1181              :                 }
    1182              :                 // Fan outlet node name must be the same as the heating coil inlet node name
    1183            0 :                 if (FanOutletNode != HeatingCoilInletNode) {
    1184            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1185            0 :                     ShowContinueError(
    1186              :                         state,
    1187              :                         "When a blow through fan is specified, the fan outlet node name must be the same as the heating coil inlet node name.");
    1188            0 :                     ShowContinueError(state, format("...Fan outlet node name         = {}", state.dataLoopNodes->NodeID(FanOutletNode)));
    1189            0 :                     ShowContinueError(state, format("...Heating coil inlet node name = {}", state.dataLoopNodes->NodeID(HeatingCoilInletNode)));
    1190            0 :                     ErrorsFound = true;
    1191              :                 }
    1192              :                 // Heating coil outlet node name must be the same as the furnace outlet node name
    1193            0 :                 if (HeatingCoilOutletNode != thisFurnace.FurnaceOutletNodeNum) {
    1194            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1195            0 :                     if (thisFurnace.type == HVAC::UnitarySysType::Furnace_HeatOnly) {
    1196            0 :                         ShowContinueError(state,
    1197              :                                           "When a blow through fan is specified, the heating coil outlet node name must be the same as the furnace "
    1198              :                                           "outlet node name.");
    1199            0 :                         ShowContinueError(state, format("...Heating coil outlet node name = {}", state.dataLoopNodes->NodeID(HeatingCoilOutletNode)));
    1200            0 :                         ShowContinueError(
    1201            0 :                             state, format("...Furnace outlet node name      = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    1202              :                     } else {
    1203            0 :                         ShowContinueError(state,
    1204              :                                           "When a blow through fan is specified, the heating coil outlet node name must be the same as the unitary "
    1205              :                                           "system outlet node name.");
    1206            0 :                         ShowContinueError(state,
    1207            0 :                                           format("...Heating coil outlet node name  = {}", state.dataLoopNodes->NodeID(HeatingCoilOutletNode)));
    1208            0 :                         ShowContinueError(
    1209            0 :                             state, format("...UnitarySystem outlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    1210              :                     }
    1211            0 :                     ErrorsFound = true;
    1212              :                 }
    1213              :             } else { // draw through fan
    1214            0 :                 CompSetHeatInlet = Alphas(3);
    1215            0 :                 CompSetHeatOutlet = state.dataLoopNodes->NodeID(FanInletNode);
    1216            0 :                 CompSetFanInlet = state.dataLoopNodes->NodeID(FanInletNode);
    1217            0 :                 CompSetFanOutlet = Alphas(4);
    1218              :                 // Heating coil inlet node name must not be the same as the furnace inlet node name
    1219            0 :                 if (HeatingCoilInletNode != thisFurnace.FurnaceInletNodeNum) {
    1220            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1221            0 :                     if (thisFurnace.type == HVAC::UnitarySysType::Furnace_HeatOnly) {
    1222            0 :                         ShowContinueError(state,
    1223              :                                           "When a draw through fan is specified, the heating coil inlet node name must be the same as the furnace "
    1224              :                                           "inlet node name.");
    1225            0 :                         ShowContinueError(state, format("...Heating coil inlet node name = {}", state.dataLoopNodes->NodeID(HeatingCoilInletNode)));
    1226            0 :                         ShowContinueError(
    1227            0 :                             state, format("...Furnace inlet node name      = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceInletNodeNum)));
    1228              :                     } else {
    1229            0 :                         ShowContinueError(state,
    1230              :                                           "When a draw through fan is specified, the heating coil inlet node name must be the same as the unitary "
    1231              :                                           "system inlet node name.");
    1232            0 :                         ShowContinueError(state, format("...Heating coil inlet node name  = {}", state.dataLoopNodes->NodeID(HeatingCoilInletNode)));
    1233            0 :                         ShowContinueError(
    1234            0 :                             state, format("...UnitarySystem inlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceInletNodeNum)));
    1235              :                     }
    1236            0 :                     ErrorsFound = true;
    1237              :                 }
    1238              :                 // Heating coil outlet node name must be the same as the fan inlet node name
    1239            0 :                 if (HeatingCoilOutletNode != FanInletNode) {
    1240            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1241            0 :                     ShowContinueError(
    1242              :                         state,
    1243              :                         "When a draw through fan is specified, the heating coil outlet node name must be the same as the fan inlet node name.");
    1244            0 :                     ShowContinueError(state, format("...Heating coil outlet node name = {}", state.dataLoopNodes->NodeID(HeatingCoilOutletNode)));
    1245            0 :                     ShowContinueError(state, format("...Fan inlet node name           = {}", state.dataLoopNodes->NodeID(FanInletNode)));
    1246            0 :                     ErrorsFound = true;
    1247              :                 }
    1248              :                 // Fan coil outlet node name must be the same as the furnace outlet node name
    1249            0 :                 if (FanOutletNode != thisFurnace.FurnaceOutletNodeNum) {
    1250            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1251            0 :                     if (thisFurnace.type == HVAC::UnitarySysType::Furnace_HeatOnly) {
    1252            0 :                         ShowContinueError(
    1253              :                             state,
    1254              :                             "When a draw through fan is specified, the fan outlet node name must be the same as the furnace outlet node name.");
    1255            0 :                         ShowContinueError(state, format("...Fan outlet node name     = {}", state.dataLoopNodes->NodeID(FanOutletNode)));
    1256            0 :                         ShowContinueError(state,
    1257            0 :                                           format("...Furnace outlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    1258              :                     } else {
    1259            0 :                         ShowContinueError(state,
    1260              :                                           "When a draw through fan is specified, the fan outlet node name must be the same as the unitary system "
    1261              :                                           "outlet node name.");
    1262            0 :                         ShowContinueError(state, format("...Fan outlet node name           = {}", state.dataLoopNodes->NodeID(FanOutletNode)));
    1263            0 :                         ShowContinueError(
    1264            0 :                             state, format("...UnitarySystem outlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    1265              :                     }
    1266            0 :                     ErrorsFound = true;
    1267              :                 }
    1268              :             }
    1269              : 
    1270              :             // Add fan to component sets array
    1271            0 :             BranchNodeConnections::SetUpCompSets(
    1272            0 :                 state, CurrentModuleObject, thisFurnace.Name, Alphas(7), Alphas(8), CompSetFanInlet, CompSetFanOutlet);
    1273              :             // Add heating coil to component sets array
    1274            0 :             BranchNodeConnections::SetUpCompSets(
    1275            0 :                 state, CurrentModuleObject, thisFurnace.Name, Alphas(10), Alphas(11), CompSetHeatInlet, CompSetHeatOutlet);
    1276              : 
    1277              :             // Set the furnace max outlet temperature
    1278            0 :             thisFurnace.DesignMaxOutletTemp = Numbers(1);
    1279              : 
    1280              :             // Set the furnace design fan volumetric flow rate
    1281            0 :             thisFurnace.DesignFanVolFlowRate = Numbers(2);
    1282              : 
    1283              :             // Compare the flow rates.
    1284            0 :             if (thisFurnace.ActualFanVolFlowRate != DataSizing::AutoSize && thisFurnace.DesignFanVolFlowRate != DataSizing::AutoSize) {
    1285            0 :                 if (thisFurnace.DesignFanVolFlowRate > thisFurnace.ActualFanVolFlowRate) {
    1286            0 :                     ShowWarningError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1287            0 :                     ShowContinueError(
    1288            0 :                         state, format("... The {} > Max Volume Flow Rate defined in the associated fan object, should be <=.", cNumericFields(2)));
    1289            0 :                     ShowContinueError(state,
    1290            0 :                                       format("... Entered value = {:.4R}... Fan [{} = {}] Max Value = {:.4R}",
    1291            0 :                                              thisFurnace.DesignFanVolFlowRate,
    1292            0 :                                              HVAC::fanTypeNames[(int)thisFurnace.fanType],
    1293              :                                              FanName,
    1294            0 :                                              thisFurnace.ActualFanVolFlowRate));
    1295            0 :                     ShowContinueError(state, " The HVAC system  flow rate is reset to the fan flow rate and the simulation continues.");
    1296            0 :                     thisFurnace.DesignFanVolFlowRate = thisFurnace.ActualFanVolFlowRate;
    1297              :                 }
    1298              :             }
    1299            0 :             if (thisFurnace.DesignFanVolFlowRate != DataSizing::AutoSize) {
    1300            0 :                 if (thisFurnace.DesignFanVolFlowRate <= 0.0) {
    1301            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1302            0 :                     ShowContinueError(state, format("... The {} <= 0.0, it must be > 0.0.", cNumericFields(2)));
    1303            0 :                     ShowContinueError(state, format("... Entered value = {:.2R}", thisFurnace.DesignFanVolFlowRate));
    1304            0 :                     ErrorsFound = true;
    1305              :                 }
    1306              :             }
    1307              : 
    1308              :             //       HeatOnly furnace has only 1 flow rate, initialize other variables used in this module
    1309            0 :             thisFurnace.MaxHeatAirVolFlow = thisFurnace.DesignFanVolFlowRate;
    1310            0 :             thisFurnace.MaxCoolAirVolFlow = thisFurnace.DesignFanVolFlowRate;
    1311            0 :             thisFurnace.MaxNoCoolHeatAirVolFlow = thisFurnace.DesignFanVolFlowRate;
    1312            0 :             thisFurnace.AirFlowControl = AirFlowControlConstFan::UseCompressorOnFlow;
    1313              : 
    1314              :             // Set heating convergence tolerance
    1315            0 :             thisFurnace.HeatingConvergenceTolerance = 0.001;
    1316              : 
    1317              :             // set minimum outdoor temperature for compressor operation
    1318            0 :             SetMinOATCompressor(state, FurnaceNum, cCurrentModuleObject, ErrorsFound);
    1319              : 
    1320              :         } // End of the HeatOnly Furnace Loop
    1321              : 
    1322              :         // Get the data for the HeatCool Furnace or UnitarySystem
    1323            2 :         for (int HeatCoolNum = 1; HeatCoolNum <= NumHeatCool + NumUnitaryHeatCool; ++HeatCoolNum) {
    1324              : 
    1325            0 :             FanInletNode = 0;
    1326            0 :             FanOutletNode = 0;
    1327            0 :             CoolingCoilInletNode = 0;
    1328            0 :             CoolingCoilOutletNode = 0;
    1329            0 :             HeatingCoilInletNode = 0;
    1330            0 :             HeatingCoilOutletNode = 0;
    1331            0 :             int ReheatCoilInletNode = 0;
    1332            0 :             int ReheatCoilOutletNode = 0;
    1333            0 :             CoolingCoilType = ' ';
    1334            0 :             CoolingCoilName = ' ';
    1335            0 :             HeatingCoilType = ' ';
    1336            0 :             HeatingCoilName = ' ';
    1337              : 
    1338            0 :             FurnaceNum = HeatCoolNum + NumHeatOnly + NumUnitaryHeatOnly;
    1339            0 :             auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    1340              : 
    1341              :             //      Furnace and UnitarySystem objects are both read in here.
    1342              :             //      Will still have 2 differently named objects for the user, but read in with 1 DO loop.
    1343            0 :             if (HeatCoolNum <= NumHeatCool) {
    1344            0 :                 CurrentModuleObject = "AirLoopHVAC:Unitary:Furnace:HeatCool";
    1345            0 :                 currentModuleObjectType = DataLoopNode::ConnectionObjectType::AirLoopHVACUnitaryFurnaceHeatCool;
    1346            0 :                 thisFurnace.type = HVAC::UnitarySysType::Furnace_HeatCool;
    1347            0 :                 GetObjectNum = HeatCoolNum;
    1348              :             } else {
    1349            0 :                 CurrentModuleObject = "AirLoopHVAC:UnitaryHeatCool";
    1350            0 :                 currentModuleObjectType = DataLoopNode::ConnectionObjectType::AirLoopHVACUnitaryHeatCool;
    1351            0 :                 thisFurnace.type = HVAC::UnitarySysType::Unitary_HeatCool;
    1352            0 :                 GetObjectNum = HeatCoolNum - NumHeatCool;
    1353              :             }
    1354              : 
    1355            0 :             thisFurnace.iterationMode.allocate(3);
    1356              : 
    1357            0 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1358              :                                                                      CurrentModuleObject,
    1359              :                                                                      GetObjectNum,
    1360              :                                                                      Alphas,
    1361              :                                                                      NumAlphas,
    1362              :                                                                      Numbers,
    1363              :                                                                      NumNumbers,
    1364              :                                                                      IOStatus,
    1365              :                                                                      lNumericBlanks,
    1366              :                                                                      lAlphaBlanks,
    1367              :                                                                      cAlphaFields,
    1368              :                                                                      cNumericFields);
    1369              : 
    1370            0 :             GlobalNames::VerifyUniqueInterObjectName(
    1371            0 :                 state, state.dataFurnaces->UniqueFurnaceNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
    1372              : 
    1373            0 :             thisFurnace.Name = Alphas(1);
    1374              : 
    1375            0 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, thisFurnace.Name};
    1376              : 
    1377            0 :             if (lAlphaBlanks(2)) {
    1378            0 :                 thisFurnace.availSched = Sched::GetScheduleAlwaysOn(state);
    1379            0 :             } else if ((thisFurnace.availSched = Sched::GetSchedule(state, Alphas(2))) == nullptr) {
    1380            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(2), Alphas(2));
    1381            0 :                 ErrorsFound = true;
    1382              :             }
    1383              : 
    1384            0 :             thisFurnace.FurnaceInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
    1385            0 :                                                                                   Alphas(3),
    1386              :                                                                                   ErrorsFound,
    1387              :                                                                                   currentModuleObjectType,
    1388            0 :                                                                                   Alphas(1),
    1389              :                                                                                   DataLoopNode::NodeFluidType::Air,
    1390              :                                                                                   DataLoopNode::ConnectionType::Inlet,
    1391              :                                                                                   NodeInputManager::CompFluidStream::Primary,
    1392              :                                                                                   DataLoopNode::ObjectIsParent);
    1393            0 :             thisFurnace.FurnaceOutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
    1394            0 :                                                                                    Alphas(4),
    1395              :                                                                                    ErrorsFound,
    1396              :                                                                                    currentModuleObjectType,
    1397            0 :                                                                                    Alphas(1),
    1398              :                                                                                    DataLoopNode::NodeFluidType::Air,
    1399              :                                                                                    DataLoopNode::ConnectionType::Outlet,
    1400              :                                                                                    NodeInputManager::CompFluidStream::Primary,
    1401              :                                                                                    DataLoopNode::ObjectIsParent);
    1402              : 
    1403            0 :             BranchNodeConnections::TestCompSet(state, CurrentModuleObject, Alphas(1), Alphas(3), Alphas(4), "Air Nodes");
    1404              : 
    1405            0 :             if (lAlphaBlanks(5)) {
    1406            0 :                 thisFurnace.fanOp = HVAC::FanOp::Cycling;
    1407            0 :             } else if ((thisFurnace.fanOpModeSched = Sched::GetSchedule(state, Alphas(5))) == nullptr) {
    1408            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(5), Alphas(5));
    1409            0 :                 ErrorsFound = true;
    1410              :             }
    1411              : 
    1412              :             // Get the Controlling Zone or Location of the Furnace Thermostat
    1413            0 :             thisFurnace.ControlZoneNum = Util::FindItemInList(Alphas(6), state.dataHeatBal->Zone);
    1414            0 :             if (thisFurnace.ControlZoneNum == 0) {
    1415            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1416            0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(6), Alphas(6)));
    1417            0 :                 ErrorsFound = true;
    1418              :             }
    1419              : 
    1420              :             // Get the node number for the zone with the thermostat
    1421            0 :             if (thisFurnace.ControlZoneNum > 0) {
    1422            0 :                 AirNodeFound = false;
    1423            0 :                 AirLoopFound = false;
    1424            0 :                 int ControlledZoneNum = thisFurnace.ControlZoneNum;
    1425              :                 //             Find the controlled zone number for the specified thermostat location
    1426            0 :                 thisFurnace.NodeNumOfControlledZone = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).ZoneNode;
    1427              :                 //             Determine if system is on air loop served by the thermostat location specified
    1428            0 :                 for (int zoneInNode = 1; zoneInNode <= state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).NumInletNodes; ++zoneInNode) {
    1429            0 :                     int AirLoopNumber = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).InletNodeAirLoopNum(zoneInNode);
    1430            0 :                     if (AirLoopNumber > 0) {
    1431            0 :                         for (int BranchNum = 1; BranchNum <= state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).NumBranches; ++BranchNum) {
    1432            0 :                             for (int CompNum = 1;
    1433            0 :                                  CompNum <= state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).Branch(BranchNum).TotalComponents;
    1434              :                                  ++CompNum) {
    1435            0 :                                 if (!Util::SameString(state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).Branch(BranchNum).Comp(CompNum).Name,
    1436            0 :                                                       Alphas(1)) ||
    1437            0 :                                     !Util::SameString(
    1438            0 :                                         state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).Branch(BranchNum).Comp(CompNum).TypeOf,
    1439              :                                         CurrentModuleObject))
    1440            0 :                                     continue;
    1441            0 :                                 AirLoopFound = true;
    1442            0 :                                 thisFurnace.ZoneInletNode = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).InletNode(zoneInNode);
    1443            0 :                                 break;
    1444              :                             }
    1445            0 :                             if (AirLoopFound) break;
    1446              :                         }
    1447            0 :                         for (TstatZoneNum = 1; TstatZoneNum <= state.dataZoneCtrls->NumTempControlledZones; ++TstatZoneNum) {
    1448            0 :                             if (state.dataZoneCtrls->TempControlledZone(TstatZoneNum).ActualZoneNum != thisFurnace.ControlZoneNum) continue;
    1449            0 :                             AirNodeFound = true;
    1450              :                         }
    1451            0 :                         for (TstatZoneNum = 1; TstatZoneNum <= state.dataZoneCtrls->NumComfortControlledZones; ++TstatZoneNum) {
    1452            0 :                             if (state.dataZoneCtrls->ComfortControlledZone(TstatZoneNum).ActualZoneNum != thisFurnace.ControlZoneNum) continue;
    1453            0 :                             AirNodeFound = true;
    1454              :                         }
    1455              :                     }
    1456            0 :                     if (AirLoopFound) break;
    1457              :                 }
    1458            0 :                 if (!AirNodeFound) {
    1459            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1460            0 :                     ShowContinueError(state, "Did not find air node (zone with thermostat).");
    1461            0 :                     ShowContinueError(state, format("Specified {} = {}", cAlphaFields(6), Alphas(6)));
    1462            0 :                     ShowContinueError(
    1463              :                         state, "Both a ZoneHVAC:EquipmentConnections object and a ZoneControl:Thermostat object must be specified for this zone.");
    1464            0 :                     ErrorsFound = true;
    1465              :                 }
    1466            0 :                 if (!AirLoopFound) {
    1467            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1468            0 :                     ShowContinueError(state, "Did not find correct AirLoopHVAC.");
    1469            0 :                     ShowContinueError(state, format("Specified {} = {}", cAlphaFields(6), Alphas(6)));
    1470            0 :                     ErrorsFound = true;
    1471              :                 }
    1472              :             }
    1473              : 
    1474              :             // Get fan data
    1475            0 :             FanName = Alphas(8);
    1476              : 
    1477            0 :             thisFurnace.fanType = static_cast<HVAC::FanType>(getEnumValue(HVAC::fanTypeNamesUC, Alphas(7)));
    1478              : 
    1479            0 :             if (thisFurnace.fanType != HVAC::FanType::OnOff && thisFurnace.fanType != HVAC::FanType::Constant) {
    1480            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1481            0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(7), Alphas(7)));
    1482            0 :                 ErrorsFound = true;
    1483              : 
    1484            0 :             } else if ((thisFurnace.FanIndex = Fans::GetFanIndex(state, FanName)) == 0) {
    1485            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(8), FanName);
    1486            0 :                 ErrorsFound = true;
    1487              : 
    1488              :             } else {
    1489            0 :                 auto *fan = state.dataFans->fans(thisFurnace.FanIndex);
    1490            0 :                 thisFurnace.ActualFanVolFlowRate = fan->maxAirFlowRate;
    1491            0 :                 FanInletNode = fan->inletNodeNum;
    1492            0 :                 FanOutletNode = fan->outletNodeNum;
    1493            0 :                 thisFurnace.fanAvailSched = fan->availSched;
    1494              : 
    1495              :                 // Check fan's schedule for cycling fan operation if constant volume fan is used
    1496            0 :                 if (thisFurnace.fanOpModeSched != nullptr && thisFurnace.fanType == HVAC::FanType::Constant) {
    1497            0 :                     if (!thisFurnace.fanOpModeSched->checkMinMaxVals(state, Clusive::Ex, 0.0, Clusive::In, 1.0)) {
    1498            0 :                         Sched::ShowSevereBadMinMax(
    1499              :                             state,
    1500              :                             eoh,
    1501            0 :                             cAlphaFields(5),
    1502            0 :                             Alphas(5),
    1503              :                             Clusive::In,
    1504              :                             0.0,
    1505              :                             Clusive::In,
    1506              :                             1.0,
    1507            0 :                             format("For {} = {}, fan operating mode must be continuous (schedule values > 0)", cAlphaFields(7), Alphas(7)));
    1508            0 :                         ErrorsFound = true;
    1509              :                     }
    1510            0 :                 } else if (lAlphaBlanks(5) && thisFurnace.fanType != HVAC::FanType::OnOff) {
    1511            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, thisFurnace.Name));
    1512            0 :                     ShowContinueError(state, format("{} = {}", cAlphaFields(7), Alphas(7)));
    1513            0 :                     ShowContinueError(state, format("Fan type must be Fan:OnOff when {} = Blank.", cAlphaFields(5)));
    1514            0 :                     ErrorsFound = true;
    1515              :                 }
    1516              :             }
    1517              : 
    1518            0 :             thisFurnace.fanPlace = static_cast<HVAC::FanPlace>(getEnumValue(HVAC::fanPlaceNamesUC, Alphas(9)));
    1519            0 :             assert(thisFurnace.fanPlace != HVAC::FanPlace::Invalid);
    1520              : 
    1521              :             // Get coil data
    1522            0 :             HeatingCoilType = Alphas(10);
    1523            0 :             HeatingCoilName = Alphas(11);
    1524            0 :             HeatingCoilPLFCurveIndex = 0;
    1525            0 :             thisFurnace.HeatingCoilType = HeatingCoilType;
    1526            0 :             thisFurnace.HeatingCoilName = HeatingCoilName;
    1527            0 :             if (Util::SameString(HeatingCoilType, "Coil:Heating:Fuel") || Util::SameString(HeatingCoilType, "Coil:Heating:Electric")) {
    1528            0 :                 errFlag = false;
    1529            0 :                 thisFurnace.HeatingCoilType_Num = HeatingCoils::GetHeatingCoilTypeNum(state, HeatingCoilType, HeatingCoilName, errFlag);
    1530            0 :                 if (errFlag) {
    1531            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1532            0 :                     ErrorsFound = true;
    1533              :                 } else {
    1534              : 
    1535            0 :                     ValidateComponent(state, HeatingCoilType, HeatingCoilName, IsNotOK, CurrentModuleObject);
    1536            0 :                     if (IsNotOK) {
    1537            0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1538            0 :                         ErrorsFound = true;
    1539              : 
    1540              :                     } else { // mine data from heating coil
    1541              : 
    1542              :                         // Get heating coil index
    1543            0 :                         errFlag = false;
    1544            0 :                         HeatingCoils::GetCoilIndex(state, HeatingCoilName, thisFurnace.HeatingCoilIndex, errFlag);
    1545            0 :                         if (errFlag) {
    1546            0 :                             ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1547            0 :                             ErrorsFound = true;
    1548              :                         }
    1549              : 
    1550              :                         // Get the design heating capacity
    1551            0 :                         errFlag = false;
    1552            0 :                         thisFurnace.DesignHeatingCapacity = HeatingCoils::GetCoilCapacity(state, HeatingCoilType, HeatingCoilName, errFlag);
    1553            0 :                         if (errFlag) {
    1554            0 :                             ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1555            0 :                             ErrorsFound = true;
    1556              :                         }
    1557              : 
    1558              :                         // Get the Heating Coil Inlet Node
    1559            0 :                         errFlag = false;
    1560            0 :                         HeatingCoilInletNode = HeatingCoils::GetCoilInletNode(state, HeatingCoilType, HeatingCoilName, errFlag);
    1561            0 :                         if (errFlag) {
    1562            0 :                             ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1563            0 :                             ErrorsFound = true;
    1564              :                         }
    1565              : 
    1566              :                         // Get the Heating Coil Outlet Node
    1567            0 :                         errFlag = false;
    1568            0 :                         HeatingCoilOutletNode = HeatingCoils::GetCoilOutletNode(state, HeatingCoilType, HeatingCoilName, errFlag);
    1569            0 :                         if (errFlag) {
    1570            0 :                             ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1571            0 :                             ErrorsFound = true;
    1572              :                         }
    1573              : 
    1574              :                         // Get the Heating Coil PLF Curve Index
    1575            0 :                         errFlag = false;
    1576            0 :                         HeatingCoilPLFCurveIndex = HeatingCoils::GetHeatingCoilPLFCurveIndex(state, HeatingCoilType, HeatingCoilName, errFlag);
    1577            0 :                         if (errFlag) {
    1578            0 :                             ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1579            0 :                             ErrorsFound = true;
    1580              :                         }
    1581              : 
    1582              :                     } // IF (IsNotOK) THEN
    1583              :                 }
    1584              : 
    1585            0 :             } else if (Util::SameString(HeatingCoilType, "Coil:Heating:Water")) {
    1586            0 :                 thisFurnace.HeatingCoilType_Num = HVAC::Coil_HeatingWater;
    1587            0 :                 ValidateComponent(state, HeatingCoilType, HeatingCoilName, IsNotOK, CurrentModuleObject);
    1588            0 :                 if (IsNotOK) {
    1589            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1590            0 :                     ErrorsFound = true;
    1591              :                 } else { // mine data from heating coil object
    1592              : 
    1593              :                     // Get the Heating Coil water Inlet or control Node number
    1594            0 :                     errFlag = false;
    1595            0 :                     thisFurnace.CoilControlNode = WaterCoils::GetCoilWaterInletNode(state, "Coil:Heating:Water", HeatingCoilName, errFlag);
    1596            0 :                     if (errFlag) {
    1597            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1598            0 :                         ErrorsFound = true;
    1599              :                     }
    1600              : 
    1601              :                     // Get the Heating Coil hot water max volume flow rate
    1602            0 :                     errFlag = false;
    1603            0 :                     thisFurnace.MaxHeatCoilFluidFlow = WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", HeatingCoilName, errFlag);
    1604            0 :                     if (errFlag) {
    1605            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1606            0 :                         ErrorsFound = true;
    1607              :                     }
    1608              : 
    1609              :                     // Get the Heating Coil Inlet Node
    1610            0 :                     errFlag = false;
    1611            0 :                     HeatingCoilInletNode = WaterCoils::GetCoilInletNode(state, "Coil:Heating:Water", HeatingCoilName, errFlag);
    1612            0 :                     thisFurnace.HWCoilAirInletNode = HeatingCoilInletNode;
    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 Outlet Node
    1619            0 :                     errFlag = false;
    1620            0 :                     HeatingCoilOutletNode = WaterCoils::GetCoilOutletNode(state, "Coil:Heating:Water", HeatingCoilName, errFlag);
    1621            0 :                     thisFurnace.HWCoilAirOutletNode = HeatingCoilOutletNode;
    1622            0 :                     if (errFlag) {
    1623            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1624            0 :                         ErrorsFound = true;
    1625              :                     }
    1626              : 
    1627              :                     // check if user has also used a water coil controller, which they should not do
    1628            0 :                     errFlag = false;
    1629            0 :                     HVACControllers::CheckCoilWaterInletNode(state, thisFurnace.CoilControlNode, errFlag);
    1630            0 :                     if (!errFlag) { // then did find a controller so that is bad
    1631            0 :                         ShowSevereError(state,
    1632            0 :                                         format("{} = {} has a conflicting Controller:WaterCoil object", CurrentModuleObject, thisFurnace.Name));
    1633            0 :                         ShowContinueError(state, "Hot water coils are controlled directly by unitary and furnace systems.");
    1634            0 :                         ShowContinueError(state, "No water coil controller should be input for the coil.");
    1635            0 :                         ErrorsFound = true;
    1636              :                     }
    1637              :                 }
    1638              : 
    1639            0 :             } else if (Util::SameString(HeatingCoilType, "Coil:Heating:Steam")) {
    1640            0 :                 thisFurnace.HeatingCoilType_Num = HVAC::Coil_HeatingSteam;
    1641            0 :                 ValidateComponent(state, HeatingCoilType, HeatingCoilName, IsNotOK, CurrentModuleObject);
    1642            0 :                 if (IsNotOK) {
    1643            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1644            0 :                     ErrorsFound = true;
    1645              :                 } else { // mine data from heating coil object
    1646              : 
    1647            0 :                     errFlag = false;
    1648            0 :                     thisFurnace.HeatingCoilIndex = SteamCoils::GetSteamCoilIndex(state, "COIL:HEATING:STEAM", HeatingCoilName, errFlag);
    1649            0 :                     if (thisFurnace.HeatingCoilIndex == 0) {
    1650            0 :                         ShowSevereError(state, format("{} illegal {} = {}", CurrentModuleObject, cAlphaFields(11), HeatingCoilName));
    1651            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1652            0 :                         ErrorsFound = true;
    1653              :                     }
    1654              : 
    1655              :                     // Get the Heating Coil steam inlet node number
    1656            0 :                     errFlag = false;
    1657            0 :                     thisFurnace.CoilControlNode = SteamCoils::GetCoilSteamInletNode(state, "Coil:Heating:Steam", HeatingCoilName, errFlag);
    1658            0 :                     if (errFlag) {
    1659            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1660            0 :                         ErrorsFound = true;
    1661              :                     }
    1662              : 
    1663              :                     // Get the Heating Coil steam max volume flow rate
    1664            0 :                     thisFurnace.MaxHeatCoilFluidFlow = SteamCoils::GetCoilMaxSteamFlowRate(state, thisFurnace.HeatingCoilIndex, errFlag);
    1665            0 :                     if (thisFurnace.MaxHeatCoilFluidFlow > 0.0) {
    1666              :                         SteamDensity =
    1667            0 :                             Fluid::GetSteam(state)->getSatDensity(state, state.dataFurnaces->TempSteamIn, 1.0, getAirLoopHVACHeatCoolInput);
    1668            0 :                         thisFurnace.MaxHeatCoilFluidFlow *= SteamDensity;
    1669              :                     }
    1670              : 
    1671              :                     // Get the Heating Coil Inlet Node
    1672            0 :                     errFlag = false;
    1673            0 :                     HeatingCoilInletNode = SteamCoils::GetCoilAirInletNode(state, thisFurnace.HeatingCoilIndex, HeatingCoilName, errFlag);
    1674            0 :                     thisFurnace.HWCoilAirInletNode = HeatingCoilInletNode;
    1675            0 :                     if (errFlag) {
    1676            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1677            0 :                         ErrorsFound = true;
    1678              :                     }
    1679              : 
    1680              :                     // Get the Heating Coil Outlet Node
    1681            0 :                     errFlag = false;
    1682            0 :                     HeatingCoilOutletNode = SteamCoils::GetCoilAirOutletNode(state, thisFurnace.HeatingCoilIndex, HeatingCoilName, errFlag);
    1683            0 :                     thisFurnace.HWCoilAirOutletNode = HeatingCoilOutletNode;
    1684            0 :                     if (errFlag) {
    1685            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    1686            0 :                         ErrorsFound = true;
    1687              :                     }
    1688              :                 }
    1689              : 
    1690              :             } else {
    1691            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1692            0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(11), Alphas(11)));
    1693            0 :                 ErrorsFound = true;
    1694              :             } // IF (Furnace(FurnaceNum)%HeatingCoilType_Num == Coil_HeatingGasOrOtherFuel .OR. &, etc.
    1695              : 
    1696              :             // Get Cooling Coil Information if available
    1697            0 :             CoolingCoilType = Alphas(12);
    1698            0 :             CoolingCoilName = Alphas(13);
    1699              :             //       Find the type of coil. Do not print message since this may not be the correct coil type.
    1700            0 :             errFlag = false;
    1701            0 :             PrintMessage = false;
    1702              : 
    1703            0 :             if (Util::SameString(CoolingCoilType, "COIL:COOLING:DX:VARIABLESPEED") ||
    1704            0 :                 Util::SameString(CoolingCoilType, "COILSYSTEM:INTEGRATEDHEATPUMP:AIRSOURCE")) {
    1705            0 :                 thisFurnace.CoolingCoilType_Num = HVAC::Coil_CoolingAirToAirVariableSpeed;
    1706            0 :                 if (Util::SameString(CoolingCoilType, "COILSYSTEM:INTEGRATEDHEATPUMP:AIRSOURCE")) thisFurnace.bIsIHP = true;
    1707              :             } else {
    1708            0 :                 thisFurnace.CoolingCoilType_Num = DXCoils::GetCoilTypeNum(state, CoolingCoilType, CoolingCoilName, errFlag, PrintMessage);
    1709              :             }
    1710              : 
    1711              :             // If coil type not found, check to see if a HX assisted cooling coil is used.
    1712            0 :             if (thisFurnace.CoolingCoilType_Num == 0) {
    1713            0 :                 errFlag = false;
    1714            0 :                 thisFurnace.CoolingCoilType_Num =
    1715            0 :                     HVACHXAssistedCoolingCoil::GetCoilGroupTypeNum(state, CoolingCoilType, CoolingCoilName, errFlag, PrintMessage);
    1716              :             }
    1717              : 
    1718            0 :             if (thisFurnace.CoolingCoilType_Num == HVAC::CoilDX_CoolingSingleSpeed) {
    1719            0 :                 ValidateComponent(state, CoolingCoilType, CoolingCoilName, IsNotOK, CurrentModuleObject);
    1720            0 :                 if (IsNotOK) {
    1721            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1722            0 :                     ErrorsFound = true;
    1723              : 
    1724              :                 } else { // mine data from DX cooling coil
    1725              : 
    1726              :                     // Get DX cooling coil index
    1727            0 :                     DXCoils::GetDXCoilIndex(state, CoolingCoilName, thisFurnace.CoolingCoilIndex, IsNotOK);
    1728            0 :                     if (IsNotOK) {
    1729            0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1730            0 :                         ErrorsFound = true;
    1731              :                     }
    1732              : 
    1733              :                     // Get DX cooling coil capacity
    1734            0 :                     errFlag = false;
    1735            0 :                     thisFurnace.DesignCoolingCapacity = DXCoils::GetCoilCapacity(state, CoolingCoilType, CoolingCoilName, errFlag);
    1736            0 :                     if (errFlag) {
    1737            0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1738            0 :                         ErrorsFound = true;
    1739              :                     }
    1740              : 
    1741              :                     // Get the Cooling Coil Nodes
    1742            0 :                     errFlag = false;
    1743            0 :                     CoolingCoilInletNode = DXCoils::GetCoilInletNode(state, CoolingCoilType, CoolingCoilName, errFlag);
    1744            0 :                     CoolingCoilOutletNode = DXCoils::GetCoilOutletNode(state, CoolingCoilType, CoolingCoilName, errFlag);
    1745            0 :                     if (errFlag) {
    1746            0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1747            0 :                         ErrorsFound = true;
    1748              :                     }
    1749              : 
    1750              :                     // Get outdoor condenser node from DX coil object
    1751            0 :                     errFlag = false;
    1752            0 :                     if (thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingAirToAirVariableSpeed) {
    1753            0 :                         if (thisFurnace.bIsIHP) {
    1754            0 :                             IHPCoilIndex = IntegratedHeatPump::GetCoilIndexIHP(state, CoolingCoilType, CoolingCoilName, errFlag);
    1755            0 :                             IHPCoilName = state.dataIntegratedHP->IntegratedHeatPumps(IHPCoilIndex).SCCoilName;
    1756            0 :                             thisFurnace.CondenserNodeNum = VariableSpeedCoils::GetVSCoilCondenserInletNode(state, IHPCoilName, errFlag);
    1757              :                         } else {
    1758            0 :                             thisFurnace.CondenserNodeNum = VariableSpeedCoils::GetVSCoilCondenserInletNode(state, CoolingCoilName, errFlag);
    1759              :                         }
    1760              :                     } else {
    1761            0 :                         thisFurnace.CondenserNodeNum = DXCoils::GetCoilCondenserInletNode(state, CoolingCoilType, CoolingCoilName, errFlag);
    1762              :                     }
    1763            0 :                     if (errFlag) {
    1764            0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1765            0 :                         ErrorsFound = true;
    1766              :                     }
    1767              : 
    1768              :                 } // IF (IsNotOK) THEN
    1769              : 
    1770              :                 // Push heating coil PLF curve index to DX coil
    1771            0 :                 if (HeatingCoilPLFCurveIndex > 0) {
    1772            0 :                     DXCoils::SetDXCoolingCoilData(state, thisFurnace.CoolingCoilIndex, ErrorsFound, HeatingCoilPLFCurveIndex);
    1773              :                 }
    1774              : 
    1775            0 :             } else if (thisFurnace.CoolingCoilType_Num == HVAC::CoilDX_CoolingHXAssisted) {
    1776            0 :                 ValidateComponent(state, CoolingCoilType, CoolingCoilName, IsNotOK, CurrentModuleObject);
    1777            0 :                 if (IsNotOK) {
    1778            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1779            0 :                     ErrorsFound = true;
    1780              : 
    1781              :                 } else { // mine data from heat exchanger assisted cooling coil
    1782              : 
    1783              :                     // Get DX heat exchanger assisted cooling coil index
    1784            0 :                     HVACHXAssistedCoolingCoil::GetHXDXCoilIndex(state, CoolingCoilName, thisFurnace.CoolingCoilIndex, IsNotOK);
    1785            0 :                     if (IsNotOK) {
    1786            0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1787            0 :                         ErrorsFound = true;
    1788              :                     }
    1789              : 
    1790              :                     // Get DX cooling coil capacity
    1791            0 :                     errFlag = false;
    1792            0 :                     thisFurnace.DesignCoolingCapacity = HVACHXAssistedCoolingCoil::GetCoilCapacity(state, CoolingCoilType, CoolingCoilName, errFlag);
    1793            0 :                     if (errFlag) {
    1794            0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1795            0 :                         ErrorsFound = true;
    1796              :                     }
    1797              : 
    1798              :                     // Get the Cooling Coil Nodes
    1799            0 :                     errFlag = false;
    1800            0 :                     CoolingCoilInletNode = HVACHXAssistedCoolingCoil::GetCoilInletNode(state, CoolingCoilType, CoolingCoilName, errFlag);
    1801            0 :                     CoolingCoilOutletNode = HVACHXAssistedCoolingCoil::GetCoilOutletNode(state, CoolingCoilType, CoolingCoilName, errFlag);
    1802            0 :                     if (errFlag) {
    1803            0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1804            0 :                         ErrorsFound = true;
    1805              :                     }
    1806              : 
    1807              :                     // Get outdoor condenser node from heat exchanger assisted DX coil object
    1808            0 :                     errFlag = false;
    1809            0 :                     std::string ChildCoolingCoilName = HVACHXAssistedCoolingCoil::GetHXDXCoilName(state, CoolingCoilType, CoolingCoilName, IsNotOK);
    1810            0 :                     std::string ChildCoolingCoilType = HVACHXAssistedCoolingCoil::GetHXDXCoilType(state, CoolingCoilType, CoolingCoilName, IsNotOK);
    1811            0 :                     if (IsNotOK) {
    1812            0 :                         ShowContinueError(state, format("Occurs in {} = {}", cCurrentModuleObject, Alphas(1)));
    1813            0 :                         ErrorsFound = true;
    1814              :                     }
    1815              : 
    1816              :                     // if (thisFurnace.CoolingCoilType_Num == CoilDX_CoolingHXAssisted) {
    1817            0 :                     if (Util::SameString(ChildCoolingCoilType, "COIL:COOLING:DX")) {
    1818              : 
    1819            0 :                         int childCCIndex = CoilCoolingDX::factory(state, ChildCoolingCoilName);
    1820            0 :                         if (childCCIndex < 0) {
    1821            0 :                             ShowContinueError(state, format("Occurs in {} = {}", cCurrentModuleObject, Alphas(1)));
    1822            0 :                             errFlag = true;
    1823            0 :                             ErrorsFound = true;
    1824              :                         }
    1825            0 :                         auto const &newCoil = state.dataCoilCoolingDX->coilCoolingDXs[childCCIndex];
    1826              : 
    1827            0 :                         thisFurnace.CondenserNodeNum = newCoil.condInletNodeIndex;
    1828              : 
    1829              :                     }
    1830              :                     // else if (thisFurnace.CoolingCoilType_Num == Coil_CoolingAirToAirVariableSpeed) {
    1831            0 :                     else if (Util::SameString(ChildCoolingCoilType, "Coil:Cooling:DX:VariableSpeed")) {
    1832            0 :                         if (thisFurnace.bIsIHP) {
    1833            0 :                             IHPCoilIndex = IntegratedHeatPump::GetCoilIndexIHP(state, CoolingCoilType, CoolingCoilName, errFlag);
    1834            0 :                             IHPCoilName = state.dataIntegratedHP->IntegratedHeatPumps(IHPCoilIndex).SCCoilName;
    1835            0 :                             thisFurnace.CondenserNodeNum = VariableSpeedCoils::GetVSCoilCondenserInletNode(state, IHPCoilName, errFlag);
    1836              :                         } else {
    1837            0 :                             thisFurnace.CondenserNodeNum = VariableSpeedCoils::GetVSCoilCondenserInletNode(state, CoolingCoilName, errFlag);
    1838              :                         }
    1839              :                     } else {
    1840            0 :                         thisFurnace.CondenserNodeNum = DXCoils::GetCoilCondenserInletNode(
    1841              :                             state,
    1842              :                             "COIL:COOLING:DX:SINGLESPEED",
    1843            0 :                             HVACHXAssistedCoolingCoil::GetHXDXCoilName(state, CoolingCoilType, CoolingCoilName, errFlag),
    1844              :                             errFlag);
    1845              :                     }
    1846              : 
    1847            0 :                     if (errFlag) {
    1848            0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1849            0 :                         ErrorsFound = true;
    1850              :                     }
    1851              : 
    1852              :                     // Push heating coil PLF curve index to DX coil
    1853            0 :                     if (HeatingCoilPLFCurveIndex > 0) {
    1854              :                         // get the actual index to the DX cooling coil object
    1855            0 :                         DXCoilIndex = HVACHXAssistedCoolingCoil::GetActualDXCoilIndex(state, CoolingCoilType, CoolingCoilName, ErrorsFound);
    1856            0 :                         thisFurnace.ActualDXCoilIndexForHXAssisted = DXCoilIndex;
    1857              :                         int ActualCoolCoilType =
    1858            0 :                             HVACHXAssistedCoolingCoil::GetCoilObjectTypeNum(state, CoolingCoilType, CoolingCoilName, errFlag, true);
    1859            0 :                         if (ActualCoolCoilType == HVAC::CoilDX_CoolingSingleSpeed) {
    1860            0 :                             DXCoils::SetDXCoolingCoilData(state, DXCoilIndex, ErrorsFound, HeatingCoilPLFCurveIndex);
    1861              :                         }
    1862              :                         // what could we do for VS coil here? odd thing here
    1863              :                     }
    1864              : 
    1865            0 :                 } // IF (IsNotOK) THEN
    1866            0 :             } else if (thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingAirToAirVariableSpeed) {
    1867              :                 // BOS ADDED, AUG/2012, VARIIABLE SPEED DX COOLING COIL
    1868              :                 //  Furnace(FurnaceNum)%DXCoolCoilType = 'COIL:COOLING:DX:VARIABLESPEED'
    1869              :                 //  Furnace(FurnaceNum)%DXCoolCoilName = CoolingCoilName
    1870            0 :                 if (Util::SameString(CoolingCoilType, "COILSYSTEM:INTEGRATEDHEATPUMP:AIRSOURCE")) thisFurnace.bIsIHP = true;
    1871            0 :                 ValidateComponent(state, CoolingCoilType, CoolingCoilName, IsNotOK, CurrentModuleObject);
    1872              : 
    1873            0 :                 if (IsNotOK) {
    1874            0 :                     ShowContinueError(state, format("...specified in {}=\"{}\".", CurrentModuleObject, Alphas(1)));
    1875            0 :                     ErrorsFound = true;
    1876              :                 } else {
    1877            0 :                     errFlag = false;
    1878            0 :                     if (thisFurnace.bIsIHP) {
    1879            0 :                         thisFurnace.CoolingCoilIndex = IntegratedHeatPump::GetCoilIndexIHP(state, CoolingCoilType, CoolingCoilName, errFlag);
    1880            0 :                         IHPCoilName = state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).SCCoilName;
    1881              :                     } else {
    1882            0 :                         thisFurnace.CoolingCoilIndex =
    1883            0 :                             VariableSpeedCoils::GetCoilIndexVariableSpeed(state, CoolingCoilType, CoolingCoilName, errFlag);
    1884            0 :                         IHPCoilName = CoolingCoilName;
    1885              :                     }
    1886              : 
    1887            0 :                     if (errFlag) {
    1888            0 :                         ShowContinueError(state, format("...specified in {}=\"{}\".", CurrentModuleObject, Alphas(1)));
    1889            0 :                         ErrorsFound = true;
    1890              :                     }
    1891              : 
    1892            0 :                     if (thisFurnace.bIsIHP) {
    1893              :                         CoolingCoilInletNode =
    1894            0 :                             VariableSpeedCoils::GetCoilInletNodeVariableSpeed(state, "COIL:COOLING:DX:VARIABLESPEED", IHPCoilName, errFlag);
    1895              :                         CoolingCoilOutletNode =
    1896            0 :                             VariableSpeedCoils::GetCoilOutletNodeVariableSpeed(state, "COIL:COOLING:DX:VARIABLESPEED", IHPCoilName, errFlag);
    1897            0 :                         thisFurnace.CondenserNodeNum = VariableSpeedCoils::GetVSCoilCondenserInletNode(state, IHPCoilName, errFlag);
    1898              :                     } else {
    1899            0 :                         CoolingCoilInletNode = VariableSpeedCoils::GetCoilInletNodeVariableSpeed(state, CoolingCoilType, CoolingCoilName, errFlag);
    1900            0 :                         CoolingCoilOutletNode = VariableSpeedCoils::GetCoilOutletNodeVariableSpeed(state, CoolingCoilType, CoolingCoilName, errFlag);
    1901            0 :                         thisFurnace.CondenserNodeNum = VariableSpeedCoils::GetVSCoilCondenserInletNode(state, CoolingCoilName, errFlag);
    1902              :                     }
    1903              : 
    1904            0 :                     if (errFlag) {
    1905            0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1906            0 :                         ErrorsFound = true;
    1907              :                     }
    1908              :                 }
    1909              :             } else {
    1910            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1911            0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(12), Alphas(12)));
    1912            0 :                 ErrorsFound = true;
    1913              :             }
    1914              : 
    1915            0 :             if (Util::SameString(Alphas(14), "None") || Util::SameString(Alphas(14), "Multimode") || Util::SameString(Alphas(14), "CoolReheat")) {
    1916            0 :                 AirNodeFound = false;
    1917            0 :                 if (Util::SameString(Alphas(14), "Multimode")) {
    1918            0 :                     thisFurnace.DehumidControlType_Num = DehumidificationControlMode::Multimode;
    1919            0 :                     thisFurnace.Humidistat = true;
    1920            0 :                     if (thisFurnace.CoolingCoilType_Num != HVAC::CoilDX_CoolingHXAssisted) {
    1921            0 :                         ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1922            0 :                         ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(14), Alphas(14)));
    1923            0 :                         ShowContinueError(state, "Multimode control must be used with a Heat Exchanger Assisted Cooling Coil.");
    1924            0 :                         if (lAlphaBlanks(15)) {
    1925            0 :                             ShowContinueError(state,
    1926              :                                               "Dehumidification control type is assumed to be None since a reheat coil has not been specified and "
    1927              :                                               "the simulation continues.");
    1928            0 :                             thisFurnace.Humidistat = false;
    1929            0 :                             thisFurnace.DehumidControlType_Num = DehumidificationControlMode::None;
    1930              :                         } else {
    1931            0 :                             ShowContinueError(state, "Dehumidification control type is assumed to be CoolReheat and the simulation continues.");
    1932            0 :                             thisFurnace.DehumidControlType_Num = DehumidificationControlMode::CoolReheat;
    1933              :                         }
    1934              :                     }
    1935              :                 }
    1936            0 :                 if (Util::SameString(Alphas(14), "CoolReheat")) {
    1937            0 :                     thisFurnace.DehumidControlType_Num = DehumidificationControlMode::CoolReheat;
    1938            0 :                     thisFurnace.Humidistat = true;
    1939            0 :                     if (lAlphaBlanks(15)) {
    1940            0 :                         ShowWarningError(state, format("{} \"{}\"", CurrentModuleObject, Alphas(1)));
    1941            0 :                         ShowContinueError(state,
    1942              :                                           "Dehumidification control type is assumed to be None since a reheat coil has not been specified and the "
    1943              :                                           "simulation continues.");
    1944            0 :                         thisFurnace.Humidistat = false;
    1945            0 :                         thisFurnace.DehumidControlType_Num = DehumidificationControlMode::None;
    1946              :                     }
    1947              :                 }
    1948            0 :                 if (Util::SameString(Alphas(14), "None")) {
    1949            0 :                     thisFurnace.DehumidControlType_Num = DehumidificationControlMode::None;
    1950            0 :                     thisFurnace.Humidistat = false;
    1951              :                 }
    1952            0 :                 if (thisFurnace.Humidistat) {
    1953            0 :                     for (HStatZoneNum = 1; HStatZoneNum <= state.dataZoneCtrls->NumHumidityControlZones; ++HStatZoneNum) {
    1954            0 :                         if (state.dataZoneCtrls->HumidityControlZone(HStatZoneNum).ActualZoneNum != thisFurnace.ControlZoneNum) continue;
    1955            0 :                         AirNodeFound = true;
    1956              :                     }
    1957            0 :                     if (!AirNodeFound) {
    1958            0 :                         ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1959            0 :                         ShowContinueError(state, "Did not find Air Node (Zone with Humidistat).");
    1960            0 :                         ShowContinueError(state, format("Specified {} = {}", cAlphaFields(6), Alphas(6)));
    1961            0 :                         ErrorsFound = true;
    1962              :                     }
    1963              :                 }
    1964              :             } else { // invalid input
    1965            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    1966            0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(14), Alphas(14)));
    1967            0 :                 thisFurnace.Humidistat = false;
    1968            0 :                 ErrorsFound = true;
    1969              :             }
    1970              : 
    1971              :             //       Check placement of cooling coil with respect to fan placement and dehumidification control type
    1972            0 :             if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
    1973            0 :                 if (FanOutletNode == HeatingCoilInletNode && thisFurnace.DehumidControlType_Num != DehumidificationControlMode::CoolReheat) {
    1974            0 :                     thisFurnace.CoolingCoilUpstream = false;
    1975              :                 }
    1976              :             } else {
    1977            0 :                 if (HeatingCoilOutletNode == CoolingCoilInletNode && thisFurnace.DehumidControlType_Num != DehumidificationControlMode::CoolReheat) {
    1978            0 :                     thisFurnace.CoolingCoilUpstream = false;
    1979              :                 }
    1980              :             }
    1981              : 
    1982              :             // Get reheat coil data if humidistat is used
    1983            0 :             ReheatingCoilType = Alphas(15);
    1984            0 :             ReheatingCoilName = Alphas(16);
    1985            0 :             thisFurnace.SuppHeatCoilType = ReheatingCoilType;
    1986            0 :             thisFurnace.SuppHeatCoilName = ReheatingCoilName;
    1987            0 :             errFlag = false;
    1988            0 :             if (!lAlphaBlanks(15)) {
    1989            0 :                 if (Util::SameString(ReheatingCoilType, "Coil:Heating:Fuel") || Util::SameString(ReheatingCoilType, "Coil:Heating:Electric") ||
    1990            0 :                     Util::SameString(ReheatingCoilType, "Coil:Heating:Desuperheater")) {
    1991              : 
    1992            0 :                     thisFurnace.SuppHeatCoilType_Num = HeatingCoils::GetHeatingCoilTypeNum(state, ReheatingCoilType, ReheatingCoilName, errFlag);
    1993            0 :                     if (errFlag) {
    1994            0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1995            0 :                         ErrorsFound = true;
    1996              :                     } else {
    1997              : 
    1998            0 :                         ValidateComponent(state, ReheatingCoilType, ReheatingCoilName, IsNotOK, CurrentModuleObject);
    1999            0 :                         if (IsNotOK) {
    2000            0 :                             ShowContinueError(state, format("In {} \"{}\"", CurrentModuleObject, Alphas(1)));
    2001            0 :                             ErrorsFound = true;
    2002              : 
    2003              :                         } else { // mine data from reheat coil
    2004              : 
    2005              :                             // Get the heating coil index
    2006            0 :                             HeatingCoils::GetCoilIndex(state, ReheatingCoilName, thisFurnace.SuppHeatCoilIndex, IsNotOK);
    2007            0 :                             if (IsNotOK) {
    2008            0 :                                 ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2009            0 :                                 ErrorsFound = true;
    2010              :                             }
    2011              : 
    2012              :                             // Get the design supplemental heating capacity
    2013            0 :                             errFlag = false;
    2014            0 :                             thisFurnace.DesignSuppHeatingCapacity =
    2015            0 :                                 HeatingCoils::GetCoilCapacity(state, ReheatingCoilType, ReheatingCoilName, errFlag);
    2016            0 :                             if (errFlag) {
    2017            0 :                                 ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2018            0 :                                 ErrorsFound = true;
    2019              :                             }
    2020              : 
    2021              :                             // Get the Reheat Coil Inlet Node
    2022            0 :                             errFlag = false;
    2023            0 :                             ReheatCoilInletNode = HeatingCoils::GetCoilInletNode(state, ReheatingCoilType, ReheatingCoilName, errFlag);
    2024            0 :                             if (errFlag) {
    2025            0 :                                 ShowContinueError(state, format("...occurs in {} \"{}\"", CurrentModuleObject, Alphas(1)));
    2026            0 :                                 ErrorsFound = true;
    2027              :                             }
    2028              : 
    2029              :                             // Get the Reheat Coil Outlet Node
    2030            0 :                             errFlag = false;
    2031            0 :                             ReheatCoilOutletNode = HeatingCoils::GetCoilOutletNode(state, ReheatingCoilType, ReheatingCoilName, errFlag);
    2032            0 :                             if (errFlag) {
    2033            0 :                                 ShowContinueError(state, format("...occurs in {} \"{}\"", CurrentModuleObject, Alphas(1)));
    2034            0 :                                 ErrorsFound = true;
    2035              :                             }
    2036              : 
    2037              :                         } // IF (IsNotOK) THEN
    2038              :                     }
    2039              : 
    2040            0 :                 } else if (Util::SameString(ReheatingCoilType, "Coil:Heating:Water")) {
    2041            0 :                     thisFurnace.SuppHeatCoilType_Num = HVAC::Coil_HeatingWater;
    2042            0 :                     ValidateComponent(state, ReheatingCoilType, ReheatingCoilName, IsNotOK, CurrentModuleObject);
    2043            0 :                     if (IsNotOK) {
    2044            0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2045            0 :                         ErrorsFound = true;
    2046              :                     } else { // mine data from heating coil object
    2047              : 
    2048              :                         // Get the Heating Coil water Inlet or control Node number
    2049            0 :                         errFlag = false;
    2050            0 :                         thisFurnace.SuppCoilControlNode = WaterCoils::GetCoilWaterInletNode(state, "Coil:Heating:Water", ReheatingCoilName, errFlag);
    2051            0 :                         if (errFlag) {
    2052            0 :                             ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    2053            0 :                             ErrorsFound = true;
    2054              :                         }
    2055              : 
    2056              :                         // Get the ReHeat Coil hot water max volume flow rate
    2057            0 :                         errFlag = false;
    2058            0 :                         thisFurnace.MaxSuppCoilFluidFlow =
    2059            0 :                             WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", ReheatingCoilName, errFlag);
    2060            0 :                         if (errFlag) {
    2061            0 :                             ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    2062            0 :                             ErrorsFound = true;
    2063              :                         }
    2064              : 
    2065              :                         // Get the ReHeat Coil Inlet Node
    2066            0 :                         errFlag = false;
    2067            0 :                         ReheatCoilInletNode = WaterCoils::GetCoilInletNode(state, "Coil:Heating:Water", ReheatingCoilName, errFlag);
    2068            0 :                         thisFurnace.SuppCoilAirInletNode = ReheatCoilInletNode;
    2069            0 :                         if (errFlag) {
    2070            0 :                             ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    2071            0 :                             ErrorsFound = true;
    2072              :                         }
    2073              : 
    2074              :                         // Get the ReHeat Coil Outlet Node
    2075            0 :                         errFlag = false;
    2076            0 :                         ReheatCoilOutletNode = WaterCoils::GetCoilOutletNode(state, "Coil:Heating:Water", ReheatingCoilName, errFlag);
    2077            0 :                         thisFurnace.SuppCoilAirOutletNode = ReheatCoilOutletNode;
    2078            0 :                         if (errFlag) {
    2079            0 :                             ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    2080            0 :                             ErrorsFound = true;
    2081              :                         }
    2082              : 
    2083              :                         // check if user has also used a water coil controller, which they should not do
    2084            0 :                         errFlag = false;
    2085            0 :                         HVACControllers::CheckCoilWaterInletNode(state, thisFurnace.CoilControlNode, errFlag);
    2086            0 :                         if (!errFlag) { // then did find a controller so that is bad
    2087            0 :                             ShowSevereError(state,
    2088            0 :                                             format("{} = {} has a conflicting Controller:WaterCoil object", CurrentModuleObject, thisFurnace.Name));
    2089            0 :                             ShowContinueError(state, "Hot water coils are controlled directly by unitary and furnace systems.");
    2090            0 :                             ShowContinueError(state, "No water coil controller should be input for the coil.");
    2091            0 :                             ErrorsFound = true;
    2092              :                         }
    2093              :                     }
    2094              : 
    2095            0 :                 } else if (Util::SameString(ReheatingCoilType, "Coil:Heating:Steam")) {
    2096            0 :                     thisFurnace.SuppHeatCoilType_Num = HVAC::Coil_HeatingSteam;
    2097            0 :                     ValidateComponent(state, ReheatingCoilType, ReheatingCoilName, IsNotOK, CurrentModuleObject);
    2098            0 :                     if (IsNotOK) {
    2099            0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2100            0 :                         ErrorsFound = true;
    2101              :                     } else { // mine data from heating coil object
    2102              : 
    2103            0 :                         errFlag = false;
    2104            0 :                         thisFurnace.SuppHeatCoilIndex = SteamCoils::GetSteamCoilIndex(state, "COIL:HEATING:STEAM", ReheatingCoilName, errFlag);
    2105            0 :                         if (thisFurnace.SuppHeatCoilIndex == 0) {
    2106            0 :                             ShowSevereError(state, format("{} illegal {} = {}", CurrentModuleObject, cAlphaFields(11), ReheatingCoilName));
    2107            0 :                             ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    2108            0 :                             ErrorsFound = true;
    2109              :                         }
    2110              : 
    2111              :                         // Get the Heating Coil steam inlet node number
    2112            0 :                         errFlag = false;
    2113            0 :                         thisFurnace.SuppCoilControlNode = SteamCoils::GetCoilSteamInletNode(state, "Coil:Heating:Steam", ReheatingCoilName, errFlag);
    2114            0 :                         if (errFlag) {
    2115            0 :                             ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    2116            0 :                             ErrorsFound = true;
    2117              :                         }
    2118              : 
    2119              :                         // Get the Heating Coil steam max volume flow rate
    2120            0 :                         thisFurnace.MaxSuppCoilFluidFlow = SteamCoils::GetCoilMaxSteamFlowRate(state, thisFurnace.SuppHeatCoilIndex, errFlag);
    2121            0 :                         if (thisFurnace.MaxSuppCoilFluidFlow > 0.0) {
    2122              :                             SteamDensity =
    2123            0 :                                 Fluid::GetSteam(state)->getSatDensity(state, state.dataFurnaces->TempSteamIn, 1.0, getAirLoopHVACHeatCoolInput);
    2124            0 :                             thisFurnace.MaxSuppCoilFluidFlow =
    2125            0 :                                 SteamCoils::GetCoilMaxSteamFlowRate(state, thisFurnace.SuppHeatCoilIndex, errFlag) * SteamDensity;
    2126              :                         }
    2127              : 
    2128              :                         // Get the Heating Coil Inlet Node
    2129            0 :                         errFlag = false;
    2130            0 :                         ReheatCoilInletNode = SteamCoils::GetCoilAirInletNode(state, thisFurnace.SuppHeatCoilIndex, ReheatingCoilName, errFlag);
    2131            0 :                         thisFurnace.SuppCoilAirInletNode = ReheatCoilInletNode;
    2132            0 :                         if (errFlag) {
    2133            0 :                             ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    2134            0 :                             ErrorsFound = true;
    2135              :                         }
    2136              : 
    2137              :                         // Get the Heating Coil Outlet Node
    2138            0 :                         errFlag = false;
    2139            0 :                         ReheatCoilOutletNode = SteamCoils::GetCoilAirOutletNode(state, thisFurnace.SuppHeatCoilIndex, ReheatingCoilName, errFlag);
    2140            0 :                         thisFurnace.SuppCoilAirOutletNode = ReheatCoilOutletNode;
    2141            0 :                         if (errFlag) {
    2142            0 :                             ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    2143            0 :                             ErrorsFound = true;
    2144              :                         }
    2145              :                     }
    2146              : 
    2147              :                 } else { // Illegal heating coil
    2148            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    2149            0 :                     ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(15), Alphas(15)));
    2150            0 :                     ErrorsFound = true;
    2151              :                 } // IF (Furnace(FurnaceNum)%SuppHeatCoilType_Num == Coil_HeatingGasOrOtherFuel .OR. &, etc.
    2152              : 
    2153              :             } // IF(.NOT. lAlphaBlanks(15))THEN
    2154              : 
    2155            0 :             if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
    2156              : 
    2157            0 :                 if (FanInletNode != thisFurnace.FurnaceInletNodeNum) {
    2158            0 :                     ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2159            0 :                     if (thisFurnace.type == HVAC::UnitarySysType::Furnace_HeatCool) {
    2160            0 :                         ShowContinueError(
    2161              :                             state, "When a blow through fan is specified, the fan inlet node name must be the same as the furnace inlet node name.");
    2162            0 :                         ShowContinueError(state, format("...Fan inlet node name     = {}", state.dataLoopNodes->NodeID(FanInletNode)));
    2163            0 :                         ShowContinueError(state,
    2164            0 :                                           format("...Furnace inlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceInletNodeNum)));
    2165              :                     } else {
    2166            0 :                         ShowContinueError(
    2167              :                             state,
    2168              :                             "When a blow through fan is specified, the fan inlet node name must be the same as the unitary system inlet node name.");
    2169            0 :                         ShowContinueError(state, format("...Fan inlet node name           = {}", state.dataLoopNodes->NodeID(FanInletNode)));
    2170            0 :                         ShowContinueError(
    2171            0 :                             state, format("...UnitarySystem inlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceInletNodeNum)));
    2172              :                     }
    2173            0 :                     ErrorsFound = true;
    2174              :                 }
    2175            0 :                 if (thisFurnace.CoolingCoilUpstream) {
    2176            0 :                     if (FanOutletNode != CoolingCoilInletNode) {
    2177            0 :                         ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2178            0 :                         ShowContinueError(
    2179              :                             state,
    2180              :                             "When a blow through fan is specified, the fan outlet node name must be the same as the cooling coil inlet node name.");
    2181            0 :                         ShowContinueError(state, format("...Fan outlet node name         = {}", state.dataLoopNodes->NodeID(FanOutletNode)));
    2182            0 :                         ShowContinueError(state, format("...Cooling coil inlet node name = {}", state.dataLoopNodes->NodeID(CoolingCoilInletNode)));
    2183            0 :                         ErrorsFound = true;
    2184              :                     }
    2185            0 :                     if (CoolingCoilOutletNode != HeatingCoilInletNode) {
    2186            0 :                         ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2187            0 :                         ShowContinueError(state, "The cooling coil outlet node name must be the same as the heating coil inlet node name.");
    2188            0 :                         ShowContinueError(state, format("...Cooling coil outlet node name = {}", state.dataLoopNodes->NodeID(CoolingCoilOutletNode)));
    2189            0 :                         ShowContinueError(state, format("...Heating coil inlet node name  = {}", state.dataLoopNodes->NodeID(HeatingCoilInletNode)));
    2190            0 :                         ErrorsFound = true;
    2191              :                     }
    2192            0 :                     if ((thisFurnace.Humidistat && thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat) ||
    2193              :                         ReheatCoilInletNode > 0) {
    2194            0 :                         if (HeatingCoilOutletNode != ReheatCoilInletNode) {
    2195            0 :                             ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2196            0 :                             ShowContinueError(state,
    2197              :                                               "When a blow through fan is specified, the heating coil outlet node name must be the same as the "
    2198              :                                               "reheat coil inlet node name.");
    2199            0 :                             ShowContinueError(state,
    2200            0 :                                               format("...Heating coil outlet node name = {}", state.dataLoopNodes->NodeID(HeatingCoilOutletNode)));
    2201            0 :                             ShowContinueError(state,
    2202            0 :                                               format("...Reheat coil inlet node name   = {}", state.dataLoopNodes->NodeID(ReheatCoilInletNode)));
    2203            0 :                             ErrorsFound = true;
    2204              :                         }
    2205            0 :                         if (ReheatCoilOutletNode != thisFurnace.FurnaceOutletNodeNum) {
    2206            0 :                             ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2207            0 :                             if (thisFurnace.type == HVAC::UnitarySysType::Furnace_HeatCool) {
    2208            0 :                                 ShowContinueError(state, "The reheat coil outlet node name must be the same as the furnace outlet node name.");
    2209            0 :                                 ShowContinueError(state,
    2210            0 :                                                   format("...Reheat coil outlet node name = {}", state.dataLoopNodes->NodeID(ReheatCoilOutletNode)));
    2211            0 :                                 ShowContinueError(
    2212              :                                     state,
    2213            0 :                                     format("...Furnace outlet node name     = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    2214              :                             } else {
    2215            0 :                                 ShowContinueError(state, "The reheat coil outlet node name must be the same as the unitary system outlet node name.");
    2216            0 :                                 ShowContinueError(
    2217            0 :                                     state, format("...Reheat coil outlet node name   = {}", state.dataLoopNodes->NodeID(ReheatCoilOutletNode)));
    2218            0 :                                 ShowContinueError(
    2219              :                                     state,
    2220            0 :                                     format("...UnitarySystem outlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    2221              :                             }
    2222            0 :                             ErrorsFound = true;
    2223              :                         }
    2224              :                     } else { // IF((Furnace(FurnaceNum)%Humidistat ...
    2225              :                         // Heating coil outlet node name must be the same as the furnace outlet node name
    2226            0 :                         if (HeatingCoilOutletNode != thisFurnace.FurnaceOutletNodeNum) {
    2227            0 :                             ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    2228            0 :                             if (thisFurnace.type == HVAC::UnitarySysType::Furnace_HeatOnly) {
    2229            0 :                                 ShowContinueError(state,
    2230              :                                                   "When a blow through fan is specified, the heating coil outlet node name must be the same as the "
    2231              :                                                   "furnace outlet node name.");
    2232            0 :                                 ShowContinueError(
    2233            0 :                                     state, format("...Heating coil outlet node name = {}", state.dataLoopNodes->NodeID(HeatingCoilOutletNode)));
    2234            0 :                                 ShowContinueError(
    2235              :                                     state,
    2236            0 :                                     format("...Furnace outlet node name      = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    2237              :                             } else {
    2238            0 :                                 ShowContinueError(state,
    2239              :                                                   "When a blow through fan is specified, the heating coil outlet node name must be the same as the "
    2240              :                                                   "unitary system outlet node name.");
    2241            0 :                                 ShowContinueError(
    2242            0 :                                     state, format("...Heating coil outlet node name  = {}", state.dataLoopNodes->NodeID(HeatingCoilOutletNode)));
    2243            0 :                                 ShowContinueError(
    2244              :                                     state,
    2245            0 :                                     format("...UnitarySystem outlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    2246              :                             }
    2247            0 :                             ErrorsFound = true;
    2248              :                         }
    2249              :                     }
    2250              :                 } else { // IF(Furnace(FurnaceNum)%CoolingCoilUpstream)THEN
    2251            0 :                     if (FanOutletNode != HeatingCoilInletNode) {
    2252            0 :                         ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2253            0 :                         ShowContinueError(
    2254              :                             state,
    2255              :                             "When a blow through fan is specified, the fan outlet node name must be the same as the heating coil inlet node name.");
    2256            0 :                         ShowContinueError(state, format("...Fan outlet node name         = {}", state.dataLoopNodes->NodeID(FanOutletNode)));
    2257            0 :                         ShowContinueError(state, format("...Heating coil inlet node name = {}", state.dataLoopNodes->NodeID(HeatingCoilInletNode)));
    2258            0 :                         ErrorsFound = true;
    2259              :                     }
    2260            0 :                     if (HeatingCoilOutletNode != CoolingCoilInletNode) {
    2261            0 :                         ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2262            0 :                         ShowContinueError(state, "The heating coil outlet node name must be the same as the cooling coil inlet node name.");
    2263            0 :                         ShowContinueError(state, format("...Heating coil outlet node name = {}", state.dataLoopNodes->NodeID(HeatingCoilOutletNode)));
    2264            0 :                         ShowContinueError(state, format("...Cooling coil inlet node name  = {}", state.dataLoopNodes->NodeID(CoolingCoilInletNode)));
    2265            0 :                         ErrorsFound = true;
    2266              :                     }
    2267            0 :                     if (CoolingCoilOutletNode != thisFurnace.FurnaceOutletNodeNum) {
    2268            0 :                         ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2269            0 :                         if (thisFurnace.type == HVAC::UnitarySysType::Furnace_HeatCool) {
    2270            0 :                             ShowContinueError(state,
    2271              :                                               "When a blow through fan is specified, the cooling coil outlet node name must be the same as the "
    2272              :                                               "furnace outlet node name.");
    2273            0 :                             ShowContinueError(state,
    2274            0 :                                               format("...Cooling coil outlet node name = {}", state.dataLoopNodes->NodeID(CoolingCoilOutletNode)));
    2275            0 :                             ShowContinueError(
    2276              :                                 state,
    2277            0 :                                 format("...Furnace outlet node name      = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    2278              :                         } else {
    2279            0 :                             ShowContinueError(state,
    2280              :                                               "When a blow through fan is specified, the cooling coil outlet node name must be the same as the "
    2281              :                                               "unitary system outlet node name.");
    2282            0 :                             ShowContinueError(state,
    2283            0 :                                               format("...Cooling coil outlet node name   = {}", state.dataLoopNodes->NodeID(CoolingCoilOutletNode)));
    2284            0 :                             ShowContinueError(
    2285              :                                 state,
    2286            0 :                                 format("...UnitarySystem outlet node name  = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    2287              :                         }
    2288            0 :                         ErrorsFound = true;
    2289              :                     }
    2290              :                 }
    2291              : 
    2292              :             } else { // ELSE from IF(Furnace(FurnaceNum)%FanPlace .EQ. BlowThru)THEN
    2293              : 
    2294            0 :                 if (thisFurnace.CoolingCoilUpstream) {
    2295            0 :                     if (CoolingCoilInletNode != thisFurnace.FurnaceInletNodeNum) {
    2296            0 :                         ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2297            0 :                         if (thisFurnace.type == HVAC::UnitarySysType::Furnace_HeatCool) {
    2298            0 :                             ShowContinueError(state,
    2299              :                                               "When a draw through fan is specified, the cooling coil inlet node name must be the same as the "
    2300              :                                               "furnace inlet node name.");
    2301            0 :                             ShowContinueError(state,
    2302            0 :                                               format("...Cooling coil inlet node name = {}", state.dataLoopNodes->NodeID(CoolingCoilInletNode)));
    2303            0 :                             ShowContinueError(
    2304            0 :                                 state, format("...Furnace inlet node name      = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceInletNodeNum)));
    2305              :                         } else {
    2306            0 :                             ShowContinueError(state,
    2307              :                                               "When a draw through fan is specified, the cooling coil inlet node name must be the same as the "
    2308              :                                               "unitary system inlet node name.");
    2309            0 :                             ShowContinueError(state,
    2310            0 :                                               format("...Cooling coil inlet node name  = {}", state.dataLoopNodes->NodeID(CoolingCoilInletNode)));
    2311            0 :                             ShowContinueError(
    2312            0 :                                 state, format("...UnitarySystem inlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceInletNodeNum)));
    2313              :                         }
    2314            0 :                         ErrorsFound = true;
    2315              :                     }
    2316            0 :                     if (CoolingCoilOutletNode != HeatingCoilInletNode) {
    2317            0 :                         ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2318            0 :                         ShowContinueError(state, "The cooling coil outlet node name must be the same as the heating coil inlet node name.");
    2319            0 :                         ShowContinueError(state, format("...Cooling coil outlet node name = {}", state.dataLoopNodes->NodeID(CoolingCoilOutletNode)));
    2320            0 :                         ShowContinueError(state, format("...Heating coil inlet node name  = {}", state.dataLoopNodes->NodeID(HeatingCoilInletNode)));
    2321            0 :                         ErrorsFound = true;
    2322              :                     }
    2323            0 :                     if (HeatingCoilOutletNode != FanInletNode) {
    2324            0 :                         ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2325            0 :                         ShowContinueError(
    2326              :                             state,
    2327              :                             "When a draw through fan is specified, the heating coil outlet node name must be the same as the fan inlet node name.");
    2328            0 :                         ShowContinueError(state, format("...Heating coil outlet node name = {}", state.dataLoopNodes->NodeID(HeatingCoilOutletNode)));
    2329            0 :                         ShowContinueError(state, format("...Fan inlet node name           = {}", state.dataLoopNodes->NodeID(FanInletNode)));
    2330            0 :                         ErrorsFound = true;
    2331              :                     }
    2332            0 :                     if ((thisFurnace.Humidistat && thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat) ||
    2333              :                         ReheatCoilInletNode > 0) {
    2334            0 :                         if (FanOutletNode != ReheatCoilInletNode) {
    2335            0 :                             ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2336            0 :                             ShowContinueError(state,
    2337              :                                               "When a draw through fan is specified, the fan outlet node name must be the same as the reheat coil "
    2338              :                                               "inlet node name.");
    2339            0 :                             ShowContinueError(state, format("...Fan outlet node name        = {}", state.dataLoopNodes->NodeID(FanOutletNode)));
    2340            0 :                             ShowContinueError(state, format("...Reheat coil inlet node name = {}", state.dataLoopNodes->NodeID(ReheatCoilInletNode)));
    2341            0 :                             ErrorsFound = true;
    2342              :                         }
    2343            0 :                         if (ReheatCoilOutletNode != thisFurnace.FurnaceOutletNodeNum) {
    2344            0 :                             ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2345            0 :                             if (thisFurnace.type == HVAC::UnitarySysType::Furnace_HeatCool) {
    2346            0 :                                 ShowContinueError(state, "The reheat coil outlet node name must be the same as the furnace outlet node name.");
    2347            0 :                                 ShowContinueError(state,
    2348            0 :                                                   format("...Reheat coil outlet node name = {}", state.dataLoopNodes->NodeID(ReheatCoilOutletNode)));
    2349            0 :                                 ShowContinueError(
    2350              :                                     state,
    2351            0 :                                     format("...Furnace outlet node name     = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    2352              :                             } else {
    2353            0 :                                 ShowContinueError(state, "The reheat coil outlet node name must be the same as the unitary system outlet node name.");
    2354            0 :                                 ShowContinueError(
    2355            0 :                                     state, format("...Reheat coil outlet node name   = {}", state.dataLoopNodes->NodeID(ReheatCoilOutletNode)));
    2356            0 :                                 ShowContinueError(
    2357              :                                     state,
    2358            0 :                                     format("...UnitarySystem outlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    2359              :                             }
    2360            0 :                             ErrorsFound = true;
    2361              :                         }
    2362              :                     } else {
    2363            0 :                         if (FanOutletNode != thisFurnace.FurnaceOutletNodeNum) {
    2364            0 :                             ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2365            0 :                             ShowContinueError(state,
    2366              :                                               "When a draw through fan is specified, the fan outlet node name must be the same as the unitary system "
    2367              :                                               "outlet node name.");
    2368            0 :                             ShowContinueError(state, format("...Fan outlet node name        = {}", state.dataLoopNodes->NodeID(FanOutletNode)));
    2369            0 :                             ShowContinueError(
    2370              :                                 state,
    2371            0 :                                 format("...Unitary system outlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    2372            0 :                             ErrorsFound = true;
    2373              :                         }
    2374              :                     }
    2375              :                 } else { // IF(Furnace(FurnaceNum)%CoolingCoilUpstream)THEN
    2376            0 :                     if (HeatingCoilInletNode != thisFurnace.FurnaceInletNodeNum) {
    2377            0 :                         ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2378            0 :                         if (thisFurnace.type == HVAC::UnitarySysType::Furnace_HeatCool) {
    2379            0 :                             ShowContinueError(state,
    2380              :                                               "When a draw through fan is specified, the heating coil inlet node name must be the same as the "
    2381              :                                               "furnace inlet node name.");
    2382            0 :                             ShowContinueError(state,
    2383            0 :                                               format("...Heating coil inlet node name = {}", state.dataLoopNodes->NodeID(HeatingCoilInletNode)));
    2384            0 :                             ShowContinueError(
    2385            0 :                                 state, format("...Furnace inlet node name      = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceInletNodeNum)));
    2386              :                         } else {
    2387            0 :                             ShowContinueError(state,
    2388              :                                               "When a draw through fan is specified, the heating coil inlet node name must be the same as the "
    2389              :                                               "unitary system inlet node name.");
    2390            0 :                             ShowContinueError(state,
    2391            0 :                                               format("...Heating coil inlet node name  = {}", state.dataLoopNodes->NodeID(HeatingCoilInletNode)));
    2392            0 :                             ShowContinueError(
    2393            0 :                                 state, format("...UnitarySystem inlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceInletNodeNum)));
    2394              :                         }
    2395            0 :                         ErrorsFound = true;
    2396              :                     }
    2397            0 :                     if (HeatingCoilOutletNode != CoolingCoilInletNode) {
    2398            0 :                         ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2399            0 :                         ShowContinueError(state, "The heating coil outlet node name must be the same as the cooling coil inlet node name.");
    2400            0 :                         ShowContinueError(state, format("...Heating coil outlet node name = {}", state.dataLoopNodes->NodeID(HeatingCoilOutletNode)));
    2401            0 :                         ShowContinueError(state, format("...Cooling coil inlet node name  = {}", state.dataLoopNodes->NodeID(CoolingCoilInletNode)));
    2402            0 :                         ErrorsFound = true;
    2403              :                     }
    2404            0 :                     if (CoolingCoilOutletNode != FanInletNode) {
    2405            0 :                         ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2406            0 :                         ShowContinueError(
    2407              :                             state,
    2408              :                             "When a draw through fan is specified, the cooling coil outlet node name must be the same as the fan inlet node name.");
    2409            0 :                         ShowContinueError(state, format("...Cooling coil outlet node name = {}", state.dataLoopNodes->NodeID(CoolingCoilOutletNode)));
    2410            0 :                         ShowContinueError(state, format("...Fan inlet node name           = {}", state.dataLoopNodes->NodeID(FanInletNode)));
    2411            0 :                         ErrorsFound = true;
    2412              :                     }
    2413            0 :                     if (FanOutletNode != thisFurnace.FurnaceOutletNodeNum) {
    2414            0 :                         ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    2415            0 :                         if (thisFurnace.type == HVAC::UnitarySysType::Furnace_HeatCool) {
    2416            0 :                             ShowContinueError(
    2417              :                                 state,
    2418              :                                 "When a draw through fan is specified, the fan outlet node name must be the same as the furnace outlet node name.");
    2419            0 :                             ShowContinueError(state, format("...Fan outlet node name     = {}", state.dataLoopNodes->NodeID(FanOutletNode)));
    2420            0 :                             ShowContinueError(
    2421            0 :                                 state, format("...Furnace outlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    2422              :                         } else {
    2423            0 :                             ShowContinueError(state,
    2424              :                                               "When a draw through fan is specified, the fan outlet node name must be the same as the unitary system "
    2425              :                                               "outlet node name.");
    2426            0 :                             ShowContinueError(state, format("...Fan outlet node name           = {}", state.dataLoopNodes->NodeID(FanOutletNode)));
    2427            0 :                             ShowContinueError(
    2428              :                                 state,
    2429            0 :                                 format("...UnitarySystem outlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    2430              :                         }
    2431            0 :                         ErrorsFound = true;
    2432              :                     }
    2433              :                 }
    2434              :             } // ELSE from IF(Furnace(FurnaceNum)%FanPlace .EQ. BlowThru)THEN
    2435              : 
    2436              :             // Add fan to component sets array
    2437            0 :             BranchNodeConnections::SetUpCompSets(state,
    2438              :                                                  CurrentModuleObject,
    2439            0 :                                                  Alphas(1),
    2440            0 :                                                  Alphas(7),
    2441            0 :                                                  Alphas(8),
    2442            0 :                                                  state.dataLoopNodes->NodeID(FanInletNode),
    2443            0 :                                                  state.dataLoopNodes->NodeID(FanOutletNode));
    2444              : 
    2445              :             // Add DX cooling coil to component sets array
    2446            0 :             if (thisFurnace.bIsIHP) {
    2447            0 :                 BranchNodeConnections::SetUpCompSets(state,
    2448              :                                                      CurrentModuleObject,
    2449            0 :                                                      Alphas(1),
    2450            0 :                                                      Alphas(12),
    2451            0 :                                                      Alphas(13) + " Cooling Coil",
    2452            0 :                                                      state.dataLoopNodes->NodeID(CoolingCoilInletNode),
    2453            0 :                                                      state.dataLoopNodes->NodeID(CoolingCoilOutletNode));
    2454              :             } else {
    2455            0 :                 BranchNodeConnections::SetUpCompSets(state,
    2456              :                                                      CurrentModuleObject,
    2457            0 :                                                      Alphas(1),
    2458            0 :                                                      Alphas(12),
    2459            0 :                                                      Alphas(13),
    2460            0 :                                                      state.dataLoopNodes->NodeID(CoolingCoilInletNode),
    2461            0 :                                                      state.dataLoopNodes->NodeID(CoolingCoilOutletNode));
    2462              :             }
    2463              : 
    2464              :             // Add heating coil to component sets array
    2465            0 :             if (thisFurnace.bIsIHP) {
    2466            0 :                 BranchNodeConnections::SetUpCompSets(state,
    2467              :                                                      CurrentModuleObject,
    2468            0 :                                                      Alphas(1),
    2469            0 :                                                      Alphas(10),
    2470            0 :                                                      Alphas(11) + " Heating Coil",
    2471            0 :                                                      state.dataLoopNodes->NodeID(HeatingCoilInletNode),
    2472            0 :                                                      state.dataLoopNodes->NodeID(HeatingCoilOutletNode));
    2473              :             } else {
    2474            0 :                 BranchNodeConnections::SetUpCompSets(state,
    2475              :                                                      CurrentModuleObject,
    2476            0 :                                                      Alphas(1),
    2477            0 :                                                      Alphas(10),
    2478            0 :                                                      Alphas(11),
    2479            0 :                                                      state.dataLoopNodes->NodeID(HeatingCoilInletNode),
    2480            0 :                                                      state.dataLoopNodes->NodeID(HeatingCoilOutletNode));
    2481              :             }
    2482              : 
    2483            0 :             if (ReheatCoilInletNode > 0) {
    2484              : 
    2485              :                 // Add reheating coil to component sets array
    2486            0 :                 BranchNodeConnections::SetUpCompSets(state,
    2487              :                                                      CurrentModuleObject,
    2488            0 :                                                      Alphas(1),
    2489            0 :                                                      Alphas(15),
    2490            0 :                                                      Alphas(16),
    2491            0 :                                                      state.dataLoopNodes->NodeID(ReheatCoilInletNode),
    2492            0 :                                                      state.dataLoopNodes->NodeID(ReheatCoilOutletNode));
    2493              :             }
    2494              : 
    2495              :             // Set the furnace max outlet temperature
    2496            0 :             thisFurnace.DesignMaxOutletTemp = Numbers(1);
    2497              : 
    2498            0 :             thisFurnace.MaxCoolAirVolFlow = Numbers(2);
    2499            0 :             if (thisFurnace.MaxCoolAirVolFlow <= 0 && thisFurnace.MaxCoolAirVolFlow != DataSizing::AutoSize) {
    2500            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    2501            0 :                 ShowContinueError(state, format("Illegal {} = {:.7T}", cNumericFields(2), Numbers(2)));
    2502            0 :                 ErrorsFound = true;
    2503              :             }
    2504              : 
    2505            0 :             thisFurnace.MaxHeatAirVolFlow = Numbers(3);
    2506            0 :             if (thisFurnace.MaxHeatAirVolFlow <= 0 && thisFurnace.MaxHeatAirVolFlow != DataSizing::AutoSize) {
    2507            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    2508            0 :                 ShowContinueError(state, format("Illegal {} = {:.7T}", cNumericFields(3), Numbers(3)));
    2509            0 :                 ErrorsFound = true;
    2510              :             }
    2511              : 
    2512            0 :             thisFurnace.MaxNoCoolHeatAirVolFlow = Numbers(4);
    2513            0 :             if (thisFurnace.MaxNoCoolHeatAirVolFlow < 0 && thisFurnace.MaxNoCoolHeatAirVolFlow != DataSizing::AutoSize) {
    2514            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    2515            0 :                 ShowContinueError(state, format("Illegal {} = {:.7T}", cNumericFields(4), Numbers(4)));
    2516            0 :                 ErrorsFound = true;
    2517              :             }
    2518              : 
    2519            0 :             if (Numbers(2) != DataSizing::AutoSize && Numbers(3) != DataSizing::AutoSize && Numbers(4) != DataSizing::AutoSize) {
    2520            0 :                 thisFurnace.DesignFanVolFlowRate = max(Numbers(2), Numbers(3), Numbers(4));
    2521              :             } else {
    2522            0 :                 thisFurnace.DesignFanVolFlowRate = DataSizing::AutoSize;
    2523              :             }
    2524              : 
    2525            0 :             if (thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingAirToAirVariableSpeed) {
    2526            0 :                 errFlag = false;
    2527            0 :                 if (thisFurnace.bIsIHP) {
    2528            0 :                     thisFurnace.CoolingCoilIndex = IntegratedHeatPump::GetCoilIndexIHP(state, CoolingCoilType, CoolingCoilName, errFlag);
    2529            0 :                     IHPCoilName = state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).SCCoilName;
    2530            0 :                     thisFurnace.MaxCoolAirVolFlow =
    2531            0 :                         VariableSpeedCoils::GetCoilAirFlowRateVariableSpeed(state, "COIL:COOLING:DX:VARIABLESPEED", IHPCoilName, errFlag);
    2532              :                 } else {
    2533            0 :                     thisFurnace.MaxCoolAirVolFlow =
    2534            0 :                         VariableSpeedCoils::GetCoilAirFlowRateVariableSpeed(state, CoolingCoilType, CoolingCoilName, errFlag);
    2535              :                 }
    2536              : 
    2537            0 :                 if (errFlag) {
    2538            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2539            0 :                     ErrorsFound = true;
    2540              :                 }
    2541              : 
    2542            0 :                 thisFurnace.MaxNoCoolHeatAirVolFlow = min(thisFurnace.MaxHeatAirVolFlow, thisFurnace.MaxCoolAirVolFlow);
    2543            0 :                 if (thisFurnace.MaxHeatAirVolFlow != DataSizing::AutoSize && thisFurnace.MaxCoolAirVolFlow != DataSizing::AutoSize) {
    2544            0 :                     thisFurnace.DesignFanVolFlowRate = max(thisFurnace.MaxHeatAirVolFlow, thisFurnace.MaxCoolAirVolFlow);
    2545              :                 } else {
    2546            0 :                     thisFurnace.DesignFanVolFlowRate = DataSizing::AutoSize;
    2547              :                 }
    2548              :             }
    2549              : 
    2550            0 :             if (thisFurnace.ActualFanVolFlowRate != DataSizing::AutoSize) {
    2551            0 :                 if (thisFurnace.ActualFanVolFlowRate < thisFurnace.MaxCoolAirVolFlow && thisFurnace.MaxCoolAirVolFlow != DataSizing::AutoSize) {
    2552            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    2553            0 :                     ShowContinueError(
    2554              :                         state,
    2555            0 :                         format("... air flow rate = {:.7T} in fan object {} is less than the maximum HVAC system air flow rate in cooling mode.",
    2556            0 :                                thisFurnace.ActualFanVolFlowRate,
    2557              :                                FanName));
    2558            0 :                     ShowContinueError(state, format(" The {} is reset to the fan flow rate and the simulation continues.", cNumericFields(2)));
    2559            0 :                     thisFurnace.MaxCoolAirVolFlow = thisFurnace.ActualFanVolFlowRate;
    2560            0 :                     thisFurnace.DesignFanVolFlowRate = thisFurnace.ActualFanVolFlowRate;
    2561              :                 }
    2562            0 :                 if (thisFurnace.ActualFanVolFlowRate < thisFurnace.MaxHeatAirVolFlow && thisFurnace.MaxHeatAirVolFlow != 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 heating 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(3)));
    2570            0 :                     thisFurnace.MaxHeatAirVolFlow = thisFurnace.ActualFanVolFlowRate;
    2571            0 :                     thisFurnace.DesignFanVolFlowRate = thisFurnace.ActualFanVolFlowRate;
    2572              :                 }
    2573              :             }
    2574              : 
    2575            0 :             if (thisFurnace.fanOpModeSched != nullptr) {
    2576              :                 // Is this correct? 0.0 for max also?
    2577            0 :                 if (!thisFurnace.fanOpModeSched->checkMinMaxVals(state, Clusive::In, 0.0, Clusive::In, 0.0)) {
    2578              :                     //           set air flow control mode:
    2579              :                     //             UseCompressorOnFlow = operate at last cooling or heating air flow requested when compressor is off
    2580              :                     //             UseCompressorOffFlow = operate at value specified by user
    2581              :                     //           AirFlowControl only valid if fan opmode = ContFanCycComp
    2582            0 :                     if (thisFurnace.MaxNoCoolHeatAirVolFlow == 0.0) {
    2583            0 :                         thisFurnace.AirFlowControl = AirFlowControlConstFan::UseCompressorOnFlow;
    2584              :                     } else {
    2585            0 :                         thisFurnace.AirFlowControl = AirFlowControlConstFan::UseCompressorOffFlow;
    2586              :                     }
    2587              :                 }
    2588              :             }
    2589              : 
    2590            0 :             if (thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingAirToAirVariableSpeed) {
    2591            0 :                 errFlag = false;
    2592            0 :                 if (thisFurnace.bIsIHP) {
    2593            0 :                     thisFurnace.CoolingCoilIndex = IntegratedHeatPump::GetCoilIndexIHP(state, CoolingCoilType, CoolingCoilName, errFlag);
    2594            0 :                     IHPCoilName = state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).SCCoilName;
    2595            0 :                     thisFurnace.DesignCoolingCapacity =
    2596            0 :                         VariableSpeedCoils::GetCoilCapacityVariableSpeed(state, "COIL:COOLING:DX:VARIABLESPEED", IHPCoilName, errFlag);
    2597              :                 } else {
    2598            0 :                     thisFurnace.DesignCoolingCapacity =
    2599            0 :                         VariableSpeedCoils::GetCoilCapacityVariableSpeed(state, CoolingCoilType, CoolingCoilName, errFlag);
    2600              :                 }
    2601              : 
    2602            0 :                 if (errFlag) {
    2603            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2604            0 :                     ErrorsFound = true;
    2605              :                 }
    2606              :             }
    2607              : 
    2608              :             // Set heating convergence tolerance
    2609            0 :             thisFurnace.HeatingConvergenceTolerance = 0.001;
    2610              : 
    2611              :             // Set cooling convergence tolerance
    2612            0 :             thisFurnace.CoolingConvergenceTolerance = 0.001;
    2613              : 
    2614              :             // set minimum outdoor temperature for compressor operation
    2615            0 :             SetMinOATCompressor(state, FurnaceNum, cCurrentModuleObject, ErrorsFound);
    2616              : 
    2617              :         } // End of the HeatCool Furnace Loop
    2618              : 
    2619              :         // Get the data for the Unitary System HeatPump AirToAir (UnitarySystem:HeatPump:AirToAir)
    2620            4 :         for (int HeatPumpNum = 1; HeatPumpNum <= NumHeatPump; ++HeatPumpNum) {
    2621              : 
    2622            2 :             CurrentModuleObject = "AirLoopHVAC:UnitaryHeatPump:AirToAir";
    2623            2 :             FanInletNode = 0;
    2624            2 :             FanOutletNode = 0;
    2625            2 :             CoolingCoilInletNode = 0;
    2626            2 :             CoolingCoilOutletNode = 0;
    2627            2 :             HeatingCoilInletNode = 0;
    2628            2 :             HeatingCoilOutletNode = 0;
    2629            2 :             SupHeatCoilInletNode = 0;
    2630            2 :             SupHeatCoilOutletNode = 0;
    2631            2 :             CoolingCoilType = ' ';
    2632            2 :             CoolingCoilName = ' ';
    2633            2 :             HeatingCoilType = ' ';
    2634            2 :             HeatingCoilName = ' ';
    2635              : 
    2636            2 :             FurnaceNum = NumHeatOnly + NumHeatCool + NumUnitaryHeatOnly + NumUnitaryHeatCool + HeatPumpNum;
    2637            2 :             auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    2638            2 :             thisFurnace.iterationMode.allocate(3);
    2639              : 
    2640            2 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    2641              :                                                                      CurrentModuleObject,
    2642              :                                                                      HeatPumpNum,
    2643              :                                                                      Alphas,
    2644              :                                                                      NumAlphas,
    2645              :                                                                      Numbers,
    2646              :                                                                      NumNumbers,
    2647              :                                                                      IOStatus,
    2648              :                                                                      lNumericBlanks,
    2649              :                                                                      lAlphaBlanks,
    2650              :                                                                      cAlphaFields,
    2651              :                                                                      cNumericFields);
    2652              : 
    2653            4 :             GlobalNames::VerifyUniqueInterObjectName(
    2654            2 :                 state, state.dataFurnaces->UniqueFurnaceNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
    2655              : 
    2656            2 :             thisFurnace.type = HVAC::UnitarySysType::Unitary_HeatPump_AirToAir;
    2657            2 :             thisFurnace.Name = Alphas(1);
    2658              : 
    2659            2 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, thisFurnace.Name};
    2660              : 
    2661            2 :             if (lAlphaBlanks(2)) {
    2662            0 :                 thisFurnace.availSched = Sched::GetScheduleAlwaysOn(state);
    2663            2 :             } else if ((thisFurnace.availSched = Sched::GetSchedule(state, Alphas(2))) == nullptr) {
    2664            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(2), Alphas(2));
    2665            0 :                 ErrorsFound = true;
    2666              :             }
    2667              : 
    2668            2 :             thisFurnace.FurnaceInletNodeNum =
    2669            2 :                 NodeInputManager::GetOnlySingleNode(state,
    2670            2 :                                                     Alphas(3),
    2671              :                                                     ErrorsFound,
    2672              :                                                     DataLoopNode::ConnectionObjectType::AirLoopHVACUnitaryHeatPumpAirToAir,
    2673            2 :                                                     Alphas(1),
    2674              :                                                     DataLoopNode::NodeFluidType::Air,
    2675              :                                                     DataLoopNode::ConnectionType::Inlet,
    2676              :                                                     NodeInputManager::CompFluidStream::Primary,
    2677              :                                                     DataLoopNode::ObjectIsParent);
    2678              : 
    2679            2 :             thisFurnace.FurnaceOutletNodeNum =
    2680            4 :                 NodeInputManager::GetOnlySingleNode(state,
    2681            2 :                                                     Alphas(4),
    2682              :                                                     ErrorsFound,
    2683              :                                                     DataLoopNode::ConnectionObjectType::AirLoopHVACUnitaryHeatPumpAirToAir,
    2684            2 :                                                     Alphas(1),
    2685              :                                                     DataLoopNode::NodeFluidType::Air,
    2686              :                                                     DataLoopNode::ConnectionType::Outlet,
    2687              :                                                     NodeInputManager::CompFluidStream::Primary,
    2688              :                                                     DataLoopNode::ObjectIsParent);
    2689              : 
    2690            2 :             BranchNodeConnections::TestCompSet(state, CurrentModuleObject, Alphas(1), Alphas(3), Alphas(4), "Air Nodes");
    2691              : 
    2692              :             // Get the Controlling Zone or Location of the Furnace Thermostat
    2693            2 :             thisFurnace.ControlZoneNum = Util::FindItemInList(Alphas(5), state.dataHeatBal->Zone);
    2694            2 :             if (thisFurnace.ControlZoneNum == 0) {
    2695            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    2696            0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(5), Alphas(5)));
    2697            0 :                 ErrorsFound = true;
    2698              :             }
    2699              : 
    2700              :             // Get the node number for the zone with the thermostat
    2701            2 :             if (thisFurnace.ControlZoneNum > 0) {
    2702            2 :                 AirNodeFound = false;
    2703            2 :                 AirLoopFound = false;
    2704            2 :                 int ControlledZoneNum = thisFurnace.ControlZoneNum;
    2705              :                 //             Find the controlled zone number for the specified thermostat location
    2706            2 :                 thisFurnace.NodeNumOfControlledZone = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).ZoneNode;
    2707              :                 //             Determine if furnace is on air loop served by the thermostat location specified
    2708            3 :                 for (int zoneInNode = 1; zoneInNode <= state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).NumInletNodes; ++zoneInNode) {
    2709            3 :                     int AirLoopNumber = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).InletNodeAirLoopNum(zoneInNode);
    2710            3 :                     if (AirLoopNumber > 0) {
    2711            2 :                         for (int BranchNum = 1; BranchNum <= state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).NumBranches; ++BranchNum) {
    2712            3 :                             for (int CompNum = 1;
    2713            3 :                                  CompNum <= state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).Branch(BranchNum).TotalComponents;
    2714              :                                  ++CompNum) {
    2715            3 :                                 if (!Util::SameString(state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).Branch(BranchNum).Comp(CompNum).Name,
    2716            8 :                                                       Alphas(1)) ||
    2717            2 :                                     !Util::SameString(
    2718            2 :                                         state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).Branch(BranchNum).Comp(CompNum).TypeOf,
    2719              :                                         CurrentModuleObject))
    2720            1 :                                     continue;
    2721            2 :                                 AirLoopFound = true;
    2722            2 :                                 thisFurnace.ZoneInletNode = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).InletNode(zoneInNode);
    2723            2 :                                 break;
    2724              :                             }
    2725            2 :                             if (AirLoopFound) break;
    2726              :                         }
    2727            4 :                         for (TstatZoneNum = 1; TstatZoneNum <= state.dataZoneCtrls->NumTempControlledZones; ++TstatZoneNum) {
    2728            2 :                             if (state.dataZoneCtrls->TempControlledZone(TstatZoneNum).ActualZoneNum != thisFurnace.ControlZoneNum) continue;
    2729            2 :                             AirNodeFound = true;
    2730              :                         }
    2731            2 :                         for (TstatZoneNum = 1; TstatZoneNum <= state.dataZoneCtrls->NumComfortControlledZones; ++TstatZoneNum) {
    2732            0 :                             if (state.dataZoneCtrls->ComfortControlledZone(TstatZoneNum).ActualZoneNum != thisFurnace.ControlZoneNum) continue;
    2733            0 :                             AirNodeFound = true;
    2734              :                         }
    2735              :                     }
    2736            3 :                     if (AirLoopFound) break;
    2737              :                 }
    2738            2 :                 if (!AirNodeFound) {
    2739            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    2740            0 :                     ShowContinueError(state, "Did not find air node (zone with thermostat).");
    2741            0 :                     ShowContinueError(state, format("Specified {} = {}", cAlphaFields(5), Alphas(5)));
    2742            0 :                     ShowContinueError(
    2743              :                         state, "Both a ZoneHVAC:EquipmentConnections object and a ZoneControl:Thermostat object must be specified for this zone.");
    2744            0 :                     ErrorsFound = true;
    2745              :                 }
    2746            2 :                 if (!AirLoopFound) {
    2747            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    2748            0 :                     ShowContinueError(state, "Did not find correct AirLoopHVAC.");
    2749            0 :                     ShowContinueError(state, format("Specified {} = {}", cAlphaFields(5), Alphas(5)));
    2750            0 :                     ErrorsFound = true;
    2751              :                 }
    2752              :             }
    2753              : 
    2754              :             // Get fan data
    2755            2 :             FanName = Alphas(7);
    2756              : 
    2757            2 :             thisFurnace.fanType = static_cast<HVAC::FanType>(getEnumValue(HVAC::fanTypeNamesUC, Alphas(6)));
    2758              : 
    2759            2 :             if (thisFurnace.fanType == HVAC::FanType::OnOff || thisFurnace.fanType == HVAC::FanType::Constant) {
    2760              : 
    2761            2 :                 if ((thisFurnace.FanIndex = Fans::GetFanIndex(state, FanName)) == 0) {
    2762            0 :                     ShowSevereItemNotFound(state, eoh, cAlphaFields(7), FanName);
    2763            0 :                     ErrorsFound = true;
    2764              :                 } else {
    2765            2 :                     auto *fan = state.dataFans->fans(thisFurnace.FanIndex);
    2766            2 :                     FanInletNode = fan->inletNodeNum;
    2767            2 :                     FanOutletNode = fan->outletNodeNum;
    2768            2 :                     thisFurnace.fanAvailSched = fan->availSched;
    2769            2 :                     thisFurnace.ActualFanVolFlowRate = fan->maxAirFlowRate;
    2770              :                 }
    2771              :             }
    2772              : 
    2773              :             // Get heating coil type and name data
    2774            2 :             HeatingCoilType = Alphas(8);
    2775            2 :             HeatingCoilName = Alphas(9);
    2776              : 
    2777            2 :             errFlag = false;
    2778              : 
    2779            4 :             if (Util::SameString(HeatingCoilType, "COIL:HEATING:DX:VARIABLESPEED") ||
    2780            4 :                 Util::SameString(HeatingCoilType, "COILSYSTEM:INTEGRATEDHEATPUMP:AIRSOURCE")) {
    2781            0 :                 thisFurnace.HeatingCoilType_Num = HVAC::Coil_HeatingAirToAirVariableSpeed;
    2782            0 :                 if (Util::SameString(HeatingCoilType, "COILSYSTEM:INTEGRATEDHEATPUMP:AIRSOURCE")) thisFurnace.bIsIHP = true;
    2783              :             } else {
    2784            2 :                 thisFurnace.HeatingCoilType_Num = DXCoils::GetCoilTypeNum(state, HeatingCoilType, HeatingCoilName, errFlag);
    2785              :             }
    2786              : 
    2787            2 :             if (errFlag) {
    2788            0 :                 ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2789            0 :                 ErrorsFound = true;
    2790              :             }
    2791              : 
    2792            2 :             if (thisFurnace.HeatingCoilType_Num == HVAC::CoilDX_HeatingEmpirical) {
    2793            2 :                 ValidateComponent(state, HeatingCoilType, HeatingCoilName, IsNotOK, CurrentModuleObject);
    2794            2 :                 if (IsNotOK) {
    2795            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2796            0 :                     ErrorsFound = true;
    2797              : 
    2798              :                 } else { // mine data from DX heating coil
    2799              : 
    2800            2 :                     DXCoils::GetDXCoilIndex(state, HeatingCoilName, thisFurnace.HeatingCoilIndex, IsNotOK);
    2801            2 :                     if (IsNotOK) {
    2802            0 :                         ShowContinueError(state, format("...occurs {} = {}", CurrentModuleObject, Alphas(1)));
    2803            0 :                         ErrorsFound = true;
    2804              :                     }
    2805              : 
    2806              :                     // Get the Heating Coil Node Names
    2807            2 :                     errFlag = false;
    2808            2 :                     HeatingCoilInletNode = DXCoils::GetCoilInletNode(state, HeatingCoilType, HeatingCoilName, errFlag);
    2809            2 :                     HeatingCoilOutletNode = DXCoils::GetCoilOutletNode(state, HeatingCoilType, HeatingCoilName, errFlag);
    2810            2 :                     if (errFlag) {
    2811            0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2812            0 :                         ErrorsFound = true;
    2813              :                     }
    2814              : 
    2815              :                     // Get the design heating capacity
    2816            2 :                     errFlag = false;
    2817            2 :                     thisFurnace.DesignHeatingCapacity = DXCoils::GetCoilCapacity(state, HeatingCoilType, HeatingCoilName, errFlag);
    2818            2 :                     if (errFlag) {
    2819            0 :                         ShowContinueError(state, format("...occurs in {} ={}", CurrentModuleObject, Alphas(1)));
    2820            0 :                         ErrorsFound = true;
    2821              :                     }
    2822              : 
    2823              :                 } // IF (IsNotOK) THEN
    2824            0 :             } else if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingAirToAirVariableSpeed) {
    2825            0 :                 ValidateComponent(state, HeatingCoilType, HeatingCoilName, IsNotOK, CurrentModuleObject);
    2826            0 :                 if (IsNotOK) {
    2827            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2828            0 :                     ErrorsFound = true;
    2829              :                 } else {
    2830            0 :                     if (thisFurnace.bIsIHP) {
    2831            0 :                         thisFurnace.HeatingCoilIndex = IntegratedHeatPump::GetCoilIndexIHP(state, HeatingCoilType, HeatingCoilName, errFlag);
    2832            0 :                         IHPCoilIndex = thisFurnace.HeatingCoilIndex;
    2833            0 :                         IHPCoilName = state.dataIntegratedHP->IntegratedHeatPumps(IHPCoilIndex).SHCoilName;
    2834              :                         HeatingCoilInletNode =
    2835            0 :                             VariableSpeedCoils::GetCoilInletNodeVariableSpeed(state, "COIL:HEATING:DX:VARIABLESPEED", IHPCoilName, errFlag);
    2836              :                         HeatingCoilOutletNode =
    2837            0 :                             VariableSpeedCoils::GetCoilOutletNodeVariableSpeed(state, "COIL:HEATING:DX:VARIABLESPEED", IHPCoilName, errFlag);
    2838              :                     } else {
    2839            0 :                         thisFurnace.HeatingCoilIndex =
    2840            0 :                             VariableSpeedCoils::GetCoilIndexVariableSpeed(state, HeatingCoilType, HeatingCoilName, errFlag);
    2841            0 :                         HeatingCoilInletNode = VariableSpeedCoils::GetCoilInletNodeVariableSpeed(state, HeatingCoilType, HeatingCoilName, errFlag);
    2842            0 :                         HeatingCoilOutletNode = VariableSpeedCoils::GetCoilOutletNodeVariableSpeed(state, HeatingCoilType, HeatingCoilName, errFlag);
    2843              :                     }
    2844              :                 }
    2845              :             } else {
    2846            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    2847            0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(8), Alphas(8)));
    2848            0 :                 ErrorsFound = true;
    2849              :             }
    2850              : 
    2851              :             // Get Cooling Coil Information if available
    2852            2 :             CoolingCoilType = Alphas(10);
    2853            2 :             CoolingCoilName = Alphas(11);
    2854              : 
    2855            4 :             if (Util::SameString(CoolingCoilType, "COIL:COOLING:DX:VARIABLESPEED") ||
    2856            4 :                 Util::SameString(CoolingCoilType, "COILSYSTEM:INTEGRATEDHEATPUMP:AIRSOURCE")) {
    2857            0 :                 thisFurnace.CoolingCoilType_Num = HVAC::Coil_CoolingAirToAirVariableSpeed;
    2858            0 :                 if (Util::SameString(CoolingCoilType, "COILSYSTEM:INTEGRATEDHEATPUMP:AIRSOURCE")) thisFurnace.bIsIHP = true;
    2859              :             }
    2860              : 
    2861            2 :             ValidateComponent(state, CoolingCoilType, CoolingCoilName, IsNotOK, CurrentModuleObject);
    2862              : 
    2863            2 :             if (IsNotOK) {
    2864            0 :                 ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2865            0 :                 ErrorsFound = true;
    2866              : 
    2867              :             } else { // mine data from DX cooling coil
    2868              : 
    2869            2 :                 errFlag = false;
    2870            2 :                 PrintMessage = false;
    2871              : 
    2872            2 :                 if (thisFurnace.CoolingCoilType_Num != HVAC::Coil_CoolingAirToAirVariableSpeed) {
    2873            2 :                     thisFurnace.CoolingCoilType_Num = DXCoils::GetCoilTypeNum(state, CoolingCoilType, CoolingCoilName, errFlag, PrintMessage);
    2874              :                 }
    2875              : 
    2876              :                 // If coil type not found, check to see if a HX assisted cooling coil is used.
    2877            2 :                 if (thisFurnace.CoolingCoilType_Num == 0) {
    2878            0 :                     errFlag = false;
    2879            0 :                     PrintMessage = false;
    2880            0 :                     thisFurnace.CoolingCoilType_Num =
    2881            0 :                         HVACHXAssistedCoolingCoil::GetCoilGroupTypeNum(state, CoolingCoilType, CoolingCoilName, errFlag, PrintMessage);
    2882              :                 }
    2883              : 
    2884            2 :                 if (thisFurnace.CoolingCoilType_Num == HVAC::CoilDX_CoolingSingleSpeed) {
    2885              : 
    2886              :                     // Get the cooling coil node numbers
    2887            2 :                     errFlag = false;
    2888            2 :                     DXCoils::GetDXCoilIndex(state, CoolingCoilName, thisFurnace.CoolingCoilIndex, errFlag);
    2889            2 :                     CoolingCoilInletNode = DXCoils::GetCoilInletNode(state, CoolingCoilType, CoolingCoilName, errFlag);
    2890            2 :                     CoolingCoilOutletNode = DXCoils::GetCoilOutletNode(state, CoolingCoilType, CoolingCoilName, errFlag);
    2891            2 :                     if (errFlag) {
    2892            0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2893            0 :                         ErrorsFound = true;
    2894              :                     }
    2895              : 
    2896              :                     // Get the DX cooling coil design capacity
    2897            2 :                     errFlag = false;
    2898            2 :                     thisFurnace.DesignCoolingCapacity = DXCoils::GetCoilCapacity(state, CoolingCoilType, CoolingCoilName, errFlag);
    2899            2 :                     if (errFlag) {
    2900            0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2901            0 :                         ErrorsFound = true;
    2902              :                     }
    2903              : 
    2904            0 :                 } else if (thisFurnace.CoolingCoilType_Num == HVAC::CoilDX_CoolingHXAssisted) {
    2905              : 
    2906              :                     // Get the cooling coil node numbers
    2907            0 :                     errFlag = false;
    2908            0 :                     HVACHXAssistedCoolingCoil::GetHXDXCoilIndex(state, CoolingCoilName, thisFurnace.CoolingCoilIndex, errFlag);
    2909            0 :                     CoolingCoilInletNode = HVACHXAssistedCoolingCoil::GetCoilInletNode(state, CoolingCoilType, CoolingCoilName, errFlag);
    2910            0 :                     CoolingCoilOutletNode = HVACHXAssistedCoolingCoil::GetCoilOutletNode(state, CoolingCoilType, CoolingCoilName, errFlag);
    2911            0 :                     if (errFlag) {
    2912            0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2913            0 :                         ErrorsFound = true;
    2914              :                     }
    2915              : 
    2916              :                     // Get the heat exchanger assisted cooling coil design capacity
    2917            0 :                     errFlag = false;
    2918            0 :                     thisFurnace.DesignCoolingCapacity = HVACHXAssistedCoolingCoil::GetCoilCapacity(state, CoolingCoilType, CoolingCoilName, errFlag);
    2919            0 :                     if (errFlag) {
    2920            0 :                         ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2921            0 :                         ErrorsFound = true;
    2922              :                     }
    2923              : 
    2924              :                     // get the actual index to the DX cooling coil object
    2925            0 :                     DXCoilIndex = HVACHXAssistedCoolingCoil::GetActualDXCoilIndex(state, CoolingCoilType, CoolingCoilName, ErrorsFound);
    2926            0 :                     thisFurnace.ActualDXCoilIndexForHXAssisted = DXCoilIndex;
    2927              : 
    2928            0 :                 } else if (thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingAirToAirVariableSpeed) {
    2929              :                     // BOS ADDED, AUG/2012, VARIIABLE SPEED DX COOLING COIL
    2930              :                     //  Furnace(FurnaceNum)%DXCoolCoilType = 'COIL:COOLING:DX:VARIABLESPEED'
    2931              :                     //  Furnace(FurnaceNum)%DXCoolCoilName = CoolingCoilName
    2932            0 :                     ValidateComponent(state, CoolingCoilType, CoolingCoilName, IsNotOK, CurrentModuleObject);
    2933            0 :                     if (IsNotOK) {
    2934            0 :                         ShowContinueError(state, format("...specified in {}=\"{}\".", CurrentModuleObject, Alphas(1)));
    2935            0 :                         ErrorsFound = true;
    2936              :                     } else {
    2937            0 :                         errFlag = false;
    2938            0 :                         if (thisFurnace.bIsIHP) {
    2939            0 :                             thisFurnace.CoolingCoilIndex = IntegratedHeatPump::GetCoilIndexIHP(state, CoolingCoilType, CoolingCoilName, errFlag);
    2940            0 :                             IHPCoilName = state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).SCCoilName;
    2941              :                         } else {
    2942            0 :                             thisFurnace.CoolingCoilIndex =
    2943            0 :                                 VariableSpeedCoils::GetCoilIndexVariableSpeed(state, CoolingCoilType, CoolingCoilName, errFlag);
    2944            0 :                             IHPCoilName = CoolingCoilName;
    2945              :                         }
    2946              : 
    2947            0 :                         if (errFlag) {
    2948            0 :                             ShowContinueError(state, format("...specified in {}=\"{}\".", CurrentModuleObject, Alphas(1)));
    2949            0 :                             ErrorsFound = true;
    2950              :                         }
    2951              : 
    2952            0 :                         if (thisFurnace.bIsIHP) {
    2953              :                             CoolingCoilInletNode =
    2954            0 :                                 VariableSpeedCoils::GetCoilInletNodeVariableSpeed(state, "COIL:COOLING:DX:VARIABLESPEED", IHPCoilName, errFlag);
    2955              :                             CoolingCoilOutletNode =
    2956            0 :                                 VariableSpeedCoils::GetCoilOutletNodeVariableSpeed(state, "COIL:COOLING:DX:VARIABLESPEED", IHPCoilName, errFlag);
    2957            0 :                             thisFurnace.CondenserNodeNum = VariableSpeedCoils::GetVSCoilCondenserInletNode(state, IHPCoilName, errFlag);
    2958              :                         } else {
    2959              :                             CoolingCoilInletNode =
    2960            0 :                                 VariableSpeedCoils::GetCoilInletNodeVariableSpeed(state, CoolingCoilType, CoolingCoilName, errFlag);
    2961              :                             CoolingCoilOutletNode =
    2962            0 :                                 VariableSpeedCoils::GetCoilOutletNodeVariableSpeed(state, CoolingCoilType, CoolingCoilName, errFlag);
    2963            0 :                             thisFurnace.CondenserNodeNum = VariableSpeedCoils::GetVSCoilCondenserInletNode(state, CoolingCoilName, errFlag);
    2964              :                         }
    2965              : 
    2966            0 :                         if (errFlag) {
    2967            0 :                             ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    2968            0 :                             ErrorsFound = true;
    2969              :                         }
    2970              :                     }
    2971              :                 } else {
    2972            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    2973            0 :                     ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(10), Alphas(10)));
    2974            0 :                     ErrorsFound = true;
    2975              :                 }
    2976              :             }
    2977              : 
    2978            2 :             if (thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingAirToAirVariableSpeed &&
    2979            0 :                 thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingAirToAirVariableSpeed) {
    2980              :                 // Furnace(FurnaceNum)%WatertoAirHPType = WatertoAir_VarSpeedEquationFit
    2981            0 :                 if (thisFurnace.bIsIHP) {
    2982            0 :                     VariableSpeedCoils::SetVarSpeedCoilData(state,
    2983            0 :                                                             state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).SCCoilIndex,
    2984              :                                                             ErrorsFound,
    2985              :                                                             _,
    2986            0 :                                                             state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).SHCoilIndex);
    2987              :                 } else {
    2988            0 :                     VariableSpeedCoils::SetVarSpeedCoilData(state, thisFurnace.CoolingCoilIndex, ErrorsFound, _, thisFurnace.HeatingCoilIndex);
    2989              :                 }
    2990              :             }
    2991              : 
    2992              :             // Get supplemental heating coil information
    2993            2 :             SuppHeatCoilType = Alphas(12);
    2994            2 :             SuppHeatCoilName = Alphas(13);
    2995            2 :             thisFurnace.SuppHeatCoilType = SuppHeatCoilType;
    2996            2 :             thisFurnace.SuppHeatCoilName = SuppHeatCoilName;
    2997            2 :             errFlag = false;
    2998            2 :             if (Util::SameString(SuppHeatCoilType, "Coil:Heating:Fuel") || Util::SameString(SuppHeatCoilType, "Coil:Heating:Electric")) {
    2999              : 
    3000            2 :                 thisFurnace.SuppHeatCoilType_Num = HeatingCoils::GetHeatingCoilTypeNum(state, SuppHeatCoilType, SuppHeatCoilName, errFlag);
    3001            2 :                 if (errFlag) {
    3002            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3003            0 :                     ErrorsFound = true;
    3004              :                 } else {
    3005            2 :                     IsNotOK = false;
    3006            2 :                     ValidateComponent(state, SuppHeatCoilType, SuppHeatCoilName, IsNotOK, CurrentModuleObject);
    3007            2 :                     if (IsNotOK) {
    3008            0 :                         ShowContinueError(state, format("In {} \"{}\"", CurrentModuleObject, Alphas(1)));
    3009            0 :                         ErrorsFound = true;
    3010              : 
    3011              :                     } else { // mine data from the supplemental heating coil
    3012              : 
    3013            2 :                         HeatingCoils::GetCoilIndex(state, SuppHeatCoilName, thisFurnace.SuppHeatCoilIndex, IsNotOK);
    3014            2 :                         if (IsNotOK) {
    3015            0 :                             ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3016            0 :                             ErrorsFound = true;
    3017              :                         }
    3018              : 
    3019              :                         // Get the Supplemental Heating Coil Inlet Node Number
    3020            2 :                         errFlag = false;
    3021            2 :                         SupHeatCoilInletNode = HeatingCoils::GetCoilInletNode(state, SuppHeatCoilType, SuppHeatCoilName, errFlag);
    3022            2 :                         if (errFlag) {
    3023            0 :                             ShowContinueError(state, format("...occurs in {} \"{}\"", CurrentModuleObject, Alphas(1)));
    3024            0 :                             ErrorsFound = true;
    3025              :                         }
    3026              : 
    3027              :                         // Get the Supplemental Heating Coil Outlet Node Number
    3028            2 :                         errFlag = false;
    3029            2 :                         SupHeatCoilOutletNode = HeatingCoils::GetCoilOutletNode(state, SuppHeatCoilType, SuppHeatCoilName, errFlag);
    3030              : 
    3031            2 :                         if (errFlag) {
    3032            0 :                             ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3033            0 :                             ErrorsFound = true;
    3034              :                         }
    3035              : 
    3036              :                         // Get the supplemental heating coil design capacity
    3037            2 :                         errFlag = false;
    3038            2 :                         thisFurnace.DesignSuppHeatingCapacity = HeatingCoils::GetCoilCapacity(state, SuppHeatCoilType, SuppHeatCoilName, errFlag);
    3039            2 :                         if (errFlag) {
    3040            0 :                             ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3041            0 :                             ErrorsFound = true;
    3042              :                         }
    3043              : 
    3044              :                     } // IF (IsNotOK) THEN
    3045              :                 }
    3046            0 :             } else if (Util::SameString(SuppHeatCoilType, "Coil:Heating:Water")) {
    3047            0 :                 thisFurnace.SuppHeatCoilType_Num = HVAC::Coil_HeatingWater;
    3048            0 :                 ValidateComponent(state, SuppHeatCoilType, SuppHeatCoilName, IsNotOK, CurrentModuleObject);
    3049            0 :                 if (IsNotOK) {
    3050            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3051            0 :                     ErrorsFound = true;
    3052              :                 } else { // mine data from heating coil object
    3053              : 
    3054              :                     // Get the Heating Coil water Inlet or control Node number
    3055            0 :                     errFlag = false;
    3056            0 :                     thisFurnace.SuppCoilControlNode = WaterCoils::GetCoilWaterInletNode(state, "Coil:Heating:Water", SuppHeatCoilName, errFlag);
    3057            0 :                     if (errFlag) {
    3058            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3059            0 :                         ErrorsFound = true;
    3060              :                     }
    3061              : 
    3062              :                     // Get the ReHeat Coil hot water max volume flow rate
    3063            0 :                     errFlag = false;
    3064            0 :                     thisFurnace.MaxSuppCoilFluidFlow = WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", SuppHeatCoilName, errFlag);
    3065            0 :                     if (errFlag) {
    3066            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3067            0 :                         ErrorsFound = true;
    3068              :                     }
    3069              : 
    3070              :                     // Get the ReHeat Coil Inlet Node
    3071            0 :                     errFlag = false;
    3072            0 :                     SupHeatCoilInletNode = WaterCoils::GetCoilInletNode(state, "Coil:Heating:Water", SuppHeatCoilName, errFlag);
    3073            0 :                     thisFurnace.SuppCoilAirInletNode = SupHeatCoilInletNode;
    3074            0 :                     if (errFlag) {
    3075            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3076            0 :                         ErrorsFound = true;
    3077              :                     }
    3078              : 
    3079              :                     // Get the ReHeat Coil Outlet Node
    3080            0 :                     errFlag = false;
    3081            0 :                     SupHeatCoilOutletNode = WaterCoils::GetCoilOutletNode(state, "Coil:Heating:Water", SuppHeatCoilName, errFlag);
    3082            0 :                     thisFurnace.SuppCoilAirOutletNode = SupHeatCoilOutletNode;
    3083            0 :                     if (errFlag) {
    3084            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3085            0 :                         ErrorsFound = true;
    3086              :                     }
    3087            0 :                     errFlag = false;
    3088            0 :                     HVACControllers::CheckCoilWaterInletNode(state, thisFurnace.CoilControlNode, errFlag);
    3089            0 :                     if (!errFlag) { // then did find a controller so that is bad
    3090            0 :                         ShowSevereError(state,
    3091            0 :                                         format("{} = {} has a conflicting Controller:WaterCoil object", CurrentModuleObject, thisFurnace.Name));
    3092            0 :                         ShowContinueError(state, "Hot water coils are controlled directly by unitary and furnace systems.");
    3093            0 :                         ShowContinueError(state, "No water coil controller should be input for the coil.");
    3094            0 :                         ErrorsFound = true;
    3095              :                     }
    3096              :                 }
    3097              : 
    3098            0 :             } else if (Util::SameString(SuppHeatCoilType, "Coil:Heating:Steam")) {
    3099            0 :                 thisFurnace.SuppHeatCoilType_Num = HVAC::Coil_HeatingSteam;
    3100            0 :                 ValidateComponent(state, SuppHeatCoilType, SuppHeatCoilName, IsNotOK, CurrentModuleObject);
    3101            0 :                 if (IsNotOK) {
    3102            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3103            0 :                     ErrorsFound = true;
    3104              :                 } else { // mine data from heating coil object
    3105              : 
    3106            0 :                     errFlag = false;
    3107            0 :                     thisFurnace.SuppHeatCoilIndex = SteamCoils::GetSteamCoilIndex(state, "COIL:HEATING:STEAM", SuppHeatCoilName, errFlag);
    3108            0 :                     if (thisFurnace.SuppHeatCoilIndex == 0) {
    3109            0 :                         ShowSevereError(state, format("{} illegal {} = {}", CurrentModuleObject, cAlphaFields(12), SuppHeatCoilName));
    3110            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3111            0 :                         ErrorsFound = true;
    3112              :                     }
    3113              : 
    3114              :                     // Get the Heating Coil steam inlet node number
    3115            0 :                     errFlag = false;
    3116            0 :                     thisFurnace.SuppCoilControlNode = SteamCoils::GetCoilSteamInletNode(state, "Coil:Heating:Steam", SuppHeatCoilName, errFlag);
    3117            0 :                     if (errFlag) {
    3118            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3119            0 :                         ErrorsFound = true;
    3120              :                     }
    3121              : 
    3122              :                     // Get the Heating Coil steam max volume flow rate
    3123            0 :                     thisFurnace.MaxSuppCoilFluidFlow = SteamCoils::GetCoilMaxSteamFlowRate(state, thisFurnace.SuppHeatCoilIndex, errFlag);
    3124            0 :                     if (thisFurnace.MaxSuppCoilFluidFlow > 0.0) {
    3125              :                         SteamDensity =
    3126            0 :                             Fluid::GetSteam(state)->getSatDensity(state, state.dataFurnaces->TempSteamIn, 1.0, getAirLoopHVACHeatCoolInput);
    3127            0 :                         thisFurnace.MaxSuppCoilFluidFlow =
    3128            0 :                             SteamCoils::GetCoilMaxSteamFlowRate(state, thisFurnace.SuppHeatCoilIndex, errFlag) * SteamDensity;
    3129              :                     }
    3130              : 
    3131              :                     // Get the Heating Coil Inlet Node
    3132            0 :                     errFlag = false;
    3133            0 :                     SupHeatCoilInletNode = SteamCoils::GetCoilAirInletNode(state, thisFurnace.SuppHeatCoilIndex, SuppHeatCoilName, errFlag);
    3134            0 :                     thisFurnace.SuppCoilAirInletNode = SupHeatCoilInletNode;
    3135            0 :                     if (errFlag) {
    3136            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3137            0 :                         ErrorsFound = true;
    3138              :                     }
    3139              : 
    3140              :                     // Get the Heating Coil Outlet Node
    3141            0 :                     errFlag = false;
    3142            0 :                     SupHeatCoilOutletNode = SteamCoils::GetCoilAirOutletNode(state, thisFurnace.SuppHeatCoilIndex, SuppHeatCoilName, errFlag);
    3143            0 :                     thisFurnace.SuppCoilAirOutletNode = SupHeatCoilOutletNode;
    3144            0 :                     if (errFlag) {
    3145            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3146            0 :                         ErrorsFound = true;
    3147              :                     }
    3148              :                 }
    3149              : 
    3150              :             } else {
    3151            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3152            0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(12), Alphas(12)));
    3153            0 :                 ErrorsFound = true;
    3154              :             } // IF (Furnace(FurnaceNum)%HeatingCoilType_Num == Coil_HeatingGasOrOtherFuel .OR. &, etc.
    3155              : 
    3156            2 :             thisFurnace.fanPlace = static_cast<HVAC::FanPlace>(getEnumValue(HVAC::fanPlaceNamesUC, Alphas(14)));
    3157            2 :             assert(thisFurnace.fanPlace != HVAC::FanPlace::Invalid);
    3158              : 
    3159            2 :             if (lAlphaBlanks(15)) {
    3160            0 :                 thisFurnace.fanOp = HVAC::FanOp::Cycling;
    3161            0 :                 if (thisFurnace.fanType != HVAC::FanType::OnOff) {
    3162            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, thisFurnace.Name));
    3163            0 :                     ShowContinueError(state, format("{} = {}", cAlphaFields(6), Alphas(6)));
    3164            0 :                     ShowContinueError(state, format("Fan type must be Fan:OnOff when {} = Blank.", cAlphaFields(15)));
    3165            0 :                     ErrorsFound = true;
    3166              :                 }
    3167            2 :             } else if ((thisFurnace.fanOpModeSched = Sched::GetSchedule(state, Alphas(15))) == nullptr) {
    3168            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(15), Alphas(15));
    3169            0 :                 ErrorsFound = true;
    3170              :             }
    3171              : 
    3172            2 :             if (thisFurnace.fanType == HVAC::FanType::Constant && thisFurnace.fanOpModeSched != nullptr &&
    3173            0 :                 !thisFurnace.fanOpModeSched->checkMinMaxVals(state, Clusive::In, 0.0, Clusive::In, 1.0)) {
    3174            0 :                 Sched::ShowSevereBadMinMax(
    3175              :                     state,
    3176              :                     eoh,
    3177            0 :                     cAlphaFields(15),
    3178            0 :                     Alphas(15),
    3179              :                     Clusive::In,
    3180              :                     0.0,
    3181              :                     Clusive::In,
    3182              :                     1.0,
    3183            0 :                     format("For {} = {}, fan operating mode must be continuous (schedule values > 0)", cAlphaFields(7), Alphas(7)));
    3184            0 :                 ErrorsFound = true;
    3185              :             }
    3186              : 
    3187              :             // Dehumidification Control Type
    3188            2 :             if (Util::SameString(Alphas(16), "None") || Util::SameString(Alphas(16), "Multimode") || Util::SameString(Alphas(16), "CoolReheat")) {
    3189            2 :                 AirNodeFound = false;
    3190            2 :                 if (Util::SameString(Alphas(16), "Multimode")) {
    3191            0 :                     thisFurnace.DehumidControlType_Num = DehumidificationControlMode::Multimode;
    3192            0 :                     thisFurnace.Humidistat = true;
    3193            0 :                     if (thisFurnace.CoolingCoilType_Num != HVAC::CoilDX_CoolingHXAssisted) {
    3194            0 :                         ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3195            0 :                         ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(16), Alphas(16)));
    3196            0 :                         ShowContinueError(state, "Multimode control must be used with a Heat Exchanger Assisted Cooling Coil.");
    3197            0 :                         ErrorsFound = true;
    3198              :                     }
    3199              :                 }
    3200            2 :                 if (Util::SameString(Alphas(16), "CoolReheat")) {
    3201            0 :                     thisFurnace.DehumidControlType_Num = DehumidificationControlMode::CoolReheat;
    3202            0 :                     thisFurnace.Humidistat = true;
    3203              :                 }
    3204            2 :                 if (Util::SameString(Alphas(16), "None")) {
    3205            2 :                     thisFurnace.DehumidControlType_Num = DehumidificationControlMode::None;
    3206            2 :                     thisFurnace.Humidistat = false;
    3207              :                 }
    3208            2 :                 if (thisFurnace.Humidistat) {
    3209            0 :                     for (HStatZoneNum = 1; HStatZoneNum <= state.dataZoneCtrls->NumHumidityControlZones; ++HStatZoneNum) {
    3210            0 :                         if (state.dataZoneCtrls->HumidityControlZone(HStatZoneNum).ActualZoneNum != thisFurnace.ControlZoneNum) continue;
    3211            0 :                         AirNodeFound = true;
    3212              :                     }
    3213            0 :                     if (!AirNodeFound) {
    3214            0 :                         ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3215            0 :                         ShowContinueError(state, "Did not find Air Node (Zone with Humidistat).");
    3216            0 :                         ShowContinueError(state, format("Specified {} = {}", cAlphaFields(5), Alphas(5)));
    3217            0 :                         ErrorsFound = true;
    3218              :                     }
    3219              :                 }
    3220              :             } else { // invalid input or blank
    3221            0 :                 if (!lAlphaBlanks(16)) {
    3222            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3223            0 :                     ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(16), Alphas(16)));
    3224            0 :                     ErrorsFound = true;
    3225              :                 } else {
    3226            0 :                     thisFurnace.Humidistat = false;
    3227            0 :                     thisFurnace.DehumidControlType_Num = DehumidificationControlMode::None;
    3228              :                 }
    3229              :             }
    3230              : 
    3231              :             // Check node names for child components
    3232            2 :             if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
    3233            2 :                 if (FanInletNode != thisFurnace.FurnaceInletNodeNum) {
    3234            0 :                     ShowSevereError(state, format("For {} \"{}\"", CurrentModuleObject, Alphas(1)));
    3235            0 :                     ShowContinueError(
    3236              :                         state,
    3237              :                         "When a blow through fan is specified, the fan inlet node name must be the same as the unitary system inlet node name.");
    3238            0 :                     ShowContinueError(state, format("...Fan inlet node name            = {}", state.dataLoopNodes->NodeID(FanInletNode)));
    3239            0 :                     ShowContinueError(state,
    3240            0 :                                       format("...Unitary system inlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceInletNodeNum)));
    3241            0 :                     ErrorsFound = true;
    3242              :                 }
    3243            2 :                 if (FanOutletNode != CoolingCoilInletNode) {
    3244            0 :                     ShowSevereError(state, format("For {} \"{}\"", CurrentModuleObject, Alphas(1)));
    3245            0 :                     ShowContinueError(
    3246              :                         state,
    3247              :                         "When a blow through fan is specified, the fan outlet node name must be the same as the cooling coil inlet node name.");
    3248            0 :                     ShowContinueError(state, format("...Fan outlet node name         = {}", state.dataLoopNodes->NodeID(FanOutletNode)));
    3249            0 :                     ShowContinueError(state, format("...Cooling coil inlet node name = {}", state.dataLoopNodes->NodeID(CoolingCoilInletNode)));
    3250            0 :                     ErrorsFound = true;
    3251              :                 }
    3252            2 :                 if (CoolingCoilOutletNode != HeatingCoilInletNode) {
    3253            0 :                     ShowSevereError(state, format("For {} \"{}\"", CurrentModuleObject, Alphas(1)));
    3254            0 :                     ShowContinueError(state, "The cooling coil outlet node name must be the same as the heating coil inlet node name.");
    3255            0 :                     ShowContinueError(state, format("...Cooling coil outlet node name = {}", state.dataLoopNodes->NodeID(CoolingCoilOutletNode)));
    3256            0 :                     ShowContinueError(state, format("...Heating coil inlet node name  = {}", state.dataLoopNodes->NodeID(HeatingCoilInletNode)));
    3257            0 :                     ErrorsFound = true;
    3258              :                 }
    3259            2 :                 if (HeatingCoilOutletNode != SupHeatCoilInletNode) {
    3260            0 :                     ShowSevereError(state, format("For {} \"{}\"", CurrentModuleObject, Alphas(1)));
    3261            0 :                     ShowContinueError(state,
    3262              :                                       "When a blow through fan is specified, the heating coil outlet node name must be the same as the supplemental "
    3263              :                                       "heating coil inlet node name.");
    3264            0 :                     ShowContinueError(
    3265            0 :                         state, format("...Heating coil outlet node name              = {}", state.dataLoopNodes->NodeID(HeatingCoilOutletNode)));
    3266            0 :                     ShowContinueError(
    3267            0 :                         state, format("...Supplemental heating coil inlet node name  = {}", state.dataLoopNodes->NodeID(SupHeatCoilInletNode)));
    3268            0 :                     ErrorsFound = true;
    3269              :                 }
    3270            2 :                 if (SupHeatCoilOutletNode != thisFurnace.FurnaceOutletNodeNum) {
    3271            0 :                     ShowSevereError(state, format("For {} \"{}\"", CurrentModuleObject, Alphas(1)));
    3272            0 :                     ShowContinueError(state,
    3273              :                                       "The supplemental heating coil outlet node name must be the same as the unitary system outlet node name.");
    3274            0 :                     ShowContinueError(
    3275            0 :                         state, format("...Supplemental heating coil outlet node name = {}", state.dataLoopNodes->NodeID(SupHeatCoilOutletNode)));
    3276            0 :                     ShowContinueError(
    3277              :                         state,
    3278            0 :                         format("...Unitary system outlet node name            = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    3279            0 :                     ErrorsFound = true;
    3280              :                 }
    3281              :             } else {
    3282            0 :                 if (CoolingCoilInletNode != thisFurnace.FurnaceInletNodeNum) {
    3283            0 :                     ShowSevereError(state, format("For {} \"{}\"", CurrentModuleObject, Alphas(1)));
    3284            0 :                     ShowContinueError(state,
    3285              :                                       "When a draw through fan is specified, the cooling coil inlet node name must be the same as the unitary system "
    3286              :                                       "inlet node name.");
    3287            0 :                     ShowContinueError(state, format("...Cooling coil inlet node name   = {}", state.dataLoopNodes->NodeID(CoolingCoilInletNode)));
    3288            0 :                     ShowContinueError(state,
    3289            0 :                                       format("...Unitary system inlet node name = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceInletNodeNum)));
    3290            0 :                     ErrorsFound = true;
    3291              :                 }
    3292            0 :                 if (CoolingCoilOutletNode != HeatingCoilInletNode) {
    3293            0 :                     ShowSevereError(state, format("For {} \"{}\"", CurrentModuleObject, Alphas(1)));
    3294            0 :                     ShowContinueError(state, "The cooling coil outlet node name must be the same as the heating coil inlet node name.");
    3295            0 :                     ShowContinueError(state, format("...Cooling coil outlet node name = {}", state.dataLoopNodes->NodeID(CoolingCoilOutletNode)));
    3296            0 :                     ShowContinueError(state, format("...Heating coil inlet node name  = {}", state.dataLoopNodes->NodeID(HeatingCoilInletNode)));
    3297            0 :                     ErrorsFound = true;
    3298              :                 }
    3299            0 :                 if (HeatingCoilOutletNode != FanInletNode) {
    3300            0 :                     ShowSevereError(state, format("For {} \"{}\"", CurrentModuleObject, Alphas(1)));
    3301            0 :                     ShowContinueError(
    3302              :                         state,
    3303              :                         "When a draw through fan is specified, the heating coil outlet node name must be the same as the fan inlet node name.");
    3304            0 :                     ShowContinueError(state, format("...Heating coil outlet node name = {}", state.dataLoopNodes->NodeID(HeatingCoilOutletNode)));
    3305            0 :                     ShowContinueError(state, format("...Fan inlet node name           = {}", state.dataLoopNodes->NodeID(FanInletNode)));
    3306            0 :                     ErrorsFound = true;
    3307              :                 }
    3308            0 :                 if (FanOutletNode != SupHeatCoilInletNode) {
    3309            0 :                     ShowSevereError(state, format("For {} \"{}\"", CurrentModuleObject, Alphas(1)));
    3310            0 :                     ShowContinueError(state,
    3311              :                                       "When a draw through fan is specified, the fan outlet node name must be the same as the supplemental heating "
    3312              :                                       "coil inlet node name.");
    3313            0 :                     ShowContinueError(state,
    3314            0 :                                       format("...Fan outlet node name                       = {}", state.dataLoopNodes->NodeID(FanOutletNode)));
    3315            0 :                     ShowContinueError(
    3316            0 :                         state, format("...Supplemental heating coil inlet node name  = {}", state.dataLoopNodes->NodeID(SupHeatCoilInletNode)));
    3317            0 :                     ErrorsFound = true;
    3318              :                 }
    3319            0 :                 if (SupHeatCoilOutletNode != thisFurnace.FurnaceOutletNodeNum) {
    3320            0 :                     ShowSevereError(state, format("For {} \"{}\"", CurrentModuleObject, Alphas(1)));
    3321            0 :                     ShowContinueError(state,
    3322              :                                       "The supplemental heating coil outlet node name must be the same as the unitary system outlet node name.");
    3323            0 :                     ShowContinueError(
    3324            0 :                         state, format("...Supplemental heating coil outlet node name = {}", state.dataLoopNodes->NodeID(SupHeatCoilOutletNode)));
    3325            0 :                     ShowContinueError(
    3326              :                         state,
    3327            0 :                         format("...Unitary system outlet node name            = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    3328            0 :                     ErrorsFound = true;
    3329              :                 }
    3330              :             }
    3331              : 
    3332              :             // Add component sets array
    3333            2 :             if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
    3334            2 :                 CompSetFanInlet = Alphas(3);
    3335            2 :                 CompSetCoolInlet = "UNDEFINED";
    3336              :             } else {
    3337            0 :                 CompSetFanInlet = "UNDEFINED";
    3338            0 :                 CompSetCoolInlet = Alphas(3);
    3339              :             }
    3340            2 :             BranchNodeConnections::SetUpCompSets(state, CurrentModuleObject, Alphas(1), Alphas(6), Alphas(7), CompSetFanInlet, "UNDEFINED");
    3341              : 
    3342              :             // Add DX cooling coil to component sets array
    3343            2 :             if (thisFurnace.bIsIHP) {
    3344            0 :                 BranchNodeConnections::SetUpCompSets(
    3345            0 :                     state, CurrentModuleObject, Alphas(1), Alphas(10), Alphas(11) + " Cooling Coil", CompSetCoolInlet, "UNDEFINED");
    3346              :             } else {
    3347            2 :                 BranchNodeConnections::SetUpCompSets(state, CurrentModuleObject, Alphas(1), Alphas(10), Alphas(11), CompSetCoolInlet, "UNDEFINED");
    3348              :             }
    3349              :             // Add DX heating coil to component sets array
    3350            2 :             if (thisFurnace.bIsIHP) {
    3351            0 :                 BranchNodeConnections::SetUpCompSets(
    3352            0 :                     state, CurrentModuleObject, Alphas(1), Alphas(8), Alphas(9) + " Heating Coil", "UNDEFINED", "UNDEFINED");
    3353              :             } else {
    3354            2 :                 BranchNodeConnections::SetUpCompSets(state, CurrentModuleObject, Alphas(1), Alphas(8), Alphas(9), "UNDEFINED", "UNDEFINED");
    3355              :             }
    3356              : 
    3357              :             // Add supplemental heating coil to component sets array
    3358            2 :             BranchNodeConnections::SetUpCompSets(state, CurrentModuleObject, Alphas(1), Alphas(12), Alphas(13), "UNDEFINED", Alphas(4));
    3359              : 
    3360            2 :             thisFurnace.MaxCoolAirVolFlow = Numbers(1);
    3361            2 :             if (thisFurnace.MaxCoolAirVolFlow <= 0 && thisFurnace.MaxCoolAirVolFlow != DataSizing::AutoSize) {
    3362            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3363            0 :                 ShowContinueError(state, format("Illegal {} = {:.7T}", cNumericFields(1), Numbers(1)));
    3364            0 :                 ErrorsFound = true;
    3365              :             }
    3366              : 
    3367            2 :             thisFurnace.MaxHeatAirVolFlow = Numbers(2);
    3368            2 :             if (thisFurnace.MaxHeatAirVolFlow <= 0 && thisFurnace.MaxHeatAirVolFlow != DataSizing::AutoSize) {
    3369            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3370            0 :                 ShowContinueError(state, format("Illegal {} = {:.7T}", cNumericFields(2), Numbers(2)));
    3371            0 :                 ErrorsFound = true;
    3372              :             }
    3373              : 
    3374            2 :             thisFurnace.MaxNoCoolHeatAirVolFlow = Numbers(3);
    3375            2 :             if (thisFurnace.MaxNoCoolHeatAirVolFlow < 0 && thisFurnace.MaxNoCoolHeatAirVolFlow != DataSizing::AutoSize) {
    3376            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3377            0 :                 ShowContinueError(state, format("Illegal {} = {:.7T}", cNumericFields(3), Numbers(3)));
    3378            0 :                 ErrorsFound = true;
    3379              :             }
    3380              : 
    3381            2 :             if (thisFurnace.fanOpModeSched != nullptr) {
    3382            2 :                 if (!thisFurnace.fanOpModeSched->checkMinMaxVals(state, Clusive::In, 0.0, Clusive::In, 0.0)) { // Autodesk:Note Range is 0 to 0?
    3383              :                     //           set air flow control mode:
    3384              :                     //             UseCompressorOnFlow = operate at last cooling or heating air flow requested when compressor is off
    3385              :                     //             UseCompressorOffFlow = operate at value specified by user
    3386              :                     //           AirFlowControl only valid if fan opmode = ContFanCycComp
    3387            0 :                     if (thisFurnace.MaxNoCoolHeatAirVolFlow == 0.0) {
    3388            0 :                         thisFurnace.AirFlowControl = AirFlowControlConstFan::UseCompressorOnFlow;
    3389              :                     } else {
    3390            0 :                         thisFurnace.AirFlowControl = AirFlowControlConstFan::UseCompressorOffFlow;
    3391              :                     }
    3392              :                 }
    3393              :             }
    3394              : 
    3395            2 :             if (Numbers(1) != DataSizing::AutoSize && Numbers(2) != DataSizing::AutoSize && Numbers(3) != DataSizing::AutoSize) {
    3396            0 :                 thisFurnace.DesignFanVolFlowRate = max(Numbers(1), Numbers(2), Numbers(3));
    3397              :             } else {
    3398            2 :                 thisFurnace.DesignFanVolFlowRate = DataSizing::AutoSize;
    3399              :             }
    3400              : 
    3401            2 :             if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingAirToAirVariableSpeed) {
    3402            0 :                 errFlag = false;
    3403              : 
    3404            0 :                 if (thisFurnace.bIsIHP) {
    3405            0 :                     IHPCoilName = state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).SHCoilName;
    3406            0 :                     thisFurnace.MaxHeatAirVolFlow =
    3407            0 :                         VariableSpeedCoils::GetCoilAirFlowRateVariableSpeed(state, "COIL:HEATING:DX:VARIABLESPEED", IHPCoilName, errFlag);
    3408            0 :                     IHPCoilName = state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).SCCoilName;
    3409            0 :                     thisFurnace.MaxCoolAirVolFlow =
    3410            0 :                         VariableSpeedCoils::GetCoilAirFlowRateVariableSpeed(state, "COIL:COOLING:DX:VARIABLESPEED", IHPCoilName, errFlag);
    3411              :                 } else {
    3412            0 :                     thisFurnace.MaxHeatAirVolFlow =
    3413            0 :                         VariableSpeedCoils::GetCoilAirFlowRateVariableSpeed(state, HeatingCoilType, HeatingCoilName, errFlag);
    3414            0 :                     thisFurnace.MaxCoolAirVolFlow =
    3415            0 :                         VariableSpeedCoils::GetCoilAirFlowRateVariableSpeed(state, CoolingCoilType, CoolingCoilName, errFlag);
    3416              :                 }
    3417              : 
    3418            0 :                 if (errFlag) {
    3419            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3420            0 :                     ErrorsFound = true;
    3421              :                 }
    3422              : 
    3423            0 :                 thisFurnace.MaxNoCoolHeatAirVolFlow = min(thisFurnace.MaxHeatAirVolFlow, thisFurnace.MaxCoolAirVolFlow);
    3424            0 :                 if (thisFurnace.MaxHeatAirVolFlow != DataSizing::AutoSize && thisFurnace.MaxCoolAirVolFlow != DataSizing::AutoSize) {
    3425            0 :                     thisFurnace.DesignFanVolFlowRate = max(thisFurnace.MaxHeatAirVolFlow, thisFurnace.MaxCoolAirVolFlow);
    3426              :                 } else {
    3427            0 :                     thisFurnace.DesignFanVolFlowRate = DataSizing::AutoSize;
    3428              :                 }
    3429              :             }
    3430              : 
    3431            2 :             if (thisFurnace.ActualFanVolFlowRate != DataSizing::AutoSize) {
    3432            0 :                 if (thisFurnace.ActualFanVolFlowRate < thisFurnace.MaxCoolAirVolFlow && thisFurnace.MaxCoolAirVolFlow != DataSizing::AutoSize) {
    3433            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3434            0 :                     ShowContinueError(
    3435              :                         state,
    3436            0 :                         format("... air flow rate = {:.7T} in fan object {} is less than the maximum HVAC system air flow rate in cooling mode.",
    3437            0 :                                thisFurnace.ActualFanVolFlowRate,
    3438              :                                FanName));
    3439            0 :                     ShowContinueError(state, format(" The {} is reset to the fan flow rate and the simulation continues.", cNumericFields(1)));
    3440            0 :                     thisFurnace.MaxCoolAirVolFlow = thisFurnace.ActualFanVolFlowRate;
    3441            0 :                     thisFurnace.DesignFanVolFlowRate = thisFurnace.ActualFanVolFlowRate;
    3442              :                 }
    3443            0 :                 if (thisFurnace.ActualFanVolFlowRate < thisFurnace.MaxHeatAirVolFlow && thisFurnace.MaxHeatAirVolFlow != DataSizing::AutoSize) {
    3444            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3445            0 :                     ShowContinueError(
    3446              :                         state,
    3447            0 :                         format("... air flow rate = {:.7T} in fan object {} is less than the maximum HVAC system air flow rate in heating mode.",
    3448            0 :                                thisFurnace.ActualFanVolFlowRate,
    3449              :                                FanName));
    3450            0 :                     ShowContinueError(state, format(" The {} is reset to the fan flow rate and the simulation continues.", cNumericFields(2)));
    3451            0 :                     thisFurnace.MaxHeatAirVolFlow = thisFurnace.ActualFanVolFlowRate;
    3452            0 :                     thisFurnace.DesignFanVolFlowRate = thisFurnace.ActualFanVolFlowRate;
    3453              :                 }
    3454              :             }
    3455              : 
    3456              :             // Set heating convergence tolerance
    3457            2 :             thisFurnace.HeatingConvergenceTolerance = 0.001;
    3458              : 
    3459              :             //       Mine heatpump outdoor condenser node from DX coil object
    3460            2 :             errFlag = false;
    3461            2 :             if (thisFurnace.CoolingCoilType_Num == HVAC::CoilDX_CoolingSingleSpeed) {
    3462            2 :                 thisFurnace.CondenserNodeNum = DXCoils::GetCoilCondenserInletNode(state, CoolingCoilType, CoolingCoilName, errFlag);
    3463            0 :             } else if (thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingAirToAirVariableSpeed) {
    3464            0 :                 if (thisFurnace.bIsIHP) {
    3465            0 :                     IHPCoilName = state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).SCCoilName;
    3466            0 :                     thisFurnace.CondenserNodeNum = VariableSpeedCoils::GetVSCoilCondenserInletNode(state, IHPCoilName, errFlag);
    3467              :                 } else {
    3468            0 :                     thisFurnace.CondenserNodeNum = VariableSpeedCoils::GetVSCoilCondenserInletNode(state, CoolingCoilName, errFlag);
    3469              :                 }
    3470              :             } else {
    3471            0 :                 thisFurnace.CondenserNodeNum =
    3472            0 :                     DXCoils::GetCoilCondenserInletNode(state,
    3473              :                                                        "Coil:Cooling:DX:SingleSpeed",
    3474            0 :                                                        HVACHXAssistedCoolingCoil::GetHXDXCoilName(state, CoolingCoilType, CoolingCoilName, errFlag),
    3475              :                                                        errFlag);
    3476              :             }
    3477            2 :             if (errFlag) {
    3478            0 :                 ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3479            0 :                 ErrorsFound = true;
    3480              :             }
    3481              : 
    3482            2 :             if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingAirToAirVariableSpeed) {
    3483            0 :                 errFlag = false;
    3484            0 :                 if (thisFurnace.bIsIHP) {
    3485            0 :                     IHPCoilName = state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).SHCoilName;
    3486            0 :                     thisFurnace.DesignHeatingCapacity =
    3487            0 :                         VariableSpeedCoils::GetCoilCapacityVariableSpeed(state, "Coil:Heating:DX:VariableSpeed", IHPCoilName, errFlag);
    3488              :                 } else {
    3489            0 :                     thisFurnace.DesignHeatingCapacity =
    3490            0 :                         VariableSpeedCoils::GetCoilCapacityVariableSpeed(state, HeatingCoilType, HeatingCoilName, errFlag);
    3491              :                 }
    3492              : 
    3493            0 :                 if (errFlag) {
    3494            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3495            0 :                     ErrorsFound = true;
    3496              :                 }
    3497              :             }
    3498              : 
    3499            2 :             if (thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingAirToAirVariableSpeed) {
    3500            0 :                 errFlag = false;
    3501            0 :                 if (thisFurnace.bIsIHP) {
    3502            0 :                     IHPCoilName = state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).SCCoilName;
    3503            0 :                     thisFurnace.DesignCoolingCapacity =
    3504            0 :                         VariableSpeedCoils::GetCoilCapacityVariableSpeed(state, "COIL:COOLING:DX:VARIABLESPEED", IHPCoilName, errFlag);
    3505              :                 } else {
    3506            0 :                     thisFurnace.DesignCoolingCapacity =
    3507            0 :                         VariableSpeedCoils::GetCoilCapacityVariableSpeed(state, CoolingCoilType, CoolingCoilName, errFlag);
    3508              :                 }
    3509              : 
    3510            0 :                 if (errFlag) {
    3511            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3512            0 :                     ErrorsFound = true;
    3513              :                 }
    3514              :             }
    3515              : 
    3516              :             // Set cooling convergence tolerance
    3517            2 :             thisFurnace.CoolingConvergenceTolerance = 0.001;
    3518              : 
    3519              :             // Set the furnace max outlet temperature
    3520            2 :             thisFurnace.DesignMaxOutletTemp = Numbers(4);
    3521              : 
    3522              :             // Set maximum supply air temperature for supplemental heating coil
    3523            2 :             thisFurnace.MaxOATSuppHeat = Numbers(5);
    3524            4 :             OutputReportPredefined::PreDefTableEntry(
    3525            2 :                 state, state.dataOutRptPredefined->pdchDXHeatCoilSuppHiT, HeatingCoilName, thisFurnace.MaxOATSuppHeat);
    3526              : 
    3527              :             // set minimum outdoor temperature for compressor operation
    3528            2 :             SetMinOATCompressor(state, FurnaceNum, cCurrentModuleObject, ErrorsFound);
    3529              : 
    3530              :         } // End of the Unitary System HeatPump Loop
    3531              : 
    3532              :         // Get the Input for the Water to Air Heat Pump (UnitarySystem:HeatPump:WaterToAir)
    3533            2 :         for (int HeatPumpNum = 1; HeatPumpNum <= NumWaterToAirHeatPump; ++HeatPumpNum) {
    3534              : 
    3535            0 :             CurrentModuleObject = "AirLoopHVAC:UnitaryHeatPump:WaterToAir";
    3536            0 :             FanInletNode = 0;
    3537            0 :             FanOutletNode = 0;
    3538            0 :             CoolingCoilInletNode = 0;
    3539            0 :             CoolingCoilOutletNode = 0;
    3540            0 :             HeatingCoilInletNode = 0;
    3541            0 :             HeatingCoilOutletNode = 0;
    3542            0 :             SupHeatCoilInletNode = 0;
    3543            0 :             SupHeatCoilOutletNode = 0;
    3544            0 :             CoolingCoilType = ' ';
    3545            0 :             CoolingCoilName = ' ';
    3546            0 :             HeatingCoilType = ' ';
    3547            0 :             HeatingCoilName = ' ';
    3548              : 
    3549            0 :             FurnaceNum = NumHeatOnly + NumHeatCool + NumUnitaryHeatOnly + NumUnitaryHeatCool + NumHeatPump + HeatPumpNum;
    3550            0 :             auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    3551            0 :             thisFurnace.iterationMode.allocate(3);
    3552              : 
    3553            0 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    3554              :                                                                      CurrentModuleObject,
    3555              :                                                                      HeatPumpNum,
    3556              :                                                                      Alphas,
    3557              :                                                                      NumAlphas,
    3558              :                                                                      Numbers,
    3559              :                                                                      NumNumbers,
    3560              :                                                                      IOStatus,
    3561              :                                                                      lNumericBlanks,
    3562              :                                                                      lAlphaBlanks,
    3563              :                                                                      cAlphaFields,
    3564              :                                                                      cNumericFields);
    3565              : 
    3566            0 :             GlobalNames::VerifyUniqueInterObjectName(
    3567            0 :                 state, state.dataFurnaces->UniqueFurnaceNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
    3568              : 
    3569            0 :             thisFurnace.type = HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir;
    3570            0 :             thisFurnace.Name = Alphas(1);
    3571              : 
    3572            0 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, thisFurnace.Name};
    3573              : 
    3574            0 :             if (lAlphaBlanks(2)) {
    3575            0 :                 thisFurnace.availSched = Sched::GetScheduleAlwaysOn(state);
    3576            0 :             } else if ((thisFurnace.availSched = Sched::GetSchedule(state, Alphas(2))) == nullptr) {
    3577            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(2), Alphas(2));
    3578            0 :                 ErrorsFound = true;
    3579              :             }
    3580              : 
    3581            0 :             thisFurnace.FurnaceInletNodeNum =
    3582            0 :                 NodeInputManager::GetOnlySingleNode(state,
    3583            0 :                                                     Alphas(3),
    3584              :                                                     ErrorsFound,
    3585              :                                                     DataLoopNode::ConnectionObjectType::AirLoopHVACUnitaryHeatPumpWaterToAir,
    3586            0 :                                                     Alphas(1),
    3587              :                                                     DataLoopNode::NodeFluidType::Air,
    3588              :                                                     DataLoopNode::ConnectionType::Inlet,
    3589              :                                                     NodeInputManager::CompFluidStream::Primary,
    3590              :                                                     DataLoopNode::ObjectIsParent);
    3591              : 
    3592            0 :             thisFurnace.FurnaceOutletNodeNum =
    3593            0 :                 NodeInputManager::GetOnlySingleNode(state,
    3594            0 :                                                     Alphas(4),
    3595              :                                                     ErrorsFound,
    3596              :                                                     DataLoopNode::ConnectionObjectType::AirLoopHVACUnitaryHeatPumpWaterToAir,
    3597            0 :                                                     Alphas(1),
    3598              :                                                     DataLoopNode::NodeFluidType::Air,
    3599              :                                                     DataLoopNode::ConnectionType::Outlet,
    3600              :                                                     NodeInputManager::CompFluidStream::Primary,
    3601              :                                                     DataLoopNode::ObjectIsParent);
    3602              : 
    3603            0 :             BranchNodeConnections::TestCompSet(state, CurrentModuleObject, Alphas(1), Alphas(3), Alphas(4), "Air Nodes");
    3604              : 
    3605              :             // Get the Controlling Zone or Location of the Furnace Thermostat
    3606            0 :             thisFurnace.ControlZoneNum = Util::FindItemInList(Alphas(5), state.dataHeatBal->Zone);
    3607            0 :             if (thisFurnace.ControlZoneNum == 0) {
    3608            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3609            0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(5), Alphas(5)));
    3610            0 :                 ErrorsFound = true;
    3611              :             }
    3612              : 
    3613              :             // Get the node number for the zone with the thermostat
    3614            0 :             if (thisFurnace.ControlZoneNum > 0) {
    3615            0 :                 AirNodeFound = false;
    3616            0 :                 AirLoopFound = false;
    3617            0 :                 int ControlledZoneNum = thisFurnace.ControlZoneNum;
    3618              :                 //             Find the controlled zone number for the specified thermostat location
    3619            0 :                 thisFurnace.NodeNumOfControlledZone = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).ZoneNode;
    3620              :                 //             Determine if furnace is on air loop served by the thermostat location specified
    3621            0 :                 for (int zoneInNode = 1; zoneInNode <= state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).NumInletNodes; ++zoneInNode) {
    3622            0 :                     int AirLoopNumber = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).InletNodeAirLoopNum(zoneInNode);
    3623            0 :                     if (AirLoopNumber > 0) {
    3624            0 :                         for (int BranchNum = 1; BranchNum <= state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).NumBranches; ++BranchNum) {
    3625            0 :                             for (int CompNum = 1;
    3626            0 :                                  CompNum <= state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).Branch(BranchNum).TotalComponents;
    3627              :                                  ++CompNum) {
    3628            0 :                                 if (!Util::SameString(state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).Branch(BranchNum).Comp(CompNum).Name,
    3629            0 :                                                       Alphas(1)) ||
    3630            0 :                                     !Util::SameString(
    3631            0 :                                         state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).Branch(BranchNum).Comp(CompNum).TypeOf,
    3632              :                                         CurrentModuleObject))
    3633            0 :                                     continue;
    3634            0 :                                 AirLoopFound = true;
    3635            0 :                                 thisFurnace.ZoneInletNode = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).InletNode(zoneInNode);
    3636            0 :                                 break;
    3637              :                             }
    3638            0 :                             if (AirLoopFound) break;
    3639              :                         }
    3640            0 :                         for (TstatZoneNum = 1; TstatZoneNum <= state.dataZoneCtrls->NumTempControlledZones; ++TstatZoneNum) {
    3641            0 :                             if (state.dataZoneCtrls->TempControlledZone(TstatZoneNum).ActualZoneNum != thisFurnace.ControlZoneNum) continue;
    3642            0 :                             AirNodeFound = true;
    3643              :                         }
    3644            0 :                         for (TstatZoneNum = 1; TstatZoneNum <= state.dataZoneCtrls->NumComfortControlledZones; ++TstatZoneNum) {
    3645            0 :                             if (state.dataZoneCtrls->ComfortControlledZone(TstatZoneNum).ActualZoneNum != thisFurnace.ControlZoneNum) continue;
    3646            0 :                             AirNodeFound = true;
    3647              :                         }
    3648              :                     }
    3649            0 :                     if (AirLoopFound) break;
    3650              :                 }
    3651            0 :                 if (!AirNodeFound) {
    3652            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3653            0 :                     ShowContinueError(state, "Did not find air node (zone with thermostat).");
    3654            0 :                     ShowContinueError(state, format("Specified {} = {}", cAlphaFields(5), Alphas(5)));
    3655            0 :                     ShowContinueError(
    3656              :                         state, "Both a ZoneHVAC:EquipmentConnections object and a ZoneControl:Thermostat object must be specified for this zone.");
    3657            0 :                     ErrorsFound = true;
    3658              :                 }
    3659            0 :                 if (!AirLoopFound) {
    3660            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3661            0 :                     ShowContinueError(state, "Did not find correct AirLoopHVAC.");
    3662            0 :                     ShowContinueError(state, format("Specified {} = {}", cAlphaFields(5), Alphas(5)));
    3663            0 :                     ErrorsFound = true;
    3664              :                 }
    3665              :             }
    3666              : 
    3667              :             // Get fan data
    3668            0 :             FanName = Alphas(7);
    3669            0 :             errFlag = false;
    3670            0 :             thisFurnace.fanType = static_cast<HVAC::FanType>(getEnumValue(HVAC::fanTypeNamesUC, Alphas(6)));
    3671              : 
    3672            0 :             if (thisFurnace.fanType != HVAC::FanType::OnOff) {
    3673            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3674            0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(6), Alphas(6)));
    3675            0 :                 ErrorsFound = true;
    3676              : 
    3677            0 :             } else if ((thisFurnace.FanIndex = Fans::GetFanIndex(state, FanName)) == 0) {
    3678            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(7), FanName);
    3679            0 :                 ErrorsFound = true;
    3680              : 
    3681              :             } else {
    3682            0 :                 auto *fan = state.dataFans->fans(thisFurnace.FanIndex);
    3683            0 :                 FanInletNode = fan->inletNodeNum;
    3684            0 :                 FanOutletNode = fan->outletNodeNum;
    3685            0 :                 thisFurnace.fanAvailSched = fan->availSched;
    3686              :             }
    3687              : 
    3688              :             // Get heating coil type and name data
    3689            0 :             if (Alphas(8) == "COIL:HEATING:WATERTOAIRHEATPUMP:PARAMETERESTIMATION") {
    3690            0 :                 HeatingCoilType = Alphas(8);
    3691            0 :                 thisFurnace.HeatingCoilType_Num = HVAC::Coil_HeatingWaterToAirHP;
    3692            0 :                 HeatingCoilName = Alphas(9);
    3693            0 :                 ValidateComponent(state, HeatingCoilType, HeatingCoilName, IsNotOK, CurrentModuleObject);
    3694            0 :                 if (IsNotOK) {
    3695            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3696            0 :                     ErrorsFound = true;
    3697              :                 } else {
    3698            0 :                     thisFurnace.HeatingCoilIndex = WaterToAirHeatPump::GetCoilIndex(state, HeatingCoilType, HeatingCoilName, errFlag);
    3699            0 :                     HeatingCoilInletNode = WaterToAirHeatPump::GetCoilInletNode(state, HeatingCoilType, HeatingCoilName, errFlag);
    3700            0 :                     HeatingCoilOutletNode = WaterToAirHeatPump::GetCoilOutletNode(state, HeatingCoilType, HeatingCoilName, errFlag);
    3701              :                 }
    3702            0 :             } else if (Alphas(8) == "COIL:HEATING:WATERTOAIRHEATPUMP:EQUATIONFIT") {
    3703            0 :                 HeatingCoilType = Alphas(8);
    3704            0 :                 thisFurnace.HeatingCoilType_Num = HVAC::Coil_HeatingWaterToAirHPSimple;
    3705            0 :                 HeatingCoilName = Alphas(9);
    3706            0 :                 ValidateComponent(state, HeatingCoilType, HeatingCoilName, IsNotOK, CurrentModuleObject);
    3707            0 :                 if (IsNotOK) {
    3708            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3709            0 :                     ErrorsFound = true;
    3710              :                 } else {
    3711            0 :                     thisFurnace.HeatingCoilIndex = WaterToAirHeatPumpSimple::GetCoilIndex(state, HeatingCoilType, HeatingCoilName, errFlag);
    3712            0 :                     HeatingCoilInletNode = WaterToAirHeatPumpSimple::GetCoilInletNode(state, HeatingCoilType, HeatingCoilName, errFlag);
    3713            0 :                     HeatingCoilOutletNode = WaterToAirHeatPumpSimple::GetCoilOutletNode(state, HeatingCoilType, HeatingCoilName, errFlag);
    3714              :                 }
    3715            0 :             } else if (Alphas(8) == "COIL:HEATING:WATERTOAIRHEATPUMP:VARIABLESPEEDEQUATIONFIT") {
    3716            0 :                 HeatingCoilType = Alphas(8);
    3717            0 :                 thisFurnace.HeatingCoilType_Num = HVAC::Coil_HeatingWaterToAirHPVSEquationFit;
    3718            0 :                 HeatingCoilName = Alphas(9);
    3719            0 :                 ValidateComponent(state, HeatingCoilType, HeatingCoilName, IsNotOK, CurrentModuleObject);
    3720            0 :                 if (IsNotOK) {
    3721            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3722            0 :                     ErrorsFound = true;
    3723              :                 } else {
    3724            0 :                     thisFurnace.HeatingCoilIndex = VariableSpeedCoils::GetCoilIndexVariableSpeed(state, HeatingCoilType, HeatingCoilName, errFlag);
    3725            0 :                     HeatingCoilInletNode = VariableSpeedCoils::GetCoilInletNodeVariableSpeed(state, HeatingCoilType, HeatingCoilName, errFlag);
    3726            0 :                     HeatingCoilOutletNode = VariableSpeedCoils::GetCoilOutletNodeVariableSpeed(state, HeatingCoilType, HeatingCoilName, errFlag);
    3727              :                 }
    3728              :             } else {
    3729            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3730            0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(8), Alphas(8)));
    3731            0 :                 ErrorsFound = true;
    3732              :             }
    3733              : 
    3734              :             // Get Cooling Coil Information if available
    3735            0 :             if (Alphas(10) == "COIL:COOLING:WATERTOAIRHEATPUMP:PARAMETERESTIMATION") {
    3736            0 :                 CoolingCoilType = Alphas(10);
    3737            0 :                 thisFurnace.CoolingCoilType_Num = HVAC::Coil_CoolingWaterToAirHP;
    3738            0 :                 CoolingCoilName = Alphas(11);
    3739            0 :                 ValidateComponent(state, CoolingCoilType, CoolingCoilName, IsNotOK, CurrentModuleObject);
    3740            0 :                 if (IsNotOK) {
    3741            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3742            0 :                     ErrorsFound = true;
    3743              :                 } else {
    3744            0 :                     thisFurnace.CoolingCoilIndex = WaterToAirHeatPump::GetCoilIndex(state, CoolingCoilType, CoolingCoilName, errFlag);
    3745            0 :                     CoolingCoilInletNode = WaterToAirHeatPump::GetCoilInletNode(state, CoolingCoilType, CoolingCoilName, errFlag);
    3746            0 :                     CoolingCoilOutletNode = WaterToAirHeatPump::GetCoilOutletNode(state, CoolingCoilType, CoolingCoilName, errFlag);
    3747              :                 }
    3748            0 :             } else if (Alphas(10) == "COIL:COOLING:WATERTOAIRHEATPUMP:EQUATIONFIT") {
    3749            0 :                 CoolingCoilType = Alphas(10);
    3750            0 :                 thisFurnace.CoolingCoilType_Num = HVAC::Coil_CoolingWaterToAirHPSimple;
    3751            0 :                 CoolingCoilName = Alphas(11);
    3752            0 :                 ValidateComponent(state, CoolingCoilType, CoolingCoilName, IsNotOK, CurrentModuleObject);
    3753            0 :                 if (IsNotOK) {
    3754            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3755            0 :                     ErrorsFound = true;
    3756              :                 } else {
    3757            0 :                     thisFurnace.CoolingCoilIndex = WaterToAirHeatPumpSimple::GetCoilIndex(state, CoolingCoilType, CoolingCoilName, errFlag);
    3758            0 :                     CoolingCoilInletNode = WaterToAirHeatPumpSimple::GetCoilInletNode(state, CoolingCoilType, CoolingCoilName, errFlag);
    3759            0 :                     CoolingCoilOutletNode = WaterToAirHeatPumpSimple::GetCoilOutletNode(state, CoolingCoilType, CoolingCoilName, errFlag);
    3760              :                 }
    3761            0 :             } else if (Alphas(10) == "COIL:COOLING:WATERTOAIRHEATPUMP:VARIABLESPEEDEQUATIONFIT") {
    3762            0 :                 CoolingCoilType = Alphas(10);
    3763            0 :                 thisFurnace.CoolingCoilType_Num = HVAC::Coil_CoolingWaterToAirHPVSEquationFit;
    3764            0 :                 CoolingCoilName = Alphas(11);
    3765            0 :                 ValidateComponent(state, CoolingCoilType, CoolingCoilName, IsNotOK, CurrentModuleObject);
    3766            0 :                 if (IsNotOK) {
    3767            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3768            0 :                     ErrorsFound = true;
    3769              :                 } else {
    3770            0 :                     thisFurnace.CoolingCoilIndex = VariableSpeedCoils::GetCoilIndexVariableSpeed(state, CoolingCoilType, CoolingCoilName, errFlag);
    3771            0 :                     CoolingCoilInletNode = VariableSpeedCoils::GetCoilInletNodeVariableSpeed(state, CoolingCoilType, CoolingCoilName, errFlag);
    3772            0 :                     CoolingCoilOutletNode = VariableSpeedCoils::GetCoilOutletNodeVariableSpeed(state, CoolingCoilType, CoolingCoilName, errFlag);
    3773              :                 }
    3774              :             } else {
    3775            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3776            0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(10), Alphas(10)));
    3777            0 :                 ErrorsFound = true;
    3778              :             }
    3779              : 
    3780            0 :             thisFurnace.WaterCyclingMode = (NumAlphas < 18 || lAlphaBlanks(18))
    3781            0 :                                                ? HVAC::WaterFlow::Cycling
    3782            0 :                                                : static_cast<HVAC::WaterFlow>(getEnumValue(HVAC::waterFlowNamesUC, Alphas(18)));
    3783              : 
    3784              :             // end get water flow mode info
    3785            0 :             if (Alphas(8) == "COIL:HEATING:WATERTOAIRHEATPUMP:EQUATIONFIT" && Alphas(10) == "COIL:COOLING:WATERTOAIRHEATPUMP:EQUATIONFIT") {
    3786            0 :                 thisFurnace.WatertoAirHPType = WAHPCoilType::Simple;
    3787            0 :                 WaterToAirHeatPumpSimple::SetSimpleWSHPData(
    3788            0 :                     state, thisFurnace.CoolingCoilIndex, ErrorsFound, thisFurnace.WaterCyclingMode, _, thisFurnace.HeatingCoilIndex);
    3789            0 :             } else if (Alphas(8) == "COIL:HEATING:WATERTOAIRHEATPUMP:PARAMETERESTIMATION" &&
    3790            0 :                        Alphas(10) == "COIL:COOLING:WATERTOAIRHEATPUMP:PARAMETERESTIMATION") {
    3791            0 :                 thisFurnace.WatertoAirHPType = WAHPCoilType::ParEst;
    3792            0 :             } else if (Alphas(8) == "COIL:HEATING:WATERTOAIRHEATPUMP:VARIABLESPEEDEQUATIONFIT" &&
    3793            0 :                        Alphas(10) == "COIL:COOLING:WATERTOAIRHEATPUMP:VARIABLESPEEDEQUATIONFIT") {
    3794            0 :                 thisFurnace.WatertoAirHPType = WAHPCoilType::VarSpeedEquationFit;
    3795            0 :                 VariableSpeedCoils::SetVarSpeedCoilData(state, thisFurnace.CoolingCoilIndex, ErrorsFound, _, thisFurnace.HeatingCoilIndex);
    3796              :             } else {
    3797            0 :                 ShowContinueError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    3798            0 :                 ShowContinueError(state, "Cooling coil and heating coil should be of same general type");
    3799            0 :                 ErrorsFound = true;
    3800              :             }
    3801              : 
    3802              :             // Get supplemental heating coil information
    3803              : 
    3804            0 :             SuppHeatCoilType = Alphas(12);
    3805            0 :             SuppHeatCoilName = Alphas(13);
    3806            0 :             thisFurnace.SuppHeatCoilType = SuppHeatCoilType;
    3807            0 :             thisFurnace.SuppHeatCoilName = SuppHeatCoilName;
    3808            0 :             errFlag = false;
    3809            0 :             if (Util::SameString(SuppHeatCoilType, "Coil:Heating:Fuel") || Util::SameString(SuppHeatCoilType, "Coil:Heating:Electric")) {
    3810              : 
    3811            0 :                 thisFurnace.SuppHeatCoilType_Num = HeatingCoils::GetHeatingCoilTypeNum(state, SuppHeatCoilType, SuppHeatCoilName, errFlag);
    3812            0 :                 if (errFlag) {
    3813            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3814            0 :                     ErrorsFound = true;
    3815              :                 } else {
    3816            0 :                     IsNotOK = false;
    3817            0 :                     ValidateComponent(state, SuppHeatCoilType, SuppHeatCoilName, IsNotOK, CurrentModuleObject);
    3818            0 :                     if (IsNotOK) {
    3819            0 :                         ShowContinueError(state, format("In {} \"{}\"", CurrentModuleObject, Alphas(1)));
    3820            0 :                         ErrorsFound = true;
    3821              : 
    3822              :                     } else { // mine data from the supplemental heating coil
    3823              : 
    3824            0 :                         HeatingCoils::GetCoilIndex(state, SuppHeatCoilName, thisFurnace.SuppHeatCoilIndex, IsNotOK);
    3825            0 :                         if (IsNotOK) {
    3826            0 :                             ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3827            0 :                             ErrorsFound = true;
    3828              :                         }
    3829              : 
    3830              :                         // Get the Supplemental Heating Coil Inlet Node Number
    3831            0 :                         errFlag = false;
    3832            0 :                         SupHeatCoilInletNode = HeatingCoils::GetCoilInletNode(state, SuppHeatCoilType, SuppHeatCoilName, errFlag);
    3833            0 :                         if (errFlag) {
    3834            0 :                             ShowContinueError(state, format("...occurs in {} \"{}\"", CurrentModuleObject, Alphas(1)));
    3835            0 :                             ErrorsFound = true;
    3836              :                         }
    3837              : 
    3838              :                         // Get the Supplemental Heating Coil Outlet Node Number
    3839            0 :                         errFlag = false;
    3840            0 :                         SupHeatCoilOutletNode = HeatingCoils::GetCoilOutletNode(state, SuppHeatCoilType, SuppHeatCoilName, errFlag);
    3841            0 :                         if (errFlag) {
    3842            0 :                             ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3843            0 :                             ErrorsFound = true;
    3844              :                         }
    3845              : 
    3846              :                         // Get the supplemental heating coil design capacity
    3847            0 :                         errFlag = false;
    3848            0 :                         thisFurnace.DesignSuppHeatingCapacity = HeatingCoils::GetCoilCapacity(state, SuppHeatCoilType, SuppHeatCoilName, errFlag);
    3849            0 :                         if (errFlag) {
    3850            0 :                             ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3851            0 :                             ErrorsFound = true;
    3852              :                         }
    3853              : 
    3854              :                     } // IF (IsNotOK) THEN
    3855              :                 }
    3856            0 :             } else if (Util::SameString(SuppHeatCoilType, "Coil:Heating:Water")) {
    3857            0 :                 thisFurnace.SuppHeatCoilType_Num = HVAC::Coil_HeatingWater;
    3858            0 :                 ValidateComponent(state, SuppHeatCoilType, SuppHeatCoilName, IsNotOK, CurrentModuleObject);
    3859            0 :                 if (IsNotOK) {
    3860            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3861            0 :                     ErrorsFound = true;
    3862              :                 } else { // mine data from heating coil object
    3863              : 
    3864              :                     // Get the Heating Coil water Inlet or control Node number
    3865            0 :                     errFlag = false;
    3866            0 :                     thisFurnace.SuppCoilControlNode = WaterCoils::GetCoilWaterInletNode(state, "Coil:Heating:Water", SuppHeatCoilName, errFlag);
    3867            0 :                     if (errFlag) {
    3868            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3869            0 :                         ErrorsFound = true;
    3870              :                     }
    3871              : 
    3872              :                     // Get the ReHeat Coil hot water max volume flow rate
    3873            0 :                     errFlag = false;
    3874            0 :                     thisFurnace.MaxSuppCoilFluidFlow = WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", SuppHeatCoilName, errFlag);
    3875            0 :                     if (errFlag) {
    3876            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3877            0 :                         ErrorsFound = true;
    3878              :                     }
    3879              : 
    3880              :                     // Get the ReHeat Coil Inlet Node
    3881            0 :                     errFlag = false;
    3882            0 :                     SupHeatCoilInletNode = WaterCoils::GetCoilInletNode(state, "Coil:Heating:Water", SuppHeatCoilName, errFlag);
    3883            0 :                     thisFurnace.SuppCoilAirInletNode = SupHeatCoilInletNode;
    3884            0 :                     if (errFlag) {
    3885            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3886            0 :                         ErrorsFound = true;
    3887              :                     }
    3888              : 
    3889              :                     // Get the ReHeat Coil Outlet Node
    3890            0 :                     errFlag = false;
    3891            0 :                     SupHeatCoilOutletNode = WaterCoils::GetCoilOutletNode(state, "Coil:Heating:Water", SuppHeatCoilName, errFlag);
    3892            0 :                     thisFurnace.SuppCoilAirOutletNode = SupHeatCoilOutletNode;
    3893            0 :                     if (errFlag) {
    3894            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3895            0 :                         ErrorsFound = true;
    3896              :                     }
    3897              : 
    3898            0 :                     errFlag = false;
    3899            0 :                     HVACControllers::CheckCoilWaterInletNode(state, thisFurnace.CoilControlNode, errFlag);
    3900            0 :                     if (!errFlag) { // then did find a controller so that is bad
    3901            0 :                         ShowSevereError(state,
    3902            0 :                                         format("{} = {} has a conflicting Controller:WaterCoil object", CurrentModuleObject, thisFurnace.Name));
    3903            0 :                         ShowContinueError(state, "Hot water coils are controlled directly by unitary and furnace systems.");
    3904            0 :                         ShowContinueError(state, "No water coil controller should be input for the coil.");
    3905            0 :                         ErrorsFound = true;
    3906              :                     }
    3907              :                 }
    3908              : 
    3909            0 :             } else if (Util::SameString(SuppHeatCoilType, "Coil:Heating:Steam")) {
    3910            0 :                 thisFurnace.SuppHeatCoilType_Num = HVAC::Coil_HeatingSteam;
    3911            0 :                 ValidateComponent(state, SuppHeatCoilType, SuppHeatCoilName, IsNotOK, CurrentModuleObject);
    3912            0 :                 if (IsNotOK) {
    3913            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    3914            0 :                     ErrorsFound = true;
    3915              :                 } else { // mine data from heating coil object
    3916              : 
    3917            0 :                     errFlag = false;
    3918            0 :                     thisFurnace.SuppHeatCoilIndex = SteamCoils::GetSteamCoilIndex(state, SuppHeatCoilType, SuppHeatCoilName, errFlag);
    3919            0 :                     if (thisFurnace.SuppHeatCoilIndex == 0) {
    3920            0 :                         ShowSevereError(state, format("{} illegal {} = {}", CurrentModuleObject, cAlphaFields(12), SuppHeatCoilName));
    3921            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3922            0 :                         ErrorsFound = true;
    3923              :                     }
    3924              : 
    3925              :                     // Get the Heating Coil steam inlet node number
    3926            0 :                     errFlag = false;
    3927            0 :                     thisFurnace.SuppCoilControlNode = SteamCoils::GetCoilSteamInletNode(state, "Coil:Heating:Steam", SuppHeatCoilName, errFlag);
    3928            0 :                     if (errFlag) {
    3929            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3930            0 :                         ErrorsFound = true;
    3931              :                     }
    3932              : 
    3933              :                     // Get the Heating Coil steam max volume flow rate
    3934            0 :                     thisFurnace.MaxSuppCoilFluidFlow = SteamCoils::GetCoilMaxSteamFlowRate(state, thisFurnace.SuppHeatCoilIndex, errFlag);
    3935            0 :                     if (thisFurnace.MaxSuppCoilFluidFlow > 0.0) {
    3936              :                         SteamDensity =
    3937            0 :                             Fluid::GetSteam(state)->getSatDensity(state, state.dataFurnaces->TempSteamIn, 1.0, getAirLoopHVACHeatCoolInput);
    3938            0 :                         thisFurnace.MaxSuppCoilFluidFlow =
    3939            0 :                             SteamCoils::GetCoilMaxSteamFlowRate(state, thisFurnace.SuppHeatCoilIndex, errFlag) * SteamDensity;
    3940              :                     }
    3941              : 
    3942              :                     // Get the Heating Coil Inlet Node
    3943            0 :                     errFlag = false;
    3944            0 :                     SupHeatCoilInletNode = SteamCoils::GetCoilAirInletNode(state, thisFurnace.SuppHeatCoilIndex, SuppHeatCoilName, errFlag);
    3945            0 :                     thisFurnace.SuppCoilAirInletNode = SupHeatCoilInletNode;
    3946            0 :                     if (errFlag) {
    3947            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3948            0 :                         ErrorsFound = true;
    3949              :                     }
    3950              : 
    3951              :                     // Get the Heating Coil Outlet Node
    3952            0 :                     errFlag = false;
    3953            0 :                     SupHeatCoilOutletNode = SteamCoils::GetCoilAirOutletNode(state, thisFurnace.SuppHeatCoilIndex, SuppHeatCoilName, errFlag);
    3954            0 :                     thisFurnace.SuppCoilAirOutletNode = SupHeatCoilOutletNode;
    3955            0 :                     if (errFlag) {
    3956            0 :                         ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisFurnace.Name));
    3957            0 :                         ErrorsFound = true;
    3958              :                     }
    3959              :                 }
    3960              : 
    3961              :             } else {
    3962            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    3963            0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(12), Alphas(12)));
    3964            0 :                 ErrorsFound = true;
    3965              :             } // IF (Furnace(FurnaceNum)%HeatingCoilType_Num == Coil_HeatingGasOrOtherFuel .OR. &, etc.
    3966              : 
    3967            0 :             if (lAlphaBlanks(14)) {
    3968            0 :                 thisFurnace.CondenserNodeNum = 0;
    3969              :             } else {
    3970            0 :                 thisFurnace.CondenserNodeNum =
    3971            0 :                     NodeInputManager::GetOnlySingleNode(state,
    3972            0 :                                                         Alphas(14),
    3973              :                                                         ErrorsFound,
    3974              :                                                         DataLoopNode::ConnectionObjectType::AirLoopHVACUnitaryHeatPumpWaterToAir,
    3975            0 :                                                         Alphas(1),
    3976              :                                                         DataLoopNode::NodeFluidType::Air,
    3977              :                                                         DataLoopNode::ConnectionType::OutsideAirReference,
    3978              :                                                         NodeInputManager::CompFluidStream::Primary,
    3979              :                                                         DataLoopNode::ObjectIsNotParent);
    3980              :                 // need better verification.
    3981            0 :                 if (!OutAirNodeManager::CheckOutAirNodeNumber(state, thisFurnace.CondenserNodeNum)) {
    3982            0 :                     ShowSevereError(state, format("For {} = {}", CurrentModuleObject, Alphas(1)));
    3983            0 :                     ShowContinueError(state, format(" Node name of outdoor dry-bulb temperature sensor not valid outdoor air node= {}", Alphas(14)));
    3984            0 :                     ShowContinueError(state, "...does not appear in an OutdoorAir:NodeList or as an OutdoorAir:Node.");
    3985            0 :                     ErrorsFound = true;
    3986              :                 }
    3987              :             }
    3988              : 
    3989            0 :             thisFurnace.fanPlace = static_cast<HVAC::FanPlace>(getEnumValue(HVAC::fanPlaceNamesUC, Alphas(15)));
    3990            0 :             assert(thisFurnace.fanPlace != HVAC::FanPlace::Invalid);
    3991              : 
    3992            0 :             if (lAlphaBlanks(16)) {
    3993            0 :                 thisFurnace.fanOp = HVAC::FanOp::Cycling;
    3994            0 :                 if (thisFurnace.fanType != HVAC::FanType::OnOff) {
    3995            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, thisFurnace.Name));
    3996            0 :                     ShowContinueError(state, format("{} = {}", cAlphaFields(6), Alphas(6)));
    3997            0 :                     ShowContinueError(state, format("Fan type must be Fan:OnOff when {} = Blank.", cAlphaFields(16)));
    3998            0 :                     ErrorsFound = true;
    3999              :                 }
    4000            0 :             } else if ((thisFurnace.fanOpModeSched = Sched::GetSchedule(state, Alphas(16))) == nullptr) {
    4001            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(16), Alphas(16));
    4002            0 :                 ErrorsFound = true;
    4003              :             }
    4004              : 
    4005              :             // add the Dehumidification Type
    4006            0 :             if (Util::SameString(Alphas(17), "None") || Util::SameString(Alphas(17), "CoolReheat")) {
    4007            0 :                 AirNodeFound = false;
    4008            0 :                 if (Util::SameString(Alphas(17), "CoolReheat")) {
    4009            0 :                     thisFurnace.DehumidControlType_Num = DehumidificationControlMode::CoolReheat;
    4010            0 :                     thisFurnace.Humidistat = true;
    4011            0 :                     if (lAlphaBlanks(17)) {
    4012            0 :                         ShowWarningError(state, format("{} \"{}\"", CurrentModuleObject, Alphas(1)));
    4013            0 :                         ShowContinueError(state,
    4014              :                                           "Dehumidification control type is assumed to be None since a supplemental reheat coil has not been "
    4015              :                                           "specified and the simulation continues.");
    4016            0 :                         thisFurnace.Humidistat = false;
    4017            0 :                         thisFurnace.DehumidControlType_Num = DehumidificationControlMode::None;
    4018              :                     }
    4019              :                 }
    4020            0 :                 if (Util::SameString(Alphas(17), "None")) {
    4021            0 :                     thisFurnace.DehumidControlType_Num = DehumidificationControlMode::None;
    4022            0 :                     thisFurnace.Humidistat = false;
    4023              :                 }
    4024            0 :                 if (thisFurnace.Humidistat) {
    4025            0 :                     for (HStatZoneNum = 1; HStatZoneNum <= state.dataZoneCtrls->NumHumidityControlZones; ++HStatZoneNum) {
    4026            0 :                         if (state.dataZoneCtrls->HumidityControlZone(HStatZoneNum).ActualZoneNum != thisFurnace.ControlZoneNum) continue;
    4027            0 :                         AirNodeFound = true;
    4028              :                     }
    4029            0 :                     if (!AirNodeFound) {
    4030            0 :                         ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    4031            0 :                         ShowContinueError(state, "Did not find Air Node (Zone with Humidistat).");
    4032            0 :                         ShowContinueError(state, format("Specified {} = {}", cAlphaFields(5), Alphas(5)));
    4033            0 :                         ErrorsFound = true;
    4034              :                     }
    4035              :                 }
    4036              :             } else { // invalid input or blank
    4037            0 :                 if (!lAlphaBlanks(17)) {
    4038            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
    4039            0 :                     ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(17), Alphas(17)));
    4040            0 :                     ErrorsFound = true;
    4041              :                 } else {
    4042            0 :                     thisFurnace.Humidistat = false;
    4043            0 :                     thisFurnace.DehumidControlType_Num = DehumidificationControlMode::None;
    4044              :                 }
    4045              :             }
    4046              : 
    4047              :             // Add fan to component sets array
    4048              : 
    4049            0 :             if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
    4050            0 :                 CompSetFanInlet = Alphas(3);
    4051            0 :                 CompSetCoolInlet = "UNDEFINED";
    4052            0 :                 if (FanInletNode != thisFurnace.FurnaceInletNodeNum) {
    4053            0 :                     ShowSevereError(
    4054            0 :                         state, format("For {} = {}, Mismatch between unitary system inlet node and fan inlet node.", CurrentModuleObject, Alphas(1)));
    4055            0 :                     ShowContinueError(state, "..For \"BlowThrough\" fan, the inlet node name for the HeatPump should match the fan inlet node name.");
    4056            0 :                     ShowContinueError(state, format("..HeatPump Inlet Node = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceInletNodeNum)));
    4057            0 :                     ShowContinueError(state, format("..Fan Inlet Node      = {}", state.dataLoopNodes->NodeID(FanInletNode)));
    4058            0 :                     ErrorsFound = true;
    4059              :                 }
    4060            0 :                 if (FanOutletNode != CoolingCoilInletNode) {
    4061            0 :                     ShowSevereError(
    4062            0 :                         state, format("For {} = {}, Mismatch between fan outlet node and cooling coil inlet node.", CurrentModuleObject, Alphas(1)));
    4063            0 :                     ShowContinueError(state, "..For \"BlowThrough\" fan, the fan outlet node name must match the cooling coil inlet node name.");
    4064            0 :                     ShowContinueError(state, format("..Fan outlet node         = {}", state.dataLoopNodes->NodeID(FanOutletNode)));
    4065            0 :                     ShowContinueError(state, format("..Cooling coil inlet node = {}", state.dataLoopNodes->NodeID(CoolingCoilInletNode)));
    4066            0 :                     ErrorsFound = true;
    4067              :                 }
    4068            0 :                 if (CoolingCoilOutletNode != HeatingCoilInletNode) {
    4069            0 :                     ShowSevereError(state,
    4070            0 :                                     format("For {} = {}, Mismatch between cooling coil outlet node and heating coil inlet node.",
    4071              :                                            CurrentModuleObject,
    4072              :                                            Alphas(1)));
    4073            0 :                     ShowContinueError(state, "..The cooling coil outlet node name must match the heating coil inlet node name.");
    4074            0 :                     ShowContinueError(state, format("..Cooling coil outlet node = {}", state.dataLoopNodes->NodeID(CoolingCoilOutletNode)));
    4075            0 :                     ShowContinueError(state, format("..Heating coil inlet node  = {}", state.dataLoopNodes->NodeID(HeatingCoilInletNode)));
    4076            0 :                     ErrorsFound = true;
    4077              :                 }
    4078            0 :                 if (HeatingCoilOutletNode != SupHeatCoilInletNode) {
    4079            0 :                     ShowSevereError(state,
    4080            0 :                                     format("For {} = {}, Mismatch between heating coil outlet node and supplemental heating coil inlet node.",
    4081              :                                            CurrentModuleObject,
    4082              :                                            Alphas(1)));
    4083            0 :                     ShowContinueError(
    4084              :                         state,
    4085              :                         "..For \"BlowThrough\" fan, the heating coil outlet node name must match the supplemental heating coil inlet node name.");
    4086            0 :                     ShowContinueError(state,
    4087            0 :                                       format("..Heating coil outlet node             = {}", state.dataLoopNodes->NodeID(HeatingCoilOutletNode)));
    4088            0 :                     ShowContinueError(state,
    4089            0 :                                       format("..Supplemental heating coil inlet node = {}", state.dataLoopNodes->NodeID(SupHeatCoilInletNode)));
    4090            0 :                     ErrorsFound = true;
    4091              :                 }
    4092            0 :                 if (SupHeatCoilOutletNode != thisFurnace.FurnaceOutletNodeNum) {
    4093            0 :                     ShowSevereError(state,
    4094            0 :                                     format("For {} = {}, Mismatch between supplemental heating coil outlet node and HeatPump outlet node.",
    4095              :                                            CurrentModuleObject,
    4096              :                                            Alphas(1)));
    4097            0 :                     ShowContinueError(state, "..The supplemental heating coil outlet node name must match the HeatPump outlet node name.");
    4098            0 :                     ShowContinueError(state,
    4099            0 :                                       format("..Supplemental heating coil outlet node = {}", state.dataLoopNodes->NodeID(SupHeatCoilOutletNode)));
    4100            0 :                     ShowContinueError(
    4101            0 :                         state, format("..HeatPump outlet node                  = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    4102            0 :                     ErrorsFound = true;
    4103              :                 }
    4104              :             } else {
    4105            0 :                 CompSetFanInlet = "UNDEFINED";
    4106            0 :                 CompSetCoolInlet = Alphas(3);
    4107            0 :                 if (CoolingCoilInletNode != thisFurnace.FurnaceInletNodeNum) {
    4108            0 :                     ShowSevereError(state,
    4109            0 :                                     format("For {} = {}, Mismatch between unitary system inlet node and cooling coil inlet node.",
    4110              :                                            CurrentModuleObject,
    4111              :                                            Alphas(1)));
    4112            0 :                     ShowContinueError(
    4113              :                         state, "..For \"DrawThrough\" fan, the inlet node name for the HeatPump should match the cooling coil inlet node name.");
    4114            0 :                     ShowContinueError(state, format("..HeatPump inlet node     = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceInletNodeNum)));
    4115            0 :                     ShowContinueError(state, format("..Cooling coil inlet node = {}", state.dataLoopNodes->NodeID(CoolingCoilInletNode)));
    4116            0 :                     ErrorsFound = true;
    4117              :                 }
    4118            0 :                 if (CoolingCoilOutletNode != HeatingCoilInletNode) {
    4119            0 :                     ShowSevereError(state,
    4120            0 :                                     format("For {} = {}, Mismatch between cooling coil outlet node and heating coil inlet node.",
    4121              :                                            CurrentModuleObject,
    4122              :                                            Alphas(1)));
    4123            0 :                     ShowContinueError(state, "..The outlet node name for the cooling coil should match the heating coil inlet node name.");
    4124            0 :                     ShowContinueError(state, format("..Cooling coil outlet node = {}", state.dataLoopNodes->NodeID(CoolingCoilOutletNode)));
    4125            0 :                     ShowContinueError(state, format("..Heating coil inlet node  = {}", state.dataLoopNodes->NodeID(HeatingCoilInletNode)));
    4126            0 :                     ErrorsFound = true;
    4127              :                 }
    4128            0 :                 if (HeatingCoilOutletNode != FanInletNode) {
    4129            0 :                     ShowSevereError(
    4130            0 :                         state, format("For {} = {}, Mismatch between heating coil outlet node and fan inlet node.", CurrentModuleObject, Alphas(1)));
    4131            0 :                     ShowContinueError(state,
    4132              :                                       "..For \"DrawThrough\" fan, the outlet node name for the heating coil should match the fan inlet node name.");
    4133            0 :                     ShowContinueError(state, format("..Heating coil outlet node = {}", state.dataLoopNodes->NodeID(HeatingCoilOutletNode)));
    4134            0 :                     ShowContinueError(state, format("..Fan inlet node           = {}", state.dataLoopNodes->NodeID(FanInletNode)));
    4135            0 :                     ErrorsFound = true;
    4136              :                 }
    4137            0 :                 if (FanOutletNode != SupHeatCoilInletNode) {
    4138            0 :                     ShowSevereError(state,
    4139            0 :                                     format("For {} = {}, Mismatch between fan outlet node and supplemental heating coil inlet node.",
    4140              :                                            CurrentModuleObject,
    4141              :                                            Alphas(1)));
    4142            0 :                     ShowContinueError(
    4143              :                         state,
    4144              :                         "..For \"DrawThrough\" fan, the outlet node name for the fan should match the supplemental heating coil inlet node name.");
    4145            0 :                     ShowContinueError(state, format("..Fan outlet node                      = {}", state.dataLoopNodes->NodeID(FanOutletNode)));
    4146            0 :                     ShowContinueError(state,
    4147            0 :                                       format("..Supplemental heating coil inlet node = {}", state.dataLoopNodes->NodeID(SupHeatCoilInletNode)));
    4148            0 :                     ErrorsFound = true;
    4149              :                 }
    4150            0 :                 if (SupHeatCoilOutletNode != thisFurnace.FurnaceOutletNodeNum) {
    4151            0 :                     ShowSevereError(state,
    4152            0 :                                     format("For {} = {}, Mismatch between supplemental heating coil outlet node and HeatPump outlet node.",
    4153              :                                            CurrentModuleObject,
    4154              :                                            Alphas(1)));
    4155            0 :                     ShowContinueError(state, "..The supplemental heating coil outlet node name must match the HeatPump outlet node name.");
    4156            0 :                     ShowContinueError(state,
    4157            0 :                                       format("..Supplemental heating coil outlet node = {}", state.dataLoopNodes->NodeID(SupHeatCoilOutletNode)));
    4158            0 :                     ShowContinueError(
    4159            0 :                         state, format("..HeatPump outlet node                  = {}", state.dataLoopNodes->NodeID(thisFurnace.FurnaceOutletNodeNum)));
    4160            0 :                     ErrorsFound = true;
    4161              :                 }
    4162              :             }
    4163              :             //  (Set up validation here for the fan or cooling coil inlet?)
    4164            0 :             BranchNodeConnections::SetUpCompSets(state, CurrentModuleObject, Alphas(1), Alphas(6), Alphas(7), CompSetFanInlet, "UNDEFINED");
    4165              : 
    4166              :             // Add DX heating coil to component sets array
    4167            0 :             BranchNodeConnections::SetUpCompSets(state, CurrentModuleObject, Alphas(1), Alphas(8), Alphas(9), "UNDEFINED", "UNDEFINED");
    4168              : 
    4169              :             // Add DX cooling coil to component sets array
    4170            0 :             BranchNodeConnections::SetUpCompSets(state, CurrentModuleObject, Alphas(1), Alphas(10), Alphas(11), CompSetCoolInlet, "UNDEFINED");
    4171              : 
    4172              :             // Add supplemental heating coil to component sets array
    4173            0 :             BranchNodeConnections::SetUpCompSets(state, CurrentModuleObject, Alphas(1), Alphas(12), Alphas(13), "UNDEFINED", Alphas(4));
    4174              : 
    4175              :             // Set the Design Fan Volume Flow Rate
    4176            0 :             thisFurnace.ActualFanVolFlowRate = state.dataFans->fans(thisFurnace.FanIndex)->maxAirFlowRate;
    4177              : 
    4178              :             // CR8094 - simple water to air heat pump MUST operate at the same flow rate specified in the coil objects
    4179              :             //        Furnace(FurnaceNum)%DesignFanVolFlowRate = Numbers(1)
    4180              :             //        Furnace(FurnaceNum)%MaxHeatAirVolFlow    = Furnace(FurnaceNum)%DesignFanVolFlowRate
    4181              :             //        Furnace(FurnaceNum)%MaxCoolAirVolFlow    = Furnace(FurnaceNum)%DesignFanVolFlowRate
    4182              : 
    4183              :             // parameter estimate model only specifies air flow rate in parent object
    4184            0 :             if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingWaterToAirHP) {
    4185            0 :                 thisFurnace.MaxHeatAirVolFlow = Numbers(1);
    4186            0 :                 thisFurnace.MaxCoolAirVolFlow = Numbers(1);
    4187              :                 // simple HP model specifies air flow rate in both the parent and child coils. Use coil air flow rates.
    4188              :                 // simple HP model air flow rate input will not be used.
    4189            0 :             } else if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingWaterToAirHPSimple) {
    4190            0 :                 errFlag = false;
    4191            0 :                 thisFurnace.MaxHeatAirVolFlow = WaterToAirHeatPumpSimple::GetCoilAirFlowRate(state, HeatingCoilType, HeatingCoilName, errFlag);
    4192            0 :                 thisFurnace.MaxCoolAirVolFlow = WaterToAirHeatPumpSimple::GetCoilAirFlowRate(state, CoolingCoilType, CoolingCoilName, errFlag);
    4193            0 :                 if (errFlag) {
    4194            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    4195            0 :                     ErrorsFound = true;
    4196              :                 }
    4197            0 :             } else if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingWaterToAirHPVSEquationFit) {
    4198            0 :                 errFlag = false;
    4199            0 :                 thisFurnace.MaxHeatAirVolFlow = VariableSpeedCoils::GetCoilAirFlowRateVariableSpeed(state, HeatingCoilType, HeatingCoilName, errFlag);
    4200            0 :                 thisFurnace.MaxCoolAirVolFlow = VariableSpeedCoils::GetCoilAirFlowRateVariableSpeed(state, CoolingCoilType, CoolingCoilName, errFlag);
    4201            0 :                 if (errFlag) {
    4202            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    4203            0 :                     ErrorsFound = true;
    4204              :                 }
    4205              :             }
    4206              : 
    4207            0 :             thisFurnace.MaxNoCoolHeatAirVolFlow = min(thisFurnace.MaxHeatAirVolFlow, thisFurnace.MaxCoolAirVolFlow);
    4208            0 :             if (thisFurnace.MaxHeatAirVolFlow != DataSizing::AutoSize && thisFurnace.MaxCoolAirVolFlow != DataSizing::AutoSize) {
    4209            0 :                 thisFurnace.DesignFanVolFlowRate = max(thisFurnace.MaxHeatAirVolFlow, thisFurnace.MaxCoolAirVolFlow);
    4210              :             } else {
    4211            0 :                 thisFurnace.DesignFanVolFlowRate = DataSizing::AutoSize;
    4212              :             }
    4213              : 
    4214            0 :             thisFurnace.AirFlowControl = AirFlowControlConstFan::UseCompressorOnFlow;
    4215              : 
    4216            0 :             if (thisFurnace.ActualFanVolFlowRate != DataSizing::AutoSize && thisFurnace.DesignFanVolFlowRate != DataSizing::AutoSize) {
    4217            0 :                 if (thisFurnace.DesignFanVolFlowRate > thisFurnace.ActualFanVolFlowRate) {
    4218            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    4219            0 :                     ShowContinueError(state, "... has a Cooling or Heating Air Flow Rate > Max Fan Volume Flow Rate, should be <=.");
    4220            0 :                     ShowContinueError(state,
    4221            0 :                                       format("... Entered value={:.2R}... Fan [{}:{}] Max Value={:.2R}",
    4222            0 :                                              thisFurnace.DesignFanVolFlowRate,
    4223            0 :                                              HVAC::fanTypeNames[(int)thisFurnace.fanType],
    4224              :                                              FanName,
    4225            0 :                                              thisFurnace.ActualFanVolFlowRate));
    4226              :                 }
    4227              :             }
    4228            0 :             if (thisFurnace.ActualFanVolFlowRate != DataSizing::AutoSize && thisFurnace.DesignFanVolFlowRate != DataSizing::AutoSize) {
    4229            0 :                 if (thisFurnace.DesignFanVolFlowRate <= 0.0) {
    4230            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    4231            0 :                     ShowContinueError(state, "... has a Design Fan Flow Rate <= 0.0, it must be >0.0");
    4232            0 :                     ShowContinueError(state, format("... Entered value={:.2R}", thisFurnace.DesignFanVolFlowRate));
    4233            0 :                     ErrorsFound = true;
    4234              :                 }
    4235              :             }
    4236              : 
    4237              :             // Set the heat pump heating coil capacity
    4238              :             //  Get from coil module.
    4239            0 :             if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingWaterToAirHP) {
    4240            0 :                 errFlag = false;
    4241            0 :                 thisFurnace.DesignHeatingCapacity = WaterToAirHeatPump::GetCoilCapacity(state, HeatingCoilType, HeatingCoilName, errFlag);
    4242            0 :                 if (errFlag) {
    4243            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    4244            0 :                     ErrorsFound = true;
    4245              :                 }
    4246            0 :             } else if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingWaterToAirHPSimple) {
    4247            0 :                 errFlag = false;
    4248            0 :                 thisFurnace.DesignHeatingCapacity = WaterToAirHeatPumpSimple::GetCoilCapacity(state, HeatingCoilType, HeatingCoilName, errFlag);
    4249            0 :                 if (errFlag) {
    4250            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    4251            0 :                     ErrorsFound = true;
    4252              :                 }
    4253            0 :             } else if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingWaterToAirHPVSEquationFit) {
    4254            0 :                 errFlag = false;
    4255            0 :                 thisFurnace.DesignHeatingCapacity =
    4256            0 :                     VariableSpeedCoils::GetCoilCapacityVariableSpeed(state, HeatingCoilType, HeatingCoilName, errFlag);
    4257            0 :                 if (errFlag) {
    4258            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    4259            0 :                     ErrorsFound = true;
    4260              :                 }
    4261              :             }
    4262              :             // Set the heat pump heating coil convergence
    4263            0 :             thisFurnace.HeatingConvergenceTolerance = Numbers(2);
    4264              :             // Set the heat pump cooling coil capacity (Total capacity)
    4265              :             //  Get from coil module.
    4266            0 :             if (thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingWaterToAirHP) {
    4267            0 :                 errFlag = false;
    4268            0 :                 thisFurnace.DesignCoolingCapacity = WaterToAirHeatPump::GetCoilCapacity(state, CoolingCoilType, CoolingCoilName, errFlag);
    4269            0 :                 if (errFlag) {
    4270            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    4271            0 :                     ErrorsFound = true;
    4272              :                 }
    4273            0 :             } else if (thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingWaterToAirHPSimple) {
    4274            0 :                 errFlag = false;
    4275            0 :                 thisFurnace.DesignCoolingCapacity = WaterToAirHeatPumpSimple::GetCoilCapacity(state, CoolingCoilType, CoolingCoilName, errFlag);
    4276            0 :                 if (errFlag) {
    4277            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    4278            0 :                     ErrorsFound = true;
    4279              :                 }
    4280            0 :             } else if (thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingWaterToAirHPVSEquationFit) {
    4281            0 :                 errFlag = false;
    4282            0 :                 thisFurnace.DesignCoolingCapacity =
    4283            0 :                     VariableSpeedCoils::GetCoilCapacityVariableSpeed(state, CoolingCoilType, CoolingCoilName, errFlag);
    4284            0 :                 if (errFlag) {
    4285            0 :                     ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    4286            0 :                     ErrorsFound = true;
    4287              :                 }
    4288              :             }
    4289              :             // Set the heat pump cooling coil convergence
    4290            0 :             thisFurnace.CoolingConvergenceTolerance = Numbers(3);
    4291              : 
    4292              :             // Set the heatpump design supplemental heating capacity
    4293              :             //  Get from coil module.
    4294              : 
    4295              :             // Set the heatpump max outlet temperature
    4296            0 :             thisFurnace.DesignMaxOutletTemp = Numbers(4);
    4297              : 
    4298              :             // Set maximum supply air temperature for supplemental heating coil
    4299            0 :             thisFurnace.MaxOATSuppHeat = Numbers(5);
    4300            0 :             OutputReportPredefined::PreDefTableEntry(
    4301            0 :                 state, state.dataOutRptPredefined->pdchDXHeatCoilSuppHiT, HeatingCoilName, thisFurnace.MaxOATSuppHeat);
    4302              : 
    4303              :             // set minimum outdoor temperature for compressor operation
    4304            0 :             SetMinOATCompressor(state, FurnaceNum, cCurrentModuleObject, ErrorsFound);
    4305              : 
    4306              :         } // End of the Unitary System WaterToAirHeatPump Loop
    4307              : 
    4308            2 :         Alphas.deallocate();
    4309            2 :         Numbers.deallocate();
    4310              : 
    4311            2 :         if (ErrorsFound) {
    4312            0 :             ShowFatalError(state, "Errors found in getting Furnace or Unitary System input.");
    4313              :         }
    4314              : 
    4315            2 :         for (int HeatOnlyNum = 1; HeatOnlyNum <= NumHeatOnly; ++HeatOnlyNum) {
    4316            0 :             FurnaceNum = HeatOnlyNum;
    4317            0 :             auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    4318              :             // Setup Report variables for the Furnace that are not reported in the components themselves
    4319            0 :             SetupOutputVariable(state,
    4320              :                                 "Unitary System Fan Part Load Ratio",
    4321              :                                 Constant::Units::None,
    4322            0 :                                 thisFurnace.FanPartLoadRatio,
    4323              :                                 OutputProcessor::TimeStepType::System,
    4324              :                                 OutputProcessor::StoreType::Average,
    4325            0 :                                 thisFurnace.Name);
    4326            0 :             if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
    4327            0 :                 SetupEMSActuator(state,
    4328              :                                  "AirLoopHVAC:Unitary:Furnace:HeatOnly",
    4329              :                                  thisFurnace.Name,
    4330              :                                  "Autosized Supply Air Flow Rate",
    4331              :                                  "[m3/s]",
    4332            0 :                                  thisFurnace.DesignFanVolFlowRateEMSOverrideOn,
    4333            0 :                                  thisFurnace.DesignFanVolFlowRateEMSOverrideValue);
    4334              :             }
    4335              :         }
    4336              : 
    4337            2 :         for (int UnitaryHeatOnlyNum = NumHeatOnly + 1; UnitaryHeatOnlyNum <= NumHeatOnly + NumUnitaryHeatOnly; ++UnitaryHeatOnlyNum) {
    4338            0 :             FurnaceNum = UnitaryHeatOnlyNum;
    4339            0 :             auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    4340              :             // Setup Report variables for Unitary System that are not reported in the components themselves
    4341            0 :             SetupOutputVariable(state,
    4342              :                                 "Unitary System Fan Part Load Ratio",
    4343              :                                 Constant::Units::None,
    4344            0 :                                 thisFurnace.FanPartLoadRatio,
    4345              :                                 OutputProcessor::TimeStepType::System,
    4346              :                                 OutputProcessor::StoreType::Average,
    4347            0 :                                 thisFurnace.Name);
    4348            0 :             if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
    4349            0 :                 SetupEMSActuator(state,
    4350              :                                  "AirLoopHVAC:UnitaryHeatOnly",
    4351              :                                  thisFurnace.Name,
    4352              :                                  "Autosized Supply Air Flow Rate",
    4353              :                                  "[m3/s]",
    4354            0 :                                  thisFurnace.DesignFanVolFlowRateEMSOverrideOn,
    4355            0 :                                  thisFurnace.DesignFanVolFlowRateEMSOverrideValue);
    4356              :             }
    4357              :         }
    4358              : 
    4359            2 :         for (int HeatCoolNum = NumHeatOnly + NumUnitaryHeatOnly + 1; HeatCoolNum <= NumHeatOnly + NumUnitaryHeatOnly + NumHeatCool; ++HeatCoolNum) {
    4360            0 :             FurnaceNum = HeatCoolNum;
    4361            0 :             auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    4362              :             // Setup Report variables for the Furnace that are not reported in the components themselves
    4363            0 :             SetupOutputVariable(state,
    4364              :                                 "Unitary System Fan Part Load Ratio",
    4365              :                                 Constant::Units::None,
    4366            0 :                                 thisFurnace.FanPartLoadRatio,
    4367              :                                 OutputProcessor::TimeStepType::System,
    4368              :                                 OutputProcessor::StoreType::Average,
    4369            0 :                                 thisFurnace.Name);
    4370            0 :             SetupOutputVariable(state,
    4371              :                                 "Unitary System Compressor Part Load Ratio",
    4372              :                                 Constant::Units::None,
    4373            0 :                                 thisFurnace.CompPartLoadRatio,
    4374              :                                 OutputProcessor::TimeStepType::System,
    4375              :                                 OutputProcessor::StoreType::Average,
    4376            0 :                                 thisFurnace.Name);
    4377              : 
    4378            0 :             if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
    4379            0 :                 SetupEMSActuator(state,
    4380              :                                  "AirLoopHVAC:Unitary:Furnace:HeatCool",
    4381              :                                  thisFurnace.Name,
    4382              :                                  "Autosized Supply Air Flow Rate",
    4383              :                                  "[m3/s]",
    4384            0 :                                  thisFurnace.DesignFanVolFlowRateEMSOverrideOn,
    4385            0 :                                  thisFurnace.DesignFanVolFlowRateEMSOverrideValue);
    4386            0 :                 SetupEMSActuator(state,
    4387              :                                  "AirLoopHVAC:Unitary:Furnace:HeatCool",
    4388              :                                  thisFurnace.Name,
    4389              :                                  "Autosized Supply Air Flow Rate During Cooling Operation",
    4390              :                                  "[m3/s]",
    4391            0 :                                  thisFurnace.MaxCoolAirVolFlowEMSOverrideOn,
    4392            0 :                                  thisFurnace.MaxCoolAirVolFlowEMSOverrideValue);
    4393            0 :                 SetupEMSActuator(state,
    4394              :                                  "AirLoopHVAC:Unitary:Furnace:HeatCool",
    4395              :                                  thisFurnace.Name,
    4396              :                                  "Autosized Supply Air Flow Rate During Heating Operation",
    4397              :                                  "[m3/s]",
    4398            0 :                                  thisFurnace.MaxHeatAirVolFlowEMSOverrideOn,
    4399            0 :                                  thisFurnace.MaxHeatAirVolFlowEMSOverrideValue);
    4400            0 :                 SetupEMSActuator(state,
    4401              :                                  "AirLoopHVAC:Unitary:Furnace:HeatCool",
    4402              :                                  thisFurnace.Name,
    4403              :                                  "Autosized Supply Air Flow Rate During No Heating or Cooling Operation",
    4404              :                                  "[m3/s]",
    4405            0 :                                  thisFurnace.MaxNoCoolHeatAirVolFlowEMSOverrideOn,
    4406            0 :                                  thisFurnace.MaxNoCoolHeatAirVolFlowEMSOverrideValue);
    4407              :             }
    4408              :         }
    4409              : 
    4410            2 :         for (int UnitaryHeatCoolNum = NumHeatOnly + NumHeatCool + NumUnitaryHeatOnly + 1;
    4411            2 :              UnitaryHeatCoolNum <= NumHeatOnly + NumHeatCool + NumUnitaryHeatOnly + NumUnitaryHeatCool;
    4412              :              ++UnitaryHeatCoolNum) {
    4413            0 :             FurnaceNum = UnitaryHeatCoolNum;
    4414            0 :             auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    4415              :             // Setup Report variables for Unitary System that are not reported in the components themselves
    4416            0 :             SetupOutputVariable(state,
    4417              :                                 "Unitary System Fan Part Load Ratio",
    4418              :                                 Constant::Units::None,
    4419            0 :                                 thisFurnace.FanPartLoadRatio,
    4420              :                                 OutputProcessor::TimeStepType::System,
    4421              :                                 OutputProcessor::StoreType::Average,
    4422            0 :                                 thisFurnace.Name);
    4423            0 :             SetupOutputVariable(state,
    4424              :                                 "Unitary System Compressor Part Load Ratio",
    4425              :                                 Constant::Units::None,
    4426            0 :                                 thisFurnace.CompPartLoadRatio,
    4427              :                                 OutputProcessor::TimeStepType::System,
    4428              :                                 OutputProcessor::StoreType::Average,
    4429            0 :                                 thisFurnace.Name);
    4430            0 :             if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
    4431            0 :                 SetupEMSActuator(state,
    4432              :                                  "AirLoopHVAC:UnitaryHeatCool",
    4433              :                                  thisFurnace.Name,
    4434              :                                  "Autosized Supply Air Flow Rate",
    4435              :                                  "[m3/s]",
    4436            0 :                                  thisFurnace.DesignFanVolFlowRateEMSOverrideOn,
    4437            0 :                                  thisFurnace.DesignFanVolFlowRateEMSOverrideValue);
    4438            0 :                 SetupEMSActuator(state,
    4439              :                                  "AirLoopHVAC:UnitaryHeatCool",
    4440              :                                  thisFurnace.Name,
    4441              :                                  "Autosized Supply Air Flow Rate During Cooling Operation",
    4442              :                                  "[m3/s]",
    4443            0 :                                  thisFurnace.MaxCoolAirVolFlowEMSOverrideOn,
    4444            0 :                                  thisFurnace.MaxCoolAirVolFlowEMSOverrideValue);
    4445            0 :                 SetupEMSActuator(state,
    4446              :                                  "AirLoopHVAC:UnitaryHeatCool",
    4447              :                                  thisFurnace.Name,
    4448              :                                  "Autosized Supply Air Flow Rate During Heating Operation",
    4449              :                                  "[m3/s]",
    4450            0 :                                  thisFurnace.MaxHeatAirVolFlowEMSOverrideOn,
    4451            0 :                                  thisFurnace.MaxHeatAirVolFlowEMSOverrideValue);
    4452            0 :                 SetupEMSActuator(state,
    4453              :                                  "AirLoopHVAC:UnitaryHeatCool",
    4454              :                                  thisFurnace.Name,
    4455              :                                  "Autosized Supply Air Flow Rate During No Heating or Cooling Operation",
    4456              :                                  "[m3/s]",
    4457            0 :                                  thisFurnace.MaxNoCoolHeatAirVolFlowEMSOverrideOn,
    4458            0 :                                  thisFurnace.MaxNoCoolHeatAirVolFlowEMSOverrideValue);
    4459              :             }
    4460              :         }
    4461              : 
    4462            4 :         for (int HeatPumpNum = NumHeatOnly + NumHeatCool + NumUnitaryHeatOnly + NumUnitaryHeatCool + 1;
    4463            4 :              HeatPumpNum <= state.dataFurnaces->NumFurnaces - NumWaterToAirHeatPump;
    4464              :              ++HeatPumpNum) {
    4465            2 :             FurnaceNum = HeatPumpNum;
    4466            2 :             auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    4467              :             // Setup Report variables for Unitary System that are not reported in the components themselves
    4468            4 :             SetupOutputVariable(state,
    4469              :                                 "Unitary System Fan Part Load Ratio",
    4470              :                                 Constant::Units::None,
    4471            2 :                                 thisFurnace.FanPartLoadRatio,
    4472              :                                 OutputProcessor::TimeStepType::System,
    4473              :                                 OutputProcessor::StoreType::Average,
    4474            2 :                                 thisFurnace.Name);
    4475            4 :             SetupOutputVariable(state,
    4476              :                                 "Unitary System Compressor Part Load Ratio",
    4477              :                                 Constant::Units::None,
    4478            2 :                                 thisFurnace.CompPartLoadRatio,
    4479              :                                 OutputProcessor::TimeStepType::System,
    4480              :                                 OutputProcessor::StoreType::Average,
    4481            2 :                                 thisFurnace.Name);
    4482            4 :             SetupOutputVariable(state,
    4483              :                                 "Unitary System Dehumidification Induced Heating Demand Rate",
    4484              :                                 Constant::Units::W,
    4485            2 :                                 thisFurnace.DehumidInducedHeatingDemandRate,
    4486              :                                 OutputProcessor::TimeStepType::System,
    4487              :                                 OutputProcessor::StoreType::Average,
    4488            2 :                                 thisFurnace.Name);
    4489              : 
    4490            2 :             if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
    4491            0 :                 SetupEMSActuator(state,
    4492              :                                  "AirLoopHVAC:UnitaryHeatPump:AirToAir",
    4493              :                                  thisFurnace.Name,
    4494              :                                  "Autosized Supply Air Flow Rate",
    4495              :                                  "[m3/s]",
    4496            0 :                                  thisFurnace.DesignFanVolFlowRateEMSOverrideOn,
    4497            0 :                                  thisFurnace.DesignFanVolFlowRateEMSOverrideValue);
    4498              :             }
    4499              :         }
    4500              : 
    4501            2 :         for (int HeatPumpNum = NumHeatOnly + NumHeatCool + NumUnitaryHeatOnly + NumUnitaryHeatCool + NumHeatPump + 1;
    4502            2 :              HeatPumpNum <= state.dataFurnaces->NumFurnaces;
    4503              :              ++HeatPumpNum) {
    4504            0 :             FurnaceNum = HeatPumpNum;
    4505            0 :             auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    4506              :             // Setup Report variables for Unitary System that are not reported in the components themselves
    4507            0 :             SetupOutputVariable(state,
    4508              :                                 "Unitary System Fan Part Load Ratio",
    4509              :                                 Constant::Units::None,
    4510            0 :                                 thisFurnace.FanPartLoadRatio,
    4511              :                                 OutputProcessor::TimeStepType::System,
    4512              :                                 OutputProcessor::StoreType::Average,
    4513            0 :                                 thisFurnace.Name);
    4514            0 :             SetupOutputVariable(state,
    4515              :                                 "Unitary System Compressor Part Load Ratio",
    4516              :                                 Constant::Units::None,
    4517            0 :                                 thisFurnace.CompPartLoadRatio,
    4518              :                                 OutputProcessor::TimeStepType::System,
    4519              :                                 OutputProcessor::StoreType::Average,
    4520            0 :                                 thisFurnace.Name);
    4521            0 :             SetupOutputVariable(state,
    4522              :                                 "Unitary System Requested Sensible Cooling Rate",
    4523              :                                 Constant::Units::W,
    4524            0 :                                 thisFurnace.CoolingCoilSensDemand,
    4525              :                                 OutputProcessor::TimeStepType::System,
    4526              :                                 OutputProcessor::StoreType::Average,
    4527            0 :                                 thisFurnace.Name);
    4528            0 :             SetupOutputVariable(state,
    4529              :                                 "Unitary System Requested Latent Cooling Rate",
    4530              :                                 Constant::Units::W,
    4531            0 :                                 thisFurnace.CoolingCoilLatentDemand,
    4532              :                                 OutputProcessor::TimeStepType::System,
    4533              :                                 OutputProcessor::StoreType::Average,
    4534            0 :                                 thisFurnace.Name);
    4535            0 :             SetupOutputVariable(state,
    4536              :                                 "Unitary System Requested Heating Rate",
    4537              :                                 Constant::Units::W,
    4538            0 :                                 thisFurnace.HeatingCoilSensDemand,
    4539              :                                 OutputProcessor::TimeStepType::System,
    4540              :                                 OutputProcessor::StoreType::Average,
    4541            0 :                                 thisFurnace.Name);
    4542            0 :             SetupOutputVariable(state,
    4543              :                                 "Unitary System Dehumidification Induced Heating Demand Rate",
    4544              :                                 Constant::Units::W,
    4545            0 :                                 thisFurnace.DehumidInducedHeatingDemandRate,
    4546              :                                 OutputProcessor::TimeStepType::System,
    4547              :                                 OutputProcessor::StoreType::Average,
    4548            0 :                                 thisFurnace.Name);
    4549              : 
    4550            0 :             if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
    4551            0 :                 SetupEMSActuator(state,
    4552              :                                  "AirLoopHVAC:UnitaryHeatPump:WaterToAir",
    4553              :                                  thisFurnace.Name,
    4554              :                                  "Autosized Supply Air Flow Rate",
    4555              :                                  "[m3/s]",
    4556            0 :                                  thisFurnace.DesignFanVolFlowRateEMSOverrideOn,
    4557            0 :                                  thisFurnace.DesignFanVolFlowRateEMSOverrideValue);
    4558              :             }
    4559              :         }
    4560              : 
    4561            2 :         if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
    4562            0 :             for (FurnaceNum = 1; FurnaceNum <= state.dataFurnaces->NumFurnaces; ++FurnaceNum) {
    4563            0 :                 auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    4564            0 :                 SetupEMSInternalVariable(state, "Unitary HVAC Design Heating Capacity", thisFurnace.Name, "[W]", thisFurnace.DesignHeatingCapacity);
    4565            0 :                 SetupEMSInternalVariable(state, "Unitary HVAC Design Cooling Capacity", thisFurnace.Name, "[W]", thisFurnace.DesignCoolingCapacity);
    4566            0 :                 SetupEMSActuator(state,
    4567              :                                  "Unitary HVAC",
    4568              :                                  thisFurnace.Name,
    4569              :                                  "Sensible Load Request",
    4570              :                                  "[W]",
    4571            0 :                                  thisFurnace.EMSOverrideSensZoneLoadRequest,
    4572            0 :                                  thisFurnace.EMSSensibleZoneLoadValue);
    4573            0 :                 SetupEMSActuator(state,
    4574              :                                  "Unitary HVAC",
    4575              :                                  thisFurnace.Name,
    4576              :                                  "Moisture Load Request",
    4577              :                                  "[W]",
    4578            0 :                                  thisFurnace.EMSOverrideMoistZoneLoadRequest,
    4579            0 :                                  thisFurnace.EMSMoistureZoneLoadValue);
    4580              :             }
    4581              :         }
    4582              :         bool anyRan;
    4583            2 :         EMSManager::ManageEMS(state, EMSManager::EMSCallFrom::ComponentGetInput, anyRan, ObjexxFCL::Optional_int_const());
    4584            2 :     }
    4585              : 
    4586              :     // End of Get Input subroutines for this Module
    4587              :     //******************************************************************************
    4588              : 
    4589              :     // Beginning Initialization Section of the Module
    4590              :     //******************************************************************************
    4591              : 
    4592        15222 :     void InitFurnace(EnergyPlusData &state,
    4593              :                      int const FurnaceNum,         // index to Furnace
    4594              :                      int const AirLoopNum,         // index to air loop
    4595              :                      Real64 &OnOffAirFlowRatio,    // ratio of on to off air mass flow rate
    4596              :                      HVAC::FanOp &fanOp,           // fan operating mode
    4597              :                      Real64 &ZoneLoad,             // zone sensible load to be met (modified here as needed) (W)
    4598              :                      Real64 &MoistureLoad,         // zone moisture load (W)
    4599              :                      bool const FirstHVACIteration // TRUE if first HVAC iteration
    4600              :     )
    4601              :     {
    4602              : 
    4603              :         // SUBROUTINE INFORMATION:
    4604              :         //       AUTHOR         Richard J. Liesen
    4605              :         //       DATE WRITTEN   Feb 2001
    4606              :         //       MODIFIED       Oct 2001, Richard Raustad
    4607              :         //                      Sep 2008, R. Raustad - revised logic to determine load to be met
    4608              :         //                      Bereket Nigusse, June 2010 - added a procedure to calculate supply air flow fraction
    4609              :         //                      through controlled zone
    4610              :         //                      Bo Shen, March 2012 - for VS WSHP
    4611              :         //                      Bo Shen, ORNL, July 2012 - added variable-speed air source heat pump cooling and heating coils, using curve-fits
    4612              : 
    4613              :         // PURPOSE OF THIS SUBROUTINE:
    4614              :         // This subroutine is for initializations of the Furnace Components.
    4615              : 
    4616              :         // METHODOLOGY EMPLOYED:
    4617              :         // Uses the status flags to trigger initializations.
    4618              :         // The HeatCool furnace/unitarysystem and air-to-air heat pump may have alternate air flow rates
    4619              :         // in cooling, heating, and when no cooling or heating is needed. Set up the coil (comp) ON and OFF
    4620              :         // air flow rates during InitFurnace. Use these flow rates during the Calc routines to set the
    4621              :         // average mass flow rates based on PLR.
    4622              : 
    4623              :         // SUBROUTINE PARAMETER DEFINITIONS:
    4624        15222 :         Real64 constexpr Small5WLoad(5.0);
    4625        15222 :         std::string_view constexpr RoutineName("InitFurnace");
    4626              : 
    4627              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    4628              :         bool errFlag;          // error flag for mining functions
    4629              :         Real64 QZnReq;         // furnace load based on control zone frac (W)
    4630              :         Real64 PartLoadRatio;  // furnace part-load ratio
    4631              :         Real64 SensibleOutput; // no load sensible output (coils off) (W)
    4632              :         Real64 LatentOutput;   // no load latent output (coils off) (W)
    4633              :         Real64 QToCoolSetPt;   // sensible load to cooling setpoint (W)
    4634              :         Real64 QToHeatSetPt;   // sensible load to heating setpoint (W)
    4635              :         // calculation (kg/kg)
    4636              :         Real64 DeltaMassRate; // Difference of mass flow rate between
    4637              :         // inlet node and system outlet node
    4638              :         Real64 MassFlowRate; // mass flow rate to calculate loss
    4639              : 
    4640        15222 :         Real64 SumOfMassFlowRateMax(0.0);                 // the sum of mass flow rates at inlet to zones in an airloop
    4641        15222 :         Real64 CntrlZoneTerminalUnitMassFlowRateMax(0.0); // Maximum mass flow rate through controlled zone terminal unit
    4642              : 
    4643        15222 :         bool ErrorsFound(false);                 // flag returned from mining call
    4644        15222 :         Real64 mdot(0.0);                        // local temporary for mass flow rate (kg/s)
    4645        15222 :         Real64 rho(0.0);                         // local for fluid density
    4646        15222 :         Real64 SteamDensity(0.0);                // density of steam at 100C, used for steam heating coils
    4647        15222 :         Real64 CoilMaxVolFlowRate(0.0);          // coil fluid maximum volume flow rate
    4648        15222 :         Real64 QActual(0.0);                     // coil actual capacity
    4649        15222 :         Real64 SUPHEATERLOAD(0.0);               // SUPPLEMENTAL HEATER LOAD
    4650              :         Real64 RhoAir;                           // Air density at InNode
    4651              :         Furnaces::ModeOfOperation OperatingMode; // track cooling, heating, and no cooling or heating modes
    4652              :         Furnaces::ModeOfOperation OperatingModeMinusOne;
    4653              :         Furnaces::ModeOfOperation OperatingModeMinusTwo;
    4654              :         bool Oscillate; // detection of oscillating operating modes
    4655              : 
    4656        15222 :         auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    4657        15222 :         int InNode = thisFurnace.FurnaceInletNodeNum;
    4658        15222 :         int OutNode = thisFurnace.FurnaceOutletNodeNum;
    4659              : 
    4660        15222 :         if (state.dataFurnaces->InitFurnaceMyOneTimeFlag) {
    4661              :             // initialize the environment and sizing flags
    4662            2 :             state.dataFurnaces->MyEnvrnFlag.allocate(state.dataFurnaces->NumFurnaces);
    4663            2 :             state.dataFurnaces->MySizeFlag.allocate(state.dataFurnaces->NumFurnaces);
    4664            2 :             state.dataFurnaces->MySecondOneTimeFlag.allocate(state.dataFurnaces->NumFurnaces);
    4665            2 :             state.dataFurnaces->MyFanFlag.allocate(state.dataFurnaces->NumFurnaces);
    4666            2 :             state.dataFurnaces->MyCheckFlag.allocate(state.dataFurnaces->NumFurnaces);
    4667            2 :             state.dataFurnaces->MyFlowFracFlag.allocate(state.dataFurnaces->NumFurnaces);
    4668            2 :             state.dataFurnaces->MyPlantScanFlag.allocate(state.dataFurnaces->NumFurnaces);
    4669            2 :             state.dataFurnaces->MySuppCoilPlantScanFlag.allocate(state.dataFurnaces->NumFurnaces);
    4670            2 :             state.dataFurnaces->MyEnvrnFlag = true;
    4671            2 :             state.dataFurnaces->MySizeFlag = true;
    4672            2 :             state.dataFurnaces->MySecondOneTimeFlag = true;
    4673            2 :             state.dataFurnaces->MyFanFlag = true;
    4674            2 :             state.dataFurnaces->MyCheckFlag = true;
    4675            2 :             state.dataFurnaces->MyFlowFracFlag = true;
    4676            2 :             state.dataFurnaces->InitFurnaceMyOneTimeFlag = false;
    4677            2 :             state.dataFurnaces->MyPlantScanFlag = true;
    4678            2 :             state.dataFurnaces->MySuppCoilPlantScanFlag = true;
    4679              :         }
    4680              : 
    4681        15222 :         if (state.dataGlobal->BeginEnvrnFlag && state.dataFurnaces->MyAirLoopPass) {
    4682            6 :             state.dataFurnaces->AirLoopPass = 0;
    4683            6 :             state.dataFurnaces->MyAirLoopPass = false;
    4684              :         }
    4685        15222 :         if (!state.dataGlobal->BeginEnvrnFlag) {
    4686        15136 :             state.dataFurnaces->MyAirLoopPass = true;
    4687              :         }
    4688              : 
    4689        15222 :         ++state.dataFurnaces->AirLoopPass;
    4690        15222 :         if (state.dataFurnaces->AirLoopPass > 2) state.dataFurnaces->AirLoopPass = 1;
    4691              : 
    4692        15222 :         if (!state.dataGlobal->SysSizingCalc && state.dataFurnaces->MySizeFlag(FurnaceNum)) {
    4693              :             // for each furnace, do the sizing once.
    4694            2 :             SizeFurnace(state, FurnaceNum, FirstHVACIteration);
    4695            2 :             thisFurnace.ControlZoneMassFlowFrac = 1.0;
    4696              : 
    4697            2 :             state.dataFurnaces->MySizeFlag(FurnaceNum) = false;
    4698              :             // Pass the fan cycling schedule index up to the air loop. Set the air loop unitary system flag.
    4699            2 :             state.dataAirLoop->AirLoopControlInfo(AirLoopNum).cycFanSched = thisFurnace.fanOpModeSched;
    4700            2 :             state.dataAirLoop->AirLoopControlInfo(AirLoopNum).UnitarySys = true;
    4701              :             // RR this is wrong, Op mode needs to be updated each time atep
    4702            2 :             state.dataAirLoop->AirLoopControlInfo(AirLoopNum).fanOp = thisFurnace.fanOp;
    4703              : 
    4704              :             // Check that heat pump heating capacity is within 20% of cooling capacity
    4705            2 :             if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_AirToAir) {
    4706            2 :                 if (std::abs(thisFurnace.DesignCoolingCapacity - thisFurnace.DesignHeatingCapacity) / thisFurnace.DesignCoolingCapacity > 0.2) {
    4707            0 :                     ShowWarningError(state,
    4708            0 :                                      format("{} \"{}\" heating capacity is disproportionate (> 20% different) to total cooling capacity",
    4709            0 :                                             HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    4710            0 :                                             thisFurnace.Name));
    4711              :                 }
    4712              :             }
    4713              :         }
    4714              : 
    4715        15222 :         if (!state.dataGlobal->DoingSizing && state.dataFurnaces->MySecondOneTimeFlag(FurnaceNum)) {
    4716              :             // sizing all done.  check fan air flow rates
    4717            4 :             thisFurnace.ActualFanVolFlowRate = state.dataFans->fans(thisFurnace.FanIndex)->maxAirFlowRate;
    4718            4 :             if (thisFurnace.ActualFanVolFlowRate != DataSizing::AutoSize) {
    4719            2 :                 if (thisFurnace.DesignFanVolFlowRate > thisFurnace.ActualFanVolFlowRate) {
    4720            0 :                     ShowWarningError(state,
    4721            0 :                                      format("{}={} has a Design Fan Volume Flow Rate > Max Fan Volume Flow Rate, should be <=",
    4722            0 :                                             HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    4723            0 :                                             thisFurnace.Name));
    4724            0 :                     ShowContinueError(state,
    4725            0 :                                       format("... Entered value={:.2R}... Fan [{}] Max Value={:.2R}",
    4726            0 :                                              thisFurnace.DesignFanVolFlowRate,
    4727            0 :                                              HVAC::fanTypeNames[(int)thisFurnace.fanType],
    4728            0 :                                              thisFurnace.ActualFanVolFlowRate));
    4729              :                 }
    4730            2 :                 if (thisFurnace.DesignFanVolFlowRate <= 0.0) {
    4731            0 :                     ShowSevereError(state,
    4732            0 :                                     format("{}={} has a Design Fan Volume Flow Rate <= 0.0, it must be >0.0",
    4733            0 :                                            HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    4734            0 :                                            thisFurnace.Name));
    4735            0 :                     ShowContinueError(state, format("... Entered value={:.2R}", thisFurnace.DesignFanVolFlowRate));
    4736              :                 }
    4737              : 
    4738            2 :                 state.dataFurnaces->MySecondOneTimeFlag(FurnaceNum) = false;
    4739              :             }
    4740              :         }
    4741              : 
    4742              :         // Scan hot water and steam heating coil plant components for one time initializations
    4743        15222 :         if (state.dataFurnaces->MyPlantScanFlag(FurnaceNum) && allocated(state.dataPlnt->PlantLoop)) {
    4744            2 :             if ((thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingWater) || (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingSteam)) {
    4745              : 
    4746            0 :                 if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingWater) {
    4747              : 
    4748            0 :                     errFlag = false;
    4749            0 :                     PlantUtilities::ScanPlantLoopsForObject(state,
    4750              :                                                             thisFurnace.HeatingCoilName,
    4751              :                                                             DataPlant::PlantEquipmentType::CoilWaterSimpleHeating,
    4752            0 :                                                             thisFurnace.plantLoc,
    4753              :                                                             errFlag,
    4754              :                                                             _,
    4755              :                                                             _,
    4756              :                                                             _,
    4757              :                                                             _,
    4758              :                                                             _);
    4759            0 :                     if (errFlag) {
    4760            0 :                         ShowFatalError(state, "InitFurnace: Program terminated for previous conditions.");
    4761              :                     }
    4762            0 :                     thisFurnace.MaxHeatCoilFluidFlow =
    4763            0 :                         WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", thisFurnace.HeatingCoilName, ErrorsFound);
    4764            0 :                     if (thisFurnace.MaxHeatCoilFluidFlow > 0.0) {
    4765              :                         rho =
    4766            0 :                             state.dataPlnt->PlantLoop(thisFurnace.plantLoc.loopNum).glycol->getDensity(state, Constant::HWInitConvTemp, RoutineName);
    4767            0 :                         thisFurnace.MaxHeatCoilFluidFlow *= rho;
    4768              :                     }
    4769            0 :                 } else if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingSteam) {
    4770              : 
    4771            0 :                     errFlag = false;
    4772            0 :                     PlantUtilities::ScanPlantLoopsForObject(state,
    4773              :                                                             thisFurnace.HeatingCoilName,
    4774              :                                                             DataPlant::PlantEquipmentType::CoilSteamAirHeating,
    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 = SteamCoils::GetCoilMaxSteamFlowRate(state, thisFurnace.HeatingCoilIndex, ErrorsFound);
    4786            0 :                     if (thisFurnace.MaxHeatCoilFluidFlow > 0.0) {
    4787            0 :                         SteamDensity = Fluid::GetSteam(state)->getSatDensity(state, state.dataFurnaces->TempSteamIn, 1.0, RoutineName);
    4788            0 :                         thisFurnace.MaxHeatCoilFluidFlow *= SteamDensity;
    4789              :                     }
    4790              :                 }
    4791              :                 // fill outlet node for coil
    4792            0 :                 thisFurnace.CoilOutletNode = DataPlant::CompData::getPlantComponent(state, thisFurnace.plantLoc).NodeNumOut;
    4793            0 :                 state.dataFurnaces->MyPlantScanFlag(FurnaceNum) = false;
    4794              :             } else { // pthp not connected to plant
    4795            2 :                 state.dataFurnaces->MyPlantScanFlag(FurnaceNum) = false;
    4796              :             }
    4797        15220 :         } else if (state.dataFurnaces->MyPlantScanFlag(FurnaceNum) && !state.dataGlobal->AnyPlantInModel) {
    4798            0 :             state.dataFurnaces->MyPlantScanFlag(FurnaceNum) = false;
    4799              :         }
    4800              : 
    4801              :         // Scan Supplemental hot water and steam heating coil plant components for one time initializations
    4802        15222 :         if (state.dataFurnaces->MySuppCoilPlantScanFlag(FurnaceNum) && allocated(state.dataPlnt->PlantLoop)) {
    4803            2 :             if ((thisFurnace.SuppHeatCoilType_Num == HVAC::Coil_HeatingWater) || (thisFurnace.SuppHeatCoilType_Num == HVAC::Coil_HeatingSteam)) {
    4804              : 
    4805            0 :                 if (thisFurnace.SuppHeatCoilType_Num == HVAC::Coil_HeatingWater) {
    4806            0 :                     errFlag = false;
    4807            0 :                     PlantUtilities::ScanPlantLoopsForObject(state,
    4808              :                                                             thisFurnace.SuppHeatCoilName,
    4809              :                                                             DataPlant::PlantEquipmentType::CoilWaterSimpleHeating,
    4810            0 :                                                             thisFurnace.SuppPlantLoc,
    4811              :                                                             errFlag,
    4812              :                                                             _,
    4813              :                                                             _,
    4814              :                                                             _,
    4815              :                                                             _,
    4816              :                                                             _);
    4817            0 :                     if (errFlag) {
    4818            0 :                         ShowFatalError(state, "InitFurnace: Program terminated for previous conditions.");
    4819              :                     }
    4820            0 :                     thisFurnace.MaxSuppCoilFluidFlow =
    4821            0 :                         WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", thisFurnace.SuppHeatCoilName, ErrorsFound);
    4822            0 :                     if (thisFurnace.MaxSuppCoilFluidFlow > 0.0) {
    4823            0 :                         rho = state.dataPlnt->PlantLoop(thisFurnace.SuppPlantLoc.loopNum)
    4824            0 :                                   .glycol->getDensity(state, Constant::HWInitConvTemp, RoutineName);
    4825            0 :                         thisFurnace.MaxSuppCoilFluidFlow *= rho;
    4826              :                     }
    4827            0 :                 } else if (thisFurnace.SuppHeatCoilType_Num == HVAC::Coil_HeatingSteam) {
    4828            0 :                     errFlag = false;
    4829            0 :                     PlantUtilities::ScanPlantLoopsForObject(state,
    4830              :                                                             thisFurnace.SuppHeatCoilName,
    4831              :                                                             DataPlant::PlantEquipmentType::CoilSteamAirHeating,
    4832            0 :                                                             thisFurnace.SuppPlantLoc,
    4833              :                                                             errFlag,
    4834              :                                                             _,
    4835              :                                                             _,
    4836              :                                                             _,
    4837              :                                                             _,
    4838              :                                                             _);
    4839            0 :                     if (errFlag) {
    4840            0 :                         ShowFatalError(state, "InitFurnace: Program terminated for previous conditions.");
    4841              :                     }
    4842            0 :                     thisFurnace.MaxSuppCoilFluidFlow = SteamCoils::GetCoilMaxSteamFlowRate(state, thisFurnace.SuppHeatCoilIndex, ErrorsFound);
    4843            0 :                     if (thisFurnace.MaxSuppCoilFluidFlow > 0.0) {
    4844            0 :                         SteamDensity = Fluid::GetSteam(state)->getSatDensity(state, state.dataFurnaces->TempSteamIn, 1.0, RoutineName);
    4845            0 :                         thisFurnace.MaxSuppCoilFluidFlow *= SteamDensity;
    4846              :                     }
    4847              :                 }
    4848              :                 // fill outlet node for coil
    4849            0 :                 thisFurnace.SuppCoilOutletNode = DataPlant::CompData::getPlantComponent(state, thisFurnace.SuppPlantLoc).NodeNumOut;
    4850            0 :                 state.dataFurnaces->MySuppCoilPlantScanFlag(FurnaceNum) = false;
    4851              :             } else { // pthp not connected to plant
    4852            2 :                 state.dataFurnaces->MySuppCoilPlantScanFlag(FurnaceNum) = false;
    4853              :             }
    4854              : 
    4855        15220 :         } else if (state.dataFurnaces->MySuppCoilPlantScanFlag(FurnaceNum) && !state.dataGlobal->AnyPlantInModel) {
    4856            0 :             state.dataFurnaces->MySuppCoilPlantScanFlag(FurnaceNum) = false;
    4857              :         }
    4858              : 
    4859              :         // Do the Begin Environment initializations
    4860        15222 :         if (state.dataGlobal->BeginEnvrnFlag && state.dataFurnaces->MyEnvrnFlag(FurnaceNum)) {
    4861              :             // Change the Volume Flow Rates to Mass Flow Rates
    4862            6 :             thisFurnace.DesignMassFlowRate = thisFurnace.DesignFanVolFlowRate * state.dataEnvrn->StdRhoAir;
    4863            6 :             thisFurnace.MaxCoolAirMassFlow = thisFurnace.MaxCoolAirVolFlow * state.dataEnvrn->StdRhoAir;
    4864            6 :             thisFurnace.MaxHeatAirMassFlow = thisFurnace.MaxHeatAirVolFlow * state.dataEnvrn->StdRhoAir;
    4865            6 :             thisFurnace.MaxNoCoolHeatAirMassFlow = thisFurnace.MaxNoCoolHeatAirVolFlow * state.dataEnvrn->StdRhoAir;
    4866            6 :             thisFurnace.CompPartLoadRatio = 0.0;
    4867            6 :             thisFurnace.CoolingCoilSensDemand = 0.0;
    4868            6 :             thisFurnace.CoolingCoilLatentDemand = 0.0;
    4869            6 :             thisFurnace.HeatingCoilSensDemand = 0.0;
    4870              : 
    4871            6 :             thisFurnace.SenLoadLoss = 0.0;
    4872            6 :             if (thisFurnace.Humidistat) {
    4873            0 :                 thisFurnace.LatLoadLoss = 0.0;
    4874              :             }
    4875              : 
    4876              :             //   set fluid-side hardware limits
    4877            6 :             if (thisFurnace.CoilControlNode > 0) {
    4878              : 
    4879            0 :                 if (thisFurnace.MaxHeatCoilFluidFlow == DataSizing::AutoSize) {
    4880              :                     // If water coil max water flow rate is autosized, simulate once in order to mine max flow rate
    4881            0 :                     if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingWater) {
    4882            0 :                         WaterCoils::SimulateWaterCoilComponents(state, thisFurnace.HeatingCoilName, FirstHVACIteration, thisFurnace.HeatingCoilIndex);
    4883              :                         CoilMaxVolFlowRate =
    4884            0 :                             WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", thisFurnace.HeatingCoilName, ErrorsFound);
    4885            0 :                         if (CoilMaxVolFlowRate != DataSizing::AutoSize) {
    4886            0 :                             rho = state.dataPlnt->PlantLoop(thisFurnace.plantLoc.loopNum)
    4887            0 :                                       .glycol->getDensity(state, Constant::HWInitConvTemp, RoutineName);
    4888            0 :                             thisFurnace.MaxHeatCoilFluidFlow = CoilMaxVolFlowRate * rho;
    4889              :                         }
    4890              :                     }
    4891              :                     // If steam coil max steam flow rate is autosized, simulate once in order to mine max flow rate
    4892            0 :                     if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingSteam) {
    4893            0 :                         SteamCoils::SimulateSteamCoilComponents(state,
    4894              :                                                                 thisFurnace.HeatingCoilName,
    4895              :                                                                 FirstHVACIteration,
    4896            0 :                                                                 thisFurnace.HeatingCoilIndex,
    4897            0 :                                                                 1.0,
    4898              :                                                                 QActual); // QCoilReq, simulate any load > 0 to get max capacity
    4899            0 :                         CoilMaxVolFlowRate = SteamCoils::GetCoilMaxSteamFlowRate(state, thisFurnace.HeatingCoilIndex, ErrorsFound);
    4900            0 :                         if (CoilMaxVolFlowRate != DataSizing::AutoSize) {
    4901            0 :                             SteamDensity = Fluid::GetSteam(state)->getSatDensity(state, state.dataFurnaces->TempSteamIn, 1.0, RoutineName);
    4902            0 :                             thisFurnace.MaxHeatCoilFluidFlow = CoilMaxVolFlowRate * SteamDensity;
    4903              :                         }
    4904              :                     }
    4905              :                 }
    4906              : 
    4907            0 :                 PlantUtilities::InitComponentNodes(
    4908              :                     state, 0.0, thisFurnace.MaxHeatCoilFluidFlow, thisFurnace.CoilControlNode, thisFurnace.CoilOutletNode);
    4909              :             }
    4910            6 :             if (thisFurnace.SuppCoilControlNode > 0) {
    4911            0 :                 if (thisFurnace.MaxSuppCoilFluidFlow == DataSizing::AutoSize) {
    4912            0 :                     if (thisFurnace.SuppHeatCoilType_Num == HVAC::Coil_HeatingWater) {
    4913              :                         // If water coil max water flow rate is autosized, simulate once in order to mine max flow rate
    4914            0 :                         WaterCoils::SimulateWaterCoilComponents(
    4915            0 :                             state, thisFurnace.SuppHeatCoilName, FirstHVACIteration, thisFurnace.SuppHeatCoilIndex);
    4916              :                         CoilMaxVolFlowRate =
    4917            0 :                             WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", thisFurnace.SuppHeatCoilName, ErrorsFound);
    4918            0 :                         if (CoilMaxVolFlowRate != DataSizing::AutoSize) {
    4919            0 :                             rho = state.dataPlnt->PlantLoop(thisFurnace.SuppPlantLoc.loopNum)
    4920            0 :                                       .glycol->getDensity(state, Constant::HWInitConvTemp, RoutineName);
    4921            0 :                             thisFurnace.MaxSuppCoilFluidFlow = CoilMaxVolFlowRate * rho;
    4922              :                         }
    4923              :                     }
    4924            0 :                     if (thisFurnace.SuppHeatCoilType_Num == HVAC::Coil_HeatingSteam) {
    4925            0 :                         SteamCoils::SimulateSteamCoilComponents(state,
    4926              :                                                                 thisFurnace.SuppHeatCoilName,
    4927              :                                                                 FirstHVACIteration,
    4928            0 :                                                                 thisFurnace.SuppHeatCoilIndex,
    4929            0 :                                                                 1.0,
    4930              :                                                                 QActual); // QCoilReq, simulate any load > 0 to get max capacity
    4931            0 :                         CoilMaxVolFlowRate = SteamCoils::GetCoilMaxSteamFlowRate(state, thisFurnace.SuppHeatCoilIndex, ErrorsFound);
    4932            0 :                         if (CoilMaxVolFlowRate != DataSizing::AutoSize) {
    4933            0 :                             SteamDensity = Fluid::GetSteam(state)->getSatDensity(state, state.dataFurnaces->TempSteamIn, 1.0, RoutineName);
    4934            0 :                             thisFurnace.MaxSuppCoilFluidFlow = CoilMaxVolFlowRate * SteamDensity;
    4935              :                         }
    4936              :                     }
    4937            0 :                     PlantUtilities::InitComponentNodes(
    4938              :                         state, 0.0, thisFurnace.MaxSuppCoilFluidFlow, thisFurnace.SuppCoilControlNode, thisFurnace.SuppCoilOutletNode);
    4939              :                 }
    4940              :             }
    4941            6 :             state.dataFurnaces->MyEnvrnFlag(FurnaceNum) = false;
    4942              :         }
    4943              : 
    4944        15222 :         if (!state.dataGlobal->BeginEnvrnFlag) {
    4945        15136 :             state.dataFurnaces->MyEnvrnFlag(FurnaceNum) = true;
    4946              :         }
    4947              : 
    4948        15222 :         if (state.dataFurnaces->MyFanFlag(FurnaceNum)) {
    4949            4 :             if (thisFurnace.ActualFanVolFlowRate != DataSizing::AutoSize) {
    4950            2 :                 if (thisFurnace.ActualFanVolFlowRate > 0.0) {
    4951            2 :                     thisFurnace.HeatingSpeedRatio = thisFurnace.MaxHeatAirVolFlow / thisFurnace.ActualFanVolFlowRate;
    4952            2 :                     thisFurnace.CoolingSpeedRatio = thisFurnace.MaxCoolAirVolFlow / thisFurnace.ActualFanVolFlowRate;
    4953            2 :                     thisFurnace.NoHeatCoolSpeedRatio = thisFurnace.MaxNoCoolHeatAirVolFlow / thisFurnace.ActualFanVolFlowRate;
    4954              :                 }
    4955            2 :                 if (dynamic_cast<Fans::FanComponent *>(state.dataFans->fans(thisFurnace.FanIndex))->powerRatioAtSpeedRatioCurveNum > 0) {
    4956            0 :                     if (thisFurnace.ActualFanVolFlowRate == thisFurnace.MaxHeatAirVolFlow &&
    4957            0 :                         thisFurnace.ActualFanVolFlowRate == thisFurnace.MaxCoolAirVolFlow &&
    4958            0 :                         thisFurnace.ActualFanVolFlowRate == thisFurnace.MaxNoCoolHeatAirVolFlow) {
    4959            0 :                         std::string FanName = state.dataFans->fans(thisFurnace.FanIndex)->Name;
    4960            0 :                         ShowWarningError(state, format("{} \"{}\"", HVAC::unitarySysTypeNames[(int)thisFurnace.type], thisFurnace.Name));
    4961            0 :                         ShowContinueError(state,
    4962            0 :                                           format("...For fan type and name = {} \"{}\"", HVAC::fanTypeNames[(int)thisFurnace.fanType], FanName));
    4963            0 :                         ShowContinueError(state,
    4964              :                                           "...Fan power ratio function of speed ratio curve has no impact if fan volumetric flow rate is the same as "
    4965              :                                           "the unitary system volumetric flow rate.");
    4966            0 :                         ShowContinueError(state, format("...Fan volumetric flow rate            = {:.5R} m3/s.", thisFurnace.ActualFanVolFlowRate));
    4967            0 :                         ShowContinueError(state, format("...Unitary system volumetric flow rate = {:.5R} m3/s.", thisFurnace.MaxHeatAirVolFlow));
    4968            0 :                     }
    4969              :                 }
    4970            2 :                 state.dataFurnaces->MyFanFlag(FurnaceNum) = false;
    4971              :             } else {
    4972            2 :                 thisFurnace.ActualFanVolFlowRate = state.dataFans->fans(thisFurnace.FanIndex)->maxAirFlowRate;
    4973              :             }
    4974              :         }
    4975              : 
    4976        15222 :         if (allocated(state.dataZoneEquip->ZoneEquipConfig) && state.dataFurnaces->MyCheckFlag(FurnaceNum)) {
    4977            2 :             int zoneNum = thisFurnace.ControlZoneNum;
    4978            2 :             int zoneInlet = thisFurnace.ZoneInletNode;
    4979              :             // setup furnace zone equipment sequence information based on finding matching air terminal
    4980            2 :             if (state.dataZoneEquip->ZoneEquipConfig(zoneNum).EquipListIndex > 0) {
    4981            2 :                 int coolingPriority = 0;
    4982            2 :                 int heatingPriority = 0;
    4983            2 :                 state.dataZoneEquip->ZoneEquipList(state.dataZoneEquip->ZoneEquipConfig(zoneNum).EquipListIndex)
    4984            2 :                     .getPrioritiesForInletNode(state, zoneInlet, coolingPriority, heatingPriority);
    4985            2 :                 thisFurnace.ZoneSequenceCoolingNum = coolingPriority;
    4986            2 :                 thisFurnace.ZoneSequenceHeatingNum = heatingPriority;
    4987              :             }
    4988            2 :             state.dataFurnaces->MyCheckFlag(FurnaceNum) = false;
    4989            2 :             if (thisFurnace.ZoneSequenceCoolingNum == 0 || thisFurnace.ZoneSequenceHeatingNum == 0) {
    4990            0 :                 ShowSevereError(state,
    4991            0 :                                 format("{} \"{}\": Airloop air terminal in the zone equipment list for zone = {} not found or is not allowed Zone "
    4992              :                                        "Equipment Cooling or Heating Sequence = 0.",
    4993            0 :                                        HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    4994            0 :                                        thisFurnace.Name,
    4995            0 :                                        state.dataHeatBal->Zone(thisFurnace.ControlZoneNum).Name));
    4996            0 :                 ShowFatalError(state,
    4997            0 :                                format("Subroutine InitFurnace: Errors found in getting {} input.  Preceding condition(s) causes termination.",
    4998            0 :                                       HVAC::unitarySysTypeNames[(int)thisFurnace.type]));
    4999              :             }
    5000              :         }
    5001              : 
    5002              :         // Find the number of zones (zone Inlet Nodes) attached to an air loop from the air loop number
    5003              :         int NumAirLoopZones =
    5004        15222 :             state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).NumZonesCooled + state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).NumZonesHeated;
    5005        15222 :         if (allocated(state.dataAirLoop->AirToZoneNodeInfo) && state.dataFurnaces->MyFlowFracFlag(FurnaceNum)) {
    5006            2 :             state.dataFurnaces->FlowFracFlagReady = true;
    5007            4 :             for (int ZoneInSysIndex = 1; ZoneInSysIndex <= NumAirLoopZones; ++ZoneInSysIndex) {
    5008              :                 // zone inlet nodes for cooling
    5009            2 :                 if (state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).NumZonesCooled > 0) {
    5010            2 :                     if (state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).TermUnitCoolInletNodes(ZoneInSysIndex) == -999) {
    5011              :                         // the data structure for the zones inlet nodes has not been filled
    5012            0 :                         state.dataFurnaces->FlowFracFlagReady = false;
    5013              :                     }
    5014              :                 }
    5015              :                 // zone inlet nodes for heating
    5016            2 :                 if (state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).NumZonesHeated > 0) {
    5017            0 :                     if (state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).TermUnitHeatInletNodes(ZoneInSysIndex) == -999) {
    5018              :                         // the data structure for the zones inlet nodes has not been filled
    5019            0 :                         state.dataFurnaces->FlowFracFlagReady = false;
    5020              :                     }
    5021              :                 }
    5022              :             }
    5023              :         }
    5024              : 
    5025        15222 :         if (state.dataFurnaces->MyFlowFracFlag(FurnaceNum)) {
    5026            2 :             if (allocated(state.dataAirLoop->AirToZoneNodeInfo) && state.dataFurnaces->FlowFracFlagReady) {
    5027            2 :                 SumOfMassFlowRateMax = 0.0; // initialize the sum of the maximum flows
    5028            4 :                 for (int ZoneInSysIndex = 1; ZoneInSysIndex <= NumAirLoopZones; ++ZoneInSysIndex) {
    5029            2 :                     int ZoneInletNodeNum = state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).TermUnitCoolInletNodes(ZoneInSysIndex);
    5030            2 :                     SumOfMassFlowRateMax += state.dataLoopNodes->Node(ZoneInletNodeNum).MassFlowRateMax;
    5031            2 :                     if (state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).CoolCtrlZoneNums(ZoneInSysIndex) == thisFurnace.ControlZoneNum) {
    5032            2 :                         CntrlZoneTerminalUnitMassFlowRateMax = state.dataLoopNodes->Node(ZoneInletNodeNum).MassFlowRateMax;
    5033              :                     }
    5034              :                 }
    5035            2 :                 if (SumOfMassFlowRateMax != 0.0) {
    5036            2 :                     if (CntrlZoneTerminalUnitMassFlowRateMax >= HVAC::SmallAirVolFlow) {
    5037            2 :                         thisFurnace.ControlZoneMassFlowFrac = CntrlZoneTerminalUnitMassFlowRateMax / SumOfMassFlowRateMax;
    5038              :                     } else {
    5039            0 :                         ShowSevereError(state, format("{} = {}", HVAC::unitarySysTypeNames[(int)thisFurnace.type], thisFurnace.Name));
    5040            0 :                         ShowContinueError(state, " The Fraction of Supply Air Flow That Goes Through the Controlling Zone is set to 1.");
    5041              :                     }
    5042            4 :                     BaseSizer::reportSizerOutput(state,
    5043            2 :                                                  HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    5044              :                                                  thisFurnace.Name,
    5045              :                                                  "Fraction of Supply Air Flow That Goes Through the Controlling Zone",
    5046              :                                                  thisFurnace.ControlZoneMassFlowFrac);
    5047            2 :                     state.dataFurnaces->MyFlowFracFlag(FurnaceNum) = false;
    5048              :                 }
    5049              :             }
    5050              :         }
    5051              : 
    5052              :         // Calculate air distribution losses
    5053        15222 :         if (!FirstHVACIteration && state.dataFurnaces->AirLoopPass == 1) {
    5054         3778 :             int ZoneInNode = thisFurnace.ZoneInletNode;
    5055         3778 :             MassFlowRate = state.dataLoopNodes->Node(ZoneInNode).MassFlowRate / thisFurnace.ControlZoneMassFlowFrac;
    5056         3778 :             if (state.afn->distribution_simulated) {
    5057         2764 :                 DeltaMassRate = state.dataLoopNodes->Node(thisFurnace.FurnaceOutletNodeNum).MassFlowRate -
    5058         2764 :                                 state.dataLoopNodes->Node(ZoneInNode).MassFlowRate / thisFurnace.ControlZoneMassFlowFrac;
    5059         2764 :                 if (DeltaMassRate < 0.0) DeltaMassRate = 0.0;
    5060              :             } else {
    5061         1014 :                 MassFlowRate = state.dataLoopNodes->Node(thisFurnace.FurnaceOutletNodeNum).MassFlowRate;
    5062         1014 :                 DeltaMassRate = 0.0;
    5063              :             }
    5064         3778 :             Real64 TotalOutput(0.0);         // total output rate, {W}
    5065         3778 :             Real64 SensibleOutputDelta(0.0); // delta sensible output rate, {W}
    5066         3778 :             Real64 LatentOutputDelta(0.0);   // delta latent output rate, {W}
    5067         3778 :             Real64 TotalOutputDelta(0.0);    // delta total output rate, {W}
    5068        15112 :             CalcZoneSensibleLatentOutput(MassFlowRate,
    5069         3778 :                                          state.dataLoopNodes->Node(thisFurnace.FurnaceOutletNodeNum).Temp,
    5070         3778 :                                          state.dataLoopNodes->Node(thisFurnace.FurnaceOutletNodeNum).HumRat,
    5071         3778 :                                          state.dataLoopNodes->Node(ZoneInNode).Temp,
    5072         3778 :                                          state.dataLoopNodes->Node(ZoneInNode).HumRat,
    5073         3778 :                                          thisFurnace.SenLoadLoss,
    5074         3778 :                                          thisFurnace.LatLoadLoss,
    5075              :                                          TotalOutput);
    5076        15112 :             CalcZoneSensibleLatentOutput(DeltaMassRate,
    5077         3778 :                                          state.dataLoopNodes->Node(thisFurnace.FurnaceOutletNodeNum).Temp,
    5078         3778 :                                          state.dataLoopNodes->Node(thisFurnace.FurnaceOutletNodeNum).HumRat,
    5079         3778 :                                          state.dataLoopNodes->Node(thisFurnace.NodeNumOfControlledZone).Temp,
    5080         3778 :                                          state.dataLoopNodes->Node(thisFurnace.NodeNumOfControlledZone).HumRat,
    5081              :                                          SensibleOutputDelta,
    5082              :                                          LatentOutputDelta,
    5083              :                                          TotalOutputDelta);
    5084         3778 :             thisFurnace.SenLoadLoss = thisFurnace.SenLoadLoss + SensibleOutputDelta;
    5085         3778 :             if (std::abs(thisFurnace.SensibleLoadMet) > 0.0) {
    5086         3777 :                 if (std::abs(thisFurnace.SenLoadLoss / thisFurnace.SensibleLoadMet) < 0.001) thisFurnace.SenLoadLoss = 0.0;
    5087              :             }
    5088         3778 :             if (thisFurnace.Humidistat) {
    5089            0 :                 thisFurnace.LatLoadLoss = thisFurnace.LatLoadLoss + LatentOutputDelta;
    5090            0 :                 if (std::abs(thisFurnace.LatentLoadMet) > 0.0) {
    5091            0 :                     if (std::abs(thisFurnace.LatLoadLoss / thisFurnace.LatentLoadMet) < 0.001) thisFurnace.LatLoadLoss = 0.0;
    5092              :                 }
    5093              :             }
    5094              :         }
    5095              : 
    5096        15222 :         if (thisFurnace.fanOpModeSched != nullptr) {
    5097        15222 :             thisFurnace.fanOp = (thisFurnace.fanOpModeSched->getCurrentVal() == 0.0) ? HVAC::FanOp::Cycling : HVAC::FanOp::Continuous;
    5098        15222 :             if (AirLoopNum > 0) {
    5099        15222 :                 state.dataAirLoop->AirLoopControlInfo(AirLoopNum).fanOp = thisFurnace.fanOp;
    5100              :             }
    5101              :         }
    5102              : 
    5103        15222 :         fanOp = thisFurnace.fanOp;
    5104        15222 :         state.dataFurnaces->EconomizerFlag = state.dataAirLoop->AirLoopControlInfo(AirLoopNum).EconoActive;
    5105              : 
    5106        15222 :         if (thisFurnace.ControlZoneMassFlowFrac > 0.0) {
    5107        15222 :             QZnReq = ZoneLoad / thisFurnace.ControlZoneMassFlowFrac;
    5108        15222 :             MoistureLoad /= thisFurnace.ControlZoneMassFlowFrac;
    5109        15222 :             ZoneLoad = QZnReq;
    5110              :         } else {
    5111            0 :             QZnReq = ZoneLoad;
    5112              :         }
    5113              : 
    5114              :         // Original thermostat control logic (works only for cycling fan systems)
    5115        23584 :         if (QZnReq > HVAC::SmallLoad && QZnReq > (Small5WLoad / thisFurnace.ControlZoneMassFlowFrac) &&
    5116         8362 :             !state.dataZoneEnergyDemand->CurDeadBandOrSetback(thisFurnace.ControlZoneNum)) {
    5117         8362 :             state.dataFurnaces->HeatingLoad = true;
    5118         8362 :             state.dataFurnaces->CoolingLoad = false;
    5119        13608 :         } else if (QZnReq < -HVAC::SmallLoad && std::abs(QZnReq) > (Small5WLoad / thisFurnace.ControlZoneMassFlowFrac) &&
    5120         6748 :                    !state.dataZoneEnergyDemand->CurDeadBandOrSetback(thisFurnace.ControlZoneNum)) {
    5121         6748 :             state.dataFurnaces->HeatingLoad = false;
    5122         6748 :             state.dataFurnaces->CoolingLoad = true;
    5123              :         } else {
    5124          112 :             state.dataFurnaces->HeatingLoad = false;
    5125          112 :             state.dataFurnaces->CoolingLoad = false;
    5126              :         }
    5127              : 
    5128        15222 :         if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_AirToAir ||
    5129            0 :             (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir &&
    5130            0 :              (thisFurnace.WatertoAirHPType == WAHPCoilType::Simple || thisFurnace.WatertoAirHPType == WAHPCoilType::VarSpeedEquationFit))) {
    5131        15222 :             if (MoistureLoad < 0.0 && thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat) {
    5132            0 :                 state.dataFurnaces->HPDehumidificationLoadFlag = true;
    5133            0 :                 state.dataFurnaces->HeatingLoad = false;
    5134            0 :                 state.dataFurnaces->CoolingLoad = true;
    5135              :             } else {
    5136        15222 :                 state.dataFurnaces->HPDehumidificationLoadFlag = false;
    5137              :             }
    5138              :         }
    5139              : 
    5140              :         // Check for heat only furnace
    5141        15222 :         if (thisFurnace.type != HVAC::UnitarySysType::Furnace_HeatOnly && thisFurnace.type != HVAC::UnitarySysType::Unitary_HeatOnly) {
    5142              : 
    5143        30444 :             if (thisFurnace.availSched->getCurrentVal() > 0.0) {
    5144        15222 :                 if ((state.dataFurnaces->HeatingLoad || state.dataFurnaces->CoolingLoad) || (thisFurnace.Humidistat && MoistureLoad < 0.0)) {
    5145        15110 :                     PartLoadRatio = 1.0;
    5146              :                 } else {
    5147          112 :                     PartLoadRatio = 0.0;
    5148              :                 }
    5149              :             } else {
    5150            0 :                 PartLoadRatio = 0.0;
    5151              :             }
    5152              :         } else {
    5153            0 :             PartLoadRatio = 1.0;
    5154              :         }
    5155              : 
    5156              :         // get current time step operating capacity of water and steam coils
    5157              :         // (dependent on entering water and steam temperature)
    5158        15222 :         if (FirstHVACIteration) {
    5159         4846 :             if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingWater) {
    5160              :                 // set water-side mass flow rates
    5161            0 :                 state.dataLoopNodes->Node(thisFurnace.HWCoilAirInletNode).MassFlowRate = state.dataFurnaces->CompOnMassFlow;
    5162            0 :                 mdot = thisFurnace.MaxHeatCoilFluidFlow;
    5163            0 :                 PlantUtilities::SetComponentFlowRate(state, mdot, thisFurnace.CoilControlNode, thisFurnace.CoilOutletNode, thisFurnace.plantLoc);
    5164              :                 //     simulate water coil to find operating capacity
    5165            0 :                 WaterCoils::SimulateWaterCoilComponents(
    5166            0 :                     state, thisFurnace.HeatingCoilName, FirstHVACIteration, thisFurnace.HeatingCoilIndex, QActual);
    5167            0 :                 thisFurnace.DesignHeatingCapacity = QActual;
    5168              : 
    5169              :             } // from IF(furnace%HeatingCoilType_Num == Coil_HeatingWater) THEN
    5170              : 
    5171         4846 :             if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingSteam) {
    5172              :                 // set air-side and steam-side mass flow rates
    5173            0 :                 state.dataLoopNodes->Node(thisFurnace.HWCoilAirInletNode).MassFlowRate = state.dataFurnaces->CompOnMassFlow;
    5174            0 :                 mdot = thisFurnace.MaxHeatCoilFluidFlow;
    5175            0 :                 PlantUtilities::SetComponentFlowRate(state, mdot, thisFurnace.CoilControlNode, thisFurnace.CoilOutletNode, thisFurnace.plantLoc);
    5176              : 
    5177              :                 //     simulate steam coil to find operating capacity
    5178            0 :                 SteamCoils::SimulateSteamCoilComponents(state,
    5179              :                                                         thisFurnace.HeatingCoilName,
    5180              :                                                         FirstHVACIteration,
    5181            0 :                                                         thisFurnace.HeatingCoilIndex,
    5182            0 :                                                         1.0,
    5183              :                                                         QActual); // QCoilReq, simulate any load > 0 to get max capacity of steam coil
    5184            0 :                 thisFurnace.DesignHeatingCapacity =
    5185            0 :                     SteamCoils::GetCoilCapacity(state, thisFurnace.HeatingCoilType, thisFurnace.HeatingCoilName, ErrorsFound);
    5186              : 
    5187              :             } // from IF(Furnace(FurnaceNum)%HeatingCoilType_Num == Coil_HeatingSteam) THEN
    5188              : 
    5189         4846 :             if (thisFurnace.SuppHeatCoilType_Num == HVAC::Coil_HeatingWater) {
    5190              : 
    5191              :                 //     set air-side and steam-side mass flow rates
    5192            0 :                 state.dataLoopNodes->Node(thisFurnace.SuppCoilAirInletNode).MassFlowRate = state.dataFurnaces->CompOnMassFlow;
    5193            0 :                 mdot = thisFurnace.MaxSuppCoilFluidFlow;
    5194            0 :                 PlantUtilities::SetComponentFlowRate(
    5195            0 :                     state, mdot, thisFurnace.SuppCoilControlNode, thisFurnace.SuppCoilOutletNode, thisFurnace.SuppPlantLoc);
    5196              : 
    5197              :                 //     simulate water coil to find operating capacity
    5198            0 :                 WaterCoils::SimulateWaterCoilComponents(
    5199            0 :                     state, thisFurnace.SuppHeatCoilName, FirstHVACIteration, thisFurnace.SuppHeatCoilIndex, QActual);
    5200            0 :                 thisFurnace.DesignSuppHeatingCapacity = QActual;
    5201              : 
    5202              :             } // from IF(Furnace(FurnaceNum)%SuppHeatCoilType_Num == Coil_HeatingWater) THEN
    5203         4846 :             if (thisFurnace.SuppHeatCoilType_Num == HVAC::Coil_HeatingSteam) {
    5204              :                 //     set air-side and steam-side mass flow rates
    5205            0 :                 state.dataLoopNodes->Node(thisFurnace.SuppCoilAirInletNode).MassFlowRate = state.dataFurnaces->CompOnMassFlow;
    5206            0 :                 mdot = thisFurnace.MaxSuppCoilFluidFlow;
    5207            0 :                 PlantUtilities::SetComponentFlowRate(
    5208            0 :                     state, mdot, thisFurnace.SuppCoilControlNode, thisFurnace.SuppCoilOutletNode, thisFurnace.SuppPlantLoc);
    5209              : 
    5210              :                 //     simulate steam coil to find operating capacity
    5211            0 :                 SteamCoils::SimulateSteamCoilComponents(state,
    5212              :                                                         thisFurnace.SuppHeatCoilName,
    5213              :                                                         FirstHVACIteration,
    5214            0 :                                                         thisFurnace.SuppHeatCoilIndex,
    5215            0 :                                                         1.0,
    5216              :                                                         QActual); // QCoilReq, simulate any load > 0 to get max capacity of steam coil
    5217            0 :                 thisFurnace.DesignSuppHeatingCapacity =
    5218            0 :                     SteamCoils::GetCoilCapacity(state, thisFurnace.SuppHeatCoilType, thisFurnace.SuppHeatCoilName, ErrorsFound);
    5219              : 
    5220              :             } // from IF(Furnace(FurnaceNum)%SuppHeatCoilType_Num == Coil_HeatingSteam) THEN
    5221              :         }     // from IF( FirstHVACIteration ) THEN
    5222              : 
    5223        15222 :         if (thisFurnace.NumOfSpeedCooling > 0) { // BoS, variable-speed water source hp
    5224              :             // Furnace(FurnaceNum)%IdleMassFlowRate = RhoAir*Furnace(FurnaceNum)%IdleVolumeAirRate
    5225            0 :             int NumOfSpeedCooling = thisFurnace.NumOfSpeedCooling;
    5226            0 :             int NumOfSpeedHeating = thisFurnace.NumOfSpeedHeating;
    5227              :             // IF MSHP system was not autosized and the fan is autosized, check that fan volumetric flow rate is greater than MSHP flow rates
    5228            0 :             if (thisFurnace.CheckFanFlow) {
    5229            0 :                 state.dataFurnaces->CurrentModuleObject = "AirLoopHVAC:UnitaryHeatPump:VariableSpeed";
    5230            0 :                 thisFurnace.FanVolFlow = state.dataFans->fans(thisFurnace.FanIndex)->maxAirFlowRate;
    5231              : 
    5232            0 :                 if (thisFurnace.FanVolFlow != DataSizing::AutoSize) {
    5233              :                     //     Check fan versus system supply air flow rates
    5234            0 :                     if (thisFurnace.FanVolFlow + 1e-10 < thisFurnace.CoolVolumeFlowRate(NumOfSpeedCooling)) {
    5235            0 :                         ShowWarningError(state,
    5236            0 :                                          format("{} - air flow rate = {:.7T} in fan object is less than the MSHP system air flow rate when cooling "
    5237              :                                                 "is required ({:.7T}).",
    5238            0 :                                                 state.dataFurnaces->CurrentModuleObject,
    5239            0 :                                                 thisFurnace.FanVolFlow,
    5240              :                                                 thisFurnace.CoolVolumeFlowRate(NumOfSpeedCooling)));
    5241            0 :                         ShowContinueError(
    5242              :                             state, " The MSHP system flow rate when cooling is required is reset to the fan flow rate and the simulation continues.");
    5243            0 :                         ShowContinueError(state, format(" Occurs in {} = {}", state.dataFurnaces->CurrentModuleObject, thisFurnace.Name));
    5244            0 :                         thisFurnace.CoolVolumeFlowRate(NumOfSpeedCooling) = thisFurnace.FanVolFlow;
    5245              : 
    5246            0 :                         if (thisFurnace.bIsIHP) // set max fan flow rate to the IHP collection
    5247              :                         {
    5248            0 :                             state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).MaxCoolAirVolFlow = thisFurnace.FanVolFlow;
    5249            0 :                             state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).MaxCoolAirMassFlow =
    5250            0 :                                 thisFurnace.FanVolFlow * state.dataEnvrn->StdRhoAir;
    5251              :                         }
    5252              : 
    5253              :                         // Check flow rates in other speeds and ensure flow rates are not above the max flow rate
    5254            0 :                         for (int i = NumOfSpeedCooling - 1; i >= 1; --i) {
    5255            0 :                             if (thisFurnace.CoolVolumeFlowRate(i) > thisFurnace.CoolVolumeFlowRate(i + 1)) {
    5256            0 :                                 ShowContinueError(state,
    5257            0 :                                                   format(" The MSHP system flow rate when cooling is required is reset to the flow rate at higher "
    5258              :                                                          "speed and the simulation continues at Speed{}.",
    5259              :                                                          i));
    5260            0 :                                 ShowContinueError(state, format(" Occurs in {} = {}", state.dataFurnaces->CurrentModuleObject, thisFurnace.Name));
    5261            0 :                                 thisFurnace.CoolVolumeFlowRate(i) = thisFurnace.CoolVolumeFlowRate(i + 1);
    5262              :                             }
    5263              :                         }
    5264              :                     }
    5265            0 :                     if (NumOfSpeedHeating > 0) {
    5266            0 :                         if (thisFurnace.FanVolFlow + 1e-10 < thisFurnace.HeatVolumeFlowRate(NumOfSpeedHeating)) {
    5267            0 :                             ShowWarningError(state,
    5268            0 :                                              format("{} - air flow rate = {:.7T} in fan object is less than the MSHP system air flow rate when "
    5269              :                                                     "heating is required ({:.7T}).",
    5270            0 :                                                     state.dataFurnaces->CurrentModuleObject,
    5271            0 :                                                     thisFurnace.FanVolFlow,
    5272              :                                                     thisFurnace.HeatVolumeFlowRate(NumOfSpeedHeating)));
    5273            0 :                             ShowContinueError(
    5274              :                                 state,
    5275              :                                 " The MSHP system flow rate when heating is required is reset to the fan flow rate and the simulation continues.");
    5276            0 :                             ShowContinueError(state, format(" Occurs in {} = {}", state.dataFurnaces->CurrentModuleObject, thisFurnace.Name));
    5277            0 :                             thisFurnace.HeatVolumeFlowRate(NumOfSpeedHeating) = thisFurnace.FanVolFlow;
    5278              : 
    5279            0 :                             if (thisFurnace.bIsIHP) // set max fan flow rate to the IHP collection
    5280              :                             {
    5281            0 :                                 state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).MaxHeatAirVolFlow = thisFurnace.FanVolFlow;
    5282            0 :                                 state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).MaxHeatAirMassFlow =
    5283            0 :                                     thisFurnace.FanVolFlow * state.dataEnvrn->StdRhoAir;
    5284              :                             }
    5285              : 
    5286            0 :                             for (int i = NumOfSpeedHeating - 1; i >= 1; --i) {
    5287            0 :                                 if (thisFurnace.HeatVolumeFlowRate(i) > thisFurnace.HeatVolumeFlowRate(i + 1)) {
    5288            0 :                                     ShowContinueError(state,
    5289            0 :                                                       format(" The MSHP system flow rate when heating is required is reset to the flow rate at "
    5290              :                                                              "higher speed and the simulation continues at Speed{}.",
    5291              :                                                              i));
    5292            0 :                                     ShowContinueError(state,
    5293            0 :                                                       format(" Occurs in {} system = {}", state.dataFurnaces->CurrentModuleObject, thisFurnace.Name));
    5294            0 :                                     thisFurnace.HeatVolumeFlowRate(i) = thisFurnace.HeatVolumeFlowRate(i + 1);
    5295              :                                 }
    5296              :                             }
    5297              :                         }
    5298              :                     }
    5299            0 :                     if (thisFurnace.FanVolFlow < thisFurnace.IdleVolumeAirRate && thisFurnace.IdleVolumeAirRate != 0.0) {
    5300            0 :                         ShowWarningError(state,
    5301            0 :                                          format("{} - air flow rate = {:.7T} in fan object is less than the MSHP system air flow rate when no "
    5302              :                                                 "heating or cooling is needed ({:.7T}).",
    5303            0 :                                                 state.dataFurnaces->CurrentModuleObject,
    5304            0 :                                                 thisFurnace.FanVolFlow,
    5305            0 :                                                 thisFurnace.IdleVolumeAirRate));
    5306            0 :                         ShowContinueError(state,
    5307              :                                           " The MSHP system flow rate when no heating or cooling is needed is reset to the fan flow rate and the "
    5308              :                                           "simulation continues.");
    5309            0 :                         ShowContinueError(state, format(" Occurs in {} = {}", state.dataFurnaces->CurrentModuleObject, thisFurnace.Name));
    5310            0 :                         thisFurnace.IdleVolumeAirRate = thisFurnace.FanVolFlow;
    5311              :                     }
    5312            0 :                     RhoAir = state.dataEnvrn->StdRhoAir;
    5313              :                     // set the mass flow rates from the reset volume flow rates
    5314            0 :                     for (int i = 1; i <= NumOfSpeedCooling; ++i) {
    5315            0 :                         thisFurnace.CoolMassFlowRate(i) = RhoAir * thisFurnace.CoolVolumeFlowRate(i);
    5316            0 :                         if (thisFurnace.FanVolFlow > 0.0) {
    5317            0 :                             thisFurnace.MSCoolingSpeedRatio(i) = thisFurnace.CoolVolumeFlowRate(i) / thisFurnace.FanVolFlow;
    5318              :                         }
    5319              :                     }
    5320            0 :                     for (int i = 1; i <= NumOfSpeedHeating; ++i) {
    5321            0 :                         thisFurnace.HeatMassFlowRate(i) = RhoAir * thisFurnace.HeatVolumeFlowRate(i);
    5322            0 :                         if (thisFurnace.FanVolFlow > 0.0) {
    5323            0 :                             thisFurnace.MSHeatingSpeedRatio(i) = thisFurnace.HeatVolumeFlowRate(i) / thisFurnace.FanVolFlow;
    5324              :                         }
    5325              :                     }
    5326            0 :                     thisFurnace.IdleMassFlowRate = RhoAir * thisFurnace.IdleVolumeAirRate;
    5327            0 :                     if (thisFurnace.FanVolFlow > 0.0) {
    5328            0 :                         thisFurnace.IdleSpeedRatio = thisFurnace.IdleVolumeAirRate / thisFurnace.FanVolFlow;
    5329              :                     }
    5330              :                     // set the node max and min mass flow rates based on reset volume flow rates
    5331            0 :                     if (NumOfSpeedCooling > 0 && NumOfSpeedHeating == 0) {
    5332            0 :                         state.dataLoopNodes->Node(InNode).MassFlowRateMax =
    5333            0 :                             max(thisFurnace.CoolMassFlowRate(NumOfSpeedCooling), thisFurnace.MaxHeatAirMassFlow);
    5334            0 :                         state.dataLoopNodes->Node(InNode).MassFlowRateMaxAvail =
    5335            0 :                             max(thisFurnace.CoolMassFlowRate(NumOfSpeedCooling), thisFurnace.MaxHeatAirMassFlow);
    5336            0 :                     } else if (NumOfSpeedCooling == 0 && NumOfSpeedHeating > 0) {
    5337            0 :                         state.dataLoopNodes->Node(InNode).MassFlowRateMax =
    5338            0 :                             max(thisFurnace.MaxCoolAirMassFlow, thisFurnace.HeatMassFlowRate(NumOfSpeedHeating));
    5339            0 :                         state.dataLoopNodes->Node(InNode).MassFlowRateMaxAvail =
    5340            0 :                             max(thisFurnace.MaxCoolAirMassFlow, thisFurnace.HeatMassFlowRate(NumOfSpeedHeating));
    5341              :                     } else {
    5342            0 :                         state.dataLoopNodes->Node(InNode).MassFlowRateMax =
    5343            0 :                             max(thisFurnace.CoolMassFlowRate(NumOfSpeedCooling), thisFurnace.HeatMassFlowRate(NumOfSpeedHeating));
    5344            0 :                         state.dataLoopNodes->Node(InNode).MassFlowRateMaxAvail =
    5345            0 :                             max(thisFurnace.CoolMassFlowRate(NumOfSpeedCooling), thisFurnace.HeatMassFlowRate(NumOfSpeedHeating));
    5346              :                     }
    5347            0 :                     state.dataLoopNodes->Node(InNode).MassFlowRateMin = 0.0;
    5348            0 :                     state.dataLoopNodes->Node(InNode).MassFlowRateMinAvail = 0.0;
    5349            0 :                     state.dataLoopNodes->Node(OutNode) = state.dataLoopNodes->Node(InNode);
    5350              :                 }
    5351              :             }
    5352              : 
    5353            0 :             thisFurnace.CheckFanFlow = false;
    5354              :         }
    5355        15222 :         SetOnOffMassFlowRate(state, FurnaceNum, AirLoopNum, OnOffAirFlowRatio, fanOp, QZnReq, MoistureLoad, PartLoadRatio);
    5356              : 
    5357              :         // Check ventilation/fan load for constant fan systems to see if load to be met changes
    5358              :         // Same IF logic used in Subroutine SetAverageAirFlow to determine if unit is ON or OFF
    5359              : 
    5360        15222 :         QToCoolSetPt = 0.0;
    5361        15222 :         QToHeatSetPt = 0.0;
    5362        15222 :         if (fanOp == HVAC::FanOp::Continuous && thisFurnace.availSched->getCurrentVal() > 0.0 &&
    5363            0 :             ((thisFurnace.fanAvailSched->getCurrentVal() > 0.0 || state.dataHVACGlobal->TurnFansOn) && !state.dataHVACGlobal->TurnFansOff)) {
    5364              : 
    5365            0 :             if (thisFurnace.NumOfSpeedCooling > 0) {
    5366            0 :                 CalcVarSpeedHeatPump(state,
    5367              :                                      FurnaceNum,
    5368              :                                      false,
    5369              :                                      HVAC::CompressorOp::Off,
    5370              :                                      1,
    5371              :                                      0.0,
    5372              :                                      0.0,
    5373              :                                      SensibleOutput,
    5374              :                                      LatentOutput,
    5375              :                                      0.0,
    5376              :                                      0.0,
    5377              :                                      OnOffAirFlowRatio,
    5378              :                                      SUPHEATERLOAD);
    5379              :             } else {
    5380            0 :                 CalcFurnaceOutput(state,
    5381              :                                   FurnaceNum,
    5382              :                                   false,
    5383              :                                   HVAC::FanOp::Invalid, // Looks like Invalid is used to mean that the fan is off here?
    5384              :                                   HVAC::CompressorOp::Off,
    5385              :                                   0.0,
    5386              :                                   0.0,
    5387              :                                   0.0,
    5388              :                                   0.0,
    5389              :                                   SensibleOutput,
    5390              :                                   LatentOutput,
    5391              :                                   OnOffAirFlowRatio,
    5392              :                                   false);
    5393              :             }
    5394              : 
    5395            0 :             if (thisFurnace.ControlZoneMassFlowFrac > 0.0) {
    5396            0 :                 if (thisFurnace.ZoneSequenceCoolingNum > 0 && thisFurnace.ZoneSequenceHeatingNum > 0) {
    5397            0 :                     QToCoolSetPt = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(thisFurnace.ControlZoneNum)
    5398            0 :                                        .SequencedOutputRequiredToCoolingSP(thisFurnace.ZoneSequenceCoolingNum) /
    5399            0 :                                    thisFurnace.ControlZoneMassFlowFrac;
    5400            0 :                     QToHeatSetPt = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(thisFurnace.ControlZoneNum)
    5401            0 :                                        .SequencedOutputRequiredToHeatingSP(thisFurnace.ZoneSequenceHeatingNum) /
    5402            0 :                                    thisFurnace.ControlZoneMassFlowFrac;
    5403              :                 } else {
    5404            0 :                     QToCoolSetPt = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(thisFurnace.ControlZoneNum).OutputRequiredToCoolingSP /
    5405            0 :                                    thisFurnace.ControlZoneMassFlowFrac;
    5406            0 :                     QToHeatSetPt = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(thisFurnace.ControlZoneNum).OutputRequiredToHeatingSP /
    5407            0 :                                    thisFurnace.ControlZoneMassFlowFrac;
    5408              :                 }
    5409              :                 //     If the furnace has a net cooling capacity (SensibleOutput < 0) and
    5410              :                 //     the zone temp is above the Tstat heating setpoint (QToHeatSetPt < 0) and
    5411              :                 //     the net cooling capacity does not just offset the cooling load
    5412            0 :                 if (SensibleOutput < 0.0 && QToHeatSetPt < 0.0 &&
    5413            0 :                     std::abs(QToCoolSetPt - SensibleOutput) > (Small5WLoad / thisFurnace.ControlZoneMassFlowFrac)) {
    5414              :                     //       Only switch modes when humidistat is not used or no moisture load exists, otherwise let
    5415              :                     //       reheat coil pick up load
    5416              :                     //        IF((SensibleOutput .LT. QToHeatSetPt .AND. .NOT. Furnace(FurnaceNum)%Humidistat) .OR. &
    5417              :                     //           (SensibleOutput .LT. QToHeatSetPt .AND. Furnace(FurnaceNum)%Humidistat .AND. MoistureLoad .GE. 0.0))THEN
    5418            0 :                     if ((SensibleOutput < QToHeatSetPt && !thisFurnace.Humidistat) ||
    5419            0 :                         (SensibleOutput < QToHeatSetPt && thisFurnace.Humidistat && MoistureLoad >= 0.0)) {
    5420            0 :                         QZnReq = QToHeatSetPt;
    5421            0 :                         state.dataFurnaces->CoolingLoad = false;
    5422              :                         //         Don't set mode TRUE unless mode is allowed. Also check for floating zone.
    5423            0 :                         if (state.dataHeatBalFanSys->TempControlType(thisFurnace.ControlZoneNum) == HVAC::SetptType::SingleCool ||
    5424            0 :                             state.dataHeatBalFanSys->TempControlType(thisFurnace.ControlZoneNum) == HVAC::SetptType::Uncontrolled) {
    5425            0 :                             state.dataFurnaces->HeatingLoad = false;
    5426              :                         } else {
    5427            0 :                             state.dataFurnaces->HeatingLoad = true;
    5428              :                         }
    5429              : 
    5430            0 :                         SetOnOffMassFlowRate(state, FurnaceNum, AirLoopNum, OnOffAirFlowRatio, fanOp, QZnReq, MoistureLoad, PartLoadRatio);
    5431            0 :                         if (thisFurnace.NumOfSpeedCooling > 0) {
    5432            0 :                             CalcVarSpeedHeatPump(state,
    5433              :                                                  FurnaceNum,
    5434              :                                                  false,
    5435              :                                                  HVAC::CompressorOp::Off,
    5436              :                                                  1,
    5437              :                                                  0.0,
    5438              :                                                  0.0,
    5439              :                                                  SensibleOutput,
    5440              :                                                  LatentOutput,
    5441              :                                                  0.0,
    5442              :                                                  0.0,
    5443              :                                                  OnOffAirFlowRatio,
    5444              :                                                  SUPHEATERLOAD);
    5445              :                         } else {
    5446            0 :                             CalcFurnaceOutput(state,
    5447              :                                               FurnaceNum,
    5448              :                                               false,
    5449              :                                               HVAC::FanOp::Invalid,
    5450              :                                               HVAC::CompressorOp::Off,
    5451              :                                               0.0,
    5452              :                                               0.0,
    5453              :                                               0.0,
    5454              :                                               0.0,
    5455              :                                               SensibleOutput,
    5456              :                                               LatentOutput,
    5457              :                                               OnOffAirFlowRatio,
    5458              :                                               false);
    5459              :                         }
    5460            0 :                         if (SensibleOutput > QToHeatSetPt) {
    5461              :                             // If changing operating mode (flow rates) does not overshoot heating setpoint, turn off heating
    5462            0 :                             QZnReq = 0.0;
    5463            0 :                             state.dataFurnaces->HeatingLoad = false;
    5464            0 :                             SetOnOffMassFlowRate(state, FurnaceNum, AirLoopNum, OnOffAirFlowRatio, fanOp, QZnReq, MoistureLoad, PartLoadRatio);
    5465              :                         }
    5466            0 :                     } else if (SensibleOutput < QZnReq) {
    5467              :                         //         If the net cooling capacity meets the zone cooling load but does not overshoot heating setpoint, turn off cooling
    5468              :                         //         (dehumidification may still occur)
    5469            0 :                         QZnReq = 0.0;
    5470            0 :                         state.dataFurnaces->CoolingLoad = false;
    5471            0 :                         if (state.dataFurnaces->HPDehumidificationLoadFlag) {
    5472            0 :                             state.dataFurnaces->CoolingLoad = true;
    5473            0 :                             state.dataFurnaces->HeatingLoad = false;
    5474              :                         }
    5475            0 :                         SetOnOffMassFlowRate(state, FurnaceNum, AirLoopNum, OnOffAirFlowRatio, fanOp, QZnReq, MoistureLoad, PartLoadRatio);
    5476              :                     }
    5477              :                     // the net cooling capacity just offsets the cooling load, turn off cooling
    5478            0 :                 } else if (SensibleOutput < 0.0 && QToCoolSetPt < 0.0 &&
    5479            0 :                            std::abs(QToCoolSetPt - SensibleOutput) < (Small5WLoad / thisFurnace.ControlZoneMassFlowFrac)) {
    5480            0 :                     state.dataFurnaces->CoolingLoad = false;
    5481            0 :                     if (state.dataFurnaces->HPDehumidificationLoadFlag) {
    5482            0 :                         state.dataFurnaces->CoolingLoad = true;
    5483            0 :                         state.dataFurnaces->HeatingLoad = false;
    5484              :                     }
    5485              :                 } // SensibleOutput .LT. 0.0d0 .AND. QToHeatSetPt .LT. 0.0d0
    5486              : 
    5487              :                 //     If the furnace has a net heating capacity and the zone temp is below the Tstat cooling setpoint and
    5488              :                 //     the net heating capacity does not just offset the heating load
    5489            0 :                 if (SensibleOutput > 0.0 && QToCoolSetPt > 0.0 &&
    5490            0 :                     std::abs(SensibleOutput - QToHeatSetPt) > (Small5WLoad / thisFurnace.ControlZoneMassFlowFrac)) {
    5491            0 :                     if (SensibleOutput > QToCoolSetPt) {
    5492            0 :                         QZnReq = QToCoolSetPt;
    5493              :                         //         Don't set mode TRUE unless mode is allowed. Also check for floating zone.
    5494            0 :                         if (state.dataHeatBalFanSys->TempControlType(thisFurnace.ControlZoneNum) == HVAC::SetptType::SingleHeat ||
    5495            0 :                             state.dataHeatBalFanSys->TempControlType(thisFurnace.ControlZoneNum) == HVAC::SetptType::Uncontrolled) {
    5496            0 :                             state.dataFurnaces->CoolingLoad = false;
    5497              :                         } else {
    5498            0 :                             state.dataFurnaces->CoolingLoad = true;
    5499              :                         }
    5500            0 :                         state.dataFurnaces->HeatingLoad = false;
    5501              : 
    5502            0 :                         SetOnOffMassFlowRate(state, FurnaceNum, AirLoopNum, OnOffAirFlowRatio, fanOp, QZnReq, MoistureLoad, PartLoadRatio);
    5503            0 :                         if (thisFurnace.NumOfSpeedCooling > 0) {
    5504            0 :                             CalcVarSpeedHeatPump(state,
    5505              :                                                  FurnaceNum,
    5506              :                                                  false,
    5507              :                                                  HVAC::CompressorOp::Off,
    5508              :                                                  1,
    5509              :                                                  0.0,
    5510              :                                                  0.0,
    5511              :                                                  SensibleOutput,
    5512              :                                                  LatentOutput,
    5513              :                                                  0.0,
    5514              :                                                  0.0,
    5515              :                                                  OnOffAirFlowRatio,
    5516              :                                                  SUPHEATERLOAD);
    5517              :                         } else {
    5518            0 :                             CalcFurnaceOutput(state,
    5519              :                                               FurnaceNum,
    5520              :                                               false,
    5521              :                                               HVAC::FanOp::Invalid,
    5522              :                                               HVAC::CompressorOp::Off,
    5523              :                                               0.0,
    5524              :                                               0.0,
    5525              :                                               0.0,
    5526              :                                               0.0,
    5527              :                                               SensibleOutput,
    5528              :                                               LatentOutput,
    5529              :                                               OnOffAirFlowRatio,
    5530              :                                               false);
    5531              :                         }
    5532            0 :                         if (SensibleOutput < QToCoolSetPt) {
    5533              :                             //           If changing operating mode (flow rates) does not overshoot cooling setpoint, turn off cooling
    5534            0 :                             if (state.dataFurnaces->HPDehumidificationLoadFlag) {
    5535            0 :                                 state.dataFurnaces->CoolingLoad = true;
    5536            0 :                                 state.dataFurnaces->HeatingLoad = false;
    5537              :                             } else {
    5538            0 :                                 QZnReq = 0.0;
    5539            0 :                                 state.dataFurnaces->CoolingLoad = false;
    5540              :                             }
    5541            0 :                             SetOnOffMassFlowRate(state, FurnaceNum, AirLoopNum, OnOffAirFlowRatio, fanOp, QZnReq, MoistureLoad, PartLoadRatio);
    5542              :                         }
    5543            0 :                     } else if (SensibleOutput > QZnReq) {
    5544              :                         //         If the net heating capacity meets the zone heating load but does not overshoot, turn off heating
    5545            0 :                         QZnReq = 0.0;
    5546            0 :                         state.dataFurnaces->HeatingLoad = false;
    5547            0 :                         SetOnOffMassFlowRate(state, FurnaceNum, AirLoopNum, OnOffAirFlowRatio, fanOp, QZnReq, MoistureLoad, PartLoadRatio);
    5548              :                     }
    5549              :                     //     the net heating capacity just offsets the heating load, turn off heating
    5550            0 :                 } else if (SensibleOutput > 0.0 && QToHeatSetPt > 0.0 &&
    5551            0 :                            std::abs(SensibleOutput - QToHeatSetPt) < (Small5WLoad / thisFurnace.ControlZoneMassFlowFrac)) {
    5552            0 :                     state.dataFurnaces->HeatingLoad = false;
    5553              :                 } // SensibleOutput .GT. 0.0d0 .AND. QToCoolSetPt .GT. 0.0d0
    5554              :             }     // Furnace(FurnaceNum)%ControlZoneMassFlowFrac .GT. 0.0d0
    5555            0 :             ZoneLoad = QZnReq;
    5556              :         } // fanOp .EQ. FanOp::Continuous
    5557              : 
    5558        15222 :         if (FirstHVACIteration) {
    5559         4846 :             thisFurnace.iterationCounter = 0;
    5560         4846 :             thisFurnace.iterationMode = Furnaces::ModeOfOperation::NoCoolHeat;
    5561              :         }
    5562        15222 :         thisFurnace.iterationCounter += 1;
    5563              : 
    5564              :         // push iteration mode stack and set current mode
    5565        15222 :         thisFurnace.iterationMode(3) = thisFurnace.iterationMode(2);
    5566        15222 :         thisFurnace.iterationMode(2) = thisFurnace.iterationMode(1);
    5567        15222 :         if (state.dataFurnaces->CoolingLoad) {
    5568         6748 :             thisFurnace.iterationMode(1) = Furnaces::ModeOfOperation::CoolingMode;
    5569         8474 :         } else if (state.dataFurnaces->HeatingLoad) {
    5570         8362 :             thisFurnace.iterationMode(1) = Furnaces::ModeOfOperation::HeatingMode;
    5571              :         } else {
    5572          112 :             thisFurnace.iterationMode(1) = Furnaces::ModeOfOperation::NoCoolHeat;
    5573              :         }
    5574              : 
    5575              :         // IF small loads to meet or not converging, just shut down unit
    5576        15222 :         if (std::abs(ZoneLoad) < Small5WLoad) {
    5577          112 :             ZoneLoad = 0.0;
    5578          112 :             state.dataFurnaces->CoolingLoad = false;
    5579          112 :             state.dataFurnaces->HeatingLoad = false;
    5580        15110 :         } else if (thisFurnace.iterationCounter > (state.dataHVACGlobal->MinAirLoopIterationsAfterFirst + 4)) {
    5581              :             // attempt to lock output (air flow) if oscillations are detected
    5582            0 :             OperatingMode = thisFurnace.iterationMode(1);
    5583            0 :             OperatingModeMinusOne = thisFurnace.iterationMode(2);
    5584            0 :             OperatingModeMinusTwo = thisFurnace.iterationMode(3);
    5585            0 :             Oscillate = true;
    5586            0 :             if (OperatingMode == OperatingModeMinusOne && OperatingMode == OperatingModeMinusTwo) Oscillate = false;
    5587            0 :             if (Oscillate) {
    5588            0 :                 if (QToCoolSetPt < 0.0) {
    5589            0 :                     state.dataFurnaces->HeatingLoad = false;
    5590            0 :                     state.dataFurnaces->CoolingLoad = true;
    5591            0 :                     ZoneLoad = QToCoolSetPt;
    5592            0 :                 } else if (QToHeatSetPt > 0.0) {
    5593            0 :                     state.dataFurnaces->HeatingLoad = true;
    5594            0 :                     state.dataFurnaces->CoolingLoad = false;
    5595            0 :                     ZoneLoad = QToHeatSetPt;
    5596              :                 } else {
    5597            0 :                     state.dataFurnaces->HeatingLoad = false;
    5598            0 :                     state.dataFurnaces->CoolingLoad = false;
    5599            0 :                     ZoneLoad = 0.0;
    5600              :                 }
    5601              :             }
    5602              :         }
    5603              : 
    5604              :         // EMS override point
    5605        15222 :         if (thisFurnace.EMSOverrideSensZoneLoadRequest) ZoneLoad = thisFurnace.EMSSensibleZoneLoadValue;
    5606        15222 :         if (thisFurnace.EMSOverrideMoistZoneLoadRequest) MoistureLoad = thisFurnace.EMSMoistureZoneLoadValue;
    5607        15222 :         if (thisFurnace.EMSOverrideSensZoneLoadRequest || thisFurnace.EMSOverrideMoistZoneLoadRequest) {
    5608            0 :             if ((ZoneLoad != 0.0) && (thisFurnace.EMSOverrideSensZoneLoadRequest)) {
    5609            0 :                 PartLoadRatio = 1.0;
    5610            0 :             } else if ((MoistureLoad != 0.0) && (thisFurnace.EMSOverrideMoistZoneLoadRequest)) {
    5611            0 :                 PartLoadRatio = 1.0;
    5612              :             } else {
    5613            0 :                 PartLoadRatio = 0.0;
    5614              :             }
    5615            0 :             if (thisFurnace.NumOfSpeedCooling > 0) {
    5616            0 :                 SetOnOffMassFlowRate(state, FurnaceNum, AirLoopNum, OnOffAirFlowRatio, fanOp, QZnReq, MoistureLoad, PartLoadRatio);
    5617              :             } else {
    5618              :                 // This line is suspicious - all other calls to SetOnOffMassFlowRate pass in QZnReq, not ZoneLoad
    5619              :                 // either way, it seems these two should be using the same parameters.
    5620            0 :                 SetOnOffMassFlowRate(state, FurnaceNum, AirLoopNum, OnOffAirFlowRatio, fanOp, ZoneLoad, MoistureLoad, PartLoadRatio);
    5621              :             }
    5622              :         }
    5623              : 
    5624              :         // AirflowNetwork global variable
    5625        15222 :         if (state.afn->distribution_simulated) {
    5626        11168 :             state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).AFNLoopHeatingCoilMaxRTF = 0.0;
    5627              :         }
    5628        15222 :     }
    5629              : 
    5630        15222 :     void SetOnOffMassFlowRate(EnergyPlusData &state,
    5631              :                               int const FurnaceNum,                   // index to furnace
    5632              :                               [[maybe_unused]] int const AirLoopNum,  // index to air loop !unused1208
    5633              :                               Real64 &OnOffAirFlowRatio,              // ratio of coil on to coil off air flow rate
    5634              :                               HVAC::FanOp const fanOp,                // fan operating mode
    5635              :                               [[maybe_unused]] Real64 const ZoneLoad, // sensible load to be met (W) !unused1208
    5636              :                               Real64 const MoistureLoad,              // moisture load to be met (W)
    5637              :                               Real64 const PartLoadRatio              // coil part-load ratio
    5638              :     )
    5639              :     {
    5640              : 
    5641              :         // SUBROUTINE INFORMATION:
    5642              :         //       AUTHOR         Richard Raustad
    5643              :         //       DATE WRITTEN   Sep 2008
    5644              : 
    5645              :         // PURPOSE OF THIS SUBROUTINE:
    5646              :         // This subroutine is for initializations of the Furnace Components.
    5647              : 
    5648              :         // METHODOLOGY EMPLOYED:
    5649              :         // The HeatCool furnace/unitarysystem and air-to-air heat pump may have alternate air flow rates
    5650              :         // in cooling, heating, and when no cooling or heating is needed. Set up the coil (comp) ON and OFF
    5651              :         // air flow rates. Use these flow rates during the Calc routines to set the average mass flow rates
    5652              :         // based on PLR.
    5653              : 
    5654        15222 :         auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    5655              :         // Check for heat only furnace
    5656        15222 :         if (thisFurnace.type != HVAC::UnitarySysType::Furnace_HeatOnly && thisFurnace.type != HVAC::UnitarySysType::Unitary_HeatOnly) {
    5657              : 
    5658              :             // Set the system mass flow rates
    5659        15222 :             if (fanOp == HVAC::FanOp::Continuous) {
    5660              :                 // Set the compressor or coil ON mass flow rate
    5661              :                 // constant fan mode
    5662            0 :                 if (state.dataFurnaces->HeatingLoad) {
    5663              :                     //       IF a heating and moisture load exists, operate at the cooling mass flow rate ELSE operate at the heating flow rate
    5664            0 :                     if (MoistureLoad < 0.0 && thisFurnace.Humidistat &&
    5665            0 :                         thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat) {
    5666            0 :                         state.dataFurnaces->CompOnMassFlow = thisFurnace.MaxCoolAirMassFlow;
    5667            0 :                         state.dataFurnaces->CompOnFlowRatio = thisFurnace.CoolingSpeedRatio;
    5668              :                     } else {
    5669            0 :                         state.dataFurnaces->CompOnMassFlow = thisFurnace.MaxHeatAirMassFlow;
    5670            0 :                         state.dataFurnaces->CompOnFlowRatio = thisFurnace.HeatingSpeedRatio;
    5671              :                     }
    5672            0 :                     thisFurnace.LastMode = Furnaces::ModeOfOperation::HeatingMode;
    5673              :                     //     IF a cooling load exists, operate at the cooling mass flow rate
    5674            0 :                 } else if (state.dataFurnaces->CoolingLoad) {
    5675            0 :                     state.dataFurnaces->CompOnMassFlow = thisFurnace.MaxCoolAirMassFlow;
    5676            0 :                     state.dataFurnaces->CompOnFlowRatio = thisFurnace.CoolingSpeedRatio;
    5677            0 :                     thisFurnace.LastMode = Furnaces::ModeOfOperation::CoolingMode;
    5678              :                     //     If no load exists, set the compressor on mass flow rate.
    5679              :                     //     Set equal the mass flow rate when no heating or cooling is needed if no moisture load exists.
    5680              :                     //     If the user has set the off mass flow rate to 0, set according to the last operating mode.
    5681              :                 } else {
    5682            0 :                     if (MoistureLoad < 0.0 && thisFurnace.Humidistat &&
    5683            0 :                         thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat) {
    5684            0 :                         state.dataFurnaces->CompOnMassFlow = thisFurnace.MaxCoolAirMassFlow;
    5685            0 :                         state.dataFurnaces->CompOnFlowRatio = thisFurnace.CoolingSpeedRatio;
    5686              :                     } else {
    5687            0 :                         state.dataFurnaces->CompOnMassFlow = thisFurnace.MaxNoCoolHeatAirMassFlow;
    5688            0 :                         state.dataFurnaces->CompOnFlowRatio = thisFurnace.HeatingSpeedRatio;
    5689              :                         //         User may have entered a 0 for MaxNoCoolHeatAirMassFlow
    5690            0 :                         if (state.dataFurnaces->CompOnMassFlow == 0.0) {
    5691            0 :                             if (thisFurnace.LastMode == Furnaces::ModeOfOperation::HeatingMode) {
    5692            0 :                                 state.dataFurnaces->CompOnMassFlow = thisFurnace.MaxHeatAirMassFlow;
    5693            0 :                                 state.dataFurnaces->CompOnFlowRatio = thisFurnace.HeatingSpeedRatio;
    5694              :                             } else {
    5695            0 :                                 state.dataFurnaces->CompOnMassFlow = thisFurnace.MaxCoolAirMassFlow;
    5696            0 :                                 state.dataFurnaces->CompOnFlowRatio = thisFurnace.CoolingSpeedRatio;
    5697              :                             }
    5698              :                         }
    5699              :                     }
    5700              :                 }
    5701              : 
    5702              :                 //     Set the compressor or coil OFF mass flow rate based on LOGICAL flag
    5703              :                 //     UseCompressorOnFlow is used when the user does not enter a value for no cooling or heating flow rate
    5704            0 :                 if (thisFurnace.AirFlowControl == AirFlowControlConstFan::UseCompressorOnFlow) {
    5705            0 :                     if (thisFurnace.LastMode == Furnaces::ModeOfOperation::HeatingMode) {
    5706            0 :                         if (MoistureLoad < 0.0 && thisFurnace.Humidistat &&
    5707            0 :                             thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat) {
    5708            0 :                             state.dataFurnaces->CompOffMassFlow = thisFurnace.MaxCoolAirMassFlow;
    5709            0 :                             state.dataFurnaces->CompOffFlowRatio = thisFurnace.CoolingSpeedRatio;
    5710              :                         } else {
    5711            0 :                             state.dataFurnaces->CompOffMassFlow = thisFurnace.MaxHeatAirMassFlow;
    5712            0 :                             state.dataFurnaces->CompOffFlowRatio = thisFurnace.HeatingSpeedRatio;
    5713              :                         }
    5714              :                     } else {
    5715            0 :                         state.dataFurnaces->CompOffMassFlow = thisFurnace.MaxCoolAirMassFlow;
    5716            0 :                         state.dataFurnaces->CompOffFlowRatio = thisFurnace.CoolingSpeedRatio;
    5717              :                     }
    5718              :                     //     ELSE use the user specified value
    5719              :                 } else {
    5720            0 :                     state.dataFurnaces->CompOffMassFlow = thisFurnace.MaxNoCoolHeatAirMassFlow;
    5721            0 :                     state.dataFurnaces->CompOffFlowRatio = thisFurnace.NoHeatCoolSpeedRatio;
    5722              :                 }
    5723              :             } else {
    5724              :                 //     cycling fan mode
    5725        22082 :                 if (state.dataFurnaces->HeatingLoad ||
    5726         6860 :                     (thisFurnace.Humidistat && MoistureLoad < 0.0 && thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat)) {
    5727              : 
    5728         8362 :                     if (thisFurnace.Humidistat && MoistureLoad < 0.0 &&
    5729            0 :                         thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat) {
    5730            0 :                         state.dataFurnaces->CompOnMassFlow = thisFurnace.MaxCoolAirMassFlow;
    5731            0 :                         state.dataFurnaces->CompOnFlowRatio = thisFurnace.CoolingSpeedRatio;
    5732            0 :                         thisFurnace.LastMode = Furnaces::ModeOfOperation::CoolingMode;
    5733              :                     } else {
    5734         8362 :                         state.dataFurnaces->CompOnMassFlow = thisFurnace.MaxHeatAirMassFlow;
    5735         8362 :                         state.dataFurnaces->CompOnFlowRatio = thisFurnace.HeatingSpeedRatio;
    5736         8362 :                         thisFurnace.LastMode = Furnaces::ModeOfOperation::HeatingMode;
    5737              :                     }
    5738         6860 :                 } else if (state.dataFurnaces->CoolingLoad) {
    5739         6748 :                     state.dataFurnaces->CompOnMassFlow = thisFurnace.MaxCoolAirMassFlow;
    5740         6748 :                     state.dataFurnaces->CompOnFlowRatio = thisFurnace.CoolingSpeedRatio;
    5741              :                 } else {
    5742          112 :                     state.dataFurnaces->CompOnMassFlow = 0.0;
    5743          112 :                     state.dataFurnaces->CompOnFlowRatio = 0.0;
    5744              :                 }
    5745        15222 :                 state.dataFurnaces->CompOffMassFlow = 0.0;
    5746        15222 :                 state.dataFurnaces->CompOffFlowRatio = 0.0;
    5747              :             }
    5748              :         } else { //  Is a HeatOnly furnace
    5749              : 
    5750            0 :             state.dataFurnaces->CompOnMassFlow = thisFurnace.DesignMassFlowRate;
    5751            0 :             state.dataFurnaces->CompOnFlowRatio = thisFurnace.HeatingSpeedRatio;
    5752            0 :             if (fanOp == HVAC::FanOp::Continuous) {
    5753            0 :                 state.dataFurnaces->CompOffMassFlow = thisFurnace.MaxNoCoolHeatAirMassFlow;
    5754            0 :                 state.dataFurnaces->CompOffFlowRatio = thisFurnace.HeatingSpeedRatio;
    5755              :             } else {
    5756            0 :                 state.dataFurnaces->CompOffMassFlow = 0.0;
    5757            0 :                 state.dataFurnaces->CompOffFlowRatio = 0.0;
    5758              :             }
    5759              : 
    5760              :         } // End check for heat only furnace or water-to-air heat pump
    5761              : 
    5762              :         // Set the system mass flow rates
    5763        15222 :         SetAverageAirFlow(state, FurnaceNum, PartLoadRatio, OnOffAirFlowRatio);
    5764        15222 :     }
    5765              : 
    5766            2 :     void SizeFurnace(EnergyPlusData &state, int const FurnaceNum, bool const FirstHVACIteration)
    5767              :     {
    5768              : 
    5769              :         // SUBROUTINE INFORMATION:
    5770              :         //       AUTHOR         Fred Buhl
    5771              :         //       DATE WRITTEN   January 2002
    5772              :         //       MODIFIED       Bereket Nigusse, May 2010, removed the autosize option for the input field supply air
    5773              :         //                                                 flow fraction through controlled zone.
    5774              :         //                      Bo Shen, March 2012, size the air flow rates at individual speed levels for VS WSHP
    5775              :         //                      Bo Shen, ORNL, July 2012 - added variable-speed air source heat pump cooling and heating coils, using curve-fits
    5776              : 
    5777              :         // PURPOSE OF THIS SUBROUTINE:
    5778              :         // This subroutine is for sizing Furnace Components for which nominal capacities
    5779              :         // and flow rates have not been specified in the input
    5780              : 
    5781              :         // METHODOLOGY EMPLOYED:
    5782              :         // Obtains heating capacities and flow rates from the zone or system sizing arrays.
    5783              :         // NOTE: In UNITARYSYSTEM:HEATPUMP:AIRTOAIR we are sizing the heating capacity to be
    5784              :         // equal to the cooling capacity.  Thus the cooling and
    5785              :         // and heating capacities of a DX heat pump system will be identical. In real life the ARI
    5786              :         // heating and cooling capacities are close but not identical.
    5787              : 
    5788              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    5789              :         int Iter;                 // iteration count
    5790              :         Real64 MulSpeedFlowScale; // variable speed air flow scaling factor
    5791              :         int IHPCoilIndex;         // refer to cooling or heating coil in IHP
    5792            2 :         Real64 dummy(0.0);
    5793              :         bool anyRan;
    5794            2 :         EMSManager::ManageEMS(state, EMSManager::EMSCallFrom::UnitarySystemSizing, anyRan, ObjexxFCL::Optional_int_const()); // calling point
    5795              : 
    5796            2 :         state.dataSize->DXCoolCap = 0.0;
    5797            2 :         state.dataSize->UnitaryHeatCap = 0.0;
    5798            2 :         state.dataSize->SuppHeatCap = 0.0;
    5799            2 :         auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    5800              : 
    5801            2 :         state.dataAirSystemsData->PrimaryAirSystems(state.dataSize->CurSysNum).supFanNum = thisFurnace.FanIndex;
    5802            2 :         state.dataAirSystemsData->PrimaryAirSystems(state.dataSize->CurSysNum).supFanType = thisFurnace.fanType;
    5803            2 :         state.dataSize->DataFanType = thisFurnace.fanType;
    5804            2 :         state.dataSize->DataFanIndex = thisFurnace.FanIndex;
    5805              : 
    5806            2 :         state.dataAirSystemsData->PrimaryAirSystems(state.dataSize->CurSysNum).supFanPlace = thisFurnace.fanPlace;
    5807              : 
    5808            2 :         if (thisFurnace.CoolingCoilType_Num == HVAC::CoilDX_CoolingSingleSpeed) {
    5809            2 :             DXCoils::SimDXCoil(state, BlankString, HVAC::CompressorOp::On, true, thisFurnace.CoolingCoilIndex, HVAC::FanOp::Cycling, 0.0);
    5810            0 :         } else if (thisFurnace.CoolingCoilType_Num == HVAC::CoilDX_CoolingHXAssisted) {
    5811            0 :             int HXCC_Index = thisFurnace.CoolingCoilIndex;
    5812            0 :             int childCCType_Num = state.dataHVACAssistedCC->HXAssistedCoil(HXCC_Index).CoolingCoilType_Num;
    5813            0 :             if (childCCType_Num == HVAC::CoilDX_Cooling) {
    5814            0 :                 int childCCIndex = state.dataHVACAssistedCC->HXAssistedCoil(HXCC_Index).CoolingCoilIndex;
    5815            0 :                 if (childCCIndex < 0) {
    5816            0 :                     ShowContinueError(state, "Occurs in sizing HeatExchangerAssistedCoolingCoil.");
    5817              :                 }
    5818            0 :                 auto &newCoil = state.dataCoilCoolingDX->coilCoolingDXs[childCCIndex];
    5819            0 :                 newCoil.size(state);
    5820              :             }
    5821            0 :             HVACHXAssistedCoolingCoil::SimHXAssistedCoolingCoil(
    5822            0 :                 state, BlankString, true, HVAC::CompressorOp::On, 0.0, thisFurnace.CoolingCoilIndex, HVAC::FanOp::Cycling, false, 1.0, false);
    5823            0 :         } else if (thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingWaterToAirHPSimple) {
    5824            0 :             WaterToAirHeatPumpSimple::SimWatertoAirHPSimple(state,
    5825              :                                                             BlankString,
    5826            0 :                                                             thisFurnace.CoolingCoilIndex,
    5827              :                                                             thisFurnace.CoolingCoilSensDemand,
    5828              :                                                             thisFurnace.CoolingCoilLatentDemand,
    5829              :                                                             HVAC::FanOp::Invalid, // Using invalid to mean off?
    5830              :                                                             HVAC::CompressorOp::Off,
    5831              :                                                             0.0,
    5832              :                                                             FirstHVACIteration); // CoolPartLoadRatio
    5833            0 :             if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingWaterToAirHPSimple) {
    5834            0 :                 WaterToAirHeatPumpSimple::SimWatertoAirHPSimple(state,
    5835              :                                                                 BlankString,
    5836            0 :                                                                 thisFurnace.HeatingCoilIndex,
    5837              :                                                                 thisFurnace.HeatingCoilSensDemand,
    5838              :                                                                 dummy,
    5839              :                                                                 HVAC::FanOp::Invalid, // using Invalid to mean off?
    5840              :                                                                 HVAC::CompressorOp::Off,
    5841              :                                                                 0.0,
    5842              :                                                                 FirstHVACIteration);
    5843              :             }
    5844            0 :         } else if (thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingWaterToAirHPVSEquationFit ||
    5845            0 :                    thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingAirToAirVariableSpeed) {
    5846            0 :             if (thisFurnace.bIsIHP) {
    5847            0 :                 IntegratedHeatPump::SizeIHP(state, thisFurnace.CoolingCoilIndex);
    5848            0 :                 IHPCoilIndex = state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).SCCoilIndex;
    5849            0 :                 thisFurnace.NumOfSpeedCooling = state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex).NumOfSpeeds;
    5850            0 :                 MulSpeedFlowScale = state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex).RatedAirVolFlowRate /
    5851            0 :                                     state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex)
    5852            0 :                                         .MSRatedAirVolFlowRate(state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex).NormSpedLevel);
    5853            0 :                 state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).CoolVolFlowScale = MulSpeedFlowScale;
    5854              :             } else {
    5855            0 :                 VariableSpeedCoils::SimVariableSpeedCoils(state,
    5856              :                                                           BlankString,
    5857            0 :                                                           thisFurnace.CoolingCoilIndex,
    5858              :                                                           HVAC::FanOp::Invalid, // USing Invalid for off?
    5859              :                                                           HVAC::CompressorOp::Off,
    5860              :                                                           0.0,
    5861              :                                                           1,
    5862              :                                                           0.0,
    5863              :                                                           0.0,
    5864              :                                                           0.0,
    5865              :                                                           0.0); // conduct the sizing operation in the VS WSHP
    5866            0 :                 thisFurnace.NumOfSpeedCooling = state.dataVariableSpeedCoils->VarSpeedCoil(thisFurnace.CoolingCoilIndex).NumOfSpeeds;
    5867            0 :                 MulSpeedFlowScale =
    5868            0 :                     state.dataVariableSpeedCoils->VarSpeedCoil(thisFurnace.CoolingCoilIndex).RatedAirVolFlowRate /
    5869            0 :                     state.dataVariableSpeedCoils->VarSpeedCoil(thisFurnace.CoolingCoilIndex)
    5870            0 :                         .MSRatedAirVolFlowRate(state.dataVariableSpeedCoils->VarSpeedCoil(thisFurnace.CoolingCoilIndex).NormSpedLevel);
    5871            0 :                 IHPCoilIndex = thisFurnace.CoolingCoilIndex;
    5872              :             }
    5873              : 
    5874            0 :             for (Iter = 1; Iter <= thisFurnace.NumOfSpeedCooling; ++Iter) {
    5875            0 :                 thisFurnace.CoolVolumeFlowRate(Iter) =
    5876            0 :                     state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex).MSRatedAirVolFlowRate(Iter) * MulSpeedFlowScale;
    5877            0 :                 thisFurnace.CoolMassFlowRate(Iter) =
    5878            0 :                     state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex).MSRatedAirMassFlowRate(Iter) * MulSpeedFlowScale;
    5879            0 :                 thisFurnace.MSCoolingSpeedRatio(Iter) =
    5880            0 :                     state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex).MSRatedAirVolFlowRate(Iter) /
    5881            0 :                     state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex).MSRatedAirVolFlowRate(thisFurnace.NumOfSpeedCooling);
    5882              :             }
    5883              : 
    5884            0 :             if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingWaterToAirHPVSEquationFit ||
    5885            0 :                 thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingAirToAirVariableSpeed) {
    5886              : 
    5887            0 :                 if (thisFurnace.bIsIHP) {
    5888            0 :                     IntegratedHeatPump::SizeIHP(state, thisFurnace.CoolingCoilIndex);
    5889            0 :                     IHPCoilIndex = state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).SHCoilIndex;
    5890            0 :                     thisFurnace.NumOfSpeedHeating = state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex).NumOfSpeeds;
    5891            0 :                     MulSpeedFlowScale = state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex).RatedAirVolFlowRate /
    5892            0 :                                         state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex)
    5893            0 :                                             .MSRatedAirVolFlowRate(state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex).NormSpedLevel);
    5894            0 :                     state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).HeatVolFlowScale = MulSpeedFlowScale;
    5895              :                 } else {
    5896            0 :                     VariableSpeedCoils::SimVariableSpeedCoils(state,
    5897              :                                                               BlankString,
    5898            0 :                                                               thisFurnace.HeatingCoilIndex,
    5899              :                                                               HVAC::FanOp::Invalid, // Invalid for off?
    5900              :                                                               HVAC::CompressorOp::Off,
    5901              :                                                               0.0,
    5902              :                                                               1,
    5903              :                                                               0.0,
    5904              :                                                               0.0,
    5905              :                                                               0.0,
    5906              :                                                               0.0); // conduct the sizing operation in the VS WSHP
    5907            0 :                     thisFurnace.NumOfSpeedHeating = state.dataVariableSpeedCoils->VarSpeedCoil(thisFurnace.HeatingCoilIndex).NumOfSpeeds;
    5908            0 :                     MulSpeedFlowScale =
    5909            0 :                         state.dataVariableSpeedCoils->VarSpeedCoil(thisFurnace.HeatingCoilIndex).RatedAirVolFlowRate /
    5910            0 :                         state.dataVariableSpeedCoils->VarSpeedCoil(thisFurnace.HeatingCoilIndex)
    5911            0 :                             .MSRatedAirVolFlowRate(state.dataVariableSpeedCoils->VarSpeedCoil(thisFurnace.HeatingCoilIndex).NormSpedLevel);
    5912            0 :                     IHPCoilIndex = thisFurnace.HeatingCoilIndex;
    5913              :                 }
    5914              : 
    5915            0 :                 for (Iter = 1; Iter <= thisFurnace.NumOfSpeedHeating; ++Iter) {
    5916            0 :                     thisFurnace.HeatVolumeFlowRate(Iter) =
    5917            0 :                         state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex).MSRatedAirVolFlowRate(Iter) * MulSpeedFlowScale;
    5918            0 :                     thisFurnace.HeatMassFlowRate(Iter) =
    5919            0 :                         state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex).MSRatedAirMassFlowRate(Iter) * MulSpeedFlowScale;
    5920            0 :                     thisFurnace.MSHeatingSpeedRatio(Iter) =
    5921            0 :                         state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex).MSRatedAirVolFlowRate(Iter) /
    5922            0 :                         state.dataVariableSpeedCoils->VarSpeedCoil(IHPCoilIndex).MSRatedAirVolFlowRate(thisFurnace.NumOfSpeedHeating);
    5923              :                 }
    5924              :             }
    5925              : 
    5926            0 :             if (thisFurnace.NumOfSpeedHeating > 0) {
    5927            0 :                 thisFurnace.IdleMassFlowRate = min(thisFurnace.HeatMassFlowRate(1), thisFurnace.CoolMassFlowRate(1));
    5928            0 :                 thisFurnace.IdleSpeedRatio = min(thisFurnace.MSHeatingSpeedRatio(1), thisFurnace.MSCoolingSpeedRatio(1));
    5929            0 :                 thisFurnace.IdleVolumeAirRate = min(thisFurnace.HeatVolumeFlowRate(1), thisFurnace.CoolVolumeFlowRate(1));
    5930              :             } else {
    5931            0 :                 thisFurnace.IdleMassFlowRate = thisFurnace.CoolMassFlowRate(1);
    5932            0 :                 thisFurnace.IdleSpeedRatio = thisFurnace.MSCoolingSpeedRatio(1);
    5933            0 :                 thisFurnace.IdleVolumeAirRate = thisFurnace.CoolVolumeFlowRate(1);
    5934              :             }
    5935              : 
    5936            0 :             if (thisFurnace.fanOp == HVAC::FanOp::Continuous) {
    5937            0 :                 thisFurnace.MaxNoCoolHeatAirVolFlow = thisFurnace.IdleVolumeAirRate;
    5938            0 :                 thisFurnace.MaxNoCoolHeatAirMassFlow = thisFurnace.IdleMassFlowRate;
    5939            0 :                 thisFurnace.NoHeatCoolSpeedRatio = thisFurnace.IdleSpeedRatio;
    5940              :             }
    5941              :         }
    5942              : 
    5943            2 :         if (thisFurnace.DesignFanVolFlowRate == DataSizing::AutoSize) {
    5944              : 
    5945            2 :             if (state.dataSize->CurSysNum > 0) {
    5946              : 
    5947            2 :                 CheckSysSizing(state, HVAC::unitarySysTypeNames[(int)thisFurnace.type], thisFurnace.Name);
    5948            2 :                 if (state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesMainVolFlow >= HVAC::SmallAirVolFlow) {
    5949            2 :                     thisFurnace.DesignFanVolFlowRate = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesMainVolFlow;
    5950              :                 } else {
    5951            0 :                     thisFurnace.DesignFanVolFlowRate = 0.0;
    5952              :                 }
    5953              : 
    5954            2 :                 if (thisFurnace.DesignFanVolFlowRateEMSOverrideOn) {
    5955            0 :                     thisFurnace.DesignFanVolFlowRate = thisFurnace.DesignFanVolFlowRateEMSOverrideValue;
    5956              :                 }
    5957              : 
    5958            4 :                 BaseSizer::reportSizerOutput(state,
    5959            2 :                                              HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    5960              :                                              thisFurnace.Name,
    5961              :                                              "Supply Air Flow Rate [m3/s]",
    5962              :                                              thisFurnace.DesignFanVolFlowRate);
    5963              :             }
    5964              :         }
    5965              : 
    5966            2 :         if (thisFurnace.MaxHeatAirVolFlow == DataSizing::AutoSize) {
    5967              : 
    5968            2 :             if (state.dataSize->CurSysNum > 0) {
    5969              : 
    5970            2 :                 CheckSysSizing(state, HVAC::unitarySysTypeNames[(int)thisFurnace.type], thisFurnace.Name);
    5971            2 :                 if (state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesMainVolFlow >= HVAC::SmallAirVolFlow) {
    5972            2 :                     thisFurnace.MaxHeatAirVolFlow = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesMainVolFlow;
    5973              :                 } else {
    5974            0 :                     thisFurnace.MaxHeatAirVolFlow = 0.0;
    5975              :                 }
    5976              : 
    5977            2 :                 if (thisFurnace.MaxHeatAirVolFlowEMSOverrideOn) {
    5978            0 :                     thisFurnace.MaxHeatAirVolFlow = thisFurnace.MaxHeatAirVolFlowEMSOverrideValue;
    5979              :                 }
    5980            4 :                 BaseSizer::reportSizerOutput(state,
    5981            2 :                                              HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    5982              :                                              thisFurnace.Name,
    5983              :                                              "Supply Air Flow Rate During Heating Operation [m3/s]",
    5984              :                                              thisFurnace.MaxHeatAirVolFlow);
    5985              :             }
    5986              :         }
    5987              : 
    5988            2 :         if (thisFurnace.MaxCoolAirVolFlow == DataSizing::AutoSize) {
    5989              : 
    5990            2 :             if (state.dataSize->CurSysNum > 0) {
    5991              : 
    5992            2 :                 CheckSysSizing(state, HVAC::unitarySysTypeNames[(int)thisFurnace.type], thisFurnace.Name);
    5993            2 :                 if (state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesMainVolFlow >= HVAC::SmallAirVolFlow) {
    5994            2 :                     thisFurnace.MaxCoolAirVolFlow = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesMainVolFlow;
    5995              :                 } else {
    5996            0 :                     thisFurnace.MaxCoolAirVolFlow = 0.0;
    5997              :                 }
    5998              : 
    5999            2 :                 if (thisFurnace.MaxCoolAirVolFlowEMSOverrideOn) {
    6000            0 :                     thisFurnace.MaxCoolAirVolFlow = thisFurnace.MaxCoolAirVolFlowEMSOverrideValue;
    6001              :                 }
    6002              : 
    6003            4 :                 BaseSizer::reportSizerOutput(state,
    6004            2 :                                              HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    6005              :                                              thisFurnace.Name,
    6006              :                                              "Supply Air Flow Rate During Cooling Operation [m3/s]",
    6007              :                                              thisFurnace.MaxCoolAirVolFlow);
    6008              :             }
    6009              :         }
    6010              : 
    6011            2 :         if (thisFurnace.MaxNoCoolHeatAirVolFlow == DataSizing::AutoSize) {
    6012              : 
    6013            1 :             if (state.dataSize->CurSysNum > 0) {
    6014              : 
    6015            1 :                 CheckSysSizing(state, HVAC::unitarySysTypeNames[(int)thisFurnace.type], thisFurnace.Name);
    6016            1 :                 if (state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesMainVolFlow >= HVAC::SmallAirVolFlow) {
    6017            1 :                     thisFurnace.MaxNoCoolHeatAirVolFlow = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesMainVolFlow;
    6018              :                 } else {
    6019            0 :                     thisFurnace.MaxNoCoolHeatAirVolFlow = 0.0;
    6020              :                 }
    6021              : 
    6022            1 :                 if (thisFurnace.MaxNoCoolHeatAirVolFlowEMSOverrideOn) {
    6023            0 :                     thisFurnace.MaxNoCoolHeatAirVolFlow = thisFurnace.MaxNoCoolHeatAirVolFlowEMSOverrideValue;
    6024              :                 }
    6025              : 
    6026            2 :                 BaseSizer::reportSizerOutput(state,
    6027            1 :                                              HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    6028              :                                              thisFurnace.Name,
    6029              :                                              "Supply Air Flow Rate When No Cooling or Heating is Needed [m3/s]",
    6030              :                                              thisFurnace.MaxNoCoolHeatAirVolFlow);
    6031              :             }
    6032              :         }
    6033              : 
    6034            2 :         if (thisFurnace.DesignHeatingCapacity == DataSizing::AutoSize) {
    6035              : 
    6036            2 :             if (state.dataSize->CurSysNum > 0) {
    6037              : 
    6038            2 :                 if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_AirToAir ||
    6039            0 :                     thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir) {
    6040              : 
    6041            2 :                     CheckSysSizing(state, HVAC::unitarySysTypeNames[(int)thisFurnace.type], thisFurnace.Name);
    6042              : 
    6043            2 :                     if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingWaterToAirHPSimple) {
    6044            0 :                         thisFurnace.DesignHeatingCapacity =
    6045            0 :                             state.dataWaterToAirHeatPumpSimple->SimpleWatertoAirHP(thisFurnace.HeatingCoilIndex).RatedCapHeat;
    6046              :                     } else {
    6047            2 :                         thisFurnace.DesignHeatingCapacity = state.dataSize->DXCoolCap;
    6048              :                     }
    6049              : 
    6050              :                 } else {
    6051              : 
    6052            0 :                     CheckSysSizing(state, HVAC::unitarySysTypeNames[(int)thisFurnace.type], thisFurnace.Name);
    6053              : 
    6054            0 :                     thisFurnace.DesignHeatingCapacity = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).HeatCap;
    6055              :                 }
    6056              : 
    6057            2 :                 if (thisFurnace.DesignHeatingCapacity < HVAC::SmallLoad) {
    6058            0 :                     thisFurnace.DesignHeatingCapacity = 0.0;
    6059              :                 }
    6060              : 
    6061            4 :                 BaseSizer::reportSizerOutput(state,
    6062            2 :                                              HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    6063              :                                              thisFurnace.Name,
    6064              :                                              "Nominal Heating Capacity [W]",
    6065              :                                              thisFurnace.DesignHeatingCapacity);
    6066              :             }
    6067              :         }
    6068              : 
    6069            2 :         if (thisFurnace.DesignCoolingCapacity == DataSizing::AutoSize) {
    6070              : 
    6071            2 :             if (state.dataSize->CurSysNum > 0) {
    6072              : 
    6073            2 :                 CheckSysSizing(state, HVAC::unitarySysTypeNames[(int)thisFurnace.type], thisFurnace.Name);
    6074            2 :                 if (state.dataSize->DXCoolCap >= HVAC::SmallLoad) {
    6075            2 :                     thisFurnace.DesignCoolingCapacity = state.dataSize->DXCoolCap;
    6076              :                 } else {
    6077            0 :                     thisFurnace.DesignCoolingCapacity = 0.0;
    6078              :                 }
    6079            4 :                 BaseSizer::reportSizerOutput(state,
    6080            2 :                                              HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    6081              :                                              thisFurnace.Name,
    6082              :                                              "Nominal Cooling Capacity [W]",
    6083              :                                              thisFurnace.DesignCoolingCapacity);
    6084              :             }
    6085              :         }
    6086              : 
    6087            2 :         if (thisFurnace.DesignMaxOutletTemp == DataSizing::AutoSize) {
    6088              : 
    6089            1 :             if (state.dataSize->CurSysNum > 0) {
    6090              : 
    6091            1 :                 CheckSysSizing(state, HVAC::unitarySysTypeNames[(int)thisFurnace.type], thisFurnace.Name);
    6092            1 :                 thisFurnace.DesignMaxOutletTemp = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).HeatSupTemp;
    6093            2 :                 BaseSizer::reportSizerOutput(state,
    6094            1 :                                              HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    6095              :                                              thisFurnace.Name,
    6096              :                                              "Maximum Supply Air Temperature from Supplemental Heater [C]",
    6097              :                                              thisFurnace.DesignMaxOutletTemp);
    6098              :             }
    6099              :         }
    6100              : 
    6101            2 :         if (thisFurnace.DesignSuppHeatingCapacity == DataSizing::AutoSize) {
    6102              : 
    6103            1 :             if (state.dataSize->CurSysNum > 0) {
    6104              : 
    6105            1 :                 CheckSysSizing(state, HVAC::unitarySysTypeNames[(int)thisFurnace.type], thisFurnace.Name);
    6106            1 :                 if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_AirToAir ||
    6107            0 :                     thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir) {
    6108              :                     // set the supplemental heating capacity to the actual heating load
    6109            1 :                     thisFurnace.DesignSuppHeatingCapacity = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).HeatCap;
    6110              :                     // if reheat needed for humidity control, make sure supplemental heating is at least as big
    6111              :                     // as the cooling capacity
    6112            1 :                     if (thisFurnace.Humidistat && thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat) {
    6113            0 :                         thisFurnace.DesignSuppHeatingCapacity = max(thisFurnace.DesignSuppHeatingCapacity, thisFurnace.DesignCoolingCapacity);
    6114            0 :                         if (thisFurnace.DesignSuppHeatingCapacity < HVAC::SmallLoad) {
    6115            0 :                             thisFurnace.DesignSuppHeatingCapacity = 0.0;
    6116              :                         }
    6117              :                     }
    6118              : 
    6119              :                 } else {
    6120              : 
    6121            0 :                     if (thisFurnace.Humidistat && thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat) {
    6122            0 :                         thisFurnace.DesignSuppHeatingCapacity = thisFurnace.DesignCoolingCapacity;
    6123              :                     } else {
    6124            0 :                         thisFurnace.DesignSuppHeatingCapacity = 0.0;
    6125              :                     }
    6126              :                 }
    6127              : 
    6128            2 :                 BaseSizer::reportSizerOutput(state,
    6129            1 :                                              HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    6130              :                                              thisFurnace.Name,
    6131              :                                              "Supplemental Heating Coil Nominal Capacity [W]",
    6132              :                                              thisFurnace.DesignSuppHeatingCapacity);
    6133              :             }
    6134              :         }
    6135              : 
    6136            2 :         state.dataSize->UnitaryHeatCap = thisFurnace.DesignHeatingCapacity;
    6137            2 :         state.dataSize->SuppHeatCap = thisFurnace.DesignSuppHeatingCapacity;
    6138            2 :     }
    6139              : 
    6140              :     // End Initialization Section of the Module
    6141              :     //******************************************************************************
    6142              : 
    6143              :     // Beginning of Update subroutines for the Furnace Module
    6144              :     // *****************************************************************************
    6145              : 
    6146            0 :     void CalcNewZoneHeatOnlyFlowRates(EnergyPlusData &state,
    6147              :                                       int const FurnaceNum,          // Index to furnace
    6148              :                                       bool const FirstHVACIteration, // Iteration flag
    6149              :                                       Real64 const ZoneLoad,         // load to be met by furnace (W)
    6150              :                                       Real64 &HeatCoilLoad,          // actual load passed to heating coil (W)
    6151              :                                       Real64 &OnOffAirFlowRatio      // ratio of coil on to coil off air flow rate
    6152              :     )
    6153              :     {
    6154              :         // SUBROUTINE INFORMATION:
    6155              :         //       AUTHOR         Richard Liesen
    6156              :         //       DATE WRITTEN   Feb 2001
    6157              :         //       MODIFIED       Don Shirey and R. Raustad, Mar 2001 & Mar 2003
    6158              : 
    6159              :         // PURPOSE OF THIS SUBROUTINE:
    6160              :         // This subroutine updates the coil outlet nodes by simulating a heat-only
    6161              :         // furnace or unitary system.
    6162              : 
    6163              :         // METHODOLOGY EMPLOYED:
    6164              :         // Determine the operating PLR to meet the zone sensible load.
    6165              : 
    6166              :         // SUBROUTINE PARAMETER DEFINITIONS:
    6167            0 :         int constexpr MaxIter(15);    // maximum number of iterations
    6168            0 :         Real64 constexpr MinPLR(0.0); // minimum part load ratio allowed
    6169              : 
    6170              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    6171            0 :         Real64 Error(1.0);
    6172              :         Real64 SystemSensibleLoad;   // Sensible load to be met by furnace (W)
    6173              :         Real64 FullSensibleOutput;   // Full sensible output of furnace (W)
    6174              :         Real64 FullLatentOutput;     // Full latent output of furnace = 0 (W)
    6175              :         Real64 NoSensibleOutput;     // Sensible output of furnace with no heating allowed (W)
    6176              :         Real64 NoLatentOutput;       // Latent output of furnace = 0 (W)
    6177              :         Real64 PartLoadRatio;        // Part load ratio of furnace
    6178              :         Real64 HeatErrorToler;       // Error tolerance in heating mode
    6179              :         Real64 IterRelax;            // Relaxation factor for iterations
    6180              :         Real64 ActualSensibleOutput; // Actual furnace sensible capacity
    6181              :         Real64 ActualLatentOutput;   // Actual furnace latent capacity = 0
    6182              :         Real64 deltaT;               // Heater outlet temp minus design heater outlet temp
    6183              : 
    6184            0 :         auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    6185              :         // Retrieve the load on the controlled zone
    6186            0 :         auto &furnaceInNode = state.dataLoopNodes->Node(thisFurnace.FurnaceInletNodeNum);
    6187            0 :         auto const &furnaceOutNode = state.dataLoopNodes->Node(thisFurnace.FurnaceOutletNodeNum);
    6188            0 :         int ControlZoneNode = thisFurnace.NodeNumOfControlledZone;
    6189            0 :         HVAC::FanOp fanOp = thisFurnace.fanOp; // fan operating mode
    6190            0 :         thisFurnace.MdotFurnace = thisFurnace.DesignMassFlowRate;
    6191            0 :         thisFurnace.CoolPartLoadRatio = 0.0;
    6192              : 
    6193              :         // Calculate the Cp Air of zone
    6194            0 :         Real64 cpair = Psychrometrics::PsyCpAirFnW(state.dataLoopNodes->Node(ControlZoneNode).HumRat);
    6195              : 
    6196            0 :         if (FirstHVACIteration) {
    6197            0 :             HeatCoilLoad = ZoneLoad;
    6198            0 :             state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
    6199              :         } else {
    6200              :             // If Furnace runs then set HeatCoilLoad on Heating Coil and the Mass Flow
    6201            0 :             if ((thisFurnace.availSched->getCurrentVal() > 0.0) && (furnaceInNode.MassFlowRate > 0.0) && (state.dataFurnaces->HeatingLoad)) {
    6202              : 
    6203            0 :                 furnaceInNode.MassFlowRate = thisFurnace.MdotFurnace;
    6204            0 :                 HeatCoilLoad = thisFurnace.DesignHeatingCapacity;
    6205            0 :                 SystemSensibleLoad = ZoneLoad;
    6206              : 
    6207              :                 // Get no load result
    6208            0 :                 if (fanOp == HVAC::FanOp::Cycling) {
    6209            0 :                     furnaceInNode.MassFlowRate = 0.0;
    6210              :                 }
    6211            0 :                 if (fanOp == HVAC::FanOp::Continuous) {
    6212            0 :                     state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0; // The on/off fan will not cycle, so set part-load fraction = 1
    6213              :                 }
    6214              : 
    6215              :                 //     Set the inlet mass flow rate based on user specified coil OFF flow rate
    6216            0 :                 PartLoadRatio = 0.0;
    6217            0 :                 SetAverageAirFlow(state, FurnaceNum, PartLoadRatio, OnOffAirFlowRatio);
    6218              : 
    6219            0 :                 CalcFurnaceOutput(state,
    6220              :                                   FurnaceNum,
    6221              :                                   FirstHVACIteration,
    6222              :                                   fanOp,
    6223              :                                   HVAC::CompressorOp::On,
    6224              :                                   0.0,
    6225              :                                   0.0,
    6226              :                                   0.0,
    6227              :                                   0.0,
    6228              :                                   NoSensibleOutput,
    6229              :                                   NoLatentOutput,
    6230              :                                   OnOffAirFlowRatio,
    6231              :                                   false);
    6232              : 
    6233            0 :                 furnaceInNode.MassFlowRate = thisFurnace.MdotFurnace;
    6234              : 
    6235              :                 // Set fan part-load fraction equal to 1 while getting full load result
    6236            0 :                 state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
    6237            0 :                 OnOffAirFlowRatio = 1.0;
    6238              : 
    6239              :                 // Get full load result
    6240            0 :                 CalcFurnaceOutput(state,
    6241              :                                   FurnaceNum,
    6242              :                                   FirstHVACIteration,
    6243              :                                   fanOp,
    6244              :                                   HVAC::CompressorOp::On,
    6245              :                                   0.0,
    6246              :                                   1.0,
    6247              :                                   HeatCoilLoad,
    6248              :                                   0.0,
    6249              :                                   FullSensibleOutput,
    6250              :                                   FullLatentOutput,
    6251              :                                   OnOffAirFlowRatio,
    6252              :                                   false);
    6253              : 
    6254              :                 // Since we are heating, we expect FullSensibleOutput to be > 0 and FullSensibleOutput > NoSensibleOutput
    6255              :                 // Check that this is the case; if not set PartLoadRatio = 0.0d0 (off) and return
    6256              : 
    6257            0 :                 if (FullSensibleOutput > NoSensibleOutput) {
    6258              :                     PartLoadRatio =
    6259            0 :                         max(MinPLR, min(1.0, std::abs(SystemSensibleLoad - NoSensibleOutput) / std::abs(FullSensibleOutput - NoSensibleOutput)));
    6260            0 :                     if (fanOp == HVAC::FanOp::Cycling) {
    6261            0 :                         furnaceInNode.MassFlowRate = thisFurnace.MdotFurnace * PartLoadRatio;
    6262            0 :                         HeatCoilLoad = thisFurnace.DesignHeatingCapacity * PartLoadRatio;
    6263              :                     } else { // FanOp::Continuous
    6264            0 :                         if (furnaceOutNode.Temp > thisFurnace.DesignMaxOutletTemp) {
    6265            0 :                             deltaT = furnaceOutNode.Temp - thisFurnace.DesignMaxOutletTemp;
    6266            0 :                             if (HeatCoilLoad > thisFurnace.DesignHeatingCapacity) HeatCoilLoad = thisFurnace.DesignHeatingCapacity;
    6267            0 :                             HeatCoilLoad -= furnaceInNode.MassFlowRate * cpair * deltaT;
    6268              :                         } else {
    6269            0 :                             HeatCoilLoad = SystemSensibleLoad - NoSensibleOutput;
    6270              :                         }
    6271              :                     }
    6272              : 
    6273              :                     // Calculate the part load ratio through iteration
    6274            0 :                     HeatErrorToler = thisFurnace.HeatingConvergenceTolerance; // Error tolerance for convergence from input deck
    6275            0 :                     Error = 1.0;                                              // initialize error value for comparison against tolerance
    6276            0 :                     state.dataFurnaces->Iter = 0;                             // initialize iteration counter
    6277            0 :                     IterRelax = 0.9;                                          // relaxation factor for iterations
    6278            0 :                     while (state.dataFurnaces->Iter <= MaxIter) {
    6279              : 
    6280            0 :                         if (fanOp == HVAC::FanOp::Cycling) furnaceInNode.MassFlowRate = thisFurnace.MdotFurnace * PartLoadRatio;
    6281            0 :                         CalcFurnaceOutput(state,
    6282              :                                           FurnaceNum,
    6283              :                                           FirstHVACIteration,
    6284              :                                           fanOp,
    6285              :                                           HVAC::CompressorOp::On,
    6286              :                                           0.0,
    6287              :                                           PartLoadRatio,
    6288              :                                           HeatCoilLoad,
    6289              :                                           0.0,
    6290              :                                           ActualSensibleOutput,
    6291              :                                           ActualLatentOutput,
    6292              :                                           OnOffAirFlowRatio,
    6293              :                                           false);
    6294              : 
    6295            0 :                         if (SystemSensibleLoad != 0.0) Error = (SystemSensibleLoad - ActualSensibleOutput) / (SystemSensibleLoad);
    6296            0 :                         if (std::abs(Error) <= HeatErrorToler) break;
    6297            0 :                         PartLoadRatio = max(
    6298              :                             MinPLR,
    6299              :                             min(1.0,
    6300            0 :                                 PartLoadRatio + IterRelax * (SystemSensibleLoad - ActualSensibleOutput) / (FullSensibleOutput - NoSensibleOutput)));
    6301              : 
    6302              :                         // limit the heating coil outlet air temperature to DesignMaxOutletTemp
    6303            0 :                         if (furnaceOutNode.Temp > thisFurnace.DesignMaxOutletTemp) {
    6304            0 :                             deltaT = furnaceOutNode.Temp - thisFurnace.DesignMaxOutletTemp;
    6305            0 :                             if (HeatCoilLoad > thisFurnace.DesignHeatingCapacity) HeatCoilLoad = thisFurnace.DesignHeatingCapacity;
    6306            0 :                             HeatCoilLoad -= furnaceInNode.MassFlowRate * cpair * deltaT;
    6307            0 :                             CalcFurnaceOutput(state,
    6308              :                                               FurnaceNum,
    6309              :                                               FirstHVACIteration,
    6310              :                                               fanOp,
    6311              :                                               HVAC::CompressorOp::On,
    6312              :                                               0.0,
    6313              :                                               PartLoadRatio,
    6314              :                                               HeatCoilLoad,
    6315              :                                               0.0,
    6316              :                                               ActualSensibleOutput,
    6317              :                                               ActualLatentOutput,
    6318              :                                               OnOffAirFlowRatio,
    6319              :                                               false);
    6320              : 
    6321            0 :                             if (SystemSensibleLoad != 0.0) Error = (SystemSensibleLoad - ActualSensibleOutput) / (SystemSensibleLoad);
    6322            0 :                             PartLoadRatio = max(MinPLR,
    6323              :                                                 min(1.0,
    6324            0 :                                                     PartLoadRatio + IterRelax * (SystemSensibleLoad - ActualSensibleOutput) /
    6325            0 :                                                                         (FullSensibleOutput - NoSensibleOutput)));
    6326              :                         } else {
    6327            0 :                             HeatCoilLoad = thisFurnace.DesignHeatingCapacity * PartLoadRatio;
    6328              :                         }
    6329              : 
    6330            0 :                         if (PartLoadRatio == MinPLR) break;
    6331            0 :                         if (PartLoadRatio == 1.0) break;
    6332            0 :                         ++state.dataFurnaces->Iter;
    6333            0 :                         if (state.dataFurnaces->Iter == 7) IterRelax = 0.7;
    6334            0 :                         if (state.dataFurnaces->Iter == 15) IterRelax = 0.4;
    6335              :                     }
    6336              : 
    6337            0 :                     if (state.dataFurnaces->Iter > MaxIter) {
    6338            0 :                         if (thisFurnace.HeatingMaxIterIndex2 == 0) {
    6339            0 :                             ShowWarningMessage(state,
    6340            0 :                                                format("{} \"{}\" -- Exceeded max heating iterations ({}) while adjusting furnace runtime.",
    6341            0 :                                                       HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    6342            0 :                                                       thisFurnace.Name,
    6343              :                                                       MaxIter));
    6344            0 :                             ShowContinueErrorTimeStamp(state, "");
    6345              :                         }
    6346            0 :                         ShowRecurringWarningErrorAtEnd(state,
    6347            0 :                                                        format("{} \"{}\" -- Exceeded max heating iterations error continues...",
    6348            0 :                                                               HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    6349            0 :                                                               thisFurnace.Name),
    6350            0 :                                                        thisFurnace.HeatingMaxIterIndex2);
    6351              :                     }
    6352              : 
    6353              :                 } else { // ELSE from IF(FullSensibleOutput.GT.NoSensibleOutput)THEN above
    6354              :                     // Set part load ratio to 1 and run heater at design heating capacity
    6355            0 :                     PartLoadRatio = 1.0;
    6356            0 :                     HeatCoilLoad = thisFurnace.DesignHeatingCapacity;
    6357              :                 }
    6358              :                 // Set the final results
    6359              :                 //      IF (fanOp .EQ. FanOp::Cycling) THEN
    6360              :                 //        Furnace(FurnaceNum)%MdotFurnace = Furnace(FurnaceNum)%MdotFurnace * PartLoadRatio
    6361              :                 //      END IF
    6362            0 :                 thisFurnace.MdotFurnace = furnaceInNode.MassFlowRate;
    6363              : 
    6364            0 :             } else if ((thisFurnace.availSched->getCurrentVal() > 0.0) && (furnaceInNode.MassFlowRate > 0.0) && (fanOp == HVAC::FanOp::Continuous)) {
    6365            0 :                 HeatCoilLoad = 0.0;
    6366              :             } else { // no heating and no flow
    6367            0 :                 thisFurnace.MdotFurnace = 0.0;
    6368            0 :                 HeatCoilLoad = 0.0;
    6369              :             } // End of the Scheduled Furnace If block
    6370              : 
    6371              :         } // End of the FirstHVACIteration control of the mass flow If block
    6372              : 
    6373              :         // Set the fan inlet node flow rates
    6374            0 :         furnaceInNode.MassFlowRateMaxAvail = thisFurnace.MdotFurnace;
    6375            0 :         furnaceInNode.MassFlowRate = thisFurnace.MdotFurnace;
    6376            0 :     }
    6377              : 
    6378        15225 :     void CalcNewZoneHeatCoolFlowRates(EnergyPlusData &state,
    6379              :                                       int const FurnaceNum,
    6380              :                                       bool const FirstHVACIteration,
    6381              :                                       HVAC::CompressorOp const compressorOp, // compressor operation flag (1=On, 0=Off)
    6382              :                                       Real64 const ZoneLoad,                 // the control zone load (watts)
    6383              :                                       Real64 const MoistureLoad,             // the control zone latent load (watts)
    6384              :                                       Real64 &HeatCoilLoad,                  // Heating load to be met by heating coil ( excluding heat pump DX coil)
    6385              :                                       Real64 &ReheatCoilLoad,    // Heating load to be met by reheat coil using hstat (excluding HP DX coil)
    6386              :                                       Real64 &OnOffAirFlowRatio, // Ratio of compressor ON air flow to AVERAGE air flow over time step
    6387              :                                       bool &HXUnitOn             // flag to control HX based on zone moisture load
    6388              :     )
    6389              :     {
    6390              :         // SUBROUTINE INFORMATION:
    6391              :         //       AUTHOR         Richard Liesen
    6392              :         //       DATE WRITTEN   Feb 2001
    6393              :         //       MODIFIED       R. Raustad and D. Shirey, Feb/Mar/Sept/Oct/Dec 2001, Jan/Oct 2002
    6394              :         //       RE-ENGINEERED  R. Raustad, Feb. 2005 (added RegulaFalsi for iteration technique)
    6395              : 
    6396              :         // PURPOSE OF THIS SUBROUTINE:
    6397              :         // This subroutine updates the coil outlet nodes.
    6398              : 
    6399              :         // METHODOLOGY EMPLOYED:
    6400              :         // Determine the operating PLR to meet the zone sensible load. If a humidistat is specified, determine
    6401              :         // the operating PLR (greater of the sensible and latent PLR) to meet the zone SENSIBLE load
    6402              :         // (Multimode dehumidification control) or zone LATENT load (CoolReheat dehumidification control).
    6403              :         // For dehumidification control type COOLREHEAT, both a sensible and latent PLR may exist for a
    6404              :         // single time step (heating and dehumidification can occur). For all other system types,
    6405              :         // only a single PLR is allowed for any given time step.
    6406              :         // Order of simulation depends on dehumidification control option as described below.
    6407              :         // Dehumidification control options:
    6408              :         // Dehumidification Control NONE:   Cooling performance is simulated first and then heating performance. If a HX
    6409              :         //                                  assisted cooling coil is selected, the HX is always active.
    6410              :         // Dehumidification Control COOLREHEAT: Continuous Fan Operation:
    6411              :         //                                      For cooling operation, the sensible and latent capacities are calculated to
    6412              :         //                                      meet the thermostat setpoint. If a HX assisted cooling coil is selected,
    6413              :         //                                      the HX is always active. If the latent load is not met by operating the
    6414              :         //                                      system at the sensible PLR, a new PLR is calculated to meet the humidistat
    6415              :         //                                      setpoint. The reheat coil load is then calculated to meet the HEATING
    6416              :         //                                      setpoint temperature.
    6417              :         //                                      Cycling Fan Operation:
    6418              :         //                                      The heating part-load ratio is calculated first. Since the fan will be
    6419              :         //                                      controlled at the higher of the heating or cooling PLR's, a ratio of the
    6420              :         //                                      cooling to heating PLR is used to pass to the cooling coil (MAX=1). This allows
    6421              :         //                                      the cooling coil to operate at the heating PLR when the heating PLR is
    6422              :         //                                      higher than the cooling PLR. The sensible and latent capacities are then
    6423              :         //                                      calculated to meet the thermostat setpoint.
    6424              :         //                                      If a HX assisted cooling coil is selected, the HX is always active.
    6425              :         //                                      If the latent load is not met by operating the system at the sensible PLR,
    6426              :         //                                      a new PLR is calculated to meet the humidistat setpoint.
    6427              :         //                                      The reheat coil load is then calculated to meet the HEATING setpoint temperature.
    6428              :         // Dehumidification Control MULTIMODE: For cooling operation, the sensible and latent capacities are calculated to
    6429              :         //                                     meet the thermostat setpoint. If a HX assisted cooling coil is selected,
    6430              :         //                                     the HX is off for this calculation. If the latent load is not met by operating
    6431              :         //                                     the system at the sensible PLR, a new PLR is calculated with the HX operating
    6432              :         //                                     and the target is the thermostat setpoint. Humidity is not controlled in this
    6433              :         //                                     mode. No reheat coil is used in this configuration.
    6434              :         //  Note: A supplemental heater augments the heating capacity for air-to-air heat pumps.
    6435              :         //        A reheat coil is used for the HeatCool furnace/unitarysystem to offset the sensible cooling when the
    6436              :         //        dehumidification control type is COOLREHEAT. Both the supplemental and reheat heating coil load is calculated
    6437              :         //        in the Calc routines. The actual simulation of these coils is performed in the SimFurnace routine (i.e. the
    6438              :         //        supplemental and reheat coil loads are passed as 0 to CalcFurnaceOutput).
    6439              : 
    6440              :         // SUBROUTINE PARAMETER DEFINITIONS:
    6441        15225 :         int constexpr MaxIter(100);   // maximum number of iterations
    6442        15225 :         Real64 constexpr MinPLR(0.0); // minimum part load ratio allowed
    6443              : 
    6444              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    6445              :         Real64 SystemMoistureLoad;   // Total latent load to be removed by furnace/unitary system
    6446              :         Real64 deltaT;               // Temperature rise across heating coil (C)
    6447              :         Real64 TempOutHeatingCoil;   // Temperature leaving heating coil (C)
    6448              :         Real64 FullSensibleOutput;   // Full sensible output of AC (W)
    6449              :         Real64 FullLatentOutput;     // Full latent output of AC (W)
    6450              :         Real64 NoCoolOutput;         // Sensible output of AC with no cooling allowed (W)
    6451              :         Real64 NoHeatOutput;         // Sensible output of heater with no heating allowed (W)
    6452              :         Real64 NoLatentOutput;       // Latent output of AC with no cooling allowed (W)
    6453              :         Real64 CoolErrorToler;       // Error tolerance in cooling mode
    6454              :         Real64 HeatErrorToler;       // Error tolerance in heating mode
    6455              :         Real64 ActualSensibleOutput; // Actual furnace sensible capacity
    6456              :         Real64 ActualLatentOutput;   // Actual furnace latent capacity
    6457              :         Real64 PartLoadRatio;        // Part load ratio (greater of sensible or latent part load ratio for cooling,
    6458              :         // or heating PLR)
    6459              :         Real64 LatentPartLoadRatio; // Part load ratio to meet dehumidification load
    6460              :         Real64 TempCoolOutput;      // Temporary Sensible output of AC while iterating on PLR (W)
    6461              :         Real64 TempHeatOutput;      // Temporary Sensible output of heating coil while iterating on PLR (W)
    6462              :         Real64 TempLatentOutput;    // Temporary Latent output of AC at increasing PLR (W)
    6463              :         //                                           ! (Temp variables are used to find min PLR for positive latent removal)
    6464              :         Real64 TempMinPLR;             // Temporary min latent PLR when hum control is required and iter is exceeded
    6465              :         Real64 TempMinPLR2;            // Temporary min latent PLR when cyc fan hum control is required and iter is exceeded
    6466              :         Real64 TempMaxPLR;             // Temporary max latent PLR when hum control is required and iter is exceeded
    6467              :         Real64 QToHeatSetPt;           // Load required to meet heating setpoint temp (>0 is a heating load)
    6468              :         Real64 CoolingHeatingPLRRatio; // ratio of cooling to heating PLR (MAX=1). Used in heating mode.
    6469              :         Real64 HeatingSensibleOutput;
    6470              :         Real64 HeatingLatentOutput;
    6471              :         Real64 OutdoorDryBulbTemp; // secondary coil (condenser) entering dry bulb temperature
    6472              : 
    6473        15225 :         Real64 &SystemSensibleLoad = state.dataFurnaces->SystemSensibleLoad;
    6474        15225 :         auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    6475              :         // Set local variables
    6476        15225 :         int FurnaceOutletNode = thisFurnace.FurnaceOutletNodeNum;
    6477        15225 :         int FurnaceInletNode = thisFurnace.FurnaceInletNodeNum;
    6478        15225 :         int ControlZoneNode = thisFurnace.NodeNumOfControlledZone;
    6479        15225 :         HVAC::FanOp fanOp = thisFurnace.fanOp; // fan operating mode
    6480        15225 :         bool HumControl = false;
    6481              :         // Calculate the Cp Air of zone
    6482        15225 :         Real64 cpair = Psychrometrics::PsyCpAirFnW(state.dataLoopNodes->Node(ControlZoneNode).HumRat);
    6483        15225 :         NoHeatOutput = 0.0;
    6484        15225 :         SystemSensibleLoad = 0.0;
    6485        15225 :         ReheatCoilLoad = 0.0;
    6486        15225 :         HeatCoilLoad = 0.0;
    6487        15225 :         ReheatCoilLoad = 0.0;
    6488        15225 :         PartLoadRatio = 0.0;
    6489              : 
    6490        15225 :         if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_AirToAir) {
    6491        15222 :             if (state.dataDXCoils->DXCoil(thisFurnace.HeatingCoilIndex)
    6492        15222 :                     .IsSecondaryDXCoilInZone) { // assumes compressor is in same location as secondary coil
    6493            0 :                 OutdoorDryBulbTemp =
    6494            0 :                     state.dataZoneTempPredictorCorrector->zoneHeatBalance(state.dataDXCoils->DXCoil(thisFurnace.HeatingCoilIndex).SecZonePtr).ZT;
    6495        15222 :             } else if (state.dataDXCoils->DXCoil(thisFurnace.CoolingCoilIndex).IsSecondaryDXCoilInZone) {
    6496            0 :                 OutdoorDryBulbTemp =
    6497            0 :                     state.dataZoneTempPredictorCorrector->zoneHeatBalance(state.dataDXCoils->DXCoil(thisFurnace.CoolingCoilIndex).SecZonePtr).ZT;
    6498              :             } else {
    6499        15222 :                 if (thisFurnace.CondenserNodeNum > 0) {
    6500            0 :                     OutdoorDryBulbTemp = state.dataLoopNodes->Node(thisFurnace.CondenserNodeNum).Temp;
    6501              :                 } else {
    6502        15222 :                     OutdoorDryBulbTemp = state.dataEnvrn->OutDryBulbTemp;
    6503              :                 }
    6504              :             }
    6505              :         } else {
    6506            3 :             OutdoorDryBulbTemp = state.dataEnvrn->OutDryBulbTemp;
    6507              :         }
    6508        15225 :         if (FirstHVACIteration) {
    6509              :             // Set selected values during first HVAC iteration
    6510              : 
    6511              :             // Init for heating
    6512         4847 :             if (state.dataFurnaces->HeatingLoad) {
    6513         3103 :                 if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_AirToAir ||
    6514            0 :                     (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir && thisFurnace.WatertoAirHPType == WAHPCoilType::Simple)) {
    6515         3103 :                     thisFurnace.HeatPartLoadRatio = 1.0;
    6516         3103 :                     HeatCoilLoad = 0.0;
    6517         3103 :                     thisFurnace.HeatingCoilSensDemand = 0.0;
    6518         3103 :                     thisFurnace.CoolingCoilSensDemand = 0.0;
    6519         3103 :                     thisFurnace.CoolingCoilLatentDemand = 0.0;
    6520              :                 } else { // for furnaces
    6521            0 :                     thisFurnace.HeatPartLoadRatio = 0.0;
    6522            0 :                     HeatCoilLoad = ZoneLoad;
    6523            0 :                     state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = thisFurnace.MdotFurnace;
    6524            0 :                     thisFurnace.HeatingCoilSensDemand = 0.0;
    6525            0 :                     thisFurnace.CoolingCoilSensDemand = 0.0;
    6526            0 :                     thisFurnace.CoolingCoilLatentDemand = 0.0;
    6527              :                 }
    6528         3103 :                 ReheatCoilLoad = 0.0;
    6529         3103 :                 thisFurnace.CoolPartLoadRatio = 0.0;
    6530              : 
    6531              :                 // Init for cooling
    6532         1744 :             } else if (state.dataFurnaces->CoolingLoad) {
    6533              :                 // air to air heat pumps
    6534         1687 :                 thisFurnace.CoolPartLoadRatio = 1.0;
    6535         1687 :                 thisFurnace.HeatPartLoadRatio = 0.0;
    6536         1687 :                 HeatCoilLoad = 0.0;
    6537         1687 :                 ReheatCoilLoad = 0.0;
    6538              : 
    6539              :                 // Init for moisture load only
    6540              :             } else {
    6541           57 :                 thisFurnace.CoolPartLoadRatio = 0.0;
    6542           57 :                 thisFurnace.HeatPartLoadRatio = 0.0;
    6543           57 :                 HeatCoilLoad = 0.0;
    6544           57 :                 ReheatCoilLoad = 0.0;
    6545           57 :                 thisFurnace.HeatingCoilSensDemand = 0.0;
    6546           57 :                 thisFurnace.CoolingCoilSensDemand = 0.0;
    6547           57 :                 thisFurnace.CoolingCoilLatentDemand = 0.0;
    6548              :             }
    6549              : 
    6550         4847 :             SetAverageAirFlow(state, FurnaceNum, max(thisFurnace.HeatPartLoadRatio, thisFurnace.CoolPartLoadRatio), OnOffAirFlowRatio);
    6551              :             //  if dehumidification load exists (for heat pumps) turn on the supplemental heater
    6552         4847 :             if (state.dataFurnaces->HPDehumidificationLoadFlag) HumControl = true;
    6553              :         } else { // not FirstHVACIteration
    6554              :             // Init for heating
    6555        10378 :             Real64 &CoolCoilLoad = state.dataFurnaces->CoolCoilLoad;
    6556        10378 :             if (state.dataFurnaces->HeatingLoad) {
    6557         5260 :                 CoolCoilLoad = 0.0;
    6558         5260 :                 if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_AirToAir ||
    6559            1 :                     (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir && thisFurnace.WatertoAirHPType == WAHPCoilType::Simple)) {
    6560         5260 :                     SystemSensibleLoad = ZoneLoad;
    6561         5260 :                     SystemMoistureLoad = 0.0;
    6562         5260 :                     HeatCoilLoad = 0.0;
    6563         5260 :                     thisFurnace.HeatingCoilSensDemand = SystemSensibleLoad;
    6564         5260 :                     thisFurnace.CoolingCoilSensDemand = 0.0;
    6565         5260 :                     thisFurnace.CoolingCoilLatentDemand = 0.0;
    6566              :                 } else {
    6567            0 :                     SystemMoistureLoad = MoistureLoad;
    6568            0 :                     HeatCoilLoad = ZoneLoad;
    6569              :                 }
    6570              : 
    6571              :                 // Init for cooling
    6572         5118 :             } else if (state.dataFurnaces->CoolingLoad) {
    6573         5061 :                 CoolCoilLoad = ZoneLoad;
    6574         5061 :                 SystemMoistureLoad = MoistureLoad;
    6575         5061 :                 HeatCoilLoad = 0.0;
    6576         5061 :                 thisFurnace.CoolingCoilSensDemand = std::abs(CoolCoilLoad);
    6577         5061 :                 thisFurnace.CoolingCoilLatentDemand = std::abs(SystemMoistureLoad);
    6578         5061 :                 thisFurnace.HeatingCoilSensDemand = 0.0;
    6579              : 
    6580              :                 // Init for latent
    6581              :             } else {
    6582           57 :                 SystemMoistureLoad = MoistureLoad;
    6583           57 :                 CoolCoilLoad = 0.0;
    6584           57 :                 HeatCoilLoad = 0.0;
    6585              :                 // set report variables
    6586           57 :                 thisFurnace.CoolingCoilSensDemand = 0.0;
    6587           57 :                 thisFurnace.CoolingCoilLatentDemand = SystemMoistureLoad;
    6588           57 :                 thisFurnace.HeatingCoilSensDemand = 0.0;
    6589              :             }
    6590        10378 :             HeatingSensibleOutput = 0.0;
    6591        10378 :             HeatingLatentOutput = 0.0;
    6592        10378 :             ReheatCoilLoad = 0.0;
    6593        10378 :             thisFurnace.CoolPartLoadRatio = 0.0;
    6594        10378 :             thisFurnace.HeatPartLoadRatio = 0.0;
    6595        10378 :             thisFurnace.CompPartLoadRatio = 0.0;
    6596        10378 :             thisFurnace.DehumidInducedHeatingDemandRate = 0.0;
    6597              : 
    6598              :             // When humidity control is used with cycling fan control and a heating load exists, if a moisture load
    6599              :             // also exists, the heating PLR must be available for the cooling coil calculations.
    6600              :             //*********** Heating Section ************
    6601              :             // If Furnace runs with a heating load then set HeatCoilLoad on Heating Coil and the Mass Flow
    6602              :             //         (Node(FurnaceInletNode)%MassFlowRate .gt. 0.0d0) .and. &
    6603        10378 :             if ((thisFurnace.availSched->getCurrentVal() > 0.0) && (state.dataFurnaces->HeatingLoad)) {
    6604              : 
    6605              :                 //    Heat pumps only calculate a single PLR each time step (i.e. only cooling or heating allowed in a single time step)
    6606         5260 :                 if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_AirToAir ||
    6607            1 :                     (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir && thisFurnace.WatertoAirHPType == WAHPCoilType::Simple)) {
    6608              : 
    6609         5260 :                     state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = thisFurnace.MdotFurnace;
    6610              : 
    6611              :                     // Get no load result
    6612         5260 :                     if (fanOp == HVAC::FanOp::Cycling) {
    6613         5259 :                         state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = 0.0;
    6614              :                     }
    6615              : 
    6616              :                     //     Set the inlet mass flow rate based on user specified coil OFF flow rate
    6617         5260 :                     PartLoadRatio = 0.0;
    6618              : 
    6619         5260 :                     SetAverageAirFlow(state, FurnaceNum, PartLoadRatio, OnOffAirFlowRatio);
    6620              : 
    6621              :                     // Set the input parameters for CalcFurnaceOutput
    6622         5260 :                     thisFurnace.CompPartLoadRatio = 0.0; // compressor off
    6623              : 
    6624         5260 :                     CalcFurnaceOutput(state,
    6625              :                                       FurnaceNum,
    6626              :                                       FirstHVACIteration,
    6627              :                                       fanOp,
    6628              :                                       compressorOp,
    6629              :                                       0.0,
    6630              :                                       MinPLR,
    6631              :                                       0.0,
    6632              :                                       0.0,
    6633              :                                       NoHeatOutput,
    6634              :                                       NoLatentOutput,
    6635              :                                       OnOffAirFlowRatio,
    6636              :                                       false);
    6637              : 
    6638         5260 :                     PartLoadRatio = 1.0;
    6639         5260 :                     state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = thisFurnace.MdotFurnace;
    6640              : 
    6641         5260 :                     thisFurnace.CompPartLoadRatio = 1.0; // compressor ON
    6642              : 
    6643              :                     // Set fan part-load fraction equal to 1 while getting full load result
    6644         5260 :                     state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
    6645         5260 :                     OnOffAirFlowRatio = 1.0;
    6646              : 
    6647              :                     // Get full load result
    6648         5260 :                     CalcFurnaceOutput(state,
    6649              :                                       FurnaceNum,
    6650              :                                       FirstHVACIteration,
    6651              :                                       fanOp,
    6652              :                                       compressorOp,
    6653              :                                       0.0,
    6654              :                                       PartLoadRatio,
    6655              :                                       0.0,
    6656              :                                       0.0,
    6657              :                                       FullSensibleOutput,
    6658              :                                       FullLatentOutput,
    6659              :                                       OnOffAirFlowRatio,
    6660              :                                       false);
    6661              : 
    6662              :                     // Check that SystemSensibleLoad is between FullSensibleOutput and NoHeatOutput
    6663              :                     // If so then calculate PartLoadRatio for the DX Heating coil
    6664         5260 :                     if (SystemSensibleLoad < FullSensibleOutput && SystemSensibleLoad > NoHeatOutput) {
    6665              : 
    6666              :                         // Calculate the part load ratio through iteration
    6667            8 :                         HeatErrorToler = thisFurnace.HeatingConvergenceTolerance; // Error tolerance for convergence from input deck
    6668              : 
    6669            8 :                         int SolFlag = 0; // # of iterations if positive, -1 means failed to converge, -2 means bounds are incorrect
    6670              :                         // HeatErrorToler is in fraction of load, MaxIter = 30, SolFalg = # of iterations or error as appropriate
    6671           32 :                         auto f = [&state, FurnaceNum, FirstHVACIteration, fanOp, compressorOp, SystemSensibleLoad](Real64 const PartLoadRatio) {
    6672           24 :                             return CalcFurnaceResidual(state,
    6673              :                                                        PartLoadRatio,
    6674              :                                                        FurnaceNum,
    6675              :                                                        FirstHVACIteration,
    6676              :                                                        fanOp,
    6677              :                                                        compressorOp,
    6678              :                                                        SystemSensibleLoad,
    6679              :                                                        0.0,  // par6_loadFlag,
    6680              :                                                        1.0,  // par7_sensLatentFlag,
    6681              :                                                        0.0,  // par9_HXOnFlag,
    6682           24 :                                                        0.0); // par10_HeatingCoilPLR);
    6683            8 :                         };
    6684            8 :                         General::SolveRoot(state, HeatErrorToler, MaxIter, SolFlag, PartLoadRatio, f, 0.0, 1.0);
    6685              :                         //         OnOffAirFlowRatio is updated during the above iteration. Reset to correct value based on PLR.
    6686            8 :                         OnOffAirFlowRatio = state.dataFurnaces->OnOffAirFlowRatioSave;
    6687            8 :                         if (SolFlag < 0) {
    6688            0 :                             if (SolFlag == -1) {
    6689            0 :                                 CalcFurnaceOutput(state,
    6690              :                                                   FurnaceNum,
    6691              :                                                   FirstHVACIteration,
    6692              :                                                   fanOp,
    6693              :                                                   compressorOp,
    6694              :                                                   0.0,
    6695              :                                                   PartLoadRatio,
    6696              :                                                   0.0,
    6697              :                                                   0.0,
    6698              :                                                   TempHeatOutput,
    6699              :                                                   TempLatentOutput,
    6700              :                                                   OnOffAirFlowRatio,
    6701              :                                                   false);
    6702            0 :                                 if (std::abs(SystemSensibleLoad - TempHeatOutput) > HVAC::SmallLoad) {
    6703            0 :                                     if (thisFurnace.DXHeatingMaxIterIndex == 0) {
    6704            0 :                                         ShowWarningMessage(state,
    6705            0 :                                                            format("Heating coil control failed to converge for {}:{}",
    6706            0 :                                                                   HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    6707            0 :                                                                   thisFurnace.Name));
    6708            0 :                                         ShowContinueError(state,
    6709              :                                                           "  Iteration limit exceeded in calculating DX heating coil sensible part-load ratio.");
    6710            0 :                                         ShowContinueErrorTimeStamp(
    6711              :                                             state,
    6712            0 :                                             format("Sensible load to be met by DX heating coil = {:.2T} (watts), sensible output of DX heating "
    6713              :                                                    "coil = {:.2T} (watts), and the simulation continues.",
    6714              :                                                    SystemSensibleLoad,
    6715              :                                                    TempHeatOutput));
    6716              :                                     }
    6717            0 :                                     ShowRecurringWarningErrorAtEnd(state,
    6718            0 :                                                                    format("{} \"{}\" - Iteration limit exceeded in calculating DX sensible heating "
    6719              :                                                                           "part-load ratio error continues. "
    6720              :                                                                           "Sensible load statistics:",
    6721            0 :                                                                           HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    6722            0 :                                                                           thisFurnace.Name),
    6723            0 :                                                                    thisFurnace.DXHeatingMaxIterIndex,
    6724              :                                                                    SystemSensibleLoad,
    6725              :                                                                    SystemSensibleLoad);
    6726              :                                 }
    6727            0 :                             } else if (SolFlag == -2) {
    6728            0 :                                 if (thisFurnace.DXHeatingRegulaFalsiFailedIndex == 0) {
    6729            0 :                                     ShowWarningMessage(state,
    6730            0 :                                                        format("Heating coil control failed for {}:{}",
    6731            0 :                                                               HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    6732            0 :                                                               thisFurnace.Name));
    6733            0 :                                     ShowContinueError(state, "  DX sensible heating part-load ratio determined to be outside the range of 0-1.");
    6734            0 :                                     ShowContinueErrorTimeStamp(
    6735              :                                         state,
    6736            0 :                                         format("Sensible load to be met by DX heating coil = {:.2T} (watts), and the simulation continues.",
    6737              :                                                SystemSensibleLoad));
    6738              :                                 }
    6739            0 :                                 ShowRecurringWarningErrorAtEnd(
    6740              :                                     state,
    6741            0 :                                     format("{} \"{}\" -  DX sensible heating part-load ratio out of range error continues. Sensible load statistics:",
    6742            0 :                                            HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    6743            0 :                                            thisFurnace.Name),
    6744            0 :                                     thisFurnace.DXHeatingRegulaFalsiFailedIndex,
    6745              :                                     SystemSensibleLoad,
    6746              :                                     SystemSensibleLoad);
    6747              :                             }
    6748              :                         }
    6749              : 
    6750            8 :                         thisFurnace.HeatPartLoadRatio = PartLoadRatio;
    6751              :                         //       Check if Heat Pump compressor is allowed to run based on outdoor temperature
    6752            8 :                         if (OutdoorDryBulbTemp > thisFurnace.MinOATCompressorHeating) {
    6753            0 :                             thisFurnace.CompPartLoadRatio = PartLoadRatio;
    6754              :                         } else {
    6755            8 :                             thisFurnace.CompPartLoadRatio = 0.0;
    6756              :                         }
    6757         5260 :                     } else if (SystemSensibleLoad > FullSensibleOutput) {
    6758              :                         //       SystemSensibleLoad is greater than full DX Heating coil output so heat pump runs entire
    6759              :                         //       timestep and additional supplemental heating is required
    6760         5252 :                         thisFurnace.HeatPartLoadRatio = 1.0;
    6761         5252 :                         if (OutdoorDryBulbTemp > thisFurnace.MinOATCompressorHeating) {
    6762              :                             //       Check to see if Heat Pump compressor was allowed to run based on outdoor temperature
    6763            1 :                             thisFurnace.CompPartLoadRatio = 1.0;
    6764              :                         } else {
    6765         5251 :                             thisFurnace.CompPartLoadRatio = 0.0;
    6766              :                         }
    6767            0 :                     } else if (SystemSensibleLoad < NoHeatOutput) {
    6768              :                         //       SystemSensibleLoad is less than minimum DX Heating coil output so heat pump does not run and
    6769              :                         //       the load will be met by the supplemental heater
    6770            0 :                         thisFurnace.CompPartLoadRatio = 0.0;
    6771            0 :                         thisFurnace.HeatPartLoadRatio = 1.0;
    6772              :                     }
    6773         5260 :                     if (thisFurnace.HeatPartLoadRatio == 1.0) {
    6774              :                         //       Determine the load on the supplemental heating coil
    6775         5252 :                         if ((SystemSensibleLoad - FullSensibleOutput) > thisFurnace.DesignSuppHeatingCapacity) {
    6776            1 :                             HeatCoilLoad = thisFurnace.DesignSuppHeatingCapacity;
    6777            1 :                             TempOutHeatingCoil = state.dataLoopNodes->Node(FurnaceOutletNode).Temp + HeatCoilLoad / (cpair * thisFurnace.MdotFurnace);
    6778         5251 :                         } else if (SystemSensibleLoad < NoHeatOutput) {
    6779            0 :                             HeatCoilLoad = max(0.0, SystemSensibleLoad); // BG 10/22/2008 need a case for when its all suppl heat
    6780            0 :                             TempOutHeatingCoil = state.dataLoopNodes->Node(FurnaceInletNode).Temp + HeatCoilLoad / (cpair * thisFurnace.MdotFurnace);
    6781              :                         } else {
    6782         5251 :                             HeatCoilLoad = max(0.0, (SystemSensibleLoad - FullSensibleOutput));
    6783         5251 :                             TempOutHeatingCoil = state.dataLoopNodes->Node(FurnaceOutletNode).Temp + HeatCoilLoad / (cpair * thisFurnace.MdotFurnace);
    6784              :                         }
    6785         5252 :                         if (OutdoorDryBulbTemp > thisFurnace.MaxOATSuppHeat) {
    6786            1 :                             HeatCoilLoad = 0.0;
    6787            1 :                             if (SystemSensibleLoad < NoHeatOutput) {
    6788            0 :                                 TempOutHeatingCoil = state.dataLoopNodes->Node(FurnaceInletNode).Temp;
    6789              :                             } else {
    6790            1 :                                 TempOutHeatingCoil = state.dataLoopNodes->Node(FurnaceOutletNode).Temp;
    6791              :                             }
    6792              :                         }
    6793         5252 :                         if ((TempOutHeatingCoil > thisFurnace.DesignMaxOutletTemp) && (HeatCoilLoad > 0.0)) {
    6794              :                             // deltaT = Furnace(FurnaceNum)%DesignMaxOutletTemp - Node(FurnaceOutletNode)%Temp
    6795              :                             // BG 10/22/2008 above made no sense if DX heat is off and its all supplemental,
    6796              :                             //  because Node(FurnaceOutletNode)%Temp will have been calc'd with full DX heat in last faux call to CalcFurnaceOutput
    6797              : 
    6798         1584 :                             Real64 cpairSupply = Psychrometrics::PsyCpAirFnW(state.dataLoopNodes->Node(FurnaceInletNode).HumRat);
    6799         1584 :                             deltaT = (thisFurnace.DesignMaxOutletTemp - TempOutHeatingCoil);
    6800         1584 :                             HeatCoilLoad += (state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate * cpairSupply * deltaT);
    6801         1584 :                             HeatCoilLoad = max(0.0, HeatCoilLoad);
    6802              :                         }
    6803              :                     } else {
    6804            8 :                         HeatCoilLoad = 0.0;
    6805              :                     }
    6806         5260 :                     PartLoadRatio = 0.0;
    6807              : 
    6808              :                     //   HeatCool systems can have both a sensible and latent PLR in a single time step
    6809              :                     //   (i.e. both cooling and heating can occur in a single time step)
    6810         5260 :                 } else { // else not a heatpump DX coil ** non-HP heating coils are not DX so testing if OutdoorDryBulbTemp < MinOATCompressorHeating
    6811              :                          // is not necessary **
    6812              : 
    6813            0 :                     state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = thisFurnace.MdotFurnace;
    6814            0 :                     HeatCoilLoad = thisFurnace.DesignHeatingCapacity;
    6815            0 :                     SystemSensibleLoad = ZoneLoad;
    6816              : 
    6817              :                     // Get no load result
    6818            0 :                     if (fanOp == HVAC::FanOp::Cycling) {
    6819            0 :                         state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = 0.0;
    6820              :                     }
    6821            0 :                     if (fanOp == HVAC::FanOp::Continuous) {
    6822            0 :                         state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0; // The on/off fan will not cycle, so set part-load fraction = 1
    6823              :                     }
    6824              : 
    6825              :                     //     Set the inlet mass flow rate based on user specified coil OFF flow rate
    6826            0 :                     PartLoadRatio = 0.0;
    6827            0 :                     SetAverageAirFlow(state, FurnaceNum, PartLoadRatio, OnOffAirFlowRatio);
    6828              : 
    6829            0 :                     CalcFurnaceOutput(state,
    6830              :                                       FurnaceNum,
    6831              :                                       FirstHVACIteration,
    6832              :                                       fanOp,
    6833              :                                       compressorOp,
    6834              :                                       0.0,
    6835              :                                       MinPLR,
    6836              :                                       0.0,
    6837              :                                       0.0,
    6838              :                                       NoHeatOutput,
    6839              :                                       NoLatentOutput,
    6840              :                                       OnOffAirFlowRatio,
    6841              :                                       false);
    6842              : 
    6843            0 :                     if (NoHeatOutput < SystemSensibleLoad) {
    6844            0 :                         state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = thisFurnace.MdotFurnace;
    6845              : 
    6846              :                         // Set fan part-load fraction equal to 1 while getting full load result
    6847            0 :                         state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
    6848            0 :                         OnOffAirFlowRatio = 1.0;
    6849              : 
    6850              :                         // Get full load result
    6851            0 :                         CalcFurnaceOutput(state,
    6852              :                                           FurnaceNum,
    6853              :                                           FirstHVACIteration,
    6854              :                                           fanOp,
    6855              :                                           compressorOp,
    6856              :                                           0.0,
    6857              :                                           1.0,
    6858              :                                           HeatCoilLoad,
    6859              :                                           0.0,
    6860              :                                           FullSensibleOutput,
    6861              :                                           FullLatentOutput,
    6862              :                                           OnOffAirFlowRatio,
    6863              :                                           false);
    6864              :                     } else {
    6865            0 :                         FullSensibleOutput = NoHeatOutput + 0.000000001;
    6866              :                     }
    6867              : 
    6868              :                     // Since we are heating, we expect FullSensibleOutput to be > 0 and FullSensibleOutput > NoSensibleOutput
    6869              :                     // Check that this is the case; if not set PartLoadRatio = 0.0 (off) and return
    6870              : 
    6871            0 :                     if (FullSensibleOutput > NoHeatOutput) {
    6872              : 
    6873              :                         // check bounds on sensible output prior to iteration using RegulaFalsi
    6874            0 :                         if (FullSensibleOutput <= SystemSensibleLoad) {
    6875            0 :                             PartLoadRatio = 1.0;
    6876              :                             //         save modified HeatCoilLoad in case it was reset because outlet temp > DesignMaxOutletTemp
    6877            0 :                             if (state.dataFurnaces->ModifiedHeatCoilLoad > 0.0) {
    6878            0 :                                 HeatCoilLoad = state.dataFurnaces->ModifiedHeatCoilLoad;
    6879              :                             } else {
    6880            0 :                                 HeatCoilLoad = thisFurnace.DesignHeatingCapacity;
    6881              :                             }
    6882            0 :                         } else if (NoHeatOutput >= SystemSensibleLoad) {
    6883            0 :                             PartLoadRatio = 0.0;
    6884            0 :                             HeatCoilLoad = 0.0;
    6885              :                         } else {
    6886              : 
    6887              :                             // Calculate the part load ratio through iteration
    6888            0 :                             HeatErrorToler = thisFurnace.HeatingConvergenceTolerance; // Error tolerance for convergence from input deck
    6889              : 
    6890            0 :                             int SolFlag = 0; // # of iterations if positive, -1 means failed to converge, -2 means bounds are incorrect
    6891              :                             // HeatErrorToler is in fraction load, MaxIter = 30, SolFalg = # of iterations or error as appropriate
    6892            0 :                             auto f = [&state, FurnaceNum, FirstHVACIteration, fanOp, compressorOp, SystemSensibleLoad](Real64 const PartLoadRatio) {
    6893            0 :                                 return CalcFurnaceResidual(state,
    6894              :                                                            PartLoadRatio,
    6895              :                                                            FurnaceNum,
    6896              :                                                            FirstHVACIteration,
    6897              :                                                            fanOp,
    6898              :                                                            compressorOp,
    6899              :                                                            SystemSensibleLoad,
    6900              :                                                            0.0,  // par6_loadFlag,
    6901              :                                                            1.0,  // par7_sensLatentFlag,
    6902              :                                                            0.0,  // par9_HXOnFlag,
    6903            0 :                                                            0.0); // par10_HeatingCoilPLR);
    6904            0 :                             };
    6905            0 :                             General::SolveRoot(state, HeatErrorToler, MaxIter, SolFlag, PartLoadRatio, f, 0.0, 1.0);
    6906              :                             //         OnOffAirFlowRatio is updated during the above iteration. Reset to correct value based on PLR.
    6907            0 :                             OnOffAirFlowRatio = state.dataFurnaces->OnOffAirFlowRatioSave;
    6908              :                             //         Reset HeatCoilLoad calculated in CalcFurnaceResidual (in case it was reset because output temp >
    6909              :                             //         DesignMaxOutletTemp)
    6910            0 :                             if (state.dataFurnaces->ModifiedHeatCoilLoad > 0.0) {
    6911            0 :                                 HeatCoilLoad = state.dataFurnaces->ModifiedHeatCoilLoad;
    6912              :                             } else {
    6913            0 :                                 HeatCoilLoad = thisFurnace.DesignHeatingCapacity * PartLoadRatio;
    6914              :                             }
    6915            0 :                             if (SolFlag == -1) {
    6916              : 
    6917              :                                 //           RegulaFalsi may not find heating PLR when the maximum supply air temperature is exceeded.
    6918              :                                 //           If iteration limit is exceeded, find tighter boundary of solution and repeat RegulaFalsi
    6919            0 :                                 TempMaxPLR = -0.1;
    6920            0 :                                 TempHeatOutput = NoHeatOutput;
    6921            0 :                                 while ((TempHeatOutput - SystemSensibleLoad) < 0.0 && TempMaxPLR < 1.0) {
    6922              :                                     //             find upper limit of HeatingPLR
    6923            0 :                                     TempMaxPLR += 0.1;
    6924            0 :                                     HeatCoilLoad = thisFurnace.DesignHeatingCapacity * TempMaxPLR;
    6925            0 :                                     CalcFurnaceOutput(state,
    6926              :                                                       FurnaceNum,
    6927              :                                                       FirstHVACIteration,
    6928              :                                                       fanOp,
    6929              :                                                       compressorOp,
    6930              :                                                       0.0,
    6931              :                                                       TempMaxPLR,
    6932              :                                                       HeatCoilLoad,
    6933              :                                                       0.0,
    6934              :                                                       TempHeatOutput,
    6935              :                                                       TempLatentOutput,
    6936              :                                                       OnOffAirFlowRatio,
    6937              :                                                       false);
    6938              :                                 }
    6939            0 :                                 TempMinPLR = TempMaxPLR;
    6940            0 :                                 while ((TempHeatOutput - SystemSensibleLoad) > 0.0 && TempMinPLR > 0.0) {
    6941              :                                     //             pull upper limit of HeatingPLR down to last valid limit (i.e. heat output still exceeds
    6942              :                                     //             SystemSensibleLoad)
    6943            0 :                                     TempMaxPLR = TempMinPLR;
    6944              :                                     //             find minimum limit of HeatingPLR
    6945            0 :                                     TempMinPLR -= 0.01;
    6946              : 
    6947            0 :                                     HeatCoilLoad = thisFurnace.DesignHeatingCapacity * TempMinPLR;
    6948            0 :                                     CalcFurnaceOutput(state,
    6949              :                                                       FurnaceNum,
    6950              :                                                       FirstHVACIteration,
    6951              :                                                       fanOp,
    6952              :                                                       compressorOp,
    6953              :                                                       0.0,
    6954              :                                                       TempMinPLR,
    6955              :                                                       HeatCoilLoad,
    6956              :                                                       0.0,
    6957              :                                                       TempHeatOutput,
    6958              :                                                       TempLatentOutput,
    6959              :                                                       OnOffAirFlowRatio,
    6960              :                                                       false);
    6961              :                                 }
    6962              :                                 //           Now solve again with tighter PLR limits
    6963              :                                 auto f2 = // (AUTO_OK_LAMBDA)
    6964            0 :                                     [&state, FurnaceNum, FirstHVACIteration, fanOp, compressorOp, SystemSensibleLoad](Real64 const PartLoadRatio) {
    6965            0 :                                         return CalcFurnaceResidual(state,
    6966              :                                                                    PartLoadRatio,
    6967              :                                                                    FurnaceNum,
    6968              :                                                                    FirstHVACIteration,
    6969              :                                                                    fanOp,
    6970              :                                                                    compressorOp,
    6971              :                                                                    SystemSensibleLoad,
    6972              :                                                                    0.0,  // par6_loadFlag,
    6973              :                                                                    1.0,  // par7_sensLatentFlag,
    6974              :                                                                    0.0,  // par9_HXOnFlag,
    6975            0 :                                                                    0.0); // par10_HeatingCoilPLR);
    6976            0 :                                     };
    6977            0 :                                 General::SolveRoot(state, HeatErrorToler, MaxIter, SolFlag, PartLoadRatio, f2, TempMinPLR, TempMaxPLR);
    6978            0 :                                 if (state.dataFurnaces->ModifiedHeatCoilLoad > 0.0) {
    6979            0 :                                     HeatCoilLoad = state.dataFurnaces->ModifiedHeatCoilLoad;
    6980              :                                 } else {
    6981            0 :                                     HeatCoilLoad = thisFurnace.DesignHeatingCapacity * PartLoadRatio;
    6982              :                                 }
    6983            0 :                                 CalcFurnaceOutput(state,
    6984              :                                                   FurnaceNum,
    6985              :                                                   FirstHVACIteration,
    6986              :                                                   fanOp,
    6987              :                                                   compressorOp,
    6988              :                                                   0.0,
    6989              :                                                   PartLoadRatio,
    6990              :                                                   HeatCoilLoad,
    6991              :                                                   0.0,
    6992              :                                                   TempHeatOutput,
    6993              :                                                   TempLatentOutput,
    6994              :                                                   OnOffAirFlowRatio,
    6995              :                                                   false);
    6996              : 
    6997              :                                 //           After iterating with tighter boundaries, if still out of tolerance, show warning.
    6998            0 :                                 if (SolFlag == -1 && std::abs(SystemSensibleLoad - TempHeatOutput) > HVAC::SmallLoad) {
    6999            0 :                                     if (thisFurnace.HeatingMaxIterIndex == 0) {
    7000            0 :                                         ShowWarningMessage(state,
    7001            0 :                                                            format("Heating coil control failed to converge for {}:{}",
    7002            0 :                                                                   HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    7003            0 :                                                                   thisFurnace.Name));
    7004            0 :                                         ShowContinueError(state, "  Iteration limit exceeded in calculating heating coil sensible part-load ratio.");
    7005            0 :                                         ShowContinueErrorTimeStamp(state,
    7006            0 :                                                                    format("Sensible load to be met by heating coil = {:.2T} (watts), sensible output "
    7007              :                                                                           "of heating coil = {:.2T} (watts), and the simulation continues.",
    7008              :                                                                           SystemSensibleLoad,
    7009              :                                                                           TempHeatOutput));
    7010              :                                     }
    7011            0 :                                     ShowRecurringWarningErrorAtEnd(
    7012              :                                         state,
    7013            0 :                                         format("{} \"{}\" - Iteration limit exceeded in calculating sensible heating part-load "
    7014              :                                                "ratio error continues. Sensible load statistics:",
    7015            0 :                                                HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    7016            0 :                                                thisFurnace.Name),
    7017            0 :                                         thisFurnace.HeatingMaxIterIndex,
    7018              :                                         SystemSensibleLoad,
    7019              :                                         SystemSensibleLoad);
    7020              :                                 }
    7021            0 :                             } else if (SolFlag == -2) {
    7022            0 :                                 if (thisFurnace.HeatingRegulaFalsiFailedIndex == 0) {
    7023            0 :                                     ShowWarningMessage(state,
    7024            0 :                                                        format("Heating coil control failed for {}:{}",
    7025            0 :                                                               HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    7026            0 :                                                               thisFurnace.Name));
    7027            0 :                                     ShowContinueError(state, "  Sensible heating part-load ratio determined to be outside the range of 0-1.");
    7028            0 :                                     ShowContinueErrorTimeStamp(
    7029              :                                         state,
    7030            0 :                                         format("Sensible load to be met by heating coil = {:.2T} (watts), and the simulation continues.",
    7031              :                                                SystemSensibleLoad));
    7032              :                                 }
    7033            0 :                                 ShowRecurringWarningErrorAtEnd(
    7034              :                                     state,
    7035            0 :                                     format("{} \"{}\" -  Sensible heating part-load ratio out of range error continues. Sensible load statistics:",
    7036            0 :                                            HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    7037            0 :                                            thisFurnace.Name),
    7038            0 :                                     thisFurnace.HeatingRegulaFalsiFailedIndex,
    7039              :                                     SystemSensibleLoad,
    7040              :                                     SystemSensibleLoad);
    7041              :                             }
    7042              :                         }
    7043              : 
    7044              :                     } else { // ELSE from IF(FullSensibleOutput.GT.NoSensibleOutput)THEN above
    7045              :                         // Set part load ratio to 1 and run heater at design heating capacity
    7046            0 :                         PartLoadRatio = 1.0;
    7047            0 :                         HeatCoilLoad = thisFurnace.DesignHeatingCapacity;
    7048              :                     }
    7049              : 
    7050              :                 } // End of IF HeatPump
    7051              : 
    7052              :             } // End of IF for heating
    7053              : 
    7054              :             // Non-heat pump systems do not set a heating PLR, set it here for use with the DX cooling coil calculations.
    7055              :             // Set this variable back to 0 for non-heat pump systems at the end of this routine.
    7056        10378 :             thisFurnace.HeatPartLoadRatio = max(PartLoadRatio, thisFurnace.HeatPartLoadRatio);
    7057        10378 :             CalcFurnaceOutput(state,
    7058              :                               FurnaceNum,
    7059              :                               FirstHVACIteration,
    7060              :                               fanOp,
    7061              :                               compressorOp,
    7062              :                               0.0,
    7063              :                               thisFurnace.HeatPartLoadRatio,
    7064              :                               HeatCoilLoad,
    7065              :                               0.0,
    7066              :                               HeatingSensibleOutput,
    7067              :                               HeatingLatentOutput,
    7068              :                               OnOffAirFlowRatio,
    7069              :                               false);
    7070              : 
    7071        10380 :             if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_AirToAir ||
    7072            2 :                 (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir && thisFurnace.WatertoAirHPType == WAHPCoilType::Simple &&
    7073            2 :                  state.dataFurnaces->CoolingLoad)) {
    7074        10376 :                 HeatingSensibleOutput = 0.0;
    7075        10376 :                 HeatingLatentOutput = 0.0;
    7076              :             }
    7077              :             //***********Cooling Section*****************
    7078              :             // Simulate if scheduled ON and cooling load or if a moisture load exists when using a humidistat
    7079              :             // Check of HeatingLatentOutput is used to reduce overshoot during simultaneous heating and cooling
    7080              :             // Setback flag is used to avoid continued RH control when Tstat is setback (RH should float down)
    7081        15695 :             if ((thisFurnace.availSched->getCurrentVal() > 0.0 && state.dataFurnaces->CoolingLoad) ||
    7082         5317 :                 (thisFurnace.Humidistat && thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat &&
    7083            0 :                  (SystemMoistureLoad < 0.0 || (SystemMoistureLoad >= 0.0 && HeatingLatentOutput > SystemMoistureLoad &&
    7084            0 :                                                !state.dataZoneEnergyDemand->Setback(thisFurnace.ControlZoneNum))))) {
    7085              : 
    7086              :                 //     For cooling operation, the first step is to set the HX operation flag in case a HX assisted coil is used.
    7087              :                 //      (if a HX assisted coil is not used, this flag is not used. It's only used in the CALL to SimHXAssistedCoolingCoil)
    7088              :                 //     Check the dehumidification control type:
    7089              :                 //           For dehumidification control options CoolReheat and None, the HX is always active (locked ON).
    7090              :                 //           For dehumidification control option Multimode, the system is operated first with the HX off.
    7091              :                 //           If the moisture load is not met, the HX will then be turned on and the system is re-simulated.
    7092              : 
    7093         5061 :                 if (thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat ||
    7094         5061 :                     thisFurnace.DehumidControlType_Num == DehumidificationControlMode::None) {
    7095         5061 :                     HXUnitOn = true;
    7096              :                 } else {
    7097            0 :                     HXUnitOn = false;
    7098              :                 }
    7099              : 
    7100              :                 //     The next step is to determine the system output at no load (PLR=0) and full load (PLR=1)
    7101              : 
    7102              :                 //     Set the inlet mass flow rate based on user specified coil OFF flow rate
    7103         5061 :                 PartLoadRatio = 0.0;
    7104              : 
    7105         5061 :                 thisFurnace.CompPartLoadRatio = 0.0; // compressor off
    7106              : 
    7107              :                 //     SetAverageAirFlow calculates the operating mass flow rate based on PLR and the user specified inputs
    7108              :                 //     for MaxCoolAirMassFlow and MaxNoCoolHeatAirMassFlow.
    7109              :                 //     Air flow rate is set according to max of cooling and heating PLR if heating and latent load exists.
    7110         5061 :                 if (fanOp == HVAC::FanOp::Cycling && thisFurnace.HeatPartLoadRatio > 0.0 && thisFurnace.Humidistat &&
    7111        10122 :                     thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat &&
    7112            0 :                     (SystemMoistureLoad < 0.0 || (SystemMoistureLoad >= 0.0 && HeatingLatentOutput > SystemMoistureLoad &&
    7113            0 :                                                   !state.dataZoneEnergyDemand->Setback(thisFurnace.ControlZoneNum)))) {
    7114            0 :                     CoolingHeatingPLRRatio = min(1.0, PartLoadRatio / thisFurnace.HeatPartLoadRatio);
    7115            0 :                     SetAverageAirFlow(state, FurnaceNum, max(PartLoadRatio, thisFurnace.HeatPartLoadRatio), OnOffAirFlowRatio);
    7116              : 
    7117              :                 } else {
    7118         5061 :                     CoolingHeatingPLRRatio = 1.0;
    7119         5061 :                     SetAverageAirFlow(state, FurnaceNum, PartLoadRatio, OnOffAirFlowRatio);
    7120              :                 }
    7121              : 
    7122              :                 // Get no load result (coils simulated OFF)
    7123         5061 :                 CalcFurnaceOutput(state,
    7124              :                                   FurnaceNum,
    7125              :                                   FirstHVACIteration,
    7126              :                                   fanOp,
    7127              :                                   compressorOp,
    7128              :                                   MinPLR,
    7129              :                                   PartLoadRatio,
    7130              :                                   0.0,
    7131              :                                   0.0,
    7132              :                                   NoCoolOutput,
    7133              :                                   NoLatentOutput,
    7134              :                                   OnOffAirFlowRatio,
    7135         5061 :                                   HXUnitOn,
    7136              :                                   CoolingHeatingPLRRatio);
    7137              : 
    7138              :                 //     Don't calculate full load output if no load output can meet sensible load
    7139         5061 :                 if (NoCoolOutput >= CoolCoilLoad && (CoolCoilLoad != 0.0 || state.dataFurnaces->HPDehumidificationLoadFlag)) {
    7140              :                     //       Set full mass flow rate for full load calculation
    7141         5061 :                     state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = thisFurnace.MdotFurnace;
    7142              : 
    7143              :                     // Set fan part-load fraction equal to 1 while getting full load result
    7144         5061 :                     state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
    7145         5061 :                     OnOffAirFlowRatio = 1.0;
    7146         5061 :                     PartLoadRatio = 1.0;
    7147         5061 :                     thisFurnace.CompPartLoadRatio = 1.0; // compressor ON
    7148              : 
    7149              :                     // Get full load result (coils simulated full ON)
    7150         5061 :                     CalcFurnaceOutput(state,
    7151              :                                       FurnaceNum,
    7152              :                                       FirstHVACIteration,
    7153              :                                       fanOp,
    7154              :                                       compressorOp,
    7155              :                                       PartLoadRatio,
    7156              :                                       0.0,
    7157              :                                       0.0,
    7158              :                                       0.0,
    7159              :                                       FullSensibleOutput,
    7160              :                                       FullLatentOutput,
    7161              :                                       OnOffAirFlowRatio,
    7162         5061 :                                       HXUnitOn);
    7163              :                 } else {
    7164            0 :                     FullSensibleOutput = NoCoolOutput - 0.00000001;
    7165              :                 }
    7166              : 
    7167              :                 //     The next step is to compare the results of the full load and no load results
    7168              :                 //     1) Since we are cooling, we expect FullSensibleOutput < NoCoolOutput
    7169              :                 //        Check that this is the case; if not set PartLoadRatio = 0.0 (off)
    7170              :                 //     2) Verify that the load to be met is within the range of available output
    7171              :                 //        (i.e. between FullSensibleOutput and NoCoolOutput)
    7172              :                 //     3) Set PLR if load is out of range or RegulaFalsi on PLR if system can meet the load
    7173         5061 :                 if (FullSensibleOutput < NoCoolOutput) {
    7174         5061 :                     if (CoolCoilLoad != 0.0 || state.dataFurnaces->HPDehumidificationLoadFlag) {
    7175              : 
    7176              :                         // check bounds on sensible output prior to iteration using RegulaFalsi
    7177              :                         // Negative value represents cooling load, IF FullSensibleOutput .GT. CoolCoilLoad, load is greater than capacity
    7178         5061 :                         if (FullSensibleOutput >= CoolCoilLoad) {
    7179            0 :                             PartLoadRatio = 1.0;
    7180              :                             //           Likewise IF NoCoolOutput .LT. CoolCoilLoad, then load can be met using only the fan (constant fan mode only)
    7181         5061 :                         } else if (NoCoolOutput <= CoolCoilLoad) {
    7182            0 :                             PartLoadRatio = 0.0;
    7183              :                             //           ELSE load is between NoCoolOutput and FullSensibleOuput, find PLR required to meet load
    7184              :                         } else {
    7185              : 
    7186              :                             // Calculate the sensible part load ratio through iteration
    7187         5061 :                             CoolErrorToler = thisFurnace.CoolingConvergenceTolerance; // Error tolerance for convergence from input deck
    7188         5061 :                             int SolFlag = 0; // # of iterations if positive, -1 means failed to converge, -2 means bounds are incorrect
    7189         5061 :                             Real64 par8_HXFlag = HXUnitOn ? 1.0 : 0.0;
    7190              :                             // CoolErrorToler is in fraction of load, MaxIter = 30, SolFalg = # of iterations or error as appropriate
    7191              :                             auto f =
    7192        25305 :                                 [&state, FurnaceNum, FirstHVACIteration, fanOp, compressorOp, CoolCoilLoad, par8_HXFlag](Real64 const PartLoadRatio) {
    7193        20244 :                                     return CalcFurnaceResidual(state,
    7194              :                                                                PartLoadRatio,
    7195              :                                                                FurnaceNum,
    7196              :                                                                FirstHVACIteration,
    7197              :                                                                fanOp,
    7198              :                                                                compressorOp,
    7199              :                                                                CoolCoilLoad,
    7200              :                                                                1.0,         // par6_loadFlag,
    7201              :                                                                1.0,         // par7_sensLatentFlag,
    7202              :                                                                par8_HXFlag, // par9_HXOnFlag,
    7203        20244 :                                                                0.0);        // par10_HeatingCoilPLR);
    7204         5061 :                                 };
    7205         5061 :                             General::SolveRoot(state, CoolErrorToler, MaxIter, SolFlag, PartLoadRatio, f, 0.0, 1.0);
    7206              :                             //             OnOffAirFlowRatio is updated during the above iteration. Reset to correct value based on PLR.
    7207         5061 :                             OnOffAirFlowRatio = state.dataFurnaces->OnOffAirFlowRatioSave;
    7208         5061 :                             if (SolFlag < 0) {
    7209            0 :                                 if (SolFlag == -1) {
    7210            0 :                                     CalcFurnaceOutput(state,
    7211              :                                                       FurnaceNum,
    7212              :                                                       FirstHVACIteration,
    7213              :                                                       fanOp,
    7214              :                                                       compressorOp,
    7215              :                                                       PartLoadRatio,
    7216              :                                                       0.0,
    7217              :                                                       0.0,
    7218              :                                                       0.0,
    7219              :                                                       TempCoolOutput,
    7220              :                                                       TempLatentOutput,
    7221              :                                                       OnOffAirFlowRatio,
    7222            0 :                                                       HXUnitOn);
    7223            0 :                                     if (!state.dataGlobal->WarmupFlag) {
    7224            0 :                                         if (std::abs(CoolCoilLoad - TempCoolOutput) > HVAC::SmallLoad) {
    7225            0 :                                             if (thisFurnace.SensibleMaxIterIndex == 0) {
    7226            0 :                                                 ShowWarningMessage(state,
    7227            0 :                                                                    format("Cooling coil control failed to converge for {}:{}",
    7228            0 :                                                                           HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    7229            0 :                                                                           thisFurnace.Name));
    7230            0 :                                                 ShowContinueError(
    7231              :                                                     state, "  Iteration limit exceeded in calculating DX cooling coil sensible part-load ratio.");
    7232            0 :                                                 ShowContinueErrorTimeStamp(state,
    7233            0 :                                                                            format("Sensible load to be met by DX coil = {:.2T} (watts), sensible "
    7234              :                                                                                   "output of DX coil = {:.2T} (watts), and the simulation continues.",
    7235              :                                                                                   CoolCoilLoad,
    7236              :                                                                                   TempCoolOutput));
    7237              :                                             }
    7238            0 :                                             ShowRecurringWarningErrorAtEnd(
    7239              :                                                 state,
    7240            0 :                                                 format("{} \"{}\" - Iteration limit exceeded in calculating sensible cooling "
    7241              :                                                        "part-load ratio error continues. Sensible load statistics:",
    7242            0 :                                                        HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    7243            0 :                                                        thisFurnace.Name),
    7244            0 :                                                 thisFurnace.SensibleMaxIterIndex,
    7245              :                                                 CoolCoilLoad,
    7246              :                                                 CoolCoilLoad);
    7247              :                                         }
    7248              :                                     }
    7249            0 :                                 } else if (SolFlag == -2) {
    7250            0 :                                     if (!state.dataGlobal->WarmupFlag) {
    7251            0 :                                         if (thisFurnace.SensibleRegulaFalsiFailedIndex == 0) {
    7252            0 :                                             ShowWarningMessage(state,
    7253            0 :                                                                format("Cooling coil control failed for {}:{}",
    7254            0 :                                                                       HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    7255            0 :                                                                       thisFurnace.Name));
    7256            0 :                                             ShowContinueError(state, "  Cooling sensible part-load ratio determined to be outside the range of 0-1.");
    7257            0 :                                             ShowContinueErrorTimeStamp(state, format("  Cooling sensible load = {:.2T}", CoolCoilLoad));
    7258              :                                         }
    7259            0 :                                         ShowRecurringWarningErrorAtEnd(
    7260              :                                             state,
    7261            0 :                                             format("{} \"{}\" - Cooling sensible part-load ratio out of range error continues. Sensible cooling load "
    7262              :                                                    "statistics:",
    7263            0 :                                                    HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    7264            0 :                                                    thisFurnace.Name),
    7265            0 :                                             thisFurnace.SensibleRegulaFalsiFailedIndex,
    7266              :                                             CoolCoilLoad,
    7267              :                                             CoolCoilLoad);
    7268              :                                     }
    7269              :                                 }
    7270              :                             }
    7271              :                         }
    7272              : 
    7273              :                     } else {
    7274            0 :                         PartLoadRatio = 0.0;
    7275              :                     } // EndIf for IF(CoolCoilLoad.NE.0.0)
    7276              : 
    7277              :                     //       Calculate the delivered capacity from the PLR calculated above
    7278         5061 :                     CalcFurnaceOutput(state,
    7279              :                                       FurnaceNum,
    7280              :                                       FirstHVACIteration,
    7281              :                                       fanOp,
    7282              :                                       compressorOp,
    7283              :                                       PartLoadRatio,
    7284              :                                       thisFurnace.HeatPartLoadRatio,
    7285              :                                       0.0,
    7286              :                                       0.0,
    7287              :                                       TempCoolOutput,
    7288              :                                       TempLatentOutput,
    7289              :                                       OnOffAirFlowRatio,
    7290         5061 :                                       HXUnitOn);
    7291              : 
    7292              :                     //       Calculate the latent part load ratio through iteration
    7293              :                     //       Negative SystemMoistureLoad means dehumidification load is present
    7294              :                     //       IF this furnace uses MultiMode control AND there is a moisture load AND the moisture load met by the furnace in
    7295              :                     //       cooling only mode above is sufficient to meet the moisture demand OR there is no sensible load (PLR=0 from above)
    7296              :                     //       then set LatentPartLoadRatio to 0 (no additional dehumidification is required).
    7297         5061 :                     if (thisFurnace.DehumidControlType_Num == DehumidificationControlMode::Multimode &&
    7298            0 :                         ((SystemMoistureLoad < 0.0 && TempLatentOutput < SystemMoistureLoad) || PartLoadRatio == 0.0)) {
    7299            0 :                         LatentPartLoadRatio = 0.0;
    7300              :                         //       ELSE calculate a new PLR for valid dehumidification control types if a moisture load exists.
    7301         5061 :                     } else if (thisFurnace.DehumidControlType_Num != DehumidificationControlMode::None &&
    7302            0 :                                (SystemMoistureLoad < 0.0 || (SystemMoistureLoad >= 0.0 && TempLatentOutput > SystemMoistureLoad &&
    7303            0 :                                                              !state.dataZoneEnergyDemand->Setback(thisFurnace.ControlZoneNum)))) {
    7304              : 
    7305              :                         //         IF the furnace uses dehumidification control MultiMode, turn on the HX and calculate the latent output with
    7306              :                         //         the HX ON to compare to the moisture load predicted by the humidistat.
    7307            0 :                         if (thisFurnace.DehumidControlType_Num == DehumidificationControlMode::Multimode) {
    7308            0 :                             HXUnitOn = true;
    7309            0 :                             state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = thisFurnace.MdotFurnace;
    7310              :                             // Set fan part-load fraction equal to 1 while getting full load result
    7311            0 :                             state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
    7312            0 :                             OnOffAirFlowRatio = 1.0;
    7313              :                             // Get full load result
    7314            0 :                             CalcFurnaceOutput(state,
    7315              :                                               FurnaceNum,
    7316              :                                               FirstHVACIteration,
    7317              :                                               fanOp,
    7318              :                                               compressorOp,
    7319              :                                               1.0,
    7320              :                                               0.0,
    7321              :                                               0.0,
    7322              :                                               0.0,
    7323              :                                               TempCoolOutput,
    7324              :                                               TempLatentOutput,
    7325              :                                               OnOffAirFlowRatio,
    7326            0 :                                               HXUnitOn);
    7327              :                         }
    7328              : 
    7329              :                         //         Set the global cooling to heating PLR ratio. CoolHeatPLRRat = MIN(1,CoolingPLR/HeatingPLR)
    7330            0 :                         state.dataFurnaces->CoolHeatPLRRat = 1.0; // means cooling dominated operation (applies to cycling fan mode)
    7331              : 
    7332            0 :                         if (TempLatentOutput > SystemMoistureLoad) {
    7333              :                             //           Set full mass flow rate for full load calculation
    7334            0 :                             state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = thisFurnace.MdotFurnace;
    7335              : 
    7336              :                             // Set fan part-load fraction equal to 1 while getting full load result
    7337            0 :                             state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
    7338            0 :                             OnOffAirFlowRatio = 1.0;
    7339            0 :                             thisFurnace.CompPartLoadRatio = 1.0; // compressor ON
    7340              : 
    7341              :                             // Get full load result (coils simulated full ON)
    7342            0 :                             CalcFurnaceOutput(state,
    7343              :                                               FurnaceNum,
    7344              :                                               FirstHVACIteration,
    7345              :                                               fanOp,
    7346              :                                               compressorOp,
    7347              :                                               1.0,
    7348              :                                               0.0,
    7349              :                                               0.0,
    7350              :                                               0.0,
    7351              :                                               TempCoolOutput,
    7352              :                                               TempLatentOutput,
    7353              :                                               OnOffAirFlowRatio,
    7354            0 :                                               HXUnitOn);
    7355              :                         }
    7356              : 
    7357              :                         // check bounds on latent output prior to iteration using RegulaFalsi
    7358            0 :                         if (TempLatentOutput > SystemMoistureLoad ||
    7359            0 :                             (thisFurnace.DehumidControlType_Num == DehumidificationControlMode::Multimode && TempCoolOutput > CoolCoilLoad)) {
    7360            0 :                             LatentPartLoadRatio = 1.0;
    7361            0 :                         } else if (NoLatentOutput < SystemMoistureLoad || HeatingLatentOutput < SystemMoistureLoad) {
    7362            0 :                             LatentPartLoadRatio = 0.0;
    7363              :                         } else {
    7364              : 
    7365            0 :                             CoolErrorToler = thisFurnace.CoolingConvergenceTolerance; // Error tolerance for convergence
    7366              : 
    7367            0 :                             int SolFlag = 0; // # of iterations if positive, -1 means failed to converge, -2 means bounds are incorrect
    7368              :                             // Multimode always controls to meet the SENSIBLE load (however, HXUnitOn is now TRUE)
    7369              :                             Real64 par4_load;
    7370            0 :                             if (thisFurnace.DehumidControlType_Num == DehumidificationControlMode::Multimode) {
    7371            0 :                                 par4_load = CoolCoilLoad;
    7372              :                             } else {
    7373            0 :                                 par4_load = SystemMoistureLoad;
    7374              :                             }
    7375              :                             // Multimode always controls to meet the SENSIBLE load (however, HXUnitOn is now TRUE)
    7376              :                             Real64 par6_LatentSens;
    7377            0 :                             if (thisFurnace.DehumidControlType_Num == DehumidificationControlMode::Multimode) {
    7378            0 :                                 par6_LatentSens = 1.0;
    7379              :                             } else {
    7380            0 :                                 par6_LatentSens = 0.0;
    7381              :                             }
    7382            0 :                             Real64 par8_HXUnit = HXUnitOn ? 1.0 : 0.0;
    7383              :                             Real64 par9_HtgCoilPLR;
    7384            0 :                             if (fanOp == HVAC::FanOp::Cycling && thisFurnace.HeatPartLoadRatio > 0.0 && par6_LatentSens == 0.0) {
    7385            0 :                                 par9_HtgCoilPLR = thisFurnace.HeatPartLoadRatio;
    7386              :                             } else {
    7387            0 :                                 par9_HtgCoilPLR = 0.0;
    7388              :                             }
    7389            0 :                             auto f = [&state,
    7390              :                                       FurnaceNum,
    7391              :                                       FirstHVACIteration,
    7392              :                                       fanOp,
    7393              :                                       compressorOp,
    7394              :                                       par4_load,
    7395              :                                       par6_LatentSens,
    7396              :                                       par8_HXUnit,
    7397              :                                       par9_HtgCoilPLR](Real64 const PartLoadRatio) {
    7398            0 :                                 return CalcFurnaceResidual(state,
    7399              :                                                            PartLoadRatio,
    7400              :                                                            FurnaceNum,
    7401              :                                                            FirstHVACIteration,
    7402              :                                                            fanOp,
    7403              :                                                            compressorOp,
    7404              :                                                            par4_load,
    7405              :                                                            1.0,              // par6_loadFlag,
    7406              :                                                            par6_LatentSens,  // par7_sensLatentFlag,
    7407              :                                                            par8_HXUnit,      // par9_HXOnFlag,
    7408            0 :                                                            par9_HtgCoilPLR); // par10_HeatingCoilPLR);
    7409            0 :                             };
    7410              :                             //           CoolErrorToler is in fraction of load, MaxIter = 30, SolFalg = # of iterations or error as appropriate
    7411            0 :                             General::SolveRoot(state, CoolErrorToler, MaxIter, SolFlag, LatentPartLoadRatio, f, 0.0, 1.0);
    7412              :                             //           OnOffAirFlowRatio is updated during the above iteration. Reset to correct value based on PLR.
    7413            0 :                             OnOffAirFlowRatio = state.dataFurnaces->OnOffAirFlowRatioSave;
    7414            0 :                             if (SolFlag == -1) {
    7415              :                                 //             RegulaFalsi may not find latent PLR when the latent degradation model is used.
    7416              :                                 //             If iteration limit is exceeded, find tighter boundary of solution and repeat RegulaFalsi
    7417            0 :                                 TempMaxPLR = -0.1;
    7418            0 :                                 TempLatentOutput = NoLatentOutput;
    7419            0 :                                 while ((TempLatentOutput - SystemMoistureLoad) > 0.0 && TempMaxPLR < 1.0) {
    7420              :                                     //               find upper limit of LatentPLR
    7421            0 :                                     TempMaxPLR += 0.1;
    7422              : 
    7423              :                                     //               Same calculation as is done in Function CalcFurnaceResidual for latent PLR calculation.
    7424              :                                     //               Set cooling to heating PLR for use with Subroutine CalcFurnaceOutput. IF Par(10) = 0,
    7425              :                                     //               heating PLR = 0 so set the CoolingHeatingPLRRatio to 1 so the cooling PLR is used in the
    7426              :                                     //               DX cooling coil calculations.
    7427            0 :                                     if (par9_HtgCoilPLR > 0.0) {
    7428              :                                         //                 Par(10) = Furnace(FurnaceNum)%HeatPartLoadRatio
    7429              :                                         //                 fanOp = CycFan and Furnace(FurnaceNum)%HeatPartLoadRatio must be > 0 for Part(10) to be
    7430              :                                         //                 greater than 0
    7431            0 :                                         CoolingHeatingPLRRatio = min(1.0, TempMaxPLR / thisFurnace.HeatPartLoadRatio);
    7432              :                                     } else {
    7433            0 :                                         CoolingHeatingPLRRatio = 1.0;
    7434              :                                     }
    7435              : 
    7436            0 :                                     CalcFurnaceOutput(state,
    7437              :                                                       FurnaceNum,
    7438              :                                                       FirstHVACIteration,
    7439              :                                                       fanOp,
    7440              :                                                       compressorOp,
    7441              :                                                       TempMaxPLR,
    7442              :                                                       0.0,
    7443              :                                                       0.0,
    7444              :                                                       0.0,
    7445              :                                                       TempCoolOutput,
    7446              :                                                       TempLatentOutput,
    7447              :                                                       OnOffAirFlowRatio,
    7448            0 :                                                       HXUnitOn,
    7449              :                                                       CoolingHeatingPLRRatio);
    7450              :                                 }
    7451            0 :                                 TempMinPLR = TempMaxPLR;
    7452            0 :                                 while ((TempLatentOutput - SystemMoistureLoad) < 0.0 && TempMinPLR > 0.0) {
    7453              :                                     //               pull upper limit of LatentPLR down to last valid limit (i.e. latent output still exceeds
    7454              :                                     //               SystemMoisuterLoad) CR7558 - relax final limits to allow HX assisted coils to converge
    7455            0 :                                     TempMaxPLR = TempMinPLR + 0.001;
    7456              :                                     //               find minimum limit of Latent PLR
    7457            0 :                                     TempMinPLR -= 0.001;
    7458              : 
    7459              :                                     //               Set cooling to heating PLR for use with Subroutine CalcFurnaceOutput.
    7460            0 :                                     if (par9_HtgCoilPLR > 0.0) {
    7461              :                                         //                 Par(10) = Furnace(FurnaceNum)%HeatPartLoadRatio
    7462              :                                         //                 fanOp = CycFan and Furnace(FurnaceNum)%HeatPartLoadRatio must be > 0 for Part(10) to be
    7463              :                                         //                 greater than 0 Since the latent output of cycling fan systems is 0 at PLR=0, do not allow
    7464              :                                         //                 the PLR to be 0, otherwise RegulaFalsi can fail when a heating and moisture load exists and
    7465              :                                         //                 heating PLR > latent PLR.
    7466            0 :                                         TempMinPLR2 = max(0.0000000001, TempMinPLR);
    7467            0 :                                         CoolingHeatingPLRRatio = min(1.0, TempMinPLR2 / thisFurnace.HeatPartLoadRatio);
    7468              :                                     } else {
    7469            0 :                                         TempMinPLR2 = TempMinPLR;
    7470            0 :                                         CoolingHeatingPLRRatio = 1.0;
    7471              :                                     }
    7472              : 
    7473            0 :                                     CalcFurnaceOutput(state,
    7474              :                                                       FurnaceNum,
    7475              :                                                       FirstHVACIteration,
    7476              :                                                       fanOp,
    7477              :                                                       compressorOp,
    7478              :                                                       TempMinPLR2,
    7479              :                                                       0.0,
    7480              :                                                       0.0,
    7481              :                                                       0.0,
    7482              :                                                       TempCoolOutput,
    7483              :                                                       TempLatentOutput,
    7484              :                                                       OnOffAirFlowRatio,
    7485            0 :                                                       HXUnitOn,
    7486              :                                                       CoolingHeatingPLRRatio);
    7487              :                                 }
    7488              :                                 //             tighter boundary of solution has been found, call RegulaFalsi a second time
    7489            0 :                                 auto f2 = [&state,
    7490              :                                            FurnaceNum,
    7491              :                                            FirstHVACIteration,
    7492              :                                            fanOp,
    7493              :                                            compressorOp,
    7494              :                                            par4_load,
    7495              :                                            par6_LatentSens,
    7496              :                                            par8_HXUnit,
    7497              :                                            par9_HtgCoilPLR](Real64 const PartLoadRatio) {
    7498            0 :                                     return CalcFurnaceResidual(state,
    7499              :                                                                PartLoadRatio,
    7500              :                                                                FurnaceNum,
    7501              :                                                                FirstHVACIteration,
    7502              :                                                                fanOp,
    7503              :                                                                compressorOp,
    7504              :                                                                par4_load,
    7505              :                                                                1.0,              // par6_loadFlag,
    7506              :                                                                par6_LatentSens,  // par7_sensLatentFlag,
    7507              :                                                                par8_HXUnit,      // par9_HXOnFlag,
    7508            0 :                                                                par9_HtgCoilPLR); // par10_HeatingCoilPLR);
    7509            0 :                                 };
    7510            0 :                                 General::SolveRoot(state, CoolErrorToler, MaxIter, SolFlag, LatentPartLoadRatio, f2, TempMinPLR2, TempMaxPLR);
    7511              :                                 //             OnOffAirFlowRatio is updated during the above iteration. Reset to correct value based on PLR.
    7512            0 :                                 OnOffAirFlowRatio = state.dataFurnaces->OnOffAirFlowRatioSave;
    7513            0 :                                 if (SolFlag == -1) {
    7514              : 
    7515              :                                     //               Set cooling to heating PLR for use with Subroutine CalcFurnaceOutput.
    7516            0 :                                     if (par9_HtgCoilPLR > 0.0) {
    7517              :                                         //                 Par(10) = Furnace(FurnaceNum)%HeatPartLoadRatio
    7518              :                                         //                 fanOp = CycFan and Furnace(FurnaceNum)%HeatPartLoadRatio must be > 0 for Part(10) to be
    7519              :                                         //                 greater than 0
    7520            0 :                                         CoolingHeatingPLRRatio = min(1.0, LatentPartLoadRatio / thisFurnace.HeatPartLoadRatio);
    7521              :                                     } else {
    7522            0 :                                         CoolingHeatingPLRRatio = 1.0;
    7523              :                                     }
    7524              : 
    7525            0 :                                     CalcFurnaceOutput(state,
    7526              :                                                       FurnaceNum,
    7527              :                                                       FirstHVACIteration,
    7528              :                                                       fanOp,
    7529              :                                                       compressorOp,
    7530              :                                                       LatentPartLoadRatio,
    7531              :                                                       0.0,
    7532              :                                                       0.0,
    7533              :                                                       0.0,
    7534              :                                                       TempCoolOutput,
    7535              :                                                       TempLatentOutput,
    7536              :                                                       OnOffAirFlowRatio,
    7537            0 :                                                       HXUnitOn,
    7538              :                                                       CoolingHeatingPLRRatio);
    7539            0 :                                     if (std::abs((SystemMoistureLoad - TempLatentOutput) / SystemMoistureLoad) > CoolErrorToler &&
    7540            0 :                                         std::abs(SystemMoistureLoad - TempLatentOutput) > 10.0) {
    7541            0 :                                         if (!state.dataGlobal->WarmupFlag) {
    7542            0 :                                             if (thisFurnace.LatentMaxIterIndex == 0) {
    7543            0 :                                                 ShowWarningMessage(state,
    7544            0 :                                                                    format("Cooling coil control failed to converge for {}:{}",
    7545            0 :                                                                           HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    7546            0 :                                                                           thisFurnace.Name));
    7547            0 :                                                 ShowContinueError(state,
    7548              :                                                                   "  Iteration limit exceeded in calculating cooling coil latent part-load ratio.");
    7549            0 :                                                 ShowContinueError(
    7550              :                                                     state,
    7551            0 :                                                     format("  Latent load convergence error (percent) = {:.2T}",
    7552            0 :                                                            100.0 * std::abs((SystemMoistureLoad - TempLatentOutput) / SystemMoistureLoad)));
    7553            0 :                                                 ShowContinueErrorTimeStamp(state,
    7554            0 :                                                                            format("Moisture load to be met by DX coil = {:.2T} (watts), Latent "
    7555              :                                                                                   "output of DX coil = {:.2T} (watts), and the simulation continues.",
    7556              :                                                                                   SystemMoistureLoad,
    7557              :                                                                                   TempLatentOutput));
    7558              :                                             }
    7559            0 :                                             ShowRecurringWarningErrorAtEnd(
    7560              :                                                 state,
    7561            0 :                                                 format("{} \"{}\" - Iteration limit exceeded in calculating latent part-load ratio error continues. "
    7562              :                                                        "Latent "
    7563              :                                                        "load convergence error (percent) statistics follow.",
    7564            0 :                                                        HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    7565            0 :                                                        thisFurnace.Name),
    7566            0 :                                                 thisFurnace.LatentMaxIterIndex,
    7567            0 :                                                 100.0 * std::abs((SystemMoistureLoad - TempLatentOutput) / SystemMoistureLoad),
    7568            0 :                                                 100.0 * std::abs((SystemMoistureLoad - TempLatentOutput) / SystemMoistureLoad));
    7569              :                                         }
    7570              :                                     }
    7571            0 :                                 } else if (SolFlag == -2) {
    7572            0 :                                     if (thisFurnace.LatentRegulaFalsiFailedIndex2 == 0) {
    7573            0 :                                         ShowWarningMessage(state,
    7574            0 :                                                            format("Cooling coil control failed for {}:{}",
    7575            0 :                                                                   HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    7576            0 :                                                                   thisFurnace.Name));
    7577            0 :                                         ShowContinueError(state,
    7578            0 :                                                           format("  Latent part-load ratio determined to be outside the range of {:.3T} to {:.3T}.",
    7579              :                                                                  TempMinPLR,
    7580              :                                                                  TempMaxPLR));
    7581            0 :                                         ShowContinueErrorTimeStamp(state,
    7582            0 :                                                                    format("A PLR of {:.3T} will be used and the simulation continues.", TempMinPLR));
    7583              :                                     }
    7584            0 :                                     ShowRecurringWarningErrorAtEnd(state,
    7585            0 :                                                                    format("{} \"{}\" - Cooling sensible part-load ratio out of range error "
    7586              :                                                                           "continues. System moisture load statistics:",
    7587            0 :                                                                           HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    7588            0 :                                                                           thisFurnace.Name),
    7589            0 :                                                                    thisFurnace.LatentRegulaFalsiFailedIndex2,
    7590              :                                                                    SystemMoistureLoad,
    7591              :                                                                    SystemMoistureLoad);
    7592            0 :                                     LatentPartLoadRatio = TempMinPLR;
    7593              :                                 }
    7594            0 :                             } else if (SolFlag == -2) {
    7595            0 :                                 if (thisFurnace.LatentRegulaFalsiFailedIndex == 0) {
    7596            0 :                                     ShowWarningMessage(state,
    7597            0 :                                                        format("Cooling coil control failed for {}:{}",
    7598            0 :                                                               HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    7599            0 :                                                               thisFurnace.Name));
    7600            0 :                                     ShowContinueError(state, "  Latent part-load ratio determined to be outside the range of 0-1.");
    7601            0 :                                     ShowContinueErrorTimeStamp(state, "A PLR of 0 will be used and the simulation continues.");
    7602              :                                 }
    7603            0 :                                 ShowRecurringWarningErrorAtEnd(
    7604              :                                     state,
    7605            0 :                                     format("{} \"{}\" - Latent part-load ratio out of range or 0-1 error continues. System moisture load statistics:",
    7606            0 :                                            HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    7607            0 :                                            thisFurnace.Name),
    7608            0 :                                     thisFurnace.LatentRegulaFalsiFailedIndex,
    7609              :                                     SystemMoistureLoad,
    7610              :                                     SystemMoistureLoad);
    7611            0 :                                 LatentPartLoadRatio = 0.0;
    7612              :                             }
    7613              :                         }
    7614              : 
    7615              :                         //         Cooling to heating PLR ratio is now known as CoolHeatPLRRat (Module level global set in CalcFurnaceOutput
    7616              :                         //         This same variable is use in Subroutine SimFurnace for final calculations.
    7617              :                         //         Get the actual output in case reheat needs to be calculated (HumControl=TRUE [latent PLR > sensible PLR])
    7618            0 :                         CalcFurnaceOutput(state,
    7619              :                                           FurnaceNum,
    7620              :                                           FirstHVACIteration,
    7621              :                                           fanOp,
    7622              :                                           compressorOp,
    7623              :                                           LatentPartLoadRatio,
    7624              :                                           0.0,
    7625              :                                           0.0,
    7626              :                                           0.0,
    7627              :                                           ActualSensibleOutput,
    7628              :                                           ActualLatentOutput,
    7629              :                                           OnOffAirFlowRatio,
    7630            0 :                                           HXUnitOn,
    7631            0 :                                           state.dataFurnaces->CoolHeatPLRRat);
    7632              : 
    7633              :                     } else {
    7634         5061 :                         LatentPartLoadRatio = 0.0;
    7635              :                     } // ENDIF for valid dehumidification control types
    7636              : 
    7637              :                     //       IF a humidistat is used and there is a moisture load, check if the latent PLR is greater than the (sensible) PLR
    7638              :                     //        IF(LatentPartLoadRatio .GT. PartLoadRatio .and. SystemMoistureLoad .lt. 0.0 .and. Furnace(FurnaceNum)%Humidistat) THEN
    7639         5061 :                     if (LatentPartLoadRatio > PartLoadRatio && thisFurnace.Humidistat) {
    7640              :                         // For dehumidification mode CoolReheat, compare the Sensible and Latent PLR values, if latentPLR is greater
    7641              :                         // than PLR (sensible), then overcooling is required and reheat will be activated using the HumControl flag.
    7642            0 :                         if (thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat) {
    7643            0 :                             PartLoadRatio = LatentPartLoadRatio;
    7644            0 :                             HumControl = true;
    7645              :                         }
    7646              :                         // For dehumidification mode MultiMode, compare the Sensible and Latent PLR values, if latentPLR is
    7647              :                         // greater than PLR (sensible), then use the latent PLR to control the unit.
    7648              :                         // For MultiMode control, the latent PLR is found by enabling the HX and calculating a PLR required to meet the
    7649              :                         // sensible load. Overcooling is not required, and reheat will not be activated using the HumControl flag.
    7650            0 :                         if (thisFurnace.DehumidControlType_Num == DehumidificationControlMode::Multimode) {
    7651            0 :                             PartLoadRatio = LatentPartLoadRatio;
    7652              :                         }
    7653              :                     }
    7654              : 
    7655         5061 :                     thisFurnace.CoolPartLoadRatio = PartLoadRatio;
    7656         5061 :                     if (compressorOp == HVAC::CompressorOp::Off) {
    7657            0 :                         thisFurnace.CompPartLoadRatio = 0.0;
    7658              :                     } else {
    7659         5061 :                         thisFurnace.CompPartLoadRatio = PartLoadRatio;
    7660              :                     }
    7661              : 
    7662              :                 } else { // ELSE from IF(FullSensibleOutput.LT.NoCoolOutput)THEN above
    7663              :                     // CR8679 - Unitary Heat Cool control problem, will not run to meeting cooling load
    7664              :                     // underlying problem is that FullSensibleOutput is greater than 0 due to very high inlet temp, so the system should be on
    7665              :                     // NoCoolOutput was 0 since the defect file is a cycling fan system and the system was turned off
    7666              : 
    7667              :                     // if FullSensibleOutput > NoCoolOutput, it means the system cannot meet the load and will run full out
    7668              :                     // this same logic for WSHP does not seem to work (only the Unitary Heat Pump Compressor Part-Load Ratio report
    7669              :                     // variable was affected in the HeatPumpWaterToAirRHControl.idf file while other variables showed very small diffs).
    7670              :                     // The defect files meter.csv showed 2% diffs so this IF test is used to keep the results the same in that file.
    7671              :                     // Additional logic is used here to make sure the coil actually turned on, e.g., if DX coil PLR > 0 then set to 1,
    7672              :                     // otherwise 0 (to make sure coil is actually ON and not off due to schedule, OAT, or other reason).
    7673              :                     // The global variable DXCoilPartLoadRatio(DXCoilNum) is not yet used for the WSHP to make the same check.
    7674            0 :                     if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir) {
    7675            0 :                         thisFurnace.CoolPartLoadRatio = 0.0;
    7676            0 :                         thisFurnace.CompPartLoadRatio = 0.0;
    7677              :                     } else {
    7678            0 :                         if (thisFurnace.CoolingCoilType_Num == HVAC::CoilDX_CoolingHXAssisted) {
    7679              : 
    7680              :                             // VS coil issue here...
    7681            0 :                             if (state.dataDXCoils->DXCoilPartLoadRatio(thisFurnace.ActualDXCoilIndexForHXAssisted) > 0.0) {
    7682            0 :                                 thisFurnace.CoolPartLoadRatio = 1.0;
    7683            0 :                                 thisFurnace.CompPartLoadRatio = 1.0;
    7684              :                             } else {
    7685            0 :                                 thisFurnace.CoolPartLoadRatio = 0.0;
    7686            0 :                                 thisFurnace.CompPartLoadRatio = 0.0;
    7687              :                             }
    7688              :                         } else {
    7689            0 :                             if (state.dataDXCoils->DXCoilPartLoadRatio(thisFurnace.CoolingCoilIndex) > 0.0) {
    7690            0 :                                 thisFurnace.CoolPartLoadRatio = 1.0;
    7691            0 :                                 thisFurnace.CompPartLoadRatio = 1.0;
    7692              :                             } else {
    7693            0 :                                 thisFurnace.CoolPartLoadRatio = 0.0;
    7694            0 :                                 thisFurnace.CompPartLoadRatio = 0.0;
    7695              :                             }
    7696              :                         }
    7697              :                     }
    7698              :                 }
    7699              : 
    7700              :                 //     Calculate the reheat coil output
    7701         5061 :                 if (HumControl) { // HumControl = .TRUE. if a Humidistat is installed and dehumidification control type is CoolReheat
    7702            0 :                     if (thisFurnace.ZoneSequenceHeatingNum > 0) {
    7703            0 :                         QToHeatSetPt = (state.dataZoneEnergyDemand->ZoneSysEnergyDemand(thisFurnace.ControlZoneNum)
    7704            0 :                                             .SequencedOutputRequiredToHeatingSP(thisFurnace.ZoneSequenceHeatingNum) /
    7705            0 :                                         thisFurnace.ControlZoneMassFlowFrac);
    7706              :                     } else {
    7707            0 :                         QToHeatSetPt = (state.dataZoneEnergyDemand->ZoneSysEnergyDemand(thisFurnace.ControlZoneNum).OutputRequiredToHeatingSP /
    7708            0 :                                         thisFurnace.ControlZoneMassFlowFrac);
    7709              :                     }
    7710              :                     //       Cooling mode or floating condition and dehumidification is required
    7711            0 :                     if (QToHeatSetPt < 0.0) {
    7712              :                         //         Calculate the reheat coil load wrt the heating setpoint temperature. Reheat coil picks up
    7713              :                         //         the entire excess sensible cooling (DX cooling coil and impact of outdoor air).
    7714            0 :                         ReheatCoilLoad = max(0.0, (QToHeatSetPt - ActualSensibleOutput));
    7715            0 :                         thisFurnace.DehumidInducedHeatingDemandRate = ReheatCoilLoad;
    7716              :                         //       Heating mode and dehumidification is required
    7717              :                     } else {
    7718              :                         //         Calculate the reheat coil load as the sensible capacity of the DX cooling coil only. Let
    7719              :                         //         the heating coil pick up the load due to outdoor air.
    7720            0 :                         ReheatCoilLoad = max(0.0, (ActualSensibleOutput - NoCoolOutput) * (-1.0));
    7721              :                         //         Dehumidification is not required
    7722            0 :                         if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_AirToAir ||
    7723            0 :                             (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir &&
    7724            0 :                              thisFurnace.WatertoAirHPType == WAHPCoilType::Simple)) {
    7725            0 :                             ReheatCoilLoad = max(QToHeatSetPt, QToHeatSetPt - ActualSensibleOutput);
    7726              :                         }
    7727            0 :                         thisFurnace.DehumidInducedHeatingDemandRate = max(0.0, ActualSensibleOutput * (-1.0));
    7728              :                     }
    7729              :                 } else {
    7730              :                     //       No humidistat installed
    7731         5061 :                     ReheatCoilLoad = 0.0;
    7732              :                 }
    7733              :             } // End of cooling section IF statement
    7734              : 
    7735        10378 :             if (NoHeatOutput > SystemSensibleLoad && ReheatCoilLoad > 0.0) {
    7736              :                 // Reduce reheat coil load if you are controlling high humidity but outside air
    7737              :                 // and/or the supply air fan is providing enough heat to meet the system sensible load.
    7738              :                 // This will bring the zone temp closer to the heating setpoint temp.
    7739            0 :                 ReheatCoilLoad = max(0.0, ReheatCoilLoad - (NoHeatOutput - SystemSensibleLoad));
    7740              :             }
    7741              : 
    7742              :             // Set the final air flow. MdotFurnace will be used to set the fan part-load ratio in ReportFurnace
    7743        10378 :             if (HumControl && SystemMoistureLoad < 0.0) {
    7744            0 :                 if (fanOp == HVAC::FanOp::Cycling) {
    7745              :                     //       set the flow rate at the maximum of the cooling and heating PLR's
    7746            0 :                     SetAverageAirFlow(state, FurnaceNum, max(thisFurnace.CoolPartLoadRatio, thisFurnace.HeatPartLoadRatio), OnOffAirFlowRatio);
    7747              :                 } else {
    7748              :                     //       ELSE set the flow rate at the cooling PLR
    7749            0 :                     SetAverageAirFlow(state, FurnaceNum, thisFurnace.CoolPartLoadRatio, OnOffAirFlowRatio);
    7750              :                 }
    7751              :             } else {
    7752        10378 :                 SetAverageAirFlow(state, FurnaceNum, max(thisFurnace.CoolPartLoadRatio, thisFurnace.HeatPartLoadRatio), OnOffAirFlowRatio);
    7753              :             }
    7754        10378 :             thisFurnace.MdotFurnace = state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate;
    7755              : 
    7756        10378 :             if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_AirToAir ||
    7757            2 :                 (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir && thisFurnace.WatertoAirHPType == WAHPCoilType::Simple)) {
    7758              :             } else {
    7759              :                 // Non-HeatPump (non-DX) heating coils do not set PLR, reset to 0 here. This variable was set for non-DX
    7760              :                 // coils to allow the SetAverageAirFlow CALL above to set the correct air mass flow rate. See this
    7761              :                 // IF block above in heating section. HeatPLR is not set in the ELSE part of the IF (only HeatCoilLoad is set).
    7762            0 :                 thisFurnace.HeatPartLoadRatio = 0.0;
    7763              :             }
    7764              : 
    7765              :             //*********HVAC Scheduled OFF*************
    7766              :             // No heating or cooling or dehumidification
    7767              :             //!!LKL discrepancy with < 0?
    7768        10378 :             if (thisFurnace.availSched->getCurrentVal() == 0.0 || state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate == 0.0) {
    7769           57 :                 thisFurnace.MdotFurnace = 0.0;
    7770           57 :                 CoolCoilLoad = 0.0;
    7771           57 :                 HeatCoilLoad = 0.0;
    7772           57 :                 ReheatCoilLoad = 0.0;
    7773           57 :                 state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0; // System off, so set on/off fan part-load fraction = 1
    7774           57 :                 thisFurnace.CoolPartLoadRatio = 0.0;
    7775           57 :                 thisFurnace.HeatPartLoadRatio = 0.0;
    7776           57 :                 thisFurnace.CompPartLoadRatio = 0.0;
    7777              :                 // set report variables
    7778           57 :                 thisFurnace.CoolingCoilSensDemand = 0.0;
    7779           57 :                 thisFurnace.CoolingCoilLatentDemand = 0.0;
    7780           57 :                 thisFurnace.HeatingCoilSensDemand = 0.0;
    7781              :             }
    7782              : 
    7783              :         } // End of the FirstHVACIteration control of the mass flow If block
    7784              : 
    7785              :         // Set the fan inlet node flow rates
    7786        15225 :         state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRateMaxAvail = thisFurnace.MdotFurnace;
    7787        15225 :         state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = thisFurnace.MdotFurnace;
    7788        15225 :     }
    7789              : 
    7790            0 :     void CalcWaterToAirHeatPump(EnergyPlusData &state,
    7791              :                                 int const FurnaceNum,                  // index to Furnace
    7792              :                                 bool const FirstHVACIteration,         // TRUE on first HVAC iteration
    7793              :                                 HVAC::CompressorOp const compressorOp, // compressor operation flag (1=On, 0=Off)
    7794              :                                 Real64 const ZoneLoad,                 // the control zone load (watts)
    7795              :                                 Real64 const MoistureLoad              // the control zone latent load (watts)
    7796              :     )
    7797              :     {
    7798              : 
    7799              :         // SUBROUTINE INFORMATION:
    7800              :         //       AUTHOR         Dan Fisher
    7801              :         //       DATE WRITTEN   Feb 2004
    7802              :         //       MODIFIED       R. Raustad (Oct 2006) Revised iteration technique
    7803              : 
    7804              :         // PURPOSE OF THIS SUBROUTINE:
    7805              :         // This subroutine manages the heat pump simulation
    7806              : 
    7807              :         // METHODOLOGY EMPLOYED:
    7808              :         // Calculate the part-load ratio required to meet the zone sensible load.
    7809              : 
    7810              :         // SUBROUTINE PARAMETER DEFINITIONS:
    7811            0 :         int constexpr MaxIter(600);   // maximum number of iterations
    7812            0 :         Real64 constexpr MinPLR(0.0); // minimum part load ratio allowed
    7813              : 
    7814              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    7815              :         Real64 ZoneSensLoadMet;             // Actual zone sensible load met by heat pump (W)
    7816              :         Real64 ZoneLatLoadMet;              // Actual zone latent load met by heat pump (W)
    7817              :         Real64 ZoneSensLoadMetFanONCompON;  // Max Zone sensible load heat pump can meet (W)
    7818              :         Real64 ZoneLatLoadMetFanONCompON;   // Max Zone latent load heat pump can meet (W)
    7819              :         Real64 ZoneSensLoadMetFanONCompOFF; // control zone sensible load met using only outside air
    7820              :         // and fan heat (no coil output) (W)
    7821              :         Real64 ZoneLatLoadMetFanONCompOFF; // control zone Latent   load met using only outside air
    7822              :         // and fan heat (no coil output) (W)
    7823              :         Real64 HPCoilSensDemand;   // Heat pump sensible demand
    7824              :         Real64 HPCoilSensCapacity; // Heat pump sensible capacity
    7825              : 
    7826              :         Real64 SuppHeatCoilLoad; // Load passed to supplemental heater (W)
    7827              :         Real64 CoolErrorToler;   // convergence tolerance used in cooling mode
    7828              :         Real64 HeatErrorToler;   // convergence tolerance used in heating mode
    7829              :         int SolFlag;             // flag returned from iteration routine to denote problems
    7830              : 
    7831            0 :         Real64 &TotalZoneLatentLoad = state.dataFurnaces->TotalZoneLatentLoad;
    7832            0 :         Real64 &TotalZoneSensLoad = state.dataFurnaces->TotalZoneSensLoad;
    7833            0 :         Real64 &CoolPartLoadRatio = state.dataFurnaces->CoolPartLoadRatio;
    7834            0 :         Real64 &HeatPartLoadRatio = state.dataFurnaces->HeatPartLoadRatio;
    7835            0 :         auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    7836              : 
    7837              :         // Set local variables
    7838            0 :         Real64 Dummy2 = 0.0;            // used as dummy heat and reheat coil load
    7839            0 :         Real64 OnOffAirFlowRatio = 1.0; // Ratio of compressor ON air mass flow to AVERAGE air mass flow over time step
    7840            0 :         int FurnaceInletNode = thisFurnace.FurnaceInletNodeNum;
    7841            0 :         HVAC::FanOp fanOp = thisFurnace.fanOp; // fan operating mode
    7842            0 :         thisFurnace.MdotFurnace = thisFurnace.DesignMassFlowRate;
    7843              : 
    7844              :         //*********INITIAL CALCULATIONS****************
    7845              :         // set the fan part load fraction
    7846              :         // Note: OnOffFanPartLoadFraction is passed to the
    7847              :         //       fan module by DataHVACGlobals.  It should be
    7848              :         //     set =1 for all cases except cycling fan/cycling
    7849              :         //     coil. For this case it is set to the part load
    7850              :         //     factor.  In SimOnOffFan, the part load ratio is
    7851              :         //     divided by the part load factor (OnOffFanPartLoadFraction)
    7852              :         //     in order to match the run time fraction of the cycling
    7853              :         //     fan with the run time fraction of the cycling compressor
    7854            0 :         if (FirstHVACIteration) state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
    7855              : 
    7856              :         // Calc Zone sensible loads for heating (+) and cooling (-)
    7857            0 :         TotalZoneSensLoad = ZoneLoad;
    7858              : 
    7859            0 :         if (state.dataFurnaces->HeatingLoad) {
    7860            0 :             TotalZoneLatentLoad = 0.0; // Set latent load for heating
    7861              :         } else {
    7862            0 :             TotalZoneLatentLoad = MoistureLoad; // Set latent load for cooling and no sensible load condition
    7863              :         }
    7864              : 
    7865              :         //*********COOLING CALCULATIONS****************
    7866              :         // IF scheduled on...
    7867              :         // AND air flow rate is greater than zero...
    7868              :         // AND the air system has a cooling load and is not set back or in the deadband...
    7869              :         // OR the system is controlled by a humidistat and there is a latent load
    7870            0 :         if ((thisFurnace.availSched->getCurrentVal() > 0.0 && state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate > 0.0) &&
    7871            0 :             ((state.dataFurnaces->CoolingLoad) || (thisFurnace.Humidistat && thisFurnace.CoolingCoilLatentDemand < 0.0))) {
    7872              : 
    7873              :             // Set the air flow rate to the design flow rate and set the fan operation fraction to 1 (continuous operation)
    7874            0 :             state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = thisFurnace.DesignMassFlowRate;
    7875            0 :             state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0; // see 'Note' under INITIAL CALCULATIONS
    7876              : 
    7877              :             //         !Set the operation flag to run the fan continuously
    7878              :             //         fanOp = FanOp::Continuous
    7879              : 
    7880              :             // Set the input parameters for CalcFurnaceOutput
    7881            0 :             thisFurnace.HeatingCoilSensDemand = 0.0;
    7882            0 :             thisFurnace.CoolingCoilLatentDemand = 0.0;
    7883            0 :             thisFurnace.CoolingCoilSensDemand = 0.0;
    7884            0 :             thisFurnace.CompPartLoadRatio = 0.0; // compressor off
    7885            0 :             thisFurnace.InitHeatPump = true;     // initialization call to Calc Furnace
    7886            0 :             CoolPartLoadRatio = 0.0;
    7887              : 
    7888              :             // Get no load result in order to calculate the effect of the fan and the mixed air equipment
    7889            0 :             CalcFurnaceOutput(state,
    7890              :                               FurnaceNum,
    7891              :                               FirstHVACIteration,
    7892              :                               fanOp,
    7893              :                               compressorOp,
    7894              :                               CoolPartLoadRatio,
    7895              :                               HeatPartLoadRatio,
    7896              :                               Dummy2,
    7897              :                               Dummy2,
    7898              :                               ZoneSensLoadMetFanONCompOFF,
    7899              :                               ZoneLatLoadMetFanONCompOFF,
    7900              :                               OnOffAirFlowRatio,
    7901              :                               false);
    7902              : 
    7903              :             // Set the input parameters for CalcFurnaceOutput
    7904            0 :             thisFurnace.CoolingCoilSensDemand = 1.0;
    7905            0 :             thisFurnace.CompPartLoadRatio = 1.0; // compressor ON
    7906            0 :             CoolPartLoadRatio = 1.0;
    7907              : 
    7908              :             // Get full load result in order to estimate the operating part load ratio for continuous fan operation
    7909            0 :             CalcFurnaceOutput(state,
    7910              :                               FurnaceNum,
    7911              :                               FirstHVACIteration,
    7912              :                               fanOp,
    7913              :                               compressorOp,
    7914              :                               CoolPartLoadRatio,
    7915              :                               HeatPartLoadRatio,
    7916              :                               Dummy2,
    7917              :                               Dummy2,
    7918              :                               ZoneSensLoadMetFanONCompON,
    7919              :                               ZoneLatLoadMetFanONCompON,
    7920              :                               OnOffAirFlowRatio,
    7921              :                               false);
    7922              : 
    7923              :             // Calculate the heating coil demand for continuous fan operation as:
    7924              :             //    (the zone sensible load - the zone sensible load met by fan heat and mixed air)
    7925              :             // Note; The sensible zone load met by fan heat and mixed air is calculated as:
    7926              :             //     mdotsys(control zone inlet enthalpy - control zone outlet enthalpy)
    7927              :             // This accounts for the negative sign in the equation.
    7928            0 :             HPCoilSensDemand = TotalZoneSensLoad - ZoneSensLoadMetFanONCompOFF;
    7929              : 
    7930              :             // Calculate the heating coil capacity for continuous fan operation as:
    7931              :             //    (the zone sensible load met by fan heat and mixed air and coil
    7932              :             //   - the zone sensible load met by fan heat and mixed air)
    7933            0 :             HPCoilSensCapacity = ZoneSensLoadMetFanONCompON - ZoneSensLoadMetFanONCompOFF;
    7934              : 
    7935              :             // Calculate the part load ratio for continuous fan operation with cycling coil
    7936            0 :             if (HPCoilSensCapacity == 0.0) {
    7937            0 :                 CoolPartLoadRatio = 0.0;
    7938              :             } else {
    7939            0 :                 CoolPartLoadRatio = max(MinPLR, min(1.0, std::abs(HPCoilSensDemand) / std::abs(HPCoilSensCapacity)));
    7940              :             }
    7941              : 
    7942            0 :             thisFurnace.InitHeatPump = false;
    7943              : 
    7944              :             // check bounds on sensible output prior to iteration using RegulaFalsi
    7945            0 :             if (ZoneSensLoadMetFanONCompON > TotalZoneSensLoad) {
    7946            0 :                 CoolPartLoadRatio = 1.0;
    7947            0 :                 HPCoilSensDemand = std::abs(ZoneSensLoadMetFanONCompON - ZoneSensLoadMetFanONCompOFF);
    7948            0 :                 thisFurnace.CoolingCoilSensDemand = HPCoilSensDemand;
    7949            0 :             } else if (ZoneSensLoadMetFanONCompOFF < TotalZoneSensLoad) {
    7950            0 :                 CoolPartLoadRatio = 0.0;
    7951            0 :                 thisFurnace.CompPartLoadRatio = 0.0; // compressor OFF
    7952            0 :                 thisFurnace.CoolingCoilSensDemand = 0.0;
    7953            0 :                 CalcFurnaceOutput(state,
    7954              :                                   FurnaceNum,
    7955              :                                   FirstHVACIteration,
    7956              :                                   fanOp,
    7957              :                                   compressorOp,
    7958              :                                   CoolPartLoadRatio,
    7959              :                                   HeatPartLoadRatio,
    7960              :                                   Dummy2,
    7961              :                                   Dummy2,
    7962              :                                   ZoneSensLoadMetFanONCompOFF,
    7963              :                                   ZoneLatLoadMetFanONCompOFF,
    7964              :                                   OnOffAirFlowRatio,
    7965              :                                   false);
    7966              :             } else {
    7967              :                 //         Calculate the sensible part load ratio through iteration
    7968            0 :                 CoolErrorToler = thisFurnace.CoolingConvergenceTolerance;
    7969            0 :                 SolFlag = 0; // # of iterations if positive, -1 means failed to converge, -2 means bounds are incorrect
    7970              :                 // CoolErrorToler is in fraction of load, MaxIter = 600, SolFalg = # of iterations or error as appropriate
    7971            0 :                 auto f = [&state, FurnaceNum, FirstHVACIteration, fanOp, compressorOp, TotalZoneSensLoad, ZoneSensLoadMetFanONCompOFF](
    7972              :                              Real64 const PartLoadRatio) {
    7973            0 :                     return CalcWaterToAirResidual(state,
    7974              :                                                   PartLoadRatio,
    7975              :                                                   FurnaceNum,
    7976              :                                                   FirstHVACIteration,
    7977              :                                                   fanOp,
    7978              :                                                   compressorOp,
    7979              :                                                   TotalZoneSensLoad,
    7980              :                                                   1.0,
    7981              :                                                   1.0,
    7982              :                                                   ZoneSensLoadMetFanONCompOFF,
    7983            0 :                                                   0.0);
    7984            0 :                 };
    7985            0 :                 General::SolveRoot(state, CoolErrorToler, MaxIter, SolFlag, CoolPartLoadRatio, f, 0.0, 1.0);
    7986            0 :                 if (SolFlag == -1 && !state.dataGlobal->WarmupFlag && !FirstHVACIteration) {
    7987            0 :                     state.dataHVACGlobal->OnOffFanPartLoadFraction = state.dataFurnaces->OnOffFanPartLoadFractionSave;
    7988            0 :                     CalcFurnaceOutput(state,
    7989              :                                       FurnaceNum,
    7990              :                                       FirstHVACIteration,
    7991              :                                       fanOp,
    7992              :                                       compressorOp,
    7993              :                                       CoolPartLoadRatio,
    7994              :                                       0.0,
    7995              :                                       0.0,
    7996              :                                       0.0,
    7997              :                                       ZoneSensLoadMet,
    7998              :                                       ZoneLatLoadMet,
    7999              :                                       OnOffAirFlowRatio,
    8000              :                                       false);
    8001            0 :                     if (std::abs(ZoneSensLoadMet - TotalZoneSensLoad) / TotalZoneSensLoad > CoolErrorToler) {
    8002            0 :                         if (thisFurnace.SensibleMaxIterIndex == 0) {
    8003            0 :                             ShowWarningMessage(state,
    8004            0 :                                                format("Cooling coil control failed to converge for {}:{}",
    8005            0 :                                                       HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    8006            0 :                                                       thisFurnace.Name));
    8007            0 :                             ShowContinueError(state, "  Iteration limit exceeded in calculating DX cooling coil sensible part-load ratio.");
    8008            0 :                             ShowContinueErrorTimeStamp(state,
    8009            0 :                                                        format("Sensible load to be met by DX coil = {:.2T} (watts), sensible output of DX coil = "
    8010              :                                                               "{:.2T} (watts), and the simulation continues.",
    8011              :                                                               TotalZoneSensLoad,
    8012              :                                                               ZoneSensLoadMet));
    8013              :                         }
    8014            0 :                         ShowRecurringWarningErrorAtEnd(
    8015              :                             state,
    8016            0 :                             format("{} \"{}\" - Iteration limit exceeded in calculating sensible cooling part-load ratio error "
    8017              :                                    "continues. Sensible load statistics:",
    8018            0 :                                    HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    8019            0 :                                    thisFurnace.Name),
    8020            0 :                             thisFurnace.SensibleMaxIterIndex,
    8021              :                             TotalZoneSensLoad,
    8022              :                             TotalZoneSensLoad);
    8023              :                     }
    8024            0 :                 } else if (SolFlag == -2 && !state.dataGlobal->WarmupFlag && !FirstHVACIteration) {
    8025            0 :                     CoolPartLoadRatio = max(MinPLR, min(1.0, std::abs(HPCoilSensDemand) / std::abs(HPCoilSensCapacity)));
    8026            0 :                     state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
    8027            0 :                     CalcFurnaceOutput(state,
    8028              :                                       FurnaceNum,
    8029              :                                       FirstHVACIteration,
    8030              :                                       fanOp,
    8031              :                                       compressorOp,
    8032              :                                       CoolPartLoadRatio,
    8033              :                                       0.0,
    8034              :                                       0.0,
    8035              :                                       0.0,
    8036              :                                       ZoneSensLoadMet,
    8037              :                                       ZoneLatLoadMet,
    8038              :                                       OnOffAirFlowRatio,
    8039              :                                       false);
    8040            0 :                     if ((ZoneSensLoadMet - TotalZoneSensLoad) / TotalZoneSensLoad > CoolErrorToler) {
    8041            0 :                         if (thisFurnace.SensibleRegulaFalsiFailedIndex == 0) {
    8042            0 :                             ShowWarningMessage(
    8043              :                                 state,
    8044            0 :                                 format("Cooling coil control failed for {}:{}", HVAC::unitarySysTypeNames[(int)thisFurnace.type], thisFurnace.Name));
    8045            0 :                             ShowContinueError(state, "  Cooling sensible part-load ratio determined to be outside the range of 0-1.");
    8046            0 :                             ShowContinueError(
    8047              :                                 state,
    8048            0 :                                 format("  An estimated part-load ratio = {:.2T} will be used and the simulation continues.", CoolPartLoadRatio));
    8049            0 :                             ShowContinueError(
    8050            0 :                                 state, format("  The estimated part-load ratio provides a cooling sensible capacity = {:.2T}", ZoneSensLoadMet));
    8051            0 :                             ShowContinueErrorTimeStamp(state, format("  Cooling sensible load required = {:.2T}", TotalZoneSensLoad));
    8052              :                         }
    8053            0 :                         ShowRecurringWarningErrorAtEnd(
    8054              :                             state,
    8055            0 :                             format("{} \"{}\" - Cooling sensible part-load ratio out of range error continues. Sensible cooling load statistics:",
    8056            0 :                                    HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    8057            0 :                                    thisFurnace.Name),
    8058            0 :                             thisFurnace.SensibleRegulaFalsiFailedIndex,
    8059              :                             TotalZoneSensLoad,
    8060              :                             TotalZoneSensLoad);
    8061              :                     }
    8062              :                 }
    8063              :             }
    8064              : 
    8065            0 :             if (fanOp == HVAC::FanOp::Cycling) {
    8066            0 :                 thisFurnace.MdotFurnace *= CoolPartLoadRatio;
    8067              :             }
    8068              : 
    8069              :             //*********HEATING CALCULATIONS****************
    8070              :             // If Furnace runs with a heating load then set HeatCoilLoad on Heating Coil and the Mass Flow
    8071            0 :         } else if ((thisFurnace.availSched->getCurrentVal() > 0.0) && (state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate > 0.0) &&
    8072            0 :                    state.dataFurnaces->HeatingLoad) {
    8073              : 
    8074              :             // Set the air flow rate to the design flow rate and set the fan operation fraction to 1 (continuous operation)
    8075            0 :             state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = thisFurnace.DesignMassFlowRate;
    8076            0 :             state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0; // see 'Note' under INITIAL CALCULATIONS
    8077              : 
    8078              :             //         !Set the operation flag to run the fan continuously
    8079              :             //         fanOp = FanOp::Continuous
    8080              : 
    8081              :             // Set the input parameters for CalcFurnaceOutput
    8082            0 :             thisFurnace.HeatingCoilSensDemand = 0.0;
    8083            0 :             thisFurnace.CoolingCoilLatentDemand = 0.0;
    8084            0 :             thisFurnace.CoolingCoilSensDemand = 0.0;
    8085            0 :             thisFurnace.CompPartLoadRatio = 0.0; // compressor off
    8086            0 :             thisFurnace.InitHeatPump = true;     // initialization call to Calc Furnace
    8087            0 :             HeatPartLoadRatio = 0.0;
    8088              : 
    8089              :             // Get no load result in order to calculate the effect of the fan and the mixed air equipment
    8090            0 :             CalcFurnaceOutput(state,
    8091              :                               FurnaceNum,
    8092              :                               FirstHVACIteration,
    8093              :                               fanOp,
    8094              :                               compressorOp,
    8095              :                               CoolPartLoadRatio,
    8096              :                               HeatPartLoadRatio,
    8097              :                               Dummy2,
    8098              :                               Dummy2,
    8099              :                               ZoneSensLoadMetFanONCompOFF,
    8100              :                               ZoneLatLoadMetFanONCompOFF,
    8101              :                               OnOffAirFlowRatio,
    8102              :                               false);
    8103              : 
    8104              :             // Set the input parameters for CalcFurnaceOutput
    8105            0 :             thisFurnace.HeatingCoilSensDemand = 1.0;
    8106            0 :             thisFurnace.CompPartLoadRatio = 1.0; // compressor ON
    8107            0 :             HeatPartLoadRatio = 1.0;
    8108              : 
    8109              :             // Get full load result in order to estimate the operating part load ratio for continuous fan operation
    8110              : 
    8111            0 :             CalcFurnaceOutput(state,
    8112              :                               FurnaceNum,
    8113              :                               FirstHVACIteration,
    8114              :                               fanOp,
    8115              :                               compressorOp,
    8116              :                               CoolPartLoadRatio,
    8117              :                               HeatPartLoadRatio,
    8118              :                               Dummy2,
    8119              :                               Dummy2,
    8120              :                               ZoneSensLoadMetFanONCompON,
    8121              :                               ZoneLatLoadMetFanONCompON,
    8122              :                               OnOffAirFlowRatio,
    8123              :                               false);
    8124              : 
    8125              :             // Calculate the heating coil demand for continuous fan operation as:
    8126              :             //    (the zone sensible load - the zone sensible load met by fan heat and mixed air)
    8127              :             // Note; The sensible zone load met by fan heat and mixed air is calculated as:
    8128              :             //     mdotsys(control zone inlet enthalpy - control zone outlet enthalpy)
    8129              :             // This accounts for the negative sign in the equation.
    8130            0 :             HPCoilSensDemand = TotalZoneSensLoad - ZoneSensLoadMetFanONCompOFF;
    8131              : 
    8132              :             // Calculate the heating coil capacity for continuous fan operation as:
    8133              :             //    (the zone sensible load met by fan heat and mixed air and coil
    8134              :             //   - the zone sensible load met by fan heat and mixed air)
    8135            0 :             HPCoilSensCapacity = ZoneSensLoadMetFanONCompON - ZoneSensLoadMetFanONCompOFF;
    8136              : 
    8137              :             // Calculate the part load ratio for continuous fan operation with cycling coil
    8138            0 :             if (HPCoilSensCapacity == 0.0) {
    8139            0 :                 HeatPartLoadRatio = 0.0;
    8140              :             } else {
    8141            0 :                 HeatPartLoadRatio = max(MinPLR, min(1.0, std::abs(HPCoilSensDemand) / std::abs(HPCoilSensCapacity)));
    8142              :             }
    8143              : 
    8144            0 :             thisFurnace.InitHeatPump = false;
    8145              : 
    8146              :             // check bounds on sensible output prior to iteration using RegulaFalsi
    8147            0 :             if (ZoneSensLoadMetFanONCompON < TotalZoneSensLoad) {
    8148            0 :                 HeatPartLoadRatio = 1.0;
    8149            0 :                 ZoneSensLoadMet = ZoneSensLoadMetFanONCompON;
    8150            0 :                 HPCoilSensDemand = std::abs(ZoneSensLoadMetFanONCompON - ZoneSensLoadMetFanONCompOFF);
    8151            0 :                 thisFurnace.HeatingCoilSensDemand = HPCoilSensDemand;
    8152            0 :             } else if (ZoneSensLoadMetFanONCompOFF > TotalZoneSensLoad) {
    8153            0 :                 HeatPartLoadRatio = 0.0;
    8154            0 :                 ZoneSensLoadMet = ZoneSensLoadMetFanONCompOFF;
    8155            0 :                 thisFurnace.CompPartLoadRatio = 0.0; // compressor ON
    8156            0 :                 CalcFurnaceOutput(state,
    8157              :                                   FurnaceNum,
    8158              :                                   FirstHVACIteration,
    8159              :                                   fanOp,
    8160              :                                   compressorOp,
    8161              :                                   CoolPartLoadRatio,
    8162              :                                   HeatPartLoadRatio,
    8163              :                                   Dummy2,
    8164              :                                   Dummy2,
    8165              :                                   ZoneSensLoadMet,
    8166              :                                   ZoneLatLoadMet,
    8167              :                                   OnOffAirFlowRatio,
    8168              :                                   false);
    8169              :             } else {
    8170              :                 //         Calculate the sensible part load ratio through iteration
    8171            0 :                 HeatErrorToler = thisFurnace.HeatingConvergenceTolerance;
    8172            0 :                 SolFlag = 0; // # of iterations if positive, -1 means failed to converge, -2 means bounds are incorrect
    8173              :                 // HeatErrorToler is in fraction of load, MaxIter = 600, SolFalg = # of iterations or error as appropriate
    8174            0 :                 auto f = [&state, FurnaceNum, FirstHVACIteration, fanOp, compressorOp, TotalZoneSensLoad, ZoneSensLoadMetFanONCompOFF](
    8175              :                              Real64 const PartLoadRatio) {
    8176            0 :                     return CalcWaterToAirResidual(state,
    8177              :                                                   PartLoadRatio,
    8178              :                                                   FurnaceNum,
    8179              :                                                   FirstHVACIteration,
    8180              :                                                   fanOp,
    8181              :                                                   compressorOp,
    8182              :                                                   TotalZoneSensLoad,
    8183              :                                                   0.0,
    8184              :                                                   1.0,
    8185              :                                                   ZoneSensLoadMetFanONCompOFF,
    8186            0 :                                                   0.0);
    8187            0 :                 };
    8188            0 :                 General::SolveRoot(state, HeatErrorToler, MaxIter, SolFlag, HeatPartLoadRatio, f, 0.0, 1.0);
    8189            0 :                 state.dataHVACGlobal->OnOffFanPartLoadFraction = state.dataFurnaces->OnOffFanPartLoadFractionSave;
    8190            0 :                 CalcFurnaceOutput(state,
    8191              :                                   FurnaceNum,
    8192              :                                   FirstHVACIteration,
    8193              :                                   fanOp,
    8194              :                                   compressorOp,
    8195              :                                   CoolPartLoadRatio,
    8196              :                                   HeatPartLoadRatio,
    8197              :                                   Dummy2,
    8198              :                                   Dummy2,
    8199              :                                   ZoneSensLoadMet,
    8200              :                                   ZoneLatLoadMet,
    8201              :                                   OnOffAirFlowRatio,
    8202              :                                   false);
    8203            0 :                 if (SolFlag == -1 && !state.dataGlobal->WarmupFlag && !FirstHVACIteration) {
    8204            0 :                     if (std::abs(ZoneSensLoadMet - TotalZoneSensLoad) / TotalZoneSensLoad > HeatErrorToler) {
    8205            0 :                         if (thisFurnace.WSHPHeatMaxIterIndex == 0) {
    8206            0 :                             ShowWarningMessage(state,
    8207            0 :                                                format("Heating coil control failed to converge for {}:{}",
    8208            0 :                                                       HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    8209            0 :                                                       thisFurnace.Name));
    8210            0 :                             ShowContinueError(state, "  Iteration limit exceeded in calculating DX heating coil sensible part-load ratio.");
    8211            0 :                             ShowContinueErrorTimeStamp(state,
    8212            0 :                                                        format("Sensible load to be met by DX coil = {:.2T} (watts), sensible output of DX coil = "
    8213              :                                                               "{:.2T} (watts), and the simulation continues.",
    8214              :                                                               TotalZoneSensLoad,
    8215              :                                                               ZoneSensLoadMet));
    8216              :                         }
    8217            0 :                         ShowRecurringWarningErrorAtEnd(
    8218              :                             state,
    8219            0 :                             format("{} \"{}\" - Iteration limit exceeded in calculating sensible heating part-load ratio error continues.",
    8220            0 :                                    HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    8221            0 :                                    thisFurnace.Name),
    8222            0 :                             thisFurnace.WSHPHeatMaxIterIndex,
    8223              :                             TotalZoneSensLoad,
    8224              :                             TotalZoneSensLoad);
    8225              :                     }
    8226            0 :                 } else if (SolFlag == -2) {
    8227            0 :                     HeatPartLoadRatio = max(MinPLR, min(1.0, std::abs(HPCoilSensDemand) / std::abs(HPCoilSensCapacity)));
    8228            0 :                     CalcFurnaceOutput(state,
    8229              :                                       FurnaceNum,
    8230              :                                       FirstHVACIteration,
    8231              :                                       fanOp,
    8232              :                                       compressorOp,
    8233              :                                       0.0,
    8234              :                                       HeatPartLoadRatio,
    8235              :                                       0.0,
    8236              :                                       0.0,
    8237              :                                       ZoneSensLoadMet,
    8238              :                                       ZoneLatLoadMet,
    8239              :                                       OnOffAirFlowRatio,
    8240              :                                       false);
    8241            0 :                     if ((ZoneSensLoadMet - TotalZoneSensLoad) / TotalZoneSensLoad > HeatErrorToler) {
    8242            0 :                         if (thisFurnace.WSHPHeatRegulaFalsiFailedIndex == 0) {
    8243            0 :                             ShowWarningError(
    8244              :                                 state,
    8245            0 :                                 format("Heating coil control failed for {}:{}", HVAC::unitarySysTypeNames[(int)thisFurnace.type], thisFurnace.Name));
    8246            0 :                             ShowContinueError(state, "  Heating sensible part-load ratio determined to be outside the range of 0-1.");
    8247            0 :                             ShowContinueError(
    8248              :                                 state,
    8249            0 :                                 format("  An estimated part-load ratio = {:.2T} will be used and the simulation continues.", HeatPartLoadRatio));
    8250            0 :                             ShowContinueError(
    8251            0 :                                 state, format("  The estimated part-load ratio provides a heating sensible capacity = {:.2T}", ZoneSensLoadMet));
    8252            0 :                             ShowContinueErrorTimeStamp(state, format("  Heating sensible load required = {:.2T}", TotalZoneSensLoad));
    8253              :                         }
    8254            0 :                         ShowRecurringWarningErrorAtEnd(state,
    8255            0 :                                                        format("{} \"{}\" - Heating sensible part-load ratio out of range error continues.",
    8256            0 :                                                               HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    8257            0 :                                                               thisFurnace.Name),
    8258            0 :                                                        thisFurnace.WSHPHeatRegulaFalsiFailedIndex,
    8259              :                                                        TotalZoneSensLoad,
    8260              :                                                        TotalZoneSensLoad);
    8261              :                     }
    8262              :                 }
    8263              :             }
    8264              : 
    8265              :             //       CALL supplemental heater if required
    8266            0 :             if ((TotalZoneSensLoad - ZoneSensLoadMet) > HVAC::SmallLoad && HeatPartLoadRatio >= 1.0) {
    8267            0 :                 SuppHeatCoilLoad = TotalZoneSensLoad - ZoneSensLoadMet;
    8268            0 :                 CalcFurnaceOutput(state,
    8269              :                                   FurnaceNum,
    8270              :                                   FirstHVACIteration,
    8271              :                                   fanOp,
    8272              :                                   compressorOp,
    8273              :                                   CoolPartLoadRatio,
    8274              :                                   HeatPartLoadRatio,
    8275              :                                   SuppHeatCoilLoad,
    8276              :                                   Dummy2,
    8277              :                                   ZoneSensLoadMet,
    8278              :                                   ZoneLatLoadMet,
    8279              :                                   OnOffAirFlowRatio,
    8280              :                                   false);
    8281              :             }
    8282              : 
    8283            0 :             if (fanOp == HVAC::FanOp::Cycling) {
    8284            0 :                 thisFurnace.MdotFurnace *= HeatPartLoadRatio;
    8285              :             }
    8286              : 
    8287              :             //**********HVAC Scheduled ON, but no cooling, dehumidification or heating load*********
    8288            0 :         } else if (thisFurnace.availSched->getCurrentVal() > 0.0) {
    8289            0 :             thisFurnace.InitHeatPump = true; // initialization call to Calc Furnace
    8290            0 :             HeatPartLoadRatio = 0.0;
    8291            0 :             CoolPartLoadRatio = 0.0;
    8292            0 :             state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0; //! see 'Note' under INITIAL CALCULATIONS
    8293              :             // set report variables
    8294            0 :             thisFurnace.CompPartLoadRatio = 0.0;
    8295            0 :             thisFurnace.CoolingCoilSensDemand = 0.0;
    8296            0 :             thisFurnace.CoolingCoilLatentDemand = 0.0;
    8297            0 :             thisFurnace.HeatingCoilSensDemand = 0.0;
    8298            0 :             if (fanOp == HVAC::FanOp::Cycling) {
    8299            0 :                 thisFurnace.MdotFurnace = 0.0;
    8300            0 :                 state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0; // see 'Note' under INITIAL CALCULATIONS
    8301            0 :                 CalcFurnaceOutput(state,
    8302              :                                   FurnaceNum,
    8303              :                                   FirstHVACIteration,
    8304              :                                   fanOp,
    8305              :                                   compressorOp,
    8306              :                                   CoolPartLoadRatio,
    8307              :                                   HeatPartLoadRatio,
    8308              :                                   Dummy2,
    8309              :                                   Dummy2,
    8310              :                                   ZoneSensLoadMet,
    8311              :                                   ZoneLatLoadMet,
    8312              :                                   OnOffAirFlowRatio,
    8313              :                                   false);
    8314            0 :                 thisFurnace.MdotFurnace = 0.0;
    8315              :             } else { // continuous fan, cycling coil
    8316            0 :                 CalcFurnaceOutput(state,
    8317              :                                   FurnaceNum,
    8318              :                                   FirstHVACIteration,
    8319              :                                   fanOp,
    8320              :                                   compressorOp,
    8321              :                                   CoolPartLoadRatio,
    8322              :                                   HeatPartLoadRatio,
    8323              :                                   Dummy2,
    8324              :                                   Dummy2,
    8325              :                                   ZoneSensLoadMet,
    8326              :                                   ZoneLatLoadMet,
    8327              :                                   OnOffAirFlowRatio,
    8328              :                                   false);
    8329              :             }
    8330              :             //*********No heating or cooling or dehumidification*********
    8331              :         } else {
    8332            0 :             thisFurnace.InitHeatPump = true; // initialization call to Calc Furnace
    8333            0 :             thisFurnace.MdotFurnace = 0.0;
    8334            0 :             HeatPartLoadRatio = 0.0;
    8335            0 :             CoolPartLoadRatio = 0.0;
    8336            0 :             state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0; // see 'Note' under INITIAL CALCULATIONS
    8337            0 :             thisFurnace.CompPartLoadRatio = 0.0;
    8338            0 :             thisFurnace.CoolingCoilSensDemand = 0.0;
    8339            0 :             thisFurnace.CoolingCoilLatentDemand = 0.0;
    8340            0 :             thisFurnace.HeatingCoilSensDemand = 0.0;
    8341            0 :             CalcFurnaceOutput(state,
    8342              :                               FurnaceNum,
    8343              :                               FirstHVACIteration,
    8344              :                               fanOp,
    8345              :                               compressorOp,
    8346              :                               CoolPartLoadRatio,
    8347              :                               HeatPartLoadRatio,
    8348              :                               Dummy2,
    8349              :                               Dummy2,
    8350              :                               ZoneSensLoadMet,
    8351              :                               ZoneLatLoadMet,
    8352              :                               OnOffAirFlowRatio,
    8353              :                               false);
    8354            0 :             thisFurnace.MdotFurnace = 0.0;
    8355              :         }
    8356              : 
    8357              :         // Set the fan inlet node flow rates
    8358            0 :         state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRateMaxAvail = thisFurnace.MdotFurnace;
    8359            0 :         state.dataLoopNodes->Node(FurnaceInletNode).MassFlowRate = thisFurnace.MdotFurnace;
    8360            0 :     }
    8361              : 
    8362        56349 :     void CalcFurnaceOutput(EnergyPlusData &state,
    8363              :                            int const FurnaceNum,
    8364              :                            bool const FirstHVACIteration,
    8365              :                            HVAC::FanOp const fanOp,               // Cycling fan or constant fan
    8366              :                            HVAC::CompressorOp const compressorOp, // Compressor on/off; 1=on, 0=off
    8367              :                            Real64 const CoolPartLoadRatio,        // DX cooling coil part load ratio
    8368              :                            Real64 const HeatPartLoadRatio,        // DX heating coil part load ratio (0 for other heating coil types)
    8369              :                            Real64 const HeatCoilLoad,             // Heating coil load for gas heater
    8370              :                            Real64 const ReheatCoilLoad,           // Reheating coil load for gas heater
    8371              :                            Real64 &SensibleLoadMet,               // Sensible cooling load met (furnace outlet with respect to control zone temp)
    8372              :                            Real64 &LatentLoadMet,              // Latent cooling load met (furnace outlet with respect to control zone humidity ratio)
    8373              :                            Real64 &OnOffAirFlowRatio,          // Ratio of compressor ON mass flow rate to AVERAGE
    8374              :                            bool const HXUnitOn,                // flag to enable HX based on zone moisture load
    8375              :                            Real64 const CoolingHeatingPLRRatio // cooling PLR to heating PLR ratio, used for cycling fan RH control
    8376              :     )
    8377              :     {
    8378              : 
    8379              :         // SUBROUTINE INFORMATION:
    8380              :         //       AUTHOR         Richard Raustad
    8381              :         //       DATE WRITTEN   Sept 2001
    8382              :         //       MODIFIED       Dec 2001
    8383              : 
    8384              :         // PURPOSE OF THIS SUBROUTINE:
    8385              :         // This subroutine calculates to sensible and latent loads met by the DX coils
    8386              :         // specified.  Load met is the outlet node with respect to the control zone's
    8387              :         // temperature and humidity ratio.
    8388              : 
    8389              :         // METHODOLOGY EMPLOYED:
    8390              :         // Simulate each child object in the correct order for each system type. This routine is used in the
    8391              :         // RegulaFalsi function CALL. Air mass flow rate is set each iteration based on PLR.
    8392              : 
    8393        56349 :         auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    8394        56349 :         auto &inletNode = state.dataLoopNodes->Node(thisFurnace.FurnaceInletNodeNum);
    8395        56349 :         int CoolingCoilType_Num = thisFurnace.CoolingCoilType_Num;
    8396        56349 :         Real64 QActual = 0.0; // heating coil load met or delivered
    8397        56349 :         state.dataFurnaces->ModifiedHeatCoilLoad = 0.0;
    8398              : 
    8399        56349 :         state.dataFurnaces->CoolHeatPLRRat = CoolingHeatingPLRRatio;
    8400              : 
    8401              :         // Cooling to Heating PLR Ratio (CoolHeatPLRRat) is used to track the air mass flow rate of both the heating
    8402              :         // and cooling coils when RH control is used and the heating coil operates longer than the cooling coil.
    8403              :         // When CoolPartLoadRatio/CoolHeatPLRRat is used, the PLR calculated is actually the PLR for the heating
    8404              :         // coil (heating PLR is greater than cooling PLR), it is this PLR that determines the air mass flow rate.
    8405              :         // When MAX(HeatPartLoadRatio,CoolPartLoadRatio) is used, only one of these values is non-zero.
    8406        56349 :         if (fanOp == HVAC::FanOp::Cycling) {
    8407        56345 :             if (state.dataFurnaces->CoolHeatPLRRat < 1.0) {
    8408            0 :                 if (state.dataFurnaces->CoolHeatPLRRat > 0.0) {
    8409            0 :                     inletNode.MassFlowRate = state.dataFurnaces->CompOnMassFlow * CoolPartLoadRatio / state.dataFurnaces->CoolHeatPLRRat;
    8410            0 :                     if (thisFurnace.type != HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir) {
    8411            0 :                         SetAverageAirFlow(state, FurnaceNum, CoolPartLoadRatio / state.dataFurnaces->CoolHeatPLRRat, OnOffAirFlowRatio);
    8412              :                     }
    8413              :                 } else {
    8414            0 :                     inletNode.MassFlowRate = state.dataFurnaces->CompOnMassFlow * CoolPartLoadRatio;
    8415            0 :                     if (thisFurnace.type != HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir) {
    8416            0 :                         SetAverageAirFlow(state, FurnaceNum, max(HeatPartLoadRatio, CoolPartLoadRatio), OnOffAirFlowRatio);
    8417              :                     }
    8418              :                 }
    8419              :             } else {
    8420        56345 :                 inletNode.MassFlowRate = state.dataFurnaces->CompOnMassFlow * max(HeatPartLoadRatio, CoolPartLoadRatio);
    8421        56345 :                 if (thisFurnace.type != HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir) {
    8422        56345 :                     SetAverageAirFlow(state, FurnaceNum, max(HeatPartLoadRatio, CoolPartLoadRatio), OnOffAirFlowRatio);
    8423              :                 }
    8424              :             }
    8425              :         } else {
    8426            4 :             if (thisFurnace.type != HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir) {
    8427            0 :                 SetAverageAirFlow(state, FurnaceNum, max(HeatPartLoadRatio, CoolPartLoadRatio), OnOffAirFlowRatio);
    8428              :             }
    8429              :         }
    8430              : 
    8431        56349 :         inletNode.MassFlowRateMaxAvail = inletNode.MassFlowRate;
    8432              : 
    8433              :         // Simulate the air-to-air heat pump
    8434        56349 :         if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_AirToAir) {
    8435              :             //   Simulate blow-thru fan and non-linear coils twice to update PLF used by the ONOFF Fan
    8436        56345 :             if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
    8437        56345 :                 state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
    8438        56345 :                 if (CoolingCoilType_Num == HVAC::CoilDX_CoolingHXAssisted) {
    8439            0 :                     HVACHXAssistedCoolingCoil::SimHXAssistedCoolingCoil(state,
    8440              :                                                                         BlankString,
    8441              :                                                                         FirstHVACIteration,
    8442              :                                                                         compressorOp,
    8443              :                                                                         CoolPartLoadRatio,
    8444            0 :                                                                         thisFurnace.CoolingCoilIndex,
    8445              :                                                                         fanOp,
    8446              :                                                                         HXUnitOn,
    8447              :                                                                         OnOffAirFlowRatio,
    8448            0 :                                                                         state.dataFurnaces->EconomizerFlag);
    8449              :                 } else {
    8450       112690 :                     DXCoils::SimDXCoil(state,
    8451              :                                        BlankString,
    8452              :                                        compressorOp,
    8453              :                                        FirstHVACIteration,
    8454        56345 :                                        thisFurnace.CoolingCoilIndex,
    8455              :                                        fanOp,
    8456              :                                        CoolPartLoadRatio,
    8457              :                                        OnOffAirFlowRatio);
    8458              :                 }
    8459       112690 :                 DXCoils::SimDXCoil(
    8460        56345 :                     state, BlankString, compressorOp, FirstHVACIteration, thisFurnace.HeatingCoilIndex, fanOp, HeatPartLoadRatio, OnOffAirFlowRatio);
    8461        56345 :                 state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
    8462              :             }
    8463              :             //   Simulate cooling and heating coils
    8464        56345 :             if (CoolingCoilType_Num == HVAC::CoilDX_CoolingHXAssisted) {
    8465            0 :                 HVACHXAssistedCoolingCoil::SimHXAssistedCoolingCoil(state,
    8466              :                                                                     BlankString,
    8467              :                                                                     FirstHVACIteration,
    8468              :                                                                     compressorOp,
    8469              :                                                                     CoolPartLoadRatio,
    8470            0 :                                                                     thisFurnace.CoolingCoilIndex,
    8471              :                                                                     fanOp,
    8472              :                                                                     HXUnitOn,
    8473              :                                                                     OnOffAirFlowRatio,
    8474            0 :                                                                     state.dataFurnaces->EconomizerFlag);
    8475              :             } else {
    8476       112690 :                 DXCoils::SimDXCoil(
    8477        56345 :                     state, BlankString, compressorOp, FirstHVACIteration, thisFurnace.CoolingCoilIndex, fanOp, CoolPartLoadRatio, OnOffAirFlowRatio);
    8478              :             }
    8479       112690 :             DXCoils::SimDXCoil(
    8480        56345 :                 state, BlankString, compressorOp, FirstHVACIteration, thisFurnace.HeatingCoilIndex, fanOp, HeatPartLoadRatio, OnOffAirFlowRatio);
    8481              :             //   Simulate the draw-thru fan
    8482        56345 :             if (thisFurnace.fanPlace == HVAC::FanPlace::DrawThru) {
    8483            0 :                 state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
    8484              :             }
    8485              :             //   Simulate the supplemental heating coil
    8486        56345 :             if (thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat && ReheatCoilLoad > 0.0) {
    8487            0 :                 bool SuppHeatingCoilFlag = true;
    8488            0 :                 CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, ReheatCoilLoad, fanOp, QActual);
    8489            0 :             } else {
    8490              :                 // equivalent to QCoilReq=0.0d0 or ReHeatCoilLoad = 0.0d0
    8491        56345 :                 bool SuppHeatingCoilFlag = true;
    8492        56345 :                 CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, ReheatCoilLoad, fanOp, QActual);
    8493              :             }
    8494              :             // Simulate the parameter estimate water-to-air heat pump
    8495            4 :         } else if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir && thisFurnace.WatertoAirHPType == WAHPCoilType::Simple) {
    8496              :             //    Simulate blow-thru fan and non-linear coils twice to update PLF used by the ONOFF Fan
    8497            4 :             if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
    8498            0 :                 state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
    8499              :                 // COIL:WATERTOAIRHPSIMPLE:COOLING
    8500            0 :                 WaterToAirHeatPumpSimple::SimWatertoAirHPSimple(state,
    8501              :                                                                 BlankString,
    8502            0 :                                                                 thisFurnace.CoolingCoilIndex,
    8503              :                                                                 thisFurnace.CoolingCoilSensDemand,
    8504              :                                                                 thisFurnace.CoolingCoilLatentDemand,
    8505              :                                                                 fanOp,
    8506              :                                                                 compressorOp,
    8507              :                                                                 CoolPartLoadRatio,
    8508              :                                                                 FirstHVACIteration); // CoolPartLoadRatio
    8509            0 :                 Real64 Dummy = 0.0;
    8510              :                 // COIL:WATERTOAIRHPSIMPLE:HEATING
    8511            0 :                 WaterToAirHeatPumpSimple::SimWatertoAirHPSimple(state,
    8512              :                                                                 BlankString,
    8513            0 :                                                                 thisFurnace.HeatingCoilIndex,
    8514              :                                                                 thisFurnace.HeatingCoilSensDemand,
    8515              :                                                                 Dummy,
    8516              :                                                                 fanOp,
    8517              :                                                                 compressorOp,
    8518              :                                                                 HeatPartLoadRatio,
    8519              :                                                                 FirstHVACIteration); // HeatPartLoadRatio
    8520              :                 //      Simulate the whole thing a second time so that the correct PLF required by the coils is used by the Fan. *******
    8521            0 :                 state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
    8522              :             }
    8523              :             //    Simulate the cooling and heating coils
    8524              :             // COIL:WATERTOAIRHPSIMPLE:COOLING
    8525            4 :             WaterToAirHeatPumpSimple::SimWatertoAirHPSimple(state,
    8526              :                                                             BlankString,
    8527            4 :                                                             thisFurnace.CoolingCoilIndex,
    8528              :                                                             thisFurnace.CoolingCoilSensDemand,
    8529              :                                                             thisFurnace.CoolingCoilLatentDemand,
    8530              :                                                             fanOp,
    8531              :                                                             compressorOp,
    8532              :                                                             CoolPartLoadRatio,
    8533              :                                                             FirstHVACIteration); // CoolPartLoadRatio
    8534            4 :             Real64 Dummy = 0.0;
    8535              :             // COIL:WATERTOAIRHPSIMPLE:HEATING
    8536            4 :             WaterToAirHeatPumpSimple::SimWatertoAirHPSimple(state,
    8537              :                                                             BlankString,
    8538            4 :                                                             thisFurnace.HeatingCoilIndex,
    8539              :                                                             thisFurnace.HeatingCoilSensDemand,
    8540              :                                                             Dummy,
    8541              :                                                             fanOp,
    8542              :                                                             compressorOp,
    8543              :                                                             HeatPartLoadRatio,
    8544              :                                                             FirstHVACIteration); // HeatPartLoadRatio
    8545              :             //     Simulate the draw-thru fan
    8546            4 :             if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
    8547            0 :                 state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
    8548              :             }
    8549              :             //     Simulate the supplemental heating coil
    8550            4 :             if (thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat && ReheatCoilLoad > 0.0) {
    8551            0 :                 bool SuppHeatingCoilFlag = true; // if true simulates supplemental heating coil
    8552            0 :                 CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, ReheatCoilLoad, fanOp, QActual);
    8553            0 :             } else {
    8554            4 :                 bool SuppHeatingCoilFlag = true; // if true simulates supplemental heating coil
    8555            4 :                 CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, fanOp, QActual);
    8556              :             }
    8557              :             // Simulate the detailed water-to-air heat pump
    8558            4 :         } else if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir && thisFurnace.WatertoAirHPType == WAHPCoilType::ParEst) {
    8559              :             //    Simulate the draw-thru fan
    8560            0 :             if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
    8561            0 :                 state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
    8562              :             }
    8563              :             //    Simulate the cooling and heating coils
    8564            0 :             WaterToAirHeatPump::SimWatertoAirHP(state,
    8565              :                                                 BlankString,
    8566            0 :                                                 thisFurnace.CoolingCoilIndex,
    8567              :                                                 thisFurnace.DesignMassFlowRate,
    8568              :                                                 fanOp,
    8569              :                                                 FirstHVACIteration,
    8570            0 :                                                 thisFurnace.InitHeatPump,
    8571              :                                                 thisFurnace.CoolingCoilSensDemand,
    8572              :                                                 thisFurnace.CoolingCoilLatentDemand,
    8573              :                                                 compressorOp,
    8574              :                                                 CoolPartLoadRatio);
    8575            0 :             Real64 Dummy = 0.0;
    8576            0 :             WaterToAirHeatPump::SimWatertoAirHP(state,
    8577              :                                                 BlankString,
    8578            0 :                                                 thisFurnace.HeatingCoilIndex,
    8579              :                                                 thisFurnace.DesignMassFlowRate,
    8580              :                                                 fanOp,
    8581              :                                                 FirstHVACIteration,
    8582            0 :                                                 thisFurnace.InitHeatPump,
    8583              :                                                 thisFurnace.HeatingCoilSensDemand,
    8584              :                                                 Dummy,
    8585              :                                                 compressorOp,
    8586              :                                                 HeatPartLoadRatio);
    8587              :             //    Simulate the draw-thru fan
    8588            0 :             if (thisFurnace.fanPlace == HVAC::FanPlace::DrawThru) {
    8589            0 :                 state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
    8590              :             }
    8591              :             //    Simulate the supplemental heating coil
    8592            0 :             HeatingCoils::SimulateHeatingCoilComponents(
    8593            0 :                 state, BlankString, FirstHVACIteration, HeatCoilLoad, thisFurnace.SuppHeatCoilIndex, _, true, fanOp);
    8594              : 
    8595            0 :         } else { // ELSE it's not a heat pump
    8596              :             //   Simulate blow-thru fan
    8597            0 :             if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
    8598              : 
    8599            0 :                 state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
    8600              : 
    8601              :                 //     For non-linear coils, simulate coil to update PLF used by the ONOFF Fan
    8602            0 :                 if (thisFurnace.fanType == HVAC::FanType::OnOff) {
    8603            0 :                     if (thisFurnace.type != HVAC::UnitarySysType::Unitary_HeatOnly && thisFurnace.type != HVAC::UnitarySysType::Furnace_HeatOnly) {
    8604              : 
    8605            0 :                         if (!thisFurnace.CoolingCoilUpstream) {
    8606            0 :                             bool SuppHeatingCoilFlag = false; // if false simulates heating coil
    8607            0 :                             CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, fanOp, QActual);
    8608              :                         }
    8609              : 
    8610            0 :                         if (CoolingCoilType_Num == HVAC::CoilDX_CoolingHXAssisted) {
    8611            0 :                             HVACHXAssistedCoolingCoil::SimHXAssistedCoolingCoil(state,
    8612              :                                                                                 BlankString,
    8613              :                                                                                 FirstHVACIteration,
    8614              :                                                                                 compressorOp,
    8615              :                                                                                 CoolPartLoadRatio,
    8616            0 :                                                                                 thisFurnace.CoolingCoilIndex,
    8617              :                                                                                 fanOp,
    8618              :                                                                                 HXUnitOn,
    8619              :                                                                                 OnOffAirFlowRatio,
    8620            0 :                                                                                 state.dataFurnaces->EconomizerFlag);
    8621              :                         } else {
    8622            0 :                             DXCoils::SimDXCoil(state,
    8623              :                                                BlankString,
    8624              :                                                compressorOp,
    8625              :                                                FirstHVACIteration,
    8626            0 :                                                thisFurnace.CoolingCoilIndex,
    8627              :                                                fanOp,
    8628              :                                                CoolPartLoadRatio,
    8629              :                                                OnOffAirFlowRatio,
    8630            0 :                                                state.dataFurnaces->CoolHeatPLRRat);
    8631              :                         }
    8632              :                     }
    8633              : 
    8634            0 :                     if (thisFurnace.CoolingCoilUpstream) {
    8635            0 :                         bool SuppHeatingCoilFlag = false; // if false simulates heating coil
    8636            0 :                         CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, fanOp, QActual);
    8637              :                     }
    8638            0 :                     state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
    8639              :                 } // Simple OnOff fan
    8640              : 
    8641              :             } // Blow thru fan
    8642              : 
    8643              :             //   Simulate the cooling and heating coils
    8644            0 :             if (thisFurnace.type != HVAC::UnitarySysType::Unitary_HeatOnly && thisFurnace.type != HVAC::UnitarySysType::Furnace_HeatOnly) {
    8645              : 
    8646            0 :                 if (!thisFurnace.CoolingCoilUpstream) {
    8647            0 :                     bool SuppHeatingCoilFlag = false; // if false simulates heating coil
    8648            0 :                     CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, fanOp, QActual);
    8649              :                 }
    8650              : 
    8651            0 :                 if (CoolingCoilType_Num == HVAC::CoilDX_CoolingHXAssisted) {
    8652            0 :                     HVACHXAssistedCoolingCoil::SimHXAssistedCoolingCoil(state,
    8653              :                                                                         BlankString,
    8654              :                                                                         FirstHVACIteration,
    8655              :                                                                         compressorOp,
    8656              :                                                                         CoolPartLoadRatio,
    8657            0 :                                                                         thisFurnace.CoolingCoilIndex,
    8658              :                                                                         fanOp,
    8659              :                                                                         HXUnitOn,
    8660              :                                                                         OnOffAirFlowRatio,
    8661            0 :                                                                         state.dataFurnaces->EconomizerFlag);
    8662              :                 } else {
    8663            0 :                     DXCoils::SimDXCoil(state,
    8664              :                                        BlankString,
    8665              :                                        compressorOp,
    8666              :                                        FirstHVACIteration,
    8667            0 :                                        thisFurnace.CoolingCoilIndex,
    8668              :                                        fanOp,
    8669              :                                        CoolPartLoadRatio,
    8670              :                                        OnOffAirFlowRatio,
    8671            0 :                                        state.dataFurnaces->CoolHeatPLRRat);
    8672              :                 }
    8673              :             }
    8674              : 
    8675            0 :             if (thisFurnace.CoolingCoilUpstream) {
    8676            0 :                 bool SuppHeatingCoilFlag = false; // if false simulates heating coil
    8677            0 :                 CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, fanOp, QActual);
    8678              :             }
    8679              :             //   Simulate the draw-thru fan
    8680            0 :             if (thisFurnace.fanPlace == HVAC::FanPlace::DrawThru) {
    8681            0 :                 state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
    8682              :             }
    8683            0 :             if (thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat || thisFurnace.SuppHeatCoilIndex > 0) {
    8684            0 :                 bool SuppHeatingCoilFlag = true; // if true simulates supplemental heating coil
    8685            0 :                 CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, ReheatCoilLoad, fanOp, QActual);
    8686              :             }
    8687              :         } // IF(Furnace(FurnaceNum)%type == UnitarySys_HeatPump_AirToAir)THEN
    8688              : 
    8689              :         // Get mass flow rate after components are simulated
    8690        56349 :         auto &outletNode = state.dataLoopNodes->Node(thisFurnace.FurnaceOutletNodeNum);
    8691        56349 :         Real64 AirMassFlow = inletNode.MassFlowRate; // this should be outlet node as in 9897?
    8692              : 
    8693              :         // check the DesignMaxOutletTemp and reset if necessary (for Coil:Gas:Heating or Coil:Electric:Heating only)
    8694        56349 :         if (outletNode.Temp > thisFurnace.DesignMaxOutletTemp) {
    8695            0 :             Real64 Wout = outletNode.HumRat;
    8696            0 :             Real64 Tout = thisFurnace.DesignMaxOutletTemp;
    8697            0 :             state.dataFurnaces->ModifiedHeatCoilLoad = HeatCoilLoad - (AirMassFlow * Psychrometrics::PsyCpAirFnW(Wout) * (outletNode.Temp - Tout));
    8698            0 :             outletNode.Temp = Tout;
    8699              :         }
    8700              : 
    8701              :         // If the fan runs continually do not allow coils to set OnOffFanPartLoadRatio.
    8702        56349 :         if (fanOp == HVAC::FanOp::Continuous) state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
    8703              : 
    8704        56349 :         Real64 SensibleOutput = 0.0; // sensible output rate, {W}
    8705        56349 :         Real64 LatentOutput = 0.0;   // latent output rate, {W}
    8706        56349 :         Real64 TotalOutput = 0.0;    // total output rate, {W}
    8707       112698 :         CalcZoneSensibleLatentOutput(AirMassFlow,
    8708              :                                      outletNode.Temp,
    8709              :                                      outletNode.HumRat,
    8710        56349 :                                      state.dataLoopNodes->Node(thisFurnace.NodeNumOfControlledZone).Temp,
    8711        56349 :                                      state.dataLoopNodes->Node(thisFurnace.NodeNumOfControlledZone).HumRat,
    8712              :                                      SensibleOutput,
    8713              :                                      LatentOutput,
    8714              :                                      TotalOutput);
    8715        56349 :         SensibleLoadMet = SensibleOutput - thisFurnace.SenLoadLoss;
    8716        56349 :         thisFurnace.SensibleLoadMet = SensibleLoadMet;
    8717              : 
    8718        56349 :         if (thisFurnace.Humidistat) {
    8719            0 :             LatentLoadMet = LatentOutput - thisFurnace.LatLoadLoss;
    8720              :         } else {
    8721        56349 :             LatentLoadMet = 0.0;
    8722              :         }
    8723        56349 :         thisFurnace.LatentLoadMet = LatentLoadMet;
    8724        56349 :     }
    8725              : 
    8726              :     //        End of Update subroutines for the Furnace Module
    8727              :     // *****************************************************************************
    8728              : 
    8729        20268 :     Real64 CalcFurnaceResidual(EnergyPlusData &state,
    8730              :                                Real64 const PartLoadRatio, // DX cooling coil part load ratio
    8731              :                                int FurnaceNum,
    8732              :                                bool FirstHVACIteration,
    8733              :                                HVAC::FanOp const fanOp,
    8734              :                                HVAC::CompressorOp compressorOp,
    8735              :                                Real64 LoadToBeMet,
    8736              :                                Real64 par6_loadFlag,
    8737              :                                Real64 par7_sensLatentFlag,
    8738              :                                Real64 par9_HXOnFlag,
    8739              :                                Real64 par10_HeatingCoilPLR)
    8740              :     {
    8741              : 
    8742              :         // FUNCTION INFORMATION:
    8743              :         //       AUTHOR         Richard Raustad
    8744              :         //       DATE WRITTEN   Feb 2005
    8745              : 
    8746              :         // PURPOSE OF THIS SUBROUTINE:
    8747              :         // To calculate the part-load ratio for cooling and heating coils
    8748              : 
    8749              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    8750              :         Real64 CoolPartLoadRatio;      // DX cooling coil part load ratio
    8751              :         Real64 HeatPartLoadRatio;      // DX heating coil part load ratio (0 for other heating coil types)
    8752              :         Real64 HeatCoilLoad;           // Heating coil load for gas heater
    8753              :         Real64 SensibleLoadMet;        // Sensible cooling load met (furnace outlet with respect to control zone temp)
    8754              :         Real64 LatentLoadMet;          // Latent cooling load met (furnace outlet with respect to control zone humidity ratio)
    8755              :         Real64 OnOffAirFlowRatio;      // Ratio of compressor ON air mass flow to AVERAGE air mass flow over time step
    8756              :         Real64 CoolingHeatingPLRRatio; // ratio of cooling PLR to heating PLR, used for cycling fan RH control
    8757              :         bool HXUnitOn;                 // flag to enable HX based on zone moisture load
    8758              : 
    8759              :         //        // Convert parameters to usable variables
    8760              :         //        int FurnaceNum = int(Par(1));
    8761              :         //        bool FirstHVACIteration = Par(2) == 1.0;
    8762              :         //        int FanfanOp = int(Par(3));
    8763              :         //        CompressorOperation CompressorOp = static_cast<CompressorOperation>(Par(4));
    8764              :         //        Real64 LoadToBeMet = Par(5);
    8765              :         //        Real64 par6_loadFlag = Par(6);
    8766              :         //        Real64 par7_sensLatentFlag = Par(7);
    8767              :         //        Real64 par9_HXOnFlag = Par(9);
    8768              :         //        Real64 par10_HeatingCoilPLR = Par(10);
    8769              : 
    8770        20268 :         if (par6_loadFlag == 1.0) {
    8771        20244 :             CoolPartLoadRatio = PartLoadRatio;
    8772        20244 :             HeatPartLoadRatio = 0.0;
    8773        20244 :             HeatCoilLoad = 0.0;
    8774              :         } else {
    8775           24 :             CoolPartLoadRatio = 0.0;
    8776           24 :             HeatPartLoadRatio = PartLoadRatio;
    8777              : 
    8778           24 :             int const HeatingCoilType_Num(state.dataFurnaces->Furnace(FurnaceNum).HeatingCoilType_Num);
    8779           24 :             if (HeatingCoilType_Num == HVAC::Coil_HeatingGasOrOtherFuel || HeatingCoilType_Num == HVAC::Coil_HeatingElectric ||
    8780           24 :                 HeatingCoilType_Num == HVAC::Coil_HeatingWater || HeatingCoilType_Num == HVAC::Coil_HeatingSteam) {
    8781            0 :                 HeatCoilLoad = state.dataFurnaces->Furnace(FurnaceNum).DesignHeatingCapacity * PartLoadRatio;
    8782              :             } else {
    8783           24 :                 HeatCoilLoad = 0.0;
    8784              :             }
    8785              :         }
    8786              : 
    8787              :         //  OnOffAirFlowRatio = Par(8)
    8788        20268 :         if (state.dataFurnaces->Furnace(FurnaceNum).type == HVAC::UnitarySysType::Unitary_HeatPump_WaterToAir) {
    8789            0 :             state.dataFurnaces->Furnace(FurnaceNum).CompPartLoadRatio = PartLoadRatio;
    8790              :         }
    8791              : 
    8792        20268 :         if (par9_HXOnFlag == 1.0) {
    8793        20244 :             HXUnitOn = true;
    8794              :         } else {
    8795           24 :             HXUnitOn = false;
    8796              :         }
    8797              : 
    8798        20268 :         if (par10_HeatingCoilPLR > 0.0) {
    8799              :             //    Par(10) = Furnace(FurnaceNum)%HeatPartLoadRatio
    8800              :             //    FanOp = CycFan and Furnace(FurnaceNum)%HeatPartLoadRatio must be > 0 for Part(10) to be greater than 0
    8801              :             //    This variable used when in heating mode and dehumidification (cooling) is required.
    8802            0 :             CoolingHeatingPLRRatio = min(1.0, CoolPartLoadRatio / state.dataFurnaces->Furnace(FurnaceNum).HeatPartLoadRatio);
    8803              :         } else {
    8804        20268 :             CoolingHeatingPLRRatio = 1.0;
    8805              :         }
    8806              : 
    8807              :         // Subroutine arguments
    8808        20268 :         CalcFurnaceOutput(state,
    8809              :                           FurnaceNum,
    8810              :                           FirstHVACIteration,
    8811              :                           fanOp,
    8812              :                           compressorOp,
    8813              :                           CoolPartLoadRatio,
    8814              :                           HeatPartLoadRatio,
    8815              :                           HeatCoilLoad,
    8816              :                           0.0,
    8817              :                           SensibleLoadMet,
    8818              :                           LatentLoadMet,
    8819              :                           OnOffAirFlowRatio,
    8820              :                           HXUnitOn,
    8821              :                           CoolingHeatingPLRRatio);
    8822              : 
    8823              :         // Calculate residual based on output calculation flag
    8824        20268 :         if (par7_sensLatentFlag == 1.0) {
    8825        20268 :             if (LoadToBeMet == 0.0) {
    8826            0 :                 return (SensibleLoadMet - LoadToBeMet) / 100.0;
    8827              :             } else {
    8828        20268 :                 return (SensibleLoadMet - LoadToBeMet) / LoadToBeMet;
    8829              :             }
    8830              :         } else {
    8831            0 :             if (LoadToBeMet == 0.0) {
    8832            0 :                 return (LatentLoadMet - LoadToBeMet) / 100.0;
    8833              :             } else {
    8834            0 :                 return (LatentLoadMet - LoadToBeMet) / LoadToBeMet;
    8835              :             }
    8836              :         }
    8837              :     }
    8838              : 
    8839            0 :     Real64 CalcWaterToAirResidual(EnergyPlusData &state,
    8840              :                                   Real64 const PartLoadRatio, // DX cooling coil part load ratio
    8841              :                                   int FurnaceNum,
    8842              :                                   bool FirstHVACIteration,
    8843              :                                   HVAC::FanOp const fanOp,
    8844              :                                   HVAC::CompressorOp compressorOp,
    8845              :                                   Real64 LoadToBeMet,
    8846              :                                   Real64 par6_loadTypeFlag,
    8847              :                                   Real64 par7_latentOrSensible,
    8848              :                                   Real64 ZoneSensLoadMetFanONCompOFF,
    8849              :                                   Real64 par9_HXUnitOne)
    8850              :     {
    8851              : 
    8852              :         // FUNCTION INFORMATION:
    8853              :         //       AUTHOR         Richard Raustad
    8854              :         //       DATE WRITTEN   October 2006
    8855              : 
    8856              :         // PURPOSE OF THIS SUBROUTINE:
    8857              :         // To calculate the part-load ratio for water to air HP's
    8858              :         // this is used for parameter estimation WAHPs but not equation fit WAHPs
    8859              : 
    8860              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    8861              :         Real64 CoolPartLoadRatio; // DX cooling coil part load ratio
    8862              :         Real64 HeatPartLoadRatio; // DX heating coil part load ratio (0 for other heating coil types)
    8863              :         Real64 HeatCoilLoad;      // Heating coil load for gas heater
    8864              :         Real64 ZoneSensLoadMet;   // Sensible cooling load met (furnace outlet with respect to control zone temp)
    8865              :         Real64 ZoneLatLoadMet;    // Latent cooling load met (furnace outlet with respect to control zone humidity ratio)
    8866              :         Real64 Dummy;
    8867              :         Real64 HPCoilSensDemand;
    8868              :         Real64 OnOffAirFlowRatio;
    8869              :         bool HXUnitOn; // flag to enable HX based on zone moisture load (not valid for water-to-air HP's
    8870              : 
    8871              :         // Convert parameters to usable variables
    8872              :         //        int FurnaceNum = int(Par[0]);
    8873              :         //        bool FirstHVACIteration = Par[1] == 1.0;
    8874              :         //        int FanOp = int(Par[2]);
    8875              :         //        CompressorOperation CompressorOp = static_cast<CompressorOperation>(Par[3]);
    8876              :         //        Real64 LoadToBeMet = Par[4];
    8877              :         //        Real64 par6_loadTypeFlag = Par[5];
    8878              :         //        Real64 par7_latentOrSensible = Par[6];
    8879              :         //        Real64 ZoneSensLoadMetFanONCompOFF = Par[7];
    8880              :         //        Real64 par9_HXUnitOne = Par[8];
    8881              : 
    8882              :         int CoilIndex;
    8883            0 :         if (par6_loadTypeFlag == 1.0) {
    8884            0 :             CoolPartLoadRatio = PartLoadRatio;
    8885            0 :             HeatPartLoadRatio = 0.0;
    8886            0 :             HeatCoilLoad = 0.0;
    8887            0 :             CoilIndex = state.dataFurnaces->Furnace(FurnaceNum).CoolingCoilIndex;
    8888              :         } else {
    8889            0 :             CoolPartLoadRatio = 0.0;
    8890            0 :             HeatPartLoadRatio = PartLoadRatio;
    8891            0 :             CoilIndex = state.dataFurnaces->Furnace(FurnaceNum).HeatingCoilIndex;
    8892              :         }
    8893              : 
    8894              :         // Get child component RuntimeFrac
    8895              :         Real64 RuntimeFrac;
    8896            0 :         switch (state.dataFurnaces->Furnace(FurnaceNum).WatertoAirHPType) {
    8897            0 :         case WAHPCoilType::Simple: {
    8898            0 :             RuntimeFrac = state.dataWaterToAirHeatPumpSimple->SimpleWatertoAirHP(CoilIndex).RunFrac;
    8899            0 :             break;
    8900              :         }
    8901            0 :         case WAHPCoilType::ParEst: {
    8902            0 :             RuntimeFrac = state.dataWaterToAirHeatPump->WatertoAirHP(CoilIndex).RunFrac;
    8903            0 :             break;
    8904              :         }
    8905            0 :         case WAHPCoilType::VarSpeedEquationFit: {
    8906            0 :             RuntimeFrac = state.dataVariableSpeedCoils->VarSpeedCoil(CoilIndex).RunFrac;
    8907            0 :             break;
    8908              :         }
    8909            0 :         default:
    8910            0 :             RuntimeFrac = 1.0; // Programming error. Assert failure?
    8911              :         }
    8912              : 
    8913            0 :         state.dataFurnaces->OnOffFanPartLoadFractionSave = state.dataHVACGlobal->OnOffFanPartLoadFraction;
    8914              :         // update fan and compressor run times
    8915            0 :         state.dataFurnaces->Furnace(FurnaceNum).CompPartLoadRatio = PartLoadRatio;
    8916              : 
    8917              :         // Calculate the heating coil demand as (the zone sensible load - load met by fan heat and mixed air)
    8918              :         // Note; The load met by fan heat and mixed air is calculated as mdot(zoneinletenthalpy-zoneoutletenthalpy)
    8919              :         // This accounts for the negative sign in the equation.
    8920              : 
    8921              :         // Calculate the heat coil sensible capacity as the load met by the system with the fan and compressor on less
    8922              :         // the load met by the system with the compressor off.
    8923              :         //  HPCoilSensCapacity = ZoneSensLoadMetFanONCompON - ZoneSensLoadMetFanONCompOFF
    8924              : 
    8925              :         // Set input parameters for heat pump coil model
    8926            0 :         HPCoilSensDemand = LoadToBeMet - RuntimeFrac * ZoneSensLoadMetFanONCompOFF;
    8927              :         //  HPCoilSensDemand = LoadToBeMet  - PartLoadRatio*ZoneSensLoadMetFanONCompOFF
    8928            0 :         if (par6_loadTypeFlag == 1.0) {
    8929            0 :             state.dataFurnaces->Furnace(FurnaceNum).HeatingCoilSensDemand = 0.0;
    8930            0 :             state.dataFurnaces->Furnace(FurnaceNum).CoolingCoilSensDemand = std::abs(HPCoilSensDemand);
    8931              :         } else {
    8932            0 :             state.dataFurnaces->Furnace(FurnaceNum).HeatingCoilSensDemand = HPCoilSensDemand;
    8933            0 :             state.dataFurnaces->Furnace(FurnaceNum).CoolingCoilSensDemand = 0.0;
    8934              :         }
    8935            0 :         state.dataFurnaces->Furnace(FurnaceNum).InitHeatPump = false; // initialization call to Calc Furnace
    8936              : 
    8937              :         // Calculate the zone loads met and the new part load ratio and for the specified run time
    8938            0 :         Dummy = 0.0;
    8939            0 :         OnOffAirFlowRatio = 1.0;
    8940            0 :         if (par9_HXUnitOne == 1.0) {
    8941            0 :             HXUnitOn = true;
    8942              :         } else {
    8943            0 :             HXUnitOn = false;
    8944              :         }
    8945              : 
    8946              :         //  Subroutine arguments
    8947              :         //  CALL CalcFurnaceOutput(FurnaceNum,FirstHVACIteration,FanOp,compressorOp,CoolPartLoadRatio,&
    8948              :         //                         HeatPartLoadRatio, HeatCoilLoad, ReHeatCoilLoad, SensibleLoadMet, LatentLoadMet, HXUnitOn)
    8949            0 :         CalcFurnaceOutput(state,
    8950              :                           FurnaceNum,
    8951              :                           FirstHVACIteration,
    8952              :                           fanOp,
    8953              :                           compressorOp,
    8954              :                           CoolPartLoadRatio,
    8955              :                           HeatPartLoadRatio,
    8956              :                           Dummy,
    8957              :                           Dummy,
    8958              :                           ZoneSensLoadMet,
    8959              :                           ZoneLatLoadMet,
    8960              :                           OnOffAirFlowRatio,
    8961              :                           HXUnitOn);
    8962              : 
    8963              :         // Calculate residual based on output calculation flag
    8964            0 :         if (par7_latentOrSensible == 1.0) {
    8965            0 :             return (ZoneSensLoadMet - LoadToBeMet) / LoadToBeMet;
    8966              :         } else {
    8967            0 :             return (ZoneLatLoadMet - LoadToBeMet) / LoadToBeMet;
    8968              :         }
    8969              :     }
    8970              : 
    8971        97113 :     void SetAverageAirFlow(EnergyPlusData &state,
    8972              :                            int const FurnaceNum,       // Unit index
    8973              :                            Real64 const PartLoadRatio, // unit part load ratio
    8974              :                            Real64 &OnOffAirFlowRatio   // ratio of compressor ON airflow to AVERAGE airflow over timestep
    8975              :     )
    8976              :     {
    8977              : 
    8978              :         // SUBROUTINE INFORMATION:
    8979              :         //       AUTHOR         Richard Raustad
    8980              :         //       DATE WRITTEN   July 2005
    8981              : 
    8982              :         // PURPOSE OF THIS SUBROUTINE:
    8983              :         // Set the average air mass flow rates using the part-load fraction of the HVAC system for this time step
    8984              :         // Set OnOffAirFlowRatio to be used by DX coils
    8985              : 
    8986              :         // METHODOLOGY EMPLOYED:
    8987              :         // The air flow rate in cooling, heating, and no cooling or heating can be different.
    8988              :         // Calculate the air flow rate based on initializations made in InitFurnace.
    8989              : 
    8990        97113 :         int InletNode = state.dataFurnaces->Furnace(FurnaceNum).FurnaceInletNodeNum;
    8991              :         Real64 AverageUnitMassFlow =
    8992        97113 :             (PartLoadRatio * state.dataFurnaces->CompOnMassFlow) + ((1 - PartLoadRatio) * state.dataFurnaces->CompOffMassFlow);
    8993        97113 :         if (state.dataFurnaces->CompOffFlowRatio > 0.0) {
    8994            4 :             state.dataFurnaces->FanSpeedRatio =
    8995            4 :                 (PartLoadRatio * state.dataFurnaces->CompOnFlowRatio) + ((1 - PartLoadRatio) * state.dataFurnaces->CompOffFlowRatio);
    8996              :         } else {
    8997        97109 :             state.dataFurnaces->FanSpeedRatio = state.dataFurnaces->CompOnFlowRatio;
    8998              :         }
    8999              : 
    9000              :         // IF the furnace is scheduled on or nightime cycle overrides fan schedule. Uses same logic as fan.
    9001       291339 :         if (state.dataFurnaces->Furnace(FurnaceNum).availSched->getCurrentVal() > 0.0 &&
    9002        97113 :             ((state.dataFurnaces->Furnace(FurnaceNum).fanAvailSched->getCurrentVal() > 0.0 || state.dataHVACGlobal->TurnFansOn) &&
    9003        97113 :              !state.dataHVACGlobal->TurnFansOff)) {
    9004        97107 :             state.dataLoopNodes->Node(InletNode).MassFlowRate = AverageUnitMassFlow;
    9005        97107 :             state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail = AverageUnitMassFlow;
    9006        97107 :             if (AverageUnitMassFlow > 0.0) {
    9007        66059 :                 OnOffAirFlowRatio = state.dataFurnaces->CompOnMassFlow / AverageUnitMassFlow;
    9008              :             } else {
    9009        31048 :                 OnOffAirFlowRatio = 0.0;
    9010              :             }
    9011              :         } else {
    9012            6 :             state.dataLoopNodes->Node(InletNode).MassFlowRate = 0.0;
    9013            6 :             OnOffAirFlowRatio = 1.0;
    9014              :         }
    9015              : 
    9016        97113 :         state.dataFurnaces->Furnace(FurnaceNum).MdotFurnace = state.dataFurnaces->CompOnMassFlow;
    9017        97113 :         state.dataFurnaces->OnOffAirFlowRatioSave = OnOffAirFlowRatio;
    9018        97113 :     }
    9019              : 
    9020              :     // Beginning of Reporting subroutines for the Furnace Module
    9021              :     // *****************************************************************************
    9022              : 
    9023        15224 :     void ReportFurnace(EnergyPlusData &state, int const FurnaceNum, int const AirLoopNum)
    9024              :     {
    9025              : 
    9026              :         // SUBROUTINE INFORMATION:
    9027              :         //       AUTHOR         Richard Liesen
    9028              :         //       DATE WRITTEN   Feb 2001
    9029              : 
    9030              :         // PURPOSE OF THIS SUBROUTINE:
    9031              :         // This subroutine updates the report variable for the coils.
    9032              : 
    9033              :         // METHODOLOGY EMPLOYED:
    9034              :         // Update fan part-load ratio based on mass flow rate ratio.
    9035              :         // Update global variables used by AirflowNetwork module.
    9036              : 
    9037              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    9038              :         Real64 ratio;
    9039              :         Real64 OnOffRatio;
    9040        15224 :         auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    9041              : 
    9042              :         // Report the Furnace Fan Part Load Ratio
    9043        15224 :         if (thisFurnace.NumOfSpeedCooling < 1) {
    9044        15224 :             if (thisFurnace.DesignMassFlowRate > 0.0) {
    9045        15224 :                 thisFurnace.FanPartLoadRatio = thisFurnace.MdotFurnace / thisFurnace.DesignMassFlowRate;
    9046              :             } else {
    9047            0 :                 thisFurnace.FanPartLoadRatio = 0.0;
    9048              :             }
    9049              :         }
    9050              : 
    9051              :         // Set mass flow rates during on and off cycle using an OnOff fan
    9052        15224 :         if (state.afn->distribution_simulated) {
    9053        11170 :             state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopSystemOnMassFlowrate = state.dataFurnaces->CompOnMassFlow;
    9054        11170 :             state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopSystemOffMassFlowrate = state.dataFurnaces->CompOffMassFlow;
    9055        11170 :             state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopFanOperationMode = thisFurnace.fanOp;
    9056        11170 :             state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopOnOffFanPartLoadRatio = thisFurnace.FanPartLoadRatio;
    9057        11170 :             OnOffRatio = state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopOnOffFanPartLoadRatio;
    9058        11170 :             if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatPump_AirToAir) {
    9059        11169 :                 state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopOnOffFanPartLoadRatio =
    9060        11169 :                     max(thisFurnace.FanPartLoadRatio, thisFurnace.HeatPartLoadRatio, thisFurnace.CoolPartLoadRatio);
    9061        11169 :                 state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopOnOffFanPartLoadRatio =
    9062        11169 :                     min(1.0, state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopOnOffFanPartLoadRatio);
    9063              :             }
    9064        11170 :             if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatCool) {
    9065            1 :                 if (thisFurnace.HeatPartLoadRatio == 0.0 && thisFurnace.CoolPartLoadRatio == 0.0 && thisFurnace.FanPartLoadRatio > 0.0) {
    9066            2 :                     if (state.dataFurnaces->CompOnMassFlow < max(thisFurnace.MaxCoolAirMassFlow, thisFurnace.MaxHeatAirMassFlow) &&
    9067            1 :                         state.dataFurnaces->CompOnMassFlow > 0.0) {
    9068            1 :                         ratio = max(thisFurnace.MaxCoolAirMassFlow, thisFurnace.MaxHeatAirMassFlow) / state.dataFurnaces->CompOnMassFlow;
    9069            1 :                         state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopOnOffFanPartLoadRatio =
    9070            1 :                             state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopOnOffFanPartLoadRatio * ratio;
    9071              :                     }
    9072              :                 }
    9073              :             }
    9074              :         }
    9075        15224 :         if (thisFurnace.FirstPass) {
    9076            3 :             if (!state.dataGlobal->SysSizingCalc) {
    9077            3 :                 DataSizing::resetHVACSizingGlobals(state, 0, state.dataSize->CurSysNum, thisFurnace.FirstPass);
    9078              :             }
    9079              :         }
    9080        15224 :         state.dataHVACGlobal->OnOffFanPartLoadFraction =
    9081              :             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)
    9082        15224 :     }
    9083              : 
    9084        71571 :     void CalcNonDXHeatingCoils(EnergyPlusData &state,
    9085              :                                int const FurnaceNum,           // Furnace Index
    9086              :                                bool const SuppHeatingCoilFlag, // .TRUE. if supplemental heating coil
    9087              :                                bool const FirstHVACIteration,  // flag for first HVAC iteration in the time step
    9088              :                                Real64 const QCoilLoad,         // load met by unit (watts)
    9089              :                                HVAC::FanOp const fanOp,        // fan operation mode
    9090              :                                Real64 &HeatCoilLoadmet         // Heating Load Met
    9091              :     )
    9092              :     {
    9093              :         // SUBROUTINE INFORMATION:
    9094              :         //       AUTHOR         Bereket Nigusse, FSEC/UCF
    9095              :         //       DATE WRITTEN   January 2012
    9096              : 
    9097              :         // PURPOSE OF THIS SUBROUTINE:
    9098              :         // This subroutine simulates the four non dx heating coil types: Gas, Electric, hot water and steam.
    9099              : 
    9100              :         // METHODOLOGY EMPLOYED:
    9101              :         // Simply calls the different heating coil component.  The hot water flow rate matching the coil load
    9102              :         // is calculated iteratively.
    9103              : 
    9104              :         // SUBROUTINE PARAMETER DEFINITIONS:
    9105        71571 :         Real64 constexpr ErrTolerance(0.001); // convergence limit for hotwater coil
    9106        71571 :         int constexpr SolveMaxIter(50);
    9107              : 
    9108              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    9109              :         Real64 mdot;              // heating coil steam or hot water mass flow rate
    9110              :         Real64 MinWaterFlow;      // coil minimum hot water mass flow rate, kg/s
    9111              :         Real64 MaxHotWaterFlow;   // coil maximum hot water mass flow rate, kg/s
    9112              :         Real64 HotWaterMdot;      // actual hot water mass flow rate
    9113        71571 :         int CoilTypeNum(0);       // heating coil type number
    9114        71571 :         int HeatingCoilIndex(0);  // heating coil index
    9115        71571 :         int CoilControlNode(0);   // control node for hot water and steam heating coils
    9116        71571 :         int CoilOutletNode(0);    // air outlet node of the heating coils
    9117        71571 :         PlantLocation plantLoc{}; // plant loop location
    9118              : 
    9119        71571 :         Real64 QActual = 0.0;                                               // actual heating load
    9120        71571 :         std::string &HeatingCoilName = state.dataFurnaces->HeatingCoilName; // name of heating coil
    9121        71571 :         auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    9122              : 
    9123        71571 :         if (SuppHeatingCoilFlag) {
    9124        71571 :             HeatingCoilName = thisFurnace.SuppHeatCoilName;
    9125        71571 :             HeatingCoilIndex = thisFurnace.SuppHeatCoilIndex;
    9126        71571 :             CoilControlNode = thisFurnace.SuppCoilControlNode;
    9127        71571 :             CoilOutletNode = thisFurnace.SuppCoilOutletNode;
    9128        71571 :             CoilTypeNum = thisFurnace.SuppHeatCoilType_Num;
    9129        71571 :             plantLoc = thisFurnace.SuppPlantLoc;
    9130        71571 :             MaxHotWaterFlow = thisFurnace.MaxSuppCoilFluidFlow;
    9131              :         } else {
    9132            0 :             HeatingCoilName = thisFurnace.HeatingCoilName;
    9133            0 :             HeatingCoilIndex = thisFurnace.HeatingCoilIndex;
    9134            0 :             CoilControlNode = thisFurnace.CoilControlNode;
    9135            0 :             CoilOutletNode = thisFurnace.CoilOutletNode;
    9136            0 :             CoilTypeNum = thisFurnace.HeatingCoilType_Num;
    9137            0 :             plantLoc = thisFurnace.plantLoc;
    9138            0 :             MaxHotWaterFlow = thisFurnace.MaxHeatCoilFluidFlow;
    9139              :         }
    9140              : 
    9141        71571 :         switch (CoilTypeNum) {
    9142        71567 :         case HVAC::Coil_HeatingGasOrOtherFuel:
    9143              :         case HVAC::Coil_HeatingElectric:
    9144              :         case HVAC::Coil_HeatingDesuperheater: {
    9145        71567 :             HeatingCoils::SimulateHeatingCoilComponents(
    9146              :                 state, HeatingCoilName, FirstHVACIteration, QCoilLoad, HeatingCoilIndex, QActual, SuppHeatingCoilFlag, fanOp);
    9147        71567 :         } break;
    9148            0 :         case HVAC::Coil_HeatingWater: {
    9149            0 :             if (QCoilLoad > HVAC::SmallLoad) {
    9150            0 :                 PlantUtilities::SetComponentFlowRate(state, MaxHotWaterFlow, CoilControlNode, CoilOutletNode, plantLoc);
    9151            0 :                 WaterCoils::SimulateWaterCoilComponents(state, HeatingCoilName, FirstHVACIteration, HeatingCoilIndex, QActual, fanOp);
    9152              : 
    9153            0 :                 if (QActual > (QCoilLoad + HVAC::SmallLoad)) {
    9154              :                     // control water flow to obtain output matching QCoilLoad
    9155            0 :                     MinWaterFlow = 0.0;
    9156            0 :                     auto f = [&state, FurnaceNum, FirstHVACIteration, QCoilLoad, SuppHeatingCoilFlag](Real64 const HWFlow) {
    9157            0 :                         Real64 QCoilRequested = QCoilLoad;
    9158              : 
    9159              :                         // FUNCTION LOCAL VARIABLE DECLARATIONS:
    9160              :                         Real64 QCoilActual;   // delivered coil load, W
    9161            0 :                         Real64 mdot = HWFlow; // to get non-const argument
    9162            0 :                         QCoilActual = QCoilRequested;
    9163            0 :                         if (!SuppHeatingCoilFlag) {
    9164            0 :                             PlantUtilities::SetComponentFlowRate(state,
    9165              :                                                                  mdot,
    9166            0 :                                                                  state.dataFurnaces->Furnace(FurnaceNum).CoilControlNode,
    9167            0 :                                                                  state.dataFurnaces->Furnace(FurnaceNum).CoilOutletNode,
    9168            0 :                                                                  state.dataFurnaces->Furnace(FurnaceNum).plantLoc);
    9169            0 :                             WaterCoils::SimulateWaterCoilComponents(state,
    9170            0 :                                                                     state.dataFurnaces->Furnace(FurnaceNum).HeatingCoilName,
    9171              :                                                                     FirstHVACIteration,
    9172            0 :                                                                     state.dataFurnaces->Furnace(FurnaceNum).HeatingCoilIndex,
    9173              :                                                                     QCoilActual,
    9174            0 :                                                                     state.dataFurnaces->Furnace(FurnaceNum).fanOp);
    9175              :                         } else {
    9176              :                             // supplemental coil
    9177            0 :                             PlantUtilities::SetComponentFlowRate(state,
    9178              :                                                                  mdot,
    9179            0 :                                                                  state.dataFurnaces->Furnace(FurnaceNum).SuppCoilControlNode,
    9180            0 :                                                                  state.dataFurnaces->Furnace(FurnaceNum).SuppCoilOutletNode,
    9181            0 :                                                                  state.dataFurnaces->Furnace(FurnaceNum).SuppPlantLoc);
    9182              :                             // simulate the hot water supplemental heating coil
    9183            0 :                             WaterCoils::SimulateWaterCoilComponents(state,
    9184            0 :                                                                     state.dataFurnaces->Furnace(FurnaceNum).SuppHeatCoilName,
    9185              :                                                                     FirstHVACIteration,
    9186            0 :                                                                     state.dataFurnaces->Furnace(FurnaceNum).SuppHeatCoilIndex,
    9187              :                                                                     QCoilActual,
    9188            0 :                                                                     state.dataFurnaces->Furnace(FurnaceNum).fanOp);
    9189              :                         }
    9190            0 :                         return QCoilRequested != 0.0 ? (QCoilActual - QCoilRequested) / QCoilRequested : 0.0;
    9191            0 :                     };
    9192            0 :                     int SolFlag = 0;
    9193            0 :                     General::SolveRoot(state, ErrTolerance, SolveMaxIter, SolFlag, HotWaterMdot, f, MinWaterFlow, MaxHotWaterFlow);
    9194            0 :                     if (SolFlag == -1) {
    9195            0 :                         if (thisFurnace.HotWaterCoilMaxIterIndex == 0) {
    9196            0 :                             ShowWarningMessage(state,
    9197            0 :                                                format("CalcNonDXHeatingCoils: Hot water coil control failed for {}=\"{}\"",
    9198            0 :                                                       HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    9199            0 :                                                       thisFurnace.Name));
    9200            0 :                             ShowContinueErrorTimeStamp(state, "");
    9201            0 :                             ShowContinueError(state, format("  Iteration limit [{}] exceeded in calculating hot water mass flow rate", SolveMaxIter));
    9202              :                         }
    9203            0 :                         ShowRecurringWarningErrorAtEnd(
    9204              :                             state,
    9205            0 :                             format("CalcNonDXHeatingCoils: Hot water coil control failed (iteration limit [{}]) for {}=\"{}",
    9206              :                                    SolveMaxIter,
    9207            0 :                                    HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    9208            0 :                                    thisFurnace.Name),
    9209            0 :                             thisFurnace.HotWaterCoilMaxIterIndex);
    9210            0 :                     } else if (SolFlag == -2) {
    9211            0 :                         if (thisFurnace.HotWaterCoilMaxIterIndex2 == 0) {
    9212            0 :                             ShowWarningMessage(state,
    9213            0 :                                                format("CalcNonDXHeatingCoils: Hot water coil control failed (maximum flow limits) for {}=\"{}\"",
    9214            0 :                                                       HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    9215            0 :                                                       thisFurnace.Name));
    9216            0 :                             ShowContinueErrorTimeStamp(state, "");
    9217            0 :                             ShowContinueError(state, "...Bad hot water maximum flow rate limits");
    9218            0 :                             ShowContinueError(state, format("...Given minimum water flow rate={:.3R} kg/s", MinWaterFlow));
    9219            0 :                             ShowContinueError(state, format("...Given maximum water flow rate={:.3R} kg/s", MaxHotWaterFlow));
    9220              :                         }
    9221            0 :                         ShowRecurringWarningErrorAtEnd(state,
    9222            0 :                                                        format("CalcNonDXHeatingCoils: Hot water coil control failed (flow limits) for {}=\"{}\"",
    9223            0 :                                                               HVAC::unitarySysTypeNames[(int)thisFurnace.type],
    9224            0 :                                                               thisFurnace.Name),
    9225            0 :                                                        thisFurnace.HotWaterCoilMaxIterIndex2,
    9226              :                                                        MaxHotWaterFlow,
    9227              :                                                        MinWaterFlow,
    9228              :                                                        _,
    9229              :                                                        "[kg/s]",
    9230              :                                                        "[kg/s]");
    9231              :                     }
    9232              :                 }
    9233              :             } else {
    9234            0 :                 mdot = 0.0;
    9235            0 :                 PlantUtilities::SetComponentFlowRate(state, mdot, CoilControlNode, CoilOutletNode, plantLoc);
    9236              :             }
    9237              :             // simulate the hot water heating coil
    9238            0 :             WaterCoils::SimulateWaterCoilComponents(state, HeatingCoilName, FirstHVACIteration, HeatingCoilIndex, QActual, fanOp);
    9239            0 :         } break;
    9240            0 :         case HVAC::Coil_HeatingSteam: {
    9241            0 :             if (QCoilLoad > HVAC::SmallLoad) {
    9242            0 :                 PlantUtilities::SetComponentFlowRate(state, MaxHotWaterFlow, CoilControlNode, CoilOutletNode, plantLoc);
    9243              :                 // simulate the steam heating coil
    9244            0 :                 SteamCoils::SimulateSteamCoilComponents(state, HeatingCoilName, FirstHVACIteration, HeatingCoilIndex, QCoilLoad, QActual, fanOp);
    9245              :             } else {
    9246            0 :                 mdot = 0.0;
    9247            0 :                 PlantUtilities::SetComponentFlowRate(state, mdot, CoilControlNode, CoilOutletNode, plantLoc);
    9248              :                 // simulate the steam heating coil
    9249            0 :                 SteamCoils::SimulateSteamCoilComponents(state, HeatingCoilName, FirstHVACIteration, HeatingCoilIndex, QCoilLoad, QActual, fanOp);
    9250              :             }
    9251            0 :         } break;
    9252            4 :         default:
    9253            4 :             break;
    9254              :         }
    9255              : 
    9256        71571 :         HeatCoilLoadmet = QActual;
    9257        71571 :     }
    9258              : 
    9259              :     //        End of Reporting subroutines for the Furnace Module
    9260              : 
    9261              :     //******************************************************************************
    9262              : 
    9263            0 :     void SimVariableSpeedHP(EnergyPlusData &state,
    9264              :                             int const FurnaceNum,          // number of the current engine driven Heat Pump being simulated
    9265              :                             bool const FirstHVACIteration, // TRUE if 1st HVAC simulation of system timestep
    9266              :                             int const AirLoopNum,          // index to air loop
    9267              :                             Real64 const QZnReq,           // required zone load
    9268              :                             Real64 const QLatReq,          // required latent load
    9269              :                             Real64 &OnOffAirFlowRatio      // ratio of compressor ON airflow to AVERAGE airflow over timestep
    9270              :     )
    9271              :     {
    9272              : 
    9273              :         // SUBROUTINE INFORMATION:
    9274              :         //       AUTHOR         Bo Shen, based on HVACMultiSpeedHeatPump:CalcMSHeatPump
    9275              :         //       DATE WRITTEN   March, 2012
    9276              : 
    9277              :         // PURPOSE OF THIS SUBROUTINE:
    9278              :         // Simulate a multispeed heat pump; adjust its output to match the
    9279              :         // required system load.
    9280              : 
    9281              :         // METHODOLOGY EMPLOYED:
    9282              :         // Calls ControlMSHPOutput to obtain the desired unit output
    9283              : 
    9284              :         Real64 PartLoadFrac; // compressor part load fraction
    9285              :         Real64 SpeedRatio;   // compressor speed ratio
    9286              :         Real64 QTotUnitOut;  // capacity output
    9287            0 :         auto &SpeedNum = state.dataFurnaces->SpeedNum;
    9288            0 :         auto &SupHeaterLoad = state.dataFurnaces->SupHeaterLoad;
    9289              :         HVAC::CompressorOp compressorOp; // compressor operation; 1=on, 0=off
    9290              :         Real64 QSensUnitOut;             // sensible capacity output
    9291              :         Real64 QLatUnitOut;              // latent capacity output
    9292              :         Real64 ActualSensibleOutput;     // Actual furnace sensible capacity
    9293              :         Real64 QToHeatSetPt;             // Load required to meet heating setpoint temp (>0 is a heating load)
    9294              :         Real64 NoCompOutput;             // output when no active compressor [W]
    9295              :         bool EconoActive;                // TRUE if Economizer is active
    9296              : 
    9297              :         // zero DX coils, and supplemental electric heater electricity consumption
    9298            0 :         state.dataHVACGlobal->DXElecHeatingPower = 0.0;
    9299            0 :         state.dataHVACGlobal->DXElecCoolingPower = 0.0;
    9300            0 :         state.dataFurnaces->SaveCompressorPLR = 0.0;
    9301            0 :         state.dataHVACGlobal->ElecHeatingCoilPower = 0.0;
    9302            0 :         state.dataHVACGlobal->SuppHeatingCoilPower = 0.0;
    9303            0 :         state.dataHVACGlobal->DefrostElecPower = 0.0;
    9304              : 
    9305            0 :         Real64 SystemSensibleLoad = QZnReq; // Positive value means heating required
    9306            0 :         Real64 TotalZoneSensibleLoad = QZnReq;
    9307            0 :         Real64 TotalZoneLatentLoad = QLatReq;
    9308            0 :         auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    9309              :         // initialize local variables
    9310            0 :         bool UnitOn = true;
    9311            0 :         int OutletNode = thisFurnace.FurnaceOutletNodeNum;
    9312            0 :         int InletNode = thisFurnace.FurnaceInletNodeNum;
    9313            0 :         Real64 AirMassFlow = thisFurnace.DesignMassFlowRate;
    9314            0 :         HVAC::FanOp fanOp = thisFurnace.fanOp; // fan operating mode
    9315            0 :         int ZoneNum = thisFurnace.ControlZoneNum;
    9316              : 
    9317              :         // Set latent load for heating
    9318            0 :         if (state.dataFurnaces->HeatingLoad) {
    9319            0 :             thisFurnace.HeatCoolMode = Furnaces::ModeOfOperation::HeatingMode;
    9320              :             // Set latent load for cooling and no sensible load condition
    9321            0 :         } else if (state.dataFurnaces->CoolingLoad) {
    9322            0 :             thisFurnace.HeatCoolMode = Furnaces::ModeOfOperation::CoolingMode;
    9323              :         } else {
    9324            0 :             thisFurnace.HeatCoolMode = Furnaces::ModeOfOperation::NoCoolHeat;
    9325              :         }
    9326              : 
    9327              :         // set the on/off flags
    9328            0 :         if (thisFurnace.fanOp == HVAC::FanOp::Cycling) {
    9329              :             // cycling unit only runs if there is a cooling or heating load.
    9330            0 :             if (std::abs(QZnReq) < HVAC::SmallLoad || AirMassFlow < HVAC::SmallMassFlow ||
    9331            0 :                 state.dataZoneEnergyDemand->CurDeadBandOrSetback(ZoneNum)) {
    9332            0 :                 UnitOn = false;
    9333              :             }
    9334            0 :         } else if (thisFurnace.fanOp == HVAC::FanOp::Continuous) {
    9335              :             // continuous unit: fan runs if scheduled on; coil runs only if there is a cooling or heating load
    9336            0 :             if (AirMassFlow < HVAC::SmallMassFlow) {
    9337            0 :                 UnitOn = false;
    9338              :             }
    9339              :         }
    9340              : 
    9341            0 :         state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
    9342            0 :         EconoActive = (AirLoopNum != 0) ? state.dataAirLoop->AirLoopControlInfo(AirLoopNum).EconoActive : false;
    9343              : 
    9344            0 :         Real64 SaveMassFlowRate = state.dataLoopNodes->Node(InletNode).MassFlowRate;
    9345              :         // decide current working mode for IHP
    9346            0 :         if ((FirstHVACIteration) && (thisFurnace.bIsIHP))
    9347            0 :             IntegratedHeatPump::DecideWorkMode(state, thisFurnace.CoolingCoilIndex, TotalZoneSensibleLoad, TotalZoneLatentLoad);
    9348              : 
    9349            0 :         if (!FirstHVACIteration && thisFurnace.fanOp == HVAC::FanOp::Cycling &&
    9350            0 :             (QZnReq < (-1.0 * HVAC::SmallLoad) || TotalZoneLatentLoad < (-HVAC::SmallLoad)) && EconoActive) {
    9351              :             // for cycling fan, cooling load, check whether furnace can meet load with compressor off
    9352            0 :             compressorOp = HVAC::CompressorOp::Off;
    9353            0 :             ControlVSHPOutput(state,
    9354              :                               FurnaceNum,
    9355              :                               FirstHVACIteration,
    9356              :                               compressorOp,
    9357              :                               fanOp,
    9358              :                               TotalZoneSensibleLoad,
    9359              :                               TotalZoneLatentLoad,
    9360              :                               SpeedNum,
    9361              :                               SpeedRatio,
    9362              :                               PartLoadFrac,
    9363              :                               OnOffAirFlowRatio,
    9364              :                               SupHeaterLoad);
    9365              : 
    9366            0 :             TotalZoneSensibleLoad = QZnReq;
    9367            0 :             TotalZoneLatentLoad = QLatReq;
    9368              : 
    9369            0 :             if (SpeedNum == thisFurnace.NumOfSpeedCooling && SpeedRatio == 1.0) {
    9370              :                 // compressor on (reset inlet air mass flow rate to starting value)
    9371            0 :                 state.dataLoopNodes->Node(InletNode).MassFlowRate = SaveMassFlowRate;
    9372            0 :                 compressorOp = HVAC::CompressorOp::On;
    9373            0 :                 ControlVSHPOutput(state,
    9374              :                                   FurnaceNum,
    9375              :                                   FirstHVACIteration,
    9376              :                                   compressorOp,
    9377              :                                   fanOp,
    9378              :                                   TotalZoneSensibleLoad,
    9379              :                                   TotalZoneLatentLoad,
    9380              :                                   SpeedNum,
    9381              :                                   SpeedRatio,
    9382              :                                   PartLoadFrac,
    9383              :                                   OnOffAirFlowRatio,
    9384              :                                   SupHeaterLoad);
    9385              :             }
    9386              :         } else {
    9387              :             // compressor on
    9388            0 :             compressorOp = HVAC::CompressorOp::On;
    9389              : 
    9390            0 :             ControlVSHPOutput(state,
    9391              :                               FurnaceNum,
    9392              :                               FirstHVACIteration,
    9393              :                               compressorOp,
    9394              :                               fanOp,
    9395              :                               TotalZoneSensibleLoad,
    9396              :                               TotalZoneLatentLoad,
    9397              :                               SpeedNum,
    9398              :                               SpeedRatio,
    9399              :                               PartLoadFrac,
    9400              :                               OnOffAirFlowRatio,
    9401              :                               SupHeaterLoad);
    9402              :         }
    9403              : 
    9404            0 :         if (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatCool) {
    9405            0 :             state.dataFurnaces->SaveCompressorPLR = PartLoadFrac;
    9406              :         } else {
    9407            0 :             if (SpeedNum > 1) {
    9408            0 :                 state.dataFurnaces->SaveCompressorPLR = 1.0;
    9409              :             }
    9410              : 
    9411            0 :             if (PartLoadFrac == 1.0 && state.dataFurnaces->SaveCompressorPLR < 1.0) {
    9412            0 :                 PartLoadFrac = state.dataFurnaces->SaveCompressorPLR;
    9413              :             }
    9414              :         }
    9415              : 
    9416            0 :         Real64 ReheatCoilLoad = 0.0;
    9417            0 :         TotalZoneSensibleLoad = QZnReq;
    9418            0 :         TotalZoneLatentLoad = QLatReq;
    9419              :         //     Calculate the reheat coil output
    9420            0 :         if ((thisFurnace.availSched->getCurrentVal() > 0.0) &&
    9421            0 :             (thisFurnace.Humidistat && thisFurnace.DehumidControlType_Num == DehumidificationControlMode::CoolReheat &&
    9422              :              (QLatReq < 0.0))) { // if a Humidistat is installed and dehumidification control type is CoolReheat
    9423            0 :             CalcVarSpeedHeatPump(state,
    9424              :                                  FurnaceNum,
    9425              :                                  FirstHVACIteration,
    9426              :                                  compressorOp,
    9427              :                                  SpeedNum,
    9428              :                                  SpeedRatio,
    9429              :                                  PartLoadFrac,
    9430              :                                  ActualSensibleOutput,
    9431              :                                  QLatUnitOut,
    9432              :                                  TotalZoneSensibleLoad,
    9433              :                                  TotalZoneLatentLoad,
    9434              :                                  OnOffAirFlowRatio,
    9435              :                                  ReheatCoilLoad);
    9436            0 :             if (thisFurnace.ZoneSequenceHeatingNum > 0) {
    9437            0 :                 QToHeatSetPt = (state.dataZoneEnergyDemand->ZoneSysEnergyDemand(thisFurnace.ControlZoneNum)
    9438            0 :                                     .SequencedOutputRequiredToHeatingSP(thisFurnace.ZoneSequenceHeatingNum) /
    9439            0 :                                 thisFurnace.ControlZoneMassFlowFrac);
    9440              :             } else {
    9441            0 :                 QToHeatSetPt = (state.dataZoneEnergyDemand->ZoneSysEnergyDemand(thisFurnace.ControlZoneNum).OutputRequiredToHeatingSP /
    9442            0 :                                 thisFurnace.ControlZoneMassFlowFrac);
    9443              :             }
    9444              :             //       Cooling mode or floating condition and dehumidification is required
    9445            0 :             if (QToHeatSetPt < 0.0) {
    9446              :                 //         Calculate the reheat coil load wrt the heating setpoint temperature. Reheat coil picks up
    9447              :                 //         the entire excess sensible cooling (DX cooling coil and impact of outdoor air).
    9448            0 :                 ReheatCoilLoad = max(0.0, (QToHeatSetPt - ActualSensibleOutput));
    9449            0 :                 thisFurnace.DehumidInducedHeatingDemandRate = ReheatCoilLoad;
    9450              :                 //       Heating mode and dehumidification is required
    9451              :             } else {
    9452            0 :                 ReheatCoilLoad = max(QToHeatSetPt, QToHeatSetPt - ActualSensibleOutput);
    9453            0 :                 thisFurnace.DehumidInducedHeatingDemandRate = max(0.0, ActualSensibleOutput * (-1.0));
    9454              :             }
    9455              : 
    9456            0 :             SupHeaterLoad = 0.0;
    9457            0 :             CalcVarSpeedHeatPump(state,
    9458              :                                  FurnaceNum,
    9459              :                                  FirstHVACIteration,
    9460              :                                  compressorOp,
    9461              :                                  1,
    9462              :                                  0.0,
    9463              :                                  0.0,
    9464              :                                  NoCompOutput,
    9465              :                                  QLatUnitOut,
    9466              :                                  0.0,
    9467              :                                  0.0,
    9468              :                                  OnOffAirFlowRatio,
    9469              :                                  SupHeaterLoad);
    9470              : 
    9471            0 :             if (NoCompOutput > SystemSensibleLoad && SystemSensibleLoad > 0.0 && ReheatCoilLoad > 0.0) {
    9472              :                 // Reduce reheat coil load if you are controlling high humidity but outside air
    9473              :                 // and/or the supply air fan is providing enough heat to meet the system sensible load.
    9474              :                 // This will bring the zone temp closer to the heating setpoint temp.
    9475            0 :                 ReheatCoilLoad = max(0.0, ReheatCoilLoad - (NoCompOutput - SystemSensibleLoad));
    9476              :             }
    9477              :         } else {
    9478              :             //       No humidistat installed
    9479            0 :             ReheatCoilLoad = 0.0;
    9480              :         }
    9481              : 
    9482            0 :         TotalZoneSensibleLoad = QZnReq;
    9483            0 :         TotalZoneLatentLoad = QLatReq;
    9484            0 :         if (ReheatCoilLoad > 0.0) {
    9485            0 :             CalcVarSpeedHeatPump(state,
    9486              :                                  FurnaceNum,
    9487              :                                  FirstHVACIteration,
    9488              :                                  compressorOp,
    9489              :                                  SpeedNum,
    9490              :                                  SpeedRatio,
    9491              :                                  PartLoadFrac,
    9492              :                                  QSensUnitOut,
    9493              :                                  QLatUnitOut,
    9494              :                                  TotalZoneSensibleLoad,
    9495              :                                  TotalZoneLatentLoad,
    9496              :                                  OnOffAirFlowRatio,
    9497              :                                  ReheatCoilLoad);
    9498              :         } else {
    9499            0 :             CalcVarSpeedHeatPump(state,
    9500              :                                  FurnaceNum,
    9501              :                                  FirstHVACIteration,
    9502              :                                  compressorOp,
    9503              :                                  SpeedNum,
    9504              :                                  SpeedRatio,
    9505              :                                  PartLoadFrac,
    9506              :                                  QSensUnitOut,
    9507              :                                  QLatUnitOut,
    9508              :                                  TotalZoneSensibleLoad,
    9509              :                                  TotalZoneLatentLoad,
    9510              :                                  OnOffAirFlowRatio,
    9511              :                                  SupHeaterLoad);
    9512              :         }
    9513              : 
    9514              :         // calculate delivered capacity
    9515            0 :         AirMassFlow = state.dataLoopNodes->Node(InletNode).MassFlowRate;
    9516              : 
    9517            0 :         thisFurnace.MdotFurnace = AirMassFlow;
    9518              : 
    9519            0 :         QTotUnitOut =
    9520            0 :             AirMassFlow * (state.dataLoopNodes->Node(OutletNode).Enthalpy - state.dataLoopNodes->Node(thisFurnace.NodeNumOfControlledZone).Enthalpy);
    9521              : 
    9522            0 :         state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail = AirMassFlow;
    9523            0 :         state.dataLoopNodes->Node(OutletNode).MassFlowRateMaxAvail = AirMassFlow;
    9524              : 
    9525            0 :         if (!FirstHVACIteration && AirMassFlow > 0.0 && AirLoopNum > 0) {
    9526            0 :             int TotBranchNum = state.dataAirSystemsData->PrimaryAirSystems(AirLoopNum).NumOutletBranches;
    9527            0 :             if (TotBranchNum == 1) {
    9528            0 :                 int ZoneSideNodeNum = state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).ZoneEquipSupplyNodeNum(1);
    9529              :                 // THE MASS FLOW PRECISION of the system solver is not enough for some small air flow rate iterations , BY DEBUGGING
    9530              :                 // it may cause mass flow rate oscillations between airloop and zoneequip
    9531              :                 // specify the air flow rate directly for one-to-one system, when the iteration deviation is closing the solver precision level
    9532              :                 // 0.02 is 2 * HVACFlowRateToler, in order to accommodate the system solver precision level
    9533            0 :                 if (std::abs(AirMassFlow - state.dataLoopNodes->Node(ZoneSideNodeNum).MassFlowRate) < 0.02)
    9534            0 :                     state.dataLoopNodes->Node(ZoneSideNodeNum).MassFlowRateMaxAvail = AirMassFlow;
    9535            0 :                 state.dataLoopNodes->Node(ZoneSideNodeNum).MassFlowRate = AirMassFlow;
    9536              :             }
    9537              : 
    9538              :             // the below might be useful if more divergences occur
    9539              :             // Node(PrimaryAirSystem(AirLoopNumber)%Branch(1)%NodeNumIn)%MassFlowRateMaxAvail = AirMassFlow
    9540              :             // Node(PrimaryAirSystem(AirLoopNumber)%Branch(1)%NodeNumIn)%MassFlowRate = AirMassFlow
    9541              :         }
    9542              : 
    9543              :         // report variables
    9544            0 :         thisFurnace.DehumidInducedHeatingDemandRate = ReheatCoilLoad;
    9545            0 :         if (QZnReq > HVAC::SmallLoad) { // HEATING LOAD
    9546            0 :             thisFurnace.CoolingCoilSensDemand = 0.0;
    9547            0 :             thisFurnace.HeatingCoilSensDemand = QZnReq;
    9548              :         } else {
    9549            0 :             thisFurnace.CoolingCoilSensDemand = std::abs(QZnReq);
    9550            0 :             thisFurnace.HeatingCoilSensDemand = 0.0;
    9551              :         }
    9552              : 
    9553            0 :         thisFurnace.CompPartLoadRatio = state.dataFurnaces->SaveCompressorPLR;
    9554            0 :         if (thisFurnace.fanOp == HVAC::FanOp::Cycling) {
    9555            0 :             if (SupHeaterLoad > 0.0) {
    9556            0 :                 thisFurnace.FanPartLoadRatio = 1.0;
    9557              :             } else {
    9558            0 :                 if (SpeedNum < 2) {
    9559            0 :                     thisFurnace.FanPartLoadRatio = PartLoadFrac;
    9560              :                 } else {
    9561            0 :                     thisFurnace.FanPartLoadRatio = 1.0;
    9562              :                 }
    9563              :             }
    9564              :         } else {
    9565            0 :             if (UnitOn) {
    9566            0 :                 thisFurnace.FanPartLoadRatio = 1.0;
    9567              :             } else {
    9568            0 :                 if (SpeedNum < 2) {
    9569            0 :                     thisFurnace.FanPartLoadRatio = PartLoadFrac;
    9570              :                 } else {
    9571            0 :                     thisFurnace.FanPartLoadRatio = 1.0;
    9572              :                 }
    9573              :             }
    9574              :         }
    9575            0 :     }
    9576              : 
    9577              :     //******************************************************************************
    9578              : 
    9579            0 :     void ControlVSHPOutput(EnergyPlusData &state,
    9580              :                            int const FurnaceNum,                  // Unit index of engine driven heat pump
    9581              :                            bool const FirstHVACIteration,         // flag for 1st HVAC iteration in the time step
    9582              :                            HVAC::CompressorOp const compressorOp, // compressor operation; 1=on, 0=off
    9583              :                            HVAC::FanOp const fanOp,               // operating mode: FanOp::Cycling | FanOp::Continuous
    9584              :                            Real64 &QZnReq,                        // cooling or heating output needed by zone [W]
    9585              :                            Real64 QLatReq,                        // latent cooling output needed by zone [W]
    9586              :                            int &SpeedNum,                         // Speed number
    9587              :                            Real64 &SpeedRatio,                    // unit speed ratio for DX coils
    9588              :                            Real64 &PartLoadFrac,                  // unit part load fraction
    9589              :                            Real64 &OnOffAirFlowRatio,             // ratio of compressor ON airflow to AVERAGE airflow over timestep
    9590              :                            Real64 &SupHeaterLoad                  // Supplemental heater load [W]
    9591              :     )
    9592              :     {
    9593              : 
    9594              :         // SUBROUTINE INFORMATION:
    9595              :         //       AUTHOR         Bo Shen, based on HVACMultiSpeedHeatPump:ControlMSHPOutput
    9596              :         //       DATE WRITTEN   March,  2012
    9597              : 
    9598              :         // PURPOSE OF THIS SUBROUTINE:
    9599              :         // Determine the part load fraction at low speed, and speed ratio at high speed for this time step.
    9600              : 
    9601              :         // METHODOLOGY EMPLOYED:
    9602              :         // Use RegulaFalsi technique to iterate on part-load ratio until convergence is achieved.
    9603              : 
    9604              :         // SUBROUTINE PARAMETER DEFINITIONS:
    9605            0 :         int constexpr MaxIte(500); // maximum number of iterations
    9606              : 
    9607              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    9608              :         Real64 FullOutput;   // unit full output when compressor is operating [W]
    9609              :         Real64 LowOutput;    // unit full output at low speed [W]
    9610              :         Real64 TempOutput;   // unit output when iteration limit exceeded [W]
    9611              :         Real64 NoCompOutput; // output when no active compressor [W]
    9612              :         int SolFla;          // Flag of RegulaFalsi solver
    9613              :         Real64 QCoilActual;  // coil load actually delivered returned to calling component
    9614              :         int i;               // Speed index
    9615            0 :         IntegratedHeatPump::IHPOperationMode IHPMode(IntegratedHeatPump::IHPOperationMode::Idle);
    9616              : 
    9617            0 :         SupHeaterLoad = 0.0;
    9618            0 :         PartLoadFrac = 0.0;
    9619            0 :         SpeedRatio = 0.0;
    9620            0 :         SpeedNum = 1;
    9621            0 :         Real64 LatOutput = 0.0;
    9622            0 :         Real64 noLatOutput = 0.0;
    9623            0 :         Real64 ErrorToler = 0.001; // Error tolerance for convergence from input deck
    9624              : 
    9625            0 :         auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
    9626            0 :         if (thisFurnace.availSched->getCurrentVal() == 0.0) return;
    9627              : 
    9628              :         // Get result when DX coil is off
    9629            0 :         SupHeaterLoad = 0.0;
    9630            0 :         CalcVarSpeedHeatPump(state,
    9631              :                              FurnaceNum,
    9632              :                              FirstHVACIteration,
    9633              :                              compressorOp,
    9634              :                              SpeedNum,
    9635              :                              SpeedRatio,
    9636              :                              PartLoadFrac,
    9637              :                              NoCompOutput,
    9638              :                              noLatOutput,
    9639              :                              0.0,
    9640              :                              0.0,
    9641              :                              OnOffAirFlowRatio,
    9642              :                              SupHeaterLoad);
    9643              : 
    9644            0 :         if (thisFurnace.bIsIHP) {
    9645            0 :             IHPMode = IntegratedHeatPump::GetCurWorkMode(state, thisFurnace.CoolingCoilIndex);
    9646            0 :             if ((IntegratedHeatPump::IHPOperationMode::DedicatedWaterHtg == IHPMode) ||
    9647              :                 (IntegratedHeatPump::IHPOperationMode::SCWHMatchWH == IHPMode)) { // cooling capacity is a resultant
    9648            0 :                 return;
    9649              :             }
    9650              :         }
    9651              : 
    9652              :         // If cooling and NoCompOutput < QZnReq, the coil needs to be off
    9653              :         // If heating and NoCompOutput > QZnReq, the coil needs to be off
    9654              :         // If no cooling or heating and no latent load, the coil needs to be off
    9655            0 :         if (QZnReq < -HVAC::SmallLoad) {
    9656            0 :             if (NoCompOutput < QZnReq && QLatReq >= -HVAC::SmallLoad) return;
    9657            0 :         } else if (QZnReq > HVAC::SmallLoad) {
    9658            0 :             if (NoCompOutput > QZnReq && QLatReq >= -HVAC::SmallLoad) return;
    9659            0 :             if (QLatReq <= -HVAC::SmallLoad) QZnReq = 0.0; // Zero heating load to allow dehumidification
    9660              :         } else {
    9661            0 :             if (QLatReq >= -HVAC::SmallLoad) return;
    9662              :         }
    9663              : 
    9664              :         // Get full load result
    9665            0 :         PartLoadFrac = 1.0;
    9666            0 :         SpeedRatio = 1.0;
    9667            0 :         if (thisFurnace.HeatCoolMode == Furnaces::ModeOfOperation::HeatingMode) {
    9668            0 :             SpeedNum = thisFurnace.NumOfSpeedHeating;
    9669            0 :         } else if (thisFurnace.HeatCoolMode == Furnaces::ModeOfOperation::CoolingMode) {
    9670            0 :             SpeedNum = thisFurnace.NumOfSpeedCooling;
    9671            0 :         } else if (QLatReq < -HVAC::SmallLoad) {
    9672            0 :             SpeedNum = thisFurnace.NumOfSpeedCooling;
    9673              :         } else {
    9674            0 :             SpeedNum = 1;
    9675            0 :             PartLoadFrac = 0.0;
    9676              :         }
    9677              : 
    9678            0 :         if (thisFurnace.bIsIHP) SpeedNum = IntegratedHeatPump::GetMaxSpeedNumIHP(state, thisFurnace.CoolingCoilIndex);
    9679              : 
    9680            0 :         CalcVarSpeedHeatPump(state,
    9681              :                              FurnaceNum,
    9682              :                              FirstHVACIteration,
    9683              :                              compressorOp,
    9684              :                              SpeedNum,
    9685              :                              SpeedRatio,
    9686              :                              PartLoadFrac,
    9687              :                              FullOutput,
    9688              :                              LatOutput,
    9689              :                              QZnReq,
    9690              :                              QLatReq,
    9691              :                              OnOffAirFlowRatio,
    9692              :                              SupHeaterLoad);
    9693              : 
    9694            0 :         if (QLatReq < (-1.0 * HVAC::SmallLoad)) { // dehumidification mode
    9695            0 :             if (QLatReq <= LatOutput || (QZnReq < -HVAC::SmallLoad && QZnReq <= FullOutput) || (QZnReq > HVAC::SmallLoad && QZnReq >= FullOutput)) {
    9696            0 :                 PartLoadFrac = 1.0;
    9697            0 :                 SpeedRatio = 1.0;
    9698            0 :                 thisFurnace.CompPartLoadRatio = PartLoadFrac;
    9699            0 :                 thisFurnace.CompSpeedRatio = SpeedRatio;
    9700            0 :                 thisFurnace.CompSpeedNum = SpeedNum;
    9701            0 :                 return;
    9702              :             }
    9703            0 :         } else if (QZnReq < -HVAC::SmallLoad) {
    9704            0 :             if (QZnReq <= FullOutput) {
    9705            0 :                 PartLoadFrac = 1.0;
    9706            0 :                 SpeedRatio = 1.0;
    9707            0 :                 thisFurnace.CompPartLoadRatio = PartLoadFrac;
    9708            0 :                 thisFurnace.CompSpeedRatio = SpeedRatio;
    9709            0 :                 thisFurnace.CompSpeedNum = SpeedNum;
    9710            0 :                 return;
    9711              :             }
    9712              :         } else {
    9713            0 :             if (QZnReq >= FullOutput) {
    9714            0 :                 PartLoadFrac = 1.0;
    9715            0 :                 SpeedRatio = 1.0;
    9716              :                 // may need supplemental heating so don't return in heating mode
    9717              :             }
    9718              :         }
    9719              : 
    9720            0 :         if ((QZnReq < -HVAC::SmallLoad && NoCompOutput - QZnReq > HVAC::SmallLoad) ||
    9721            0 :             (QZnReq > HVAC::SmallLoad && QZnReq - NoCompOutput > HVAC::SmallLoad)) {
    9722            0 :             if ((QZnReq > HVAC::SmallLoad && QZnReq < FullOutput) || (QZnReq < (-1.0 * HVAC::SmallLoad) && QZnReq > FullOutput)) {
    9723              :                 // Check whether the low speed coil can meet the load or not
    9724            0 :                 CalcVarSpeedHeatPump(state,
    9725              :                                      FurnaceNum,
    9726              :                                      FirstHVACIteration,
    9727              :                                      compressorOp,
    9728              :                                      1,
    9729              :                                      0.0,
    9730              :                                      1.0,
    9731              :                                      LowOutput,
    9732              :                                      LatOutput,
    9733              :                                      QZnReq,
    9734              :                                      QLatReq,
    9735              :                                      OnOffAirFlowRatio,
    9736              :                                      SupHeaterLoad);
    9737            0 :                 if ((QZnReq > HVAC::SmallLoad && QZnReq <= LowOutput) || (QZnReq < (-HVAC::SmallLoad) && QZnReq >= LowOutput)) {
    9738              :                     // Calculate the part load fraction
    9739            0 :                     SpeedRatio = 0.0;
    9740            0 :                     SpeedNum = 1;
    9741              :                     auto f = // (AUTO_OK_LAMBDA)
    9742            0 :                         [&state, FurnaceNum, FirstHVACIteration, QZnReq, OnOffAirFlowRatio, SupHeaterLoad, compressorOp](Real64 const PartLoadFrac) {
    9743            0 :                             return VSHPCyclingResidual(
    9744            0 :                                 state, PartLoadFrac, FurnaceNum, FirstHVACIteration, QZnReq, OnOffAirFlowRatio, SupHeaterLoad, compressorOp, 1.0);
    9745            0 :                         };
    9746            0 :                     General::SolveRoot(state, ErrorToler, MaxIte, SolFla, PartLoadFrac, f, 0.0, 1.0);
    9747            0 :                     if (SolFla == -1) {
    9748            0 :                         if (!state.dataGlobal->WarmupFlag) {
    9749            0 :                             if (thisFurnace.ErrCountCyc == 0) {
    9750            0 :                                 ++thisFurnace.ErrCountCyc;
    9751            0 :                                 ShowWarningError(
    9752            0 :                                     state, format("Iteration limit exceeded calculating VS WSHP unit cycling ratio, for unit={}", thisFurnace.Name));
    9753            0 :                                 ShowContinueErrorTimeStamp(state, format("Cycling ratio returned={:.2R}", PartLoadFrac));
    9754              :                             } else {
    9755            0 :                                 ShowRecurringWarningErrorAtEnd(
    9756              :                                     state,
    9757            0 :                                     thisFurnace.Name + "\": Iteration limit warning exceeding calculating DX unit cycling ratio  continues...",
    9758            0 :                                     thisFurnace.ErrIndexCyc,
    9759              :                                     PartLoadFrac,
    9760              :                                     PartLoadFrac);
    9761              :                             }
    9762              :                         }
    9763            0 :                     } else if (SolFla == -2) {
    9764            0 :                         ShowFatalError(
    9765            0 :                             state, format("VS WSHP unit cycling ratio calculation failed: cycling limits exceeded, for unit={}", thisFurnace.Name));
    9766              :                     }
    9767            0 :                 } else {
    9768              :                     // Check to see which speed to meet the load
    9769            0 :                     PartLoadFrac = 1.0;
    9770            0 :                     SpeedRatio = 1.0;
    9771            0 :                     if (QZnReq < -HVAC::SmallLoad) { // Cooling
    9772            0 :                         for (i = 2; i <= thisFurnace.NumOfSpeedCooling; ++i) {
    9773            0 :                             CalcVarSpeedHeatPump(state,
    9774              :                                                  FurnaceNum,
    9775              :                                                  FirstHVACIteration,
    9776              :                                                  compressorOp,
    9777              :                                                  i,
    9778              :                                                  SpeedRatio,
    9779              :                                                  PartLoadFrac,
    9780              :                                                  TempOutput,
    9781              :                                                  LatOutput,
    9782              :                                                  QZnReq,
    9783              :                                                  QLatReq,
    9784              :                                                  OnOffAirFlowRatio,
    9785              :                                                  SupHeaterLoad);
    9786              : 
    9787            0 :                             if (QZnReq >= TempOutput) {
    9788            0 :                                 SpeedNum = i;
    9789            0 :                                 break;
    9790              :                             }
    9791              :                         }
    9792              :                     } else {
    9793            0 :                         for (i = 2; i <= thisFurnace.NumOfSpeedHeating; ++i) {
    9794            0 :                             CalcVarSpeedHeatPump(state,
    9795              :                                                  FurnaceNum,
    9796              :                                                  FirstHVACIteration,
    9797              :                                                  compressorOp,
    9798              :                                                  i,
    9799              :                                                  SpeedRatio,
    9800              :                                                  PartLoadFrac,
    9801              :                                                  TempOutput,
    9802              :                                                  LatOutput,
    9803              :                                                  QZnReq,
    9804              :                                                  QLatReq,
    9805              :                                                  OnOffAirFlowRatio,
    9806              :                                                  SupHeaterLoad);
    9807            0 :                             if (QZnReq <= TempOutput) {
    9808            0 :                                 SpeedNum = i;
    9809            0 :                                 break;
    9810              :                             }
    9811              :                         }
    9812              :                     }
    9813            0 :                     auto f = [&state, FurnaceNum, FirstHVACIteration, QZnReq, OnOffAirFlowRatio, SupHeaterLoad, SpeedNum, compressorOp](
    9814              :                                  Real64 const SpeedRatio) {
    9815            0 :                         return VSHPSpeedResidual(
    9816            0 :                             state, SpeedRatio, FurnaceNum, FirstHVACIteration, QZnReq, OnOffAirFlowRatio, SupHeaterLoad, SpeedNum, compressorOp, 1.0);
    9817            0 :                     };
    9818            0 :                     General::SolveRoot(state, ErrorToler, MaxIte, SolFla, SpeedRatio, f, 1.0e-10, 1.0);
    9819            0 :                     if (SolFla == -1) {
    9820            0 :                         if (!state.dataGlobal->WarmupFlag) {
    9821            0 :                             if (thisFurnace.ErrCountVar == 0) {
    9822            0 :                                 ++thisFurnace.ErrCountVar;
    9823            0 :                                 ShowWarningError(
    9824            0 :                                     state, format("Iteration limit exceeded calculating VS WSHP unit speed ratio, for unit={}", thisFurnace.Name));
    9825            0 :                                 ShowContinueErrorTimeStamp(state, format("Speed ratio returned=[{:.2R}], Speed number ={}", SpeedRatio, SpeedNum));
    9826              :                             } else {
    9827            0 :                                 ShowRecurringWarningErrorAtEnd(
    9828              :                                     state,
    9829            0 :                                     thisFurnace.Name + "\": Iteration limit warning exceeding calculating DX unit speed ratio continues...",
    9830            0 :                                     thisFurnace.ErrIndexVar,
    9831              :                                     SpeedRatio,
    9832              :                                     SpeedRatio);
    9833              :                             }
    9834              :                         }
    9835            0 :                     } else if (SolFla == -2) {
    9836            0 :                         ShowFatalError(
    9837            0 :                             state, format("VS WSHP unit compressor speed calculation failed: speed limits exceeded, for unit={}", thisFurnace.Name));
    9838              :                     }
    9839              :                 }
    9840            0 :             } else {
    9841            0 :                 LatOutput = noLatOutput; // reset full output if not needed for sensible load
    9842            0 :                 SpeedNum = 1;            // reset speed from full output test
    9843              :             }
    9844            0 :         } else {
    9845            0 :             LatOutput = noLatOutput; // reset full output if not needed for sensible load
    9846            0 :             SpeedNum = 1;            // reset speed from full output test
    9847              :         }
    9848              :         // meet the latent load
    9849            0 :         if (QLatReq < -HVAC::SmallLoad && QLatReq < LatOutput) {
    9850            0 :             PartLoadFrac = 1.0;
    9851            0 :             SpeedRatio = 1.0;
    9852            0 :             for (i = SpeedNum; i <= thisFurnace.NumOfSpeedCooling; ++i) {
    9853            0 :                 CalcVarSpeedHeatPump(state,
    9854              :                                      FurnaceNum,
    9855              :                                      FirstHVACIteration,
    9856              :                                      compressorOp,
    9857              :                                      i,
    9858              :                                      SpeedRatio,
    9859              :                                      PartLoadFrac,
    9860              :                                      TempOutput,
    9861              :                                      LatOutput,
    9862              :                                      QZnReq,
    9863              :                                      QLatReq,
    9864              :                                      OnOffAirFlowRatio,
    9865              :                                      SupHeaterLoad);
    9866              : 
    9867            0 :                 if (QLatReq > LatOutput) {
    9868            0 :                     SpeedNum = i;
    9869            0 :                     break;
    9870              :                 }
    9871              :             }
    9872            0 :             if (QLatReq - LatOutput > HVAC::SmallLoad) {
    9873            0 :                 if (SpeedNum < 2) {
    9874              :                     auto f = // (AUTO_OK_LAMBDA)
    9875            0 :                         [&state, FurnaceNum, FirstHVACIteration, QLatReq, OnOffAirFlowRatio, SupHeaterLoad, compressorOp](Real64 const PartLoadFrac) {
    9876            0 :                             return VSHPCyclingResidual(
    9877            0 :                                 state, PartLoadFrac, FurnaceNum, FirstHVACIteration, QLatReq, OnOffAirFlowRatio, SupHeaterLoad, compressorOp, 0.0);
    9878            0 :                         };
    9879            0 :                     General::SolveRoot(state, ErrorToler, MaxIte, SolFla, PartLoadFrac, f, 0.0, 1.0);
    9880              :                 } else {
    9881            0 :                     auto f = [&state, FurnaceNum, FirstHVACIteration, QLatReq, OnOffAirFlowRatio, SupHeaterLoad, SpeedNum, compressorOp](
    9882              :                                  Real64 const SpeedRatio) {
    9883            0 :                         return VSHPSpeedResidual(state,
    9884              :                                                  SpeedRatio,
    9885              :                                                  FurnaceNum,
    9886              :                                                  FirstHVACIteration,
    9887              :                                                  QLatReq,
    9888              :                                                  OnOffAirFlowRatio,
    9889              :                                                  SupHeaterLoad,
    9890              :                                                  SpeedNum,
    9891              :                                                  compressorOp,
    9892            0 :                                                  0.0);
    9893            0 :                     };
    9894            0 :                     General::SolveRoot(state, ErrorToler, MaxIte, SolFla, SpeedRatio, f, 1.0e-10, 1.0);
    9895              :                 }
    9896            0 :                 if (SolFla == -1) {
    9897            0 :                     if (!state.dataGlobal->WarmupFlag) {
    9898            0 :                         if (thisFurnace.ErrCountVar2 == 0) {
    9899            0 :                             ++thisFurnace.ErrCountVar2;
    9900            0 :                             ShowWarningError(state,
    9901            0 :                                              format("Iteration limit exceeded calculating VS WSHP unit speed ratio, for unit={}", thisFurnace.Name));
    9902            0 :                             ShowContinueErrorTimeStamp(state, format("Speed ratio returned=[{:.2R}], Speed number ={}", SpeedRatio, SpeedNum));
    9903              :                         } else {
    9904            0 :                             ShowRecurringWarningErrorAtEnd(state,
    9905            0 :                                                            thisFurnace.Name +
    9906              :                                                                "\": Iteration limit warning exceeding calculating DX unit speed ratio continues...",
    9907            0 :                                                            thisFurnace.ErrIndexVar,
    9908              :                                                            SpeedRatio,
    9909              :                                                            SpeedRatio);
    9910              :                         }
    9911              :                     }
    9912            0 :                 } else if (SolFla == -2) {
    9913            0 :                     ShowFatalError(state,
    9914            0 :                                    format("VS WSHP unit compressor speed calculation failed: speed limits exceeded, for unit={}", thisFurnace.Name));
    9915              :                 }
    9916              :             }
    9917              :         }
    9918              :         // end meet the latent load
    9919              : 
    9920              :         // if the heating coil cannot meet the load, trim with supplemental heater
    9921              :         // occurs with constant fan mode when compressor is on or off
    9922              :         // occurs with cycling fan mode when compressor PLR is equal to 1
    9923            0 :         if ((QZnReq > HVAC::SmallLoad && QZnReq > FullOutput) && (thisFurnace.SuppHeatCoilIndex != 0)) {
    9924            0 :             PartLoadFrac = 1.0;
    9925            0 :             SpeedRatio = 1.0;
    9926            0 :             if (thisFurnace.NumOfSpeedHeating > 0)
    9927            0 :                 SpeedNum = thisFurnace.NumOfSpeedHeating; // maximum heating speed, avoid zero for cooling only mode
    9928              : 
    9929            0 :             if (state.dataEnvrn->OutDryBulbTemp <= thisFurnace.MaxOATSuppHeat) {
    9930            0 :                 SupHeaterLoad = QZnReq - FullOutput;
    9931              :             } else {
    9932            0 :                 SupHeaterLoad = 0.0;
    9933              :             }
    9934            0 :             CalcVarSpeedHeatPump(state,
    9935              :                                  FurnaceNum,
    9936              :                                  FirstHVACIteration,
    9937              :                                  compressorOp,
    9938              :                                  SpeedNum,
    9939              :                                  SpeedRatio,
    9940              :                                  PartLoadFrac,
    9941              :                                  TempOutput,
    9942              :                                  LatOutput,
    9943              :                                  QZnReq,
    9944              :                                  QLatReq,
    9945              :                                  OnOffAirFlowRatio,
    9946              :                                  SupHeaterLoad);
    9947              :         }
    9948              : 
    9949              :         // check the outlet of the supplemental heater to be lower than the maximum supplemental heater supply air temperature
    9950            0 :         if (state.dataLoopNodes->Node(thisFurnace.FurnaceOutletNodeNum).Temp > thisFurnace.DesignMaxOutletTemp && SupHeaterLoad > 0.0) {
    9951              : 
    9952              :             //   If the supply air temperature is to high, turn off the supplemental heater to recalculate the outlet temperature
    9953            0 :             CalcNonDXHeatingCoils(state, FurnaceNum, true, FirstHVACIteration, 0.0, fanOp, QCoilActual);
    9954              :             //   If the outlet temperature is below the maximum supplemental heater supply air temperature, reduce the load passed to
    9955              :             //   the supplemental heater, otherwise leave the supplemental heater off. If the supplemental heater is to be turned on,
    9956              :             //   use the outlet conditions when the supplemental heater was off (CALL above) as the inlet conditions for the calculation
    9957              :             //   of supplemental heater load to just meet the maximum supply air temperature from the supplemental heater.
    9958            0 :             if (state.dataLoopNodes->Node(thisFurnace.FurnaceOutletNodeNum).Temp < thisFurnace.DesignMaxOutletTemp) {
    9959            0 :                 Real64 CpAir = Psychrometrics::PsyCpAirFnW(state.dataLoopNodes->Node(thisFurnace.FurnaceOutletNodeNum).HumRat);
    9960            0 :                 SupHeaterLoad = state.dataLoopNodes->Node(thisFurnace.FurnaceInletNodeNum).MassFlowRate * CpAir *
    9961            0 :                                 (thisFurnace.DesignMaxOutletTemp - state.dataLoopNodes->Node(thisFurnace.FurnaceOutletNodeNum).Temp);
    9962              : 
    9963              :             } else {
    9964            0 :                 SupHeaterLoad = 0.0;
    9965              :             }
    9966              :         }
    9967              : 
    9968              :         // prepare module level output
    9969            0 :         thisFurnace.CompPartLoadRatio = PartLoadFrac;
    9970            0 :         thisFurnace.CompSpeedRatio = SpeedRatio;
    9971            0 :         thisFurnace.CompSpeedNum = SpeedNum;
    9972            0 :         thisFurnace.CoolingCoilLatentDemand = std::abs(QLatReq);
    9973              : 
    9974            0 :         if (thisFurnace.fanOp == HVAC::FanOp::Continuous) {
    9975            0 :             thisFurnace.FanPartLoadRatio = 1.0;
    9976              :         } else {
    9977            0 :             thisFurnace.FanPartLoadRatio = PartLoadFrac;
    9978              :         }
    9979              :     }
    9980              : 
    9981              :     //******************************************************************************
    9982              : 
    9983            0 :     void CalcVarSpeedHeatPump(EnergyPlusData &state,
    9984              :                               int const FurnaceNum,                  // Variable speed heat pump number
    9985              :                               bool const FirstHVACIteration,         // Flag for 1st HVAC iteration
    9986              :                               HVAC::CompressorOp const compressorOp, // Compressor on/off; 1=on, 0=off
    9987              :                               int const SpeedNum,                    // Speed number
    9988              :                               Real64 const SpeedRatio,               // Compressor speed ratio
    9989              :                               Real64 const PartLoadFrac,             // Compressor part load fraction
    9990              :                               Real64 &SensibleLoadMet,               // Sensible cooling load met (furnace outlet with respect to control zone temp)
    9991              :                               Real64 &LatentLoadMet,     // Latent cooling load met (furnace outlet with respect to control zone humidity ratio)
    9992              :                               Real64 const QZnReq,       // Zone load (W)
    9993              :                               Real64 const QLatReq,      // Zone latent load []
    9994              :                               Real64 &OnOffAirFlowRatio, // Ratio of compressor ON airflow to AVERAGE airflow over timestep
    9995              :                               Real64 const SupHeaterLoad // supplemental heater load (W)
    9996              :     )
    9997              :     {
    9998              :         // SUBROUTINE INFORMATION:
    9999              :         //       AUTHOR:          Bo Shen, based on HVACMultiSpeedHeatPump:CalcMSHeatPump
   10000              :         //       DATE WRITTEN:    March 2012
   10001              : 
   10002              :         // PURPOSE OF THIS SUBROUTINE:
   10003              :         //  This routine will calculates MSHP performance based on given system load
   10004              : 
   10005            0 :         Real64 SavePartloadRatio = 0.0; // part-load ratio
   10006            0 :         Real64 SaveSpeedRatio = 0.0;    // speed ratio
   10007            0 :         Real64 QCoilActual = 0.0;       // coil load actually delivered returned to calling component
   10008            0 :         Real64 HeatCoilLoad = 0.0;      // required heating coil load
   10009              : 
   10010            0 :         state.dataFurnaces->SaveCompressorPLR = 0.0;
   10011              : 
   10012              :         // Set inlet air mass flow rate based on PLR and compressor on/off air flow rates
   10013            0 :         SetVSHPAirFlow(state, FurnaceNum, PartLoadFrac, OnOffAirFlowRatio, SpeedNum, SpeedRatio);
   10014              : 
   10015            0 :         auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
   10016              : 
   10017            0 :         if ((SupHeaterLoad > 1.0e-10) && (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatCool) && (thisFurnace.SuppHeatCoilIndex == 0)) {
   10018              :             // ONLY HEATING COIL, NO SUPPLEMENTAL COIL, USED FOR REHEAT DURING DUHMI
   10019            0 :             HeatCoilLoad = thisFurnace.DesignHeatingCapacity * PartLoadFrac; // REHEAT IN FAN ON TIME
   10020              : 
   10021            0 :             if (HeatCoilLoad > SupHeaterLoad) HeatCoilLoad = SupHeaterLoad; // HEATING COIL RUN TIME < FAN ON TIME
   10022              : 
   10023            0 :         } else if ((QZnReq > HVAC::SmallLoad) && (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatCool)) {
   10024            0 :             HeatCoilLoad = thisFurnace.DesignHeatingCapacity * PartLoadFrac;
   10025              :         } else {
   10026            0 :             HeatCoilLoad = 0.0;
   10027              :         }
   10028              : 
   10029            0 :         Real64 AirMassFlow = state.dataLoopNodes->Node(thisFurnace.FurnaceInletNodeNum).MassFlowRate;
   10030              :         // if blow through, simulate fan then coils
   10031            0 :         if (thisFurnace.fanPlace == HVAC::FanPlace::BlowThru) {
   10032            0 :             state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
   10033              : 
   10034            0 :             if ((!thisFurnace.CoolingCoilUpstream) && (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatCool)) {
   10035              :                 // simulate thisFurnace heating coil
   10036            0 :                 bool SuppHeatingCoilFlag = false; // if true simulates supplemental heating coil
   10037            0 :                 CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, thisFurnace.fanOp, QCoilActual);
   10038              :             }
   10039              : 
   10040            0 :             if ((QZnReq < -HVAC::SmallLoad || (QLatReq < -HVAC::SmallLoad)) &&
   10041            0 :                 (state.dataEnvrn->OutDryBulbTemp >= thisFurnace.MinOATCompressorCooling)) { // COOLING MODE or dehumidification mode
   10042              : 
   10043            0 :                 if (thisFurnace.bIsIHP) {
   10044            0 :                     IntegratedHeatPump::SimIHP(state,
   10045              :                                                BlankString,
   10046            0 :                                                thisFurnace.CoolingCoilIndex,
   10047              :                                                thisFurnace.fanOp,
   10048              :                                                compressorOp,
   10049              :                                                PartLoadFrac,
   10050              :                                                SpeedNum,
   10051              :                                                SpeedRatio,
   10052              :                                                QZnReq,
   10053              :                                                QLatReq,
   10054              :                                                false,
   10055              :                                                false,
   10056              :                                                OnOffAirFlowRatio);
   10057              :                 } else {
   10058            0 :                     VariableSpeedCoils::SimVariableSpeedCoils(state,
   10059              :                                                               BlankString,
   10060            0 :                                                               thisFurnace.CoolingCoilIndex,
   10061              :                                                               thisFurnace.fanOp,
   10062              :                                                               compressorOp,
   10063              :                                                               PartLoadFrac,
   10064              :                                                               SpeedNum,
   10065              :                                                               SpeedRatio,
   10066              :                                                               QZnReq,
   10067              :                                                               QLatReq,
   10068              :                                                               OnOffAirFlowRatio);
   10069              :                 }
   10070              : 
   10071            0 :                 SavePartloadRatio = PartLoadFrac;
   10072            0 :                 SaveSpeedRatio = SpeedRatio;
   10073              : 
   10074            0 :                 state.dataFurnaces->SaveCompressorPLR = state.dataVariableSpeedCoils->VarSpeedCoil(thisFurnace.CoolingCoilIndex).PartLoadRatio;
   10075              :             } else {
   10076            0 :                 if (thisFurnace.bIsIHP) {
   10077            0 :                     IntegratedHeatPump::SimIHP(state,
   10078              :                                                BlankString,
   10079            0 :                                                thisFurnace.CoolingCoilIndex,
   10080              :                                                thisFurnace.fanOp,
   10081              :                                                compressorOp,
   10082              :                                                PartLoadFrac,
   10083              :                                                SpeedNum,
   10084              :                                                SpeedRatio,
   10085              :                                                QZnReq,
   10086              :                                                QLatReq,
   10087              :                                                false,
   10088              :                                                false,
   10089              :                                                OnOffAirFlowRatio);
   10090              :                 } else {
   10091            0 :                     VariableSpeedCoils::SimVariableSpeedCoils(
   10092            0 :                         state, BlankString, thisFurnace.CoolingCoilIndex, thisFurnace.fanOp, compressorOp, 0.0, 1, 0.0, 0.0, 0.0, OnOffAirFlowRatio);
   10093              :                 }
   10094              :             }
   10095              : 
   10096            0 :             if (thisFurnace.type != HVAC::UnitarySysType::Unitary_HeatCool) {
   10097            0 :                 if ((QZnReq > HVAC::SmallLoad) && state.dataFurnaces->HeatingLoad) {
   10098            0 :                     if (thisFurnace.bIsIHP) {
   10099            0 :                         IntegratedHeatPump::SimIHP(state,
   10100              :                                                    BlankString,
   10101            0 :                                                    thisFurnace.HeatingCoilIndex,
   10102              :                                                    thisFurnace.fanOp,
   10103              :                                                    compressorOp,
   10104              :                                                    PartLoadFrac,
   10105              :                                                    SpeedNum,
   10106              :                                                    SpeedRatio,
   10107              :                                                    QZnReq,
   10108              :                                                    QLatReq,
   10109              :                                                    false,
   10110              :                                                    false,
   10111              :                                                    OnOffAirFlowRatio);
   10112              :                     } else {
   10113            0 :                         VariableSpeedCoils::SimVariableSpeedCoils(state,
   10114              :                                                                   BlankString,
   10115            0 :                                                                   thisFurnace.HeatingCoilIndex,
   10116              :                                                                   thisFurnace.fanOp,
   10117              :                                                                   compressorOp,
   10118              :                                                                   PartLoadFrac,
   10119              :                                                                   SpeedNum,
   10120              :                                                                   SpeedRatio,
   10121              :                                                                   QZnReq,
   10122              :                                                                   QLatReq,
   10123              :                                                                   OnOffAirFlowRatio);
   10124              :                     }
   10125              : 
   10126            0 :                     SavePartloadRatio = PartLoadFrac;
   10127            0 :                     SaveSpeedRatio = SpeedRatio;
   10128              : 
   10129            0 :                     state.dataFurnaces->SaveCompressorPLR = state.dataVariableSpeedCoils->VarSpeedCoil(thisFurnace.HeatingCoilIndex).PartLoadRatio;
   10130              :                 } else {
   10131            0 :                     if (thisFurnace.bIsIHP) {
   10132            0 :                         IntegratedHeatPump::SimIHP(state,
   10133              :                                                    BlankString,
   10134            0 :                                                    thisFurnace.CoolingCoilIndex,
   10135              :                                                    thisFurnace.fanOp,
   10136              :                                                    compressorOp,
   10137              :                                                    PartLoadFrac,
   10138              :                                                    SpeedNum,
   10139              :                                                    SpeedRatio,
   10140              :                                                    QZnReq,
   10141              :                                                    QLatReq,
   10142              :                                                    false,
   10143              :                                                    false,
   10144              :                                                    OnOffAirFlowRatio);
   10145              :                     } else {
   10146            0 :                         VariableSpeedCoils::SimVariableSpeedCoils(state,
   10147              :                                                                   BlankString,
   10148            0 :                                                                   thisFurnace.HeatingCoilIndex,
   10149              :                                                                   thisFurnace.fanOp,
   10150              :                                                                   compressorOp,
   10151              :                                                                   0.0,
   10152              :                                                                   1,
   10153              :                                                                   0.0,
   10154              :                                                                   0.0,
   10155              :                                                                   0.0,
   10156              :                                                                   OnOffAirFlowRatio);
   10157              :                     }
   10158              :                 }
   10159            0 :             } else if (thisFurnace.CoolingCoilUpstream && (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatCool)) {
   10160              :                 // simulate thisFurnace heating coil
   10161            0 :                 bool SuppHeatingCoilFlag = false; // if true simulates supplemental heating coil
   10162            0 :                 CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, thisFurnace.fanOp, QCoilActual);
   10163              :             }
   10164              : 
   10165              :             // Call twice to ensure the fan outlet conditions are updated
   10166            0 :             state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
   10167              : 
   10168            0 :             if ((!thisFurnace.CoolingCoilUpstream) && (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatCool)) {
   10169              :                 // simulate thisFurnace heating coil
   10170            0 :                 bool SuppHeatingCoilFlag = false; // if true simulates supplemental heating coil
   10171            0 :                 CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, thisFurnace.fanOp, QCoilActual);
   10172              :             }
   10173              : 
   10174            0 :             if ((QZnReq < -HVAC::SmallLoad || (QLatReq < -HVAC::SmallLoad)) &&
   10175            0 :                 (state.dataEnvrn->OutDryBulbTemp >= thisFurnace.MinOATCompressorCooling)) {
   10176              : 
   10177            0 :                 if (thisFurnace.bIsIHP) {
   10178            0 :                     IntegratedHeatPump::SimIHP(state,
   10179              :                                                BlankString,
   10180            0 :                                                thisFurnace.CoolingCoilIndex,
   10181              :                                                thisFurnace.fanOp,
   10182              :                                                compressorOp,
   10183              :                                                PartLoadFrac,
   10184              :                                                SpeedNum,
   10185              :                                                SpeedRatio,
   10186              :                                                QZnReq,
   10187              :                                                QLatReq,
   10188              :                                                false,
   10189              :                                                false,
   10190              :                                                OnOffAirFlowRatio);
   10191              :                 } else {
   10192            0 :                     VariableSpeedCoils::SimVariableSpeedCoils(state,
   10193              :                                                               BlankString,
   10194            0 :                                                               thisFurnace.CoolingCoilIndex,
   10195              :                                                               thisFurnace.fanOp,
   10196              :                                                               compressorOp,
   10197              :                                                               PartLoadFrac,
   10198              :                                                               SpeedNum,
   10199              :                                                               SpeedRatio,
   10200              :                                                               QZnReq,
   10201              :                                                               QLatReq,
   10202              :                                                               OnOffAirFlowRatio);
   10203              :                 }
   10204              : 
   10205            0 :                 SavePartloadRatio = PartLoadFrac;
   10206            0 :                 SaveSpeedRatio = SpeedRatio;
   10207            0 :                 state.dataFurnaces->SaveCompressorPLR = state.dataVariableSpeedCoils->VarSpeedCoil(thisFurnace.CoolingCoilIndex).PartLoadRatio;
   10208              :             } else {
   10209              : 
   10210            0 :                 if (thisFurnace.bIsIHP) {
   10211            0 :                     IntegratedHeatPump::SimIHP(state,
   10212              :                                                BlankString,
   10213            0 :                                                thisFurnace.CoolingCoilIndex,
   10214              :                                                thisFurnace.fanOp,
   10215              :                                                compressorOp,
   10216              :                                                PartLoadFrac,
   10217              :                                                SpeedNum,
   10218              :                                                SpeedRatio,
   10219              :                                                QZnReq,
   10220              :                                                QLatReq,
   10221              :                                                false,
   10222              :                                                false,
   10223              :                                                OnOffAirFlowRatio);
   10224              :                 } else {
   10225            0 :                     VariableSpeedCoils::SimVariableSpeedCoils(
   10226            0 :                         state, BlankString, thisFurnace.CoolingCoilIndex, thisFurnace.fanOp, compressorOp, 0.0, 1, 0.0, 0.0, 0.0, OnOffAirFlowRatio);
   10227              :                 }
   10228              :             }
   10229              : 
   10230            0 :             if (thisFurnace.type != HVAC::UnitarySysType::Unitary_HeatCool) {
   10231            0 :                 if ((QZnReq > HVAC::SmallLoad) && state.dataFurnaces->HeatingLoad) {
   10232            0 :                     if (thisFurnace.bIsIHP) {
   10233            0 :                         IntegratedHeatPump::SimIHP(state,
   10234              :                                                    BlankString,
   10235            0 :                                                    thisFurnace.HeatingCoilIndex,
   10236              :                                                    thisFurnace.fanOp,
   10237              :                                                    compressorOp,
   10238              :                                                    PartLoadFrac,
   10239              :                                                    SpeedNum,
   10240              :                                                    SpeedRatio,
   10241              :                                                    QZnReq,
   10242              :                                                    QLatReq,
   10243              :                                                    false,
   10244              :                                                    false,
   10245              :                                                    OnOffAirFlowRatio);
   10246              :                     } else {
   10247            0 :                         VariableSpeedCoils::SimVariableSpeedCoils(state,
   10248              :                                                                   BlankString,
   10249            0 :                                                                   thisFurnace.HeatingCoilIndex,
   10250              :                                                                   thisFurnace.fanOp,
   10251              :                                                                   compressorOp,
   10252              :                                                                   PartLoadFrac,
   10253              :                                                                   SpeedNum,
   10254              :                                                                   SpeedRatio,
   10255              :                                                                   QZnReq,
   10256              :                                                                   QLatReq,
   10257              :                                                                   OnOffAirFlowRatio);
   10258              :                     }
   10259              : 
   10260            0 :                     SavePartloadRatio = PartLoadFrac;
   10261            0 :                     SaveSpeedRatio = SpeedRatio;
   10262            0 :                     state.dataFurnaces->SaveCompressorPLR = state.dataVariableSpeedCoils->VarSpeedCoil(thisFurnace.HeatingCoilIndex).PartLoadRatio;
   10263              :                 } else {
   10264            0 :                     if (thisFurnace.bIsIHP) {
   10265            0 :                         IntegratedHeatPump::SimIHP(state,
   10266              :                                                    BlankString,
   10267            0 :                                                    thisFurnace.CoolingCoilIndex,
   10268              :                                                    thisFurnace.fanOp,
   10269              :                                                    compressorOp,
   10270              :                                                    PartLoadFrac,
   10271              :                                                    SpeedNum,
   10272              :                                                    SpeedRatio,
   10273              :                                                    QZnReq,
   10274              :                                                    QLatReq,
   10275              :                                                    false,
   10276              :                                                    false,
   10277              :                                                    OnOffAirFlowRatio);
   10278              :                     } else {
   10279            0 :                         VariableSpeedCoils::SimVariableSpeedCoils(state,
   10280              :                                                                   BlankString,
   10281            0 :                                                                   thisFurnace.HeatingCoilIndex,
   10282              :                                                                   thisFurnace.fanOp,
   10283              :                                                                   compressorOp,
   10284              :                                                                   0.0,
   10285              :                                                                   1,
   10286              :                                                                   0.0,
   10287              :                                                                   0.0,
   10288              :                                                                   0.0,
   10289              :                                                                   OnOffAirFlowRatio);
   10290              :                     }
   10291              :                 }
   10292            0 :             } else if (thisFurnace.CoolingCoilUpstream && (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatCool)) {
   10293              :                 // simulate thisFurnace heating coil
   10294            0 :                 bool SuppHeatingCoilFlag = false; // if true simulates supplemental heating coil
   10295            0 :                 CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, thisFurnace.fanOp, QCoilActual);
   10296              :             }
   10297              : 
   10298              :             //  Simulate supplemental heating coil for blow through fan
   10299            0 :             if (thisFurnace.SuppHeatCoilIndex > 0) {
   10300            0 :                 bool SuppHeatingCoilFlag = true; // if true simulates supplemental heating coil
   10301            0 :                 CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, SupHeaterLoad, thisFurnace.fanOp, QCoilActual);
   10302              :             }
   10303              :         } else { // otherwise simulate DX coils then fan then supplemental heater
   10304              : 
   10305            0 :             if ((!thisFurnace.CoolingCoilUpstream) && (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatCool)) {
   10306              :                 // simulate thisFurnace heating coil
   10307            0 :                 bool SuppHeatingCoilFlag = false; // if true simulates supplemental heating coil
   10308            0 :                 CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, thisFurnace.fanOp, QCoilActual);
   10309              :             }
   10310              : 
   10311            0 :             if ((QZnReq < -HVAC::SmallLoad || (QLatReq < -HVAC::SmallLoad)) &&
   10312            0 :                 (state.dataEnvrn->OutDryBulbTemp >= thisFurnace.MinOATCompressorCooling)) {
   10313              : 
   10314            0 :                 if (thisFurnace.bIsIHP) {
   10315            0 :                     IntegratedHeatPump::SimIHP(state,
   10316              :                                                BlankString,
   10317            0 :                                                thisFurnace.CoolingCoilIndex,
   10318              :                                                thisFurnace.fanOp,
   10319              :                                                compressorOp,
   10320              :                                                PartLoadFrac,
   10321              :                                                SpeedNum,
   10322              :                                                SpeedRatio,
   10323              :                                                QZnReq,
   10324              :                                                QLatReq,
   10325              :                                                false,
   10326              :                                                false,
   10327              :                                                OnOffAirFlowRatio);
   10328              :                 } else {
   10329            0 :                     VariableSpeedCoils::SimVariableSpeedCoils(state,
   10330              :                                                               BlankString,
   10331            0 :                                                               thisFurnace.CoolingCoilIndex,
   10332              :                                                               thisFurnace.fanOp,
   10333              :                                                               compressorOp,
   10334              :                                                               PartLoadFrac,
   10335              :                                                               SpeedNum,
   10336              :                                                               SpeedRatio,
   10337              :                                                               QZnReq,
   10338              :                                                               QLatReq,
   10339              :                                                               OnOffAirFlowRatio);
   10340              :                 }
   10341              : 
   10342            0 :                 SavePartloadRatio = PartLoadFrac;
   10343            0 :                 SaveSpeedRatio = SpeedRatio;
   10344              : 
   10345            0 :                 state.dataFurnaces->SaveCompressorPLR = state.dataVariableSpeedCoils->VarSpeedCoil(thisFurnace.CoolingCoilIndex).PartLoadRatio;
   10346              :             } else {
   10347            0 :                 if (thisFurnace.bIsIHP) {
   10348            0 :                     IntegratedHeatPump::SimIHP(state,
   10349              :                                                BlankString,
   10350            0 :                                                thisFurnace.CoolingCoilIndex,
   10351              :                                                thisFurnace.fanOp,
   10352              :                                                compressorOp,
   10353              :                                                PartLoadFrac,
   10354              :                                                SpeedNum,
   10355              :                                                SpeedRatio,
   10356              :                                                QZnReq,
   10357              :                                                QLatReq,
   10358              :                                                false,
   10359              :                                                false,
   10360              :                                                OnOffAirFlowRatio);
   10361              :                 } else {
   10362            0 :                     VariableSpeedCoils::SimVariableSpeedCoils(
   10363            0 :                         state, BlankString, thisFurnace.CoolingCoilIndex, thisFurnace.fanOp, compressorOp, 0.0, 1, 0.0, 0.0, 0.0, OnOffAirFlowRatio);
   10364              :                 }
   10365              :             }
   10366              : 
   10367            0 :             if (thisFurnace.type != HVAC::UnitarySysType::Unitary_HeatCool) {
   10368            0 :                 if (QZnReq > HVAC::SmallLoad && (state.dataEnvrn->OutDryBulbTemp >= thisFurnace.MinOATCompressorCooling)) {
   10369              : 
   10370            0 :                     if (thisFurnace.bIsIHP) {
   10371            0 :                         IntegratedHeatPump::SimIHP(state,
   10372              :                                                    BlankString,
   10373            0 :                                                    thisFurnace.HeatingCoilIndex,
   10374              :                                                    thisFurnace.fanOp,
   10375              :                                                    compressorOp,
   10376              :                                                    PartLoadFrac,
   10377              :                                                    SpeedNum,
   10378              :                                                    SpeedRatio,
   10379              :                                                    QZnReq,
   10380              :                                                    QLatReq,
   10381              :                                                    false,
   10382              :                                                    false,
   10383              :                                                    OnOffAirFlowRatio);
   10384              :                     } else {
   10385            0 :                         VariableSpeedCoils::SimVariableSpeedCoils(state,
   10386              :                                                                   BlankString,
   10387            0 :                                                                   thisFurnace.HeatingCoilIndex,
   10388              :                                                                   thisFurnace.fanOp,
   10389              :                                                                   compressorOp,
   10390              :                                                                   PartLoadFrac,
   10391              :                                                                   SpeedNum,
   10392              :                                                                   SpeedRatio,
   10393              :                                                                   QZnReq,
   10394              :                                                                   QLatReq,
   10395              :                                                                   OnOffAirFlowRatio);
   10396              :                     }
   10397              : 
   10398            0 :                     SavePartloadRatio = PartLoadFrac;
   10399            0 :                     SaveSpeedRatio = SpeedRatio;
   10400            0 :                     state.dataFurnaces->SaveCompressorPLR = state.dataVariableSpeedCoils->VarSpeedCoil(thisFurnace.HeatingCoilIndex).PartLoadRatio;
   10401              :                 } else {
   10402            0 :                     if (thisFurnace.bIsIHP) {
   10403            0 :                         IntegratedHeatPump::SimIHP(state,
   10404              :                                                    BlankString,
   10405            0 :                                                    thisFurnace.CoolingCoilIndex,
   10406              :                                                    thisFurnace.fanOp,
   10407              :                                                    compressorOp,
   10408              :                                                    PartLoadFrac,
   10409              :                                                    SpeedNum,
   10410              :                                                    SpeedRatio,
   10411              :                                                    QZnReq,
   10412              :                                                    QLatReq,
   10413              :                                                    false,
   10414              :                                                    false,
   10415              :                                                    OnOffAirFlowRatio);
   10416              :                     } else {
   10417            0 :                         VariableSpeedCoils::SimVariableSpeedCoils(state,
   10418              :                                                                   BlankString,
   10419            0 :                                                                   thisFurnace.HeatingCoilIndex,
   10420              :                                                                   thisFurnace.fanOp,
   10421              :                                                                   compressorOp,
   10422              :                                                                   0.0,
   10423              :                                                                   1,
   10424              :                                                                   0.0,
   10425              :                                                                   0.0,
   10426              :                                                                   0.0,
   10427              :                                                                   OnOffAirFlowRatio);
   10428              :                     }
   10429              :                 }
   10430            0 :             } else if (thisFurnace.CoolingCoilUpstream && (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatCool)) {
   10431              :                 // simulate thisFurnace heating coil
   10432            0 :                 bool SuppHeatingCoilFlag = false; // if true simulates supplemental heating coil
   10433            0 :                 CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, HeatCoilLoad, thisFurnace.fanOp, QCoilActual);
   10434              :             }
   10435              : 
   10436            0 :             state.dataFans->fans(thisFurnace.FanIndex)->simulate(state, FirstHVACIteration, state.dataFurnaces->FanSpeedRatio);
   10437              :             //  Simulate supplemental heating coil for draw through fan
   10438            0 :             if (thisFurnace.SuppHeatCoilIndex > 0) {
   10439            0 :                 bool SuppHeatingCoilFlag = true; // if true simulates supplemental heating coil
   10440            0 :                 CalcNonDXHeatingCoils(state, FurnaceNum, SuppHeatingCoilFlag, FirstHVACIteration, SupHeaterLoad, thisFurnace.fanOp, QCoilActual);
   10441              :             }
   10442              :         }
   10443              : 
   10444              :         // If the fan runs continually do not allow coils to set OnOffFanPartLoadRatio.
   10445            0 :         if (thisFurnace.fanOp == HVAC::FanOp::Continuous) state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
   10446              : 
   10447            0 :         auto &outNode = state.dataLoopNodes->Node(thisFurnace.FurnaceOutletNodeNum);
   10448            0 :         auto &zoneNode = state.dataLoopNodes->Node(thisFurnace.NodeNumOfControlledZone);
   10449            0 :         Real64 zoneEnthalpy = Psychrometrics::PsyHFnTdbW(zoneNode.Temp, zoneNode.HumRat);
   10450            0 :         Real64 outletEnthalpy = Psychrometrics::PsyHFnTdbW(outNode.Temp, outNode.HumRat);
   10451            0 :         Real64 totalLoadMet = AirMassFlow * (outletEnthalpy - zoneEnthalpy);
   10452            0 :         SensibleLoadMet =
   10453            0 :             AirMassFlow * Psychrometrics::PsyDeltaHSenFnTdb2W2Tdb1W1(outNode.Temp, outNode.HumRat, zoneNode.Temp, zoneNode.HumRat); // sensible {W};
   10454            0 :         LatentLoadMet = totalLoadMet - SensibleLoadMet;
   10455            0 :         thisFurnace.LatentLoadMet = LatentLoadMet;
   10456            0 :     }
   10457              : 
   10458              :     //******************************************************************************
   10459              : 
   10460            0 :     Real64 VSHPCyclingResidual(EnergyPlusData &state,
   10461              :                                Real64 const PartLoadFrac, // compressor cycling ratio (1.0 is continuous, 0.0 is off)
   10462              :                                int FurnaceNum,
   10463              :                                // int ZoneNum,
   10464              :                                bool FirstHVACIteration,
   10465              :                                // int fanOp,
   10466              :                                Real64 LoadToBeMet,
   10467              :                                Real64 OnOffAirFlowRatio,
   10468              :                                Real64 SupHeaterLoad,
   10469              :                                HVAC::CompressorOp compressorOp,
   10470              :                                Real64 par9_SensLatFlag)
   10471              :     {
   10472              :         // FUNCTION INFORMATION:
   10473              :         //       AUTHOR         Bo Shen, based on HVACMultiSpeedHeatPump:MSHPCyclingResidual
   10474              :         //       DATE WRITTEN   March, 2012
   10475              : 
   10476              :         // PURPOSE OF THIS FUNCTION:
   10477              :         //  Calculates residual function ((ActualOutput - QZnReq)/QZnReq)
   10478              :         //  MSHP output depends on the part load ratio which is being varied to zero the residual.
   10479              : 
   10480              :         // METHODOLOGY EMPLOYED:
   10481              :         //  Calls CalcMSHeatPump to get ActualOutput at the given part load ratio
   10482              :         //  and calculates the residual as defined above
   10483              : 
   10484              :         // int FurnaceNum = int(Par[0]);
   10485              :         // int ZoneNum = int(Par[1]);
   10486              :         // bool FirstHVACIteration = (Par[2] == 1.0);
   10487              :         // int fanOp = int(Par[3]);
   10488              :         // Real64 LoadToBeMet = Par[4];
   10489              :         // Real64 OnOffAirFlowRatio = Par[5];
   10490              :         // Real64 SupHeaterLoad = Par[6];
   10491              :         // CompressorOperation CompressorOp = static_cast<CompressorOperation>(Par[8]);
   10492              :         // Real64 par9_SensLatFlag = Par[9];
   10493              : 
   10494              :         // FUNCTION LOCAL VARIABLE DECLARATIONS:
   10495              :         Real64 ZoneSensLoadMet; // delivered sensible capacity of MSHP
   10496              :         Real64 ZoneLatLoadMet;  // delivered latent capacity of MSHP
   10497              : 
   10498            0 :         Real64 QZnReq = 0.0;
   10499            0 :         Real64 QZnLat = 0.0;
   10500            0 :         if (par9_SensLatFlag == 1.0) {
   10501            0 :             QZnReq = LoadToBeMet;
   10502              :         } else {
   10503            0 :             QZnLat = LoadToBeMet;
   10504              :         }
   10505              : 
   10506            0 :         CalcVarSpeedHeatPump(state,
   10507              :                              FurnaceNum,
   10508              :                              FirstHVACIteration,
   10509              :                              compressorOp,
   10510              :                              1,
   10511              :                              0.0,
   10512              :                              PartLoadFrac,
   10513              :                              ZoneSensLoadMet,
   10514              :                              ZoneLatLoadMet,
   10515              :                              QZnReq,
   10516              :                              QZnLat,
   10517              :                              OnOffAirFlowRatio,
   10518              :                              SupHeaterLoad);
   10519              : 
   10520            0 :         Real64 ResScale = std::abs(LoadToBeMet);
   10521            0 :         if (ResScale < 100.0) {
   10522            0 :             ResScale = 100.0;
   10523              :         } else {
   10524            0 :             ResScale = LoadToBeMet;
   10525              :         }
   10526              : 
   10527              :         // Calculate residual based on output calculation flag
   10528            0 :         if (par9_SensLatFlag == 1.0) {
   10529            0 :             return (ZoneSensLoadMet - LoadToBeMet) / ResScale;
   10530              :         } else {
   10531            0 :             return (ZoneLatLoadMet - LoadToBeMet) / ResScale;
   10532              :         }
   10533              :     }
   10534              : 
   10535              :     //******************************************************************************
   10536              : 
   10537            0 :     Real64 VSHPSpeedResidual(EnergyPlusData &state,
   10538              :                              Real64 const SpeedRatio, // compressor cycling ratio (1.0 is continuous, 0.0 is off)
   10539              :                              int FurnaceNum,
   10540              :                              // int ZoneNum,
   10541              :                              bool FirstHVACIteration,
   10542              :                              // int fanOp
   10543              :                              Real64 LoadToBeMet,
   10544              :                              Real64 OnOffAirFlowRatio,
   10545              :                              Real64 SupHeaterLoad,
   10546              :                              int SpeedNum,
   10547              :                              HVAC::CompressorOp compressorOp,
   10548              :                              Real64 par9_SensLatFlag)
   10549              :     {
   10550              :         // FUNCTION INFORMATION:
   10551              :         //       AUTHOR         Bo Shen, , based on HVACMultiSpeedHeatPump:MSHPVarSpeedgResidual
   10552              :         //       DATE WRITTEN   March, 2012
   10553              : 
   10554              :         // PURPOSE OF THIS FUNCTION:
   10555              :         //  Calculates residual function ((ActualOutput - QZnReq)/QZnReq)
   10556              :         //  MSHP output depends on the part load ratio which is being varied to zero the residual.
   10557              : 
   10558              :         // METHODOLOGY EMPLOYED:
   10559              :         //  Calls CalcMSHeatPump to get ActualOutput at the given speed ratio (partload ratio for high speed)
   10560              :         //  and calculates the residual as defined above
   10561              : 
   10562            0 :         Real64 QZnReq = 0.0;
   10563            0 :         Real64 QZnLat = 0.0;
   10564            0 :         if (par9_SensLatFlag == 1.0) {
   10565            0 :             QZnReq = LoadToBeMet;
   10566              :         } else {
   10567            0 :             QZnLat = LoadToBeMet;
   10568              :         }
   10569              : 
   10570              :         Real64 ZoneSensLoadMet; // delivered sensible capacity of MSHP
   10571              :         Real64 ZoneLatLoadMet;  // delivered latent capacity of MSHP
   10572            0 :         CalcVarSpeedHeatPump(state,
   10573              :                              FurnaceNum,
   10574              :                              FirstHVACIteration,
   10575              :                              compressorOp,
   10576              :                              SpeedNum,
   10577              :                              SpeedRatio,
   10578              :                              1.0,
   10579              :                              ZoneSensLoadMet,
   10580              :                              ZoneLatLoadMet,
   10581              :                              QZnReq,
   10582              :                              QZnLat,
   10583              :                              OnOffAirFlowRatio,
   10584              :                              SupHeaterLoad);
   10585              : 
   10586            0 :         Real64 ResScale = std::abs(LoadToBeMet);
   10587            0 :         if (ResScale < 100.0) {
   10588            0 :             ResScale = 100.0;
   10589              :         } else {
   10590            0 :             ResScale = LoadToBeMet;
   10591              :         }
   10592              : 
   10593              :         // Calculate residual based on output calculation flag
   10594            0 :         if (par9_SensLatFlag == 1.0) {
   10595            0 :             return (ZoneSensLoadMet - LoadToBeMet) / ResScale;
   10596              :         } else {
   10597            0 :             return (ZoneLatLoadMet - LoadToBeMet) / ResScale;
   10598              :         }
   10599              :     }
   10600              : 
   10601            9 :     void SetVSHPAirFlow(EnergyPlusData &state,
   10602              :                         int const FurnaceNum,                        // Unit index
   10603              :                         Real64 const PartLoadRatio,                  // unit part load ratio
   10604              :                         Real64 &OnOffAirFlowRatio,                   // ratio of compressor ON airflow to average airflow over timestep
   10605              :                         ObjexxFCL::Optional_int_const SpeedNum,      // Speed number
   10606              :                         ObjexxFCL::Optional<Real64 const> SpeedRatio // Speed ratio
   10607              :     )
   10608              :     {
   10609              : 
   10610              :         // SUBROUTINE INFORMATION:
   10611              :         //       AUTHOR         Bo Shen, based on HVACMultiSpeedHeatPump:SetAverageAirFlow
   10612              :         //       DATE WRITTEN   March, 2012
   10613              : 
   10614              :         // PURPOSE OF THIS SUBROUTINE:
   10615              :         // Set the average air mass flow rates using the part load fraction of the heat pump for this time step
   10616              :         // Set OnOffAirFlowRatio to be used by DX coils
   10617              : 
   10618              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
   10619              :         Real64 AverageUnitMassFlow; // average supply air mass flow rate over time step
   10620              : 
   10621            9 :         auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
   10622              : 
   10623            9 :         state.dataHVACGlobal->MSHPMassFlowRateLow = 0.0;  // Mass flow rate at low speed
   10624            9 :         state.dataHVACGlobal->MSHPMassFlowRateHigh = 0.0; // Mass flow rate at high speed
   10625              : 
   10626            9 :         if (thisFurnace.fanOp == HVAC::FanOp::Continuous) {
   10627            1 :             state.dataFurnaces->CompOffMassFlow = thisFurnace.IdleMassFlowRate;
   10628            1 :             state.dataFurnaces->CompOffFlowRatio = thisFurnace.IdleSpeedRatio;
   10629              :         } else {
   10630            8 :             state.dataFurnaces->CompOffMassFlow = 0.0;
   10631            8 :             state.dataFurnaces->CompOffFlowRatio = 0.0;
   10632              :         }
   10633              : 
   10634            9 :         if (state.dataFurnaces->CoolingLoad && (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatCool)) {
   10635            3 :             if (thisFurnace.NumOfSpeedCooling > 0) {
   10636            3 :                 state.dataFurnaces->CompOnMassFlow = thisFurnace.CoolMassFlowRate(thisFurnace.NumOfSpeedCooling);
   10637            3 :                 state.dataFurnaces->CompOnFlowRatio = thisFurnace.MSCoolingSpeedRatio(thisFurnace.NumOfSpeedCooling);
   10638            3 :                 state.dataHVACGlobal->MSHPMassFlowRateLow = thisFurnace.CoolMassFlowRate(thisFurnace.NumOfSpeedCooling);
   10639            3 :                 state.dataHVACGlobal->MSHPMassFlowRateHigh = thisFurnace.CoolMassFlowRate(thisFurnace.NumOfSpeedCooling);
   10640              :             } else {
   10641            0 :                 state.dataFurnaces->CompOnMassFlow = thisFurnace.MaxCoolAirMassFlow;
   10642            0 :                 state.dataFurnaces->CompOnFlowRatio = thisFurnace.CoolingSpeedRatio;
   10643              :             }
   10644            3 :             AverageUnitMassFlow = (PartLoadRatio * state.dataFurnaces->CompOnMassFlow) + ((1 - PartLoadRatio) * state.dataFurnaces->CompOffMassFlow);
   10645            3 :             if (state.dataFurnaces->CompOffFlowRatio > 0.0) {
   10646            0 :                 state.dataFurnaces->FanSpeedRatio =
   10647            0 :                     (PartLoadRatio * state.dataFurnaces->CompOnFlowRatio) + ((1 - PartLoadRatio) * state.dataFurnaces->CompOffFlowRatio);
   10648              :             } else {
   10649            3 :                 state.dataFurnaces->FanSpeedRatio = state.dataFurnaces->CompOnFlowRatio;
   10650              :             }
   10651            6 :         } else if (state.dataFurnaces->HeatingLoad && (thisFurnace.type == HVAC::UnitarySysType::Unitary_HeatCool)) {
   10652            6 :             if (thisFurnace.NumOfSpeedHeating > 0) {
   10653            4 :                 state.dataFurnaces->CompOnMassFlow = thisFurnace.HeatMassFlowRate(thisFurnace.NumOfSpeedHeating);
   10654            4 :                 state.dataFurnaces->CompOnFlowRatio = thisFurnace.MSHeatingSpeedRatio(thisFurnace.NumOfSpeedHeating);
   10655            4 :                 state.dataHVACGlobal->MSHPMassFlowRateLow = thisFurnace.HeatMassFlowRate(thisFurnace.NumOfSpeedHeating);
   10656            4 :                 state.dataHVACGlobal->MSHPMassFlowRateHigh = thisFurnace.HeatMassFlowRate(thisFurnace.NumOfSpeedHeating);
   10657              :             } else {
   10658            2 :                 state.dataFurnaces->CompOnMassFlow = thisFurnace.MaxHeatAirMassFlow;
   10659            2 :                 state.dataFurnaces->CompOnFlowRatio = thisFurnace.HeatingSpeedRatio;
   10660              :             }
   10661            6 :             AverageUnitMassFlow = (PartLoadRatio * state.dataFurnaces->CompOnMassFlow) + ((1 - PartLoadRatio) * state.dataFurnaces->CompOffMassFlow);
   10662            6 :             if (state.dataFurnaces->CompOffFlowRatio > 0.0) {
   10663            1 :                 state.dataFurnaces->FanSpeedRatio =
   10664            1 :                     (PartLoadRatio * state.dataFurnaces->CompOnFlowRatio) + ((1 - PartLoadRatio) * state.dataFurnaces->CompOffFlowRatio);
   10665              :             } else {
   10666            5 :                 state.dataFurnaces->FanSpeedRatio = state.dataFurnaces->CompOnFlowRatio;
   10667              :             }
   10668            0 :         } else if (thisFurnace.bIsIHP) {
   10669            0 :             if (!state.dataZoneEnergyDemand->CurDeadBandOrSetback(thisFurnace.ControlZoneNum) && present(SpeedNum)) {
   10670              :                 // if(present(SpeedNum)) {
   10671            0 :                 state.dataFurnaces->CompOnMassFlow =
   10672            0 :                     IntegratedHeatPump::GetAirMassFlowRateIHP(state, thisFurnace.CoolingCoilIndex, SpeedNum, SpeedRatio, false);
   10673            0 :                 state.dataFurnaces->CompOnFlowRatio =
   10674            0 :                     state.dataFurnaces->CompOnMassFlow /
   10675            0 :                     IntegratedHeatPump::GetAirMassFlowRateIHP(
   10676              :                         state, thisFurnace.CoolingCoilIndex, IntegratedHeatPump::GetMaxSpeedNumIHP(state, thisFurnace.CoolingCoilIndex), 1.0, false);
   10677            0 :                 state.dataHVACGlobal->MSHPMassFlowRateLow =
   10678            0 :                     IntegratedHeatPump::GetAirMassFlowRateIHP(state, thisFurnace.CoolingCoilIndex, SpeedNum, 0.0, false);
   10679            0 :                 state.dataHVACGlobal->MSHPMassFlowRateHigh =
   10680            0 :                     IntegratedHeatPump::GetAirMassFlowRateIHP(state, thisFurnace.CoolingCoilIndex, SpeedNum, 1.0, false);
   10681              :             }
   10682              : 
   10683              :             // Set up fan flow rate during compressor off time
   10684            0 :             if (thisFurnace.fanOp == HVAC::FanOp::Continuous && present(SpeedNum)) {
   10685            0 :                 if (thisFurnace.AirFlowControl == AirFlowControlConstFan::UseCompressorOnFlow && state.dataFurnaces->CompOnMassFlow > 0.0) {
   10686            0 :                     state.dataFurnaces->CompOffMassFlow =
   10687            0 :                         IntegratedHeatPump::GetAirMassFlowRateIHP(state, thisFurnace.CoolingCoilIndex, SpeedNum, 1.0, false);
   10688            0 :                     state.dataFurnaces->CompOffFlowRatio =
   10689            0 :                         state.dataFurnaces->CompOffMassFlow /
   10690            0 :                         IntegratedHeatPump::GetAirMassFlowRateIHP(state,
   10691              :                                                                   thisFurnace.CoolingCoilIndex,
   10692              :                                                                   IntegratedHeatPump::GetMaxSpeedNumIHP(state, thisFurnace.CoolingCoilIndex),
   10693              :                                                                   1.0,
   10694              :                                                                   false);
   10695              :                 }
   10696              :             }
   10697              : 
   10698            0 :             if (present(SpeedNum)) {
   10699            0 :                 if (SpeedNum > 1) {
   10700            0 :                     AverageUnitMassFlow = state.dataFurnaces->CompOnMassFlow;
   10701            0 :                     state.dataFurnaces->FanSpeedRatio = state.dataFurnaces->CompOnFlowRatio;
   10702              :                 } else {
   10703            0 :                     AverageUnitMassFlow =
   10704            0 :                         (PartLoadRatio * state.dataFurnaces->CompOnMassFlow) + ((1 - PartLoadRatio) * state.dataFurnaces->CompOffMassFlow);
   10705            0 :                     if (state.dataFurnaces->CompOffFlowRatio > 0.0) {
   10706            0 :                         state.dataFurnaces->FanSpeedRatio =
   10707            0 :                             (PartLoadRatio * state.dataFurnaces->CompOnFlowRatio) + ((1 - PartLoadRatio) * state.dataFurnaces->CompOffFlowRatio);
   10708              :                     } else {
   10709            0 :                         state.dataFurnaces->FanSpeedRatio = state.dataFurnaces->CompOnFlowRatio;
   10710              :                     }
   10711              :                 }
   10712              :             } else {
   10713            0 :                 AverageUnitMassFlow =
   10714            0 :                     (PartLoadRatio * state.dataFurnaces->CompOnMassFlow) + ((1 - PartLoadRatio) * state.dataFurnaces->CompOffMassFlow);
   10715            0 :                 if (state.dataFurnaces->CompOffFlowRatio > 0.0) {
   10716            0 :                     state.dataFurnaces->FanSpeedRatio =
   10717            0 :                         (PartLoadRatio * state.dataFurnaces->CompOnFlowRatio) + ((1 - PartLoadRatio) * state.dataFurnaces->CompOffFlowRatio);
   10718              :                 } else {
   10719            0 :                     state.dataFurnaces->FanSpeedRatio = state.dataFurnaces->CompOnFlowRatio;
   10720              :                 }
   10721              :             }
   10722              : 
   10723            0 :             if (IntegratedHeatPump::IHPOperationMode::SCWHMatchWH ==
   10724            0 :                 state.dataIntegratedHP->IntegratedHeatPumps(thisFurnace.CoolingCoilIndex).CurMode) {
   10725            0 :                 state.dataFurnaces->CompOnMassFlow =
   10726            0 :                     IntegratedHeatPump::GetAirMassFlowRateIHP(state, thisFurnace.CoolingCoilIndex, SpeedNum, SpeedRatio, false);
   10727            0 :                 AverageUnitMassFlow = state.dataFurnaces->CompOnMassFlow;
   10728              :             }
   10729              :         } else {
   10730            0 :             if (!state.dataZoneEnergyDemand->CurDeadBandOrSetback(thisFurnace.ControlZoneNum) && present(SpeedNum)) {
   10731            0 :                 if (thisFurnace.HeatCoolMode == Furnaces::ModeOfOperation::HeatingMode) {
   10732            0 :                     if (SpeedNum == 1) {
   10733            0 :                         state.dataFurnaces->CompOnMassFlow = thisFurnace.HeatMassFlowRate(SpeedNum);
   10734            0 :                         state.dataFurnaces->CompOnFlowRatio = thisFurnace.MSHeatingSpeedRatio(SpeedNum);
   10735            0 :                         state.dataHVACGlobal->MSHPMassFlowRateLow = thisFurnace.HeatMassFlowRate(1);
   10736            0 :                         state.dataHVACGlobal->MSHPMassFlowRateHigh = thisFurnace.HeatMassFlowRate(1);
   10737            0 :                     } else if (SpeedNum > 1) {
   10738            0 :                         state.dataFurnaces->CompOnMassFlow =
   10739            0 :                             SpeedRatio * thisFurnace.HeatMassFlowRate(SpeedNum) + (1.0 - SpeedRatio) * thisFurnace.HeatMassFlowRate(SpeedNum - 1);
   10740            0 :                         state.dataFurnaces->CompOnFlowRatio = SpeedRatio * thisFurnace.MSHeatingSpeedRatio(SpeedNum) +
   10741            0 :                                                               (1.0 - SpeedRatio) * thisFurnace.MSHeatingSpeedRatio(SpeedNum - 1);
   10742            0 :                         state.dataHVACGlobal->MSHPMassFlowRateLow = thisFurnace.HeatMassFlowRate(SpeedNum - 1);
   10743            0 :                         state.dataHVACGlobal->MSHPMassFlowRateHigh = thisFurnace.HeatMassFlowRate(SpeedNum);
   10744              :                     }
   10745            0 :                 } else if (thisFurnace.HeatCoolMode == Furnaces::ModeOfOperation::CoolingMode) {
   10746            0 :                     if (SpeedNum == 1) {
   10747            0 :                         state.dataFurnaces->CompOnMassFlow = thisFurnace.CoolMassFlowRate(SpeedNum);
   10748            0 :                         state.dataFurnaces->CompOnFlowRatio = thisFurnace.MSCoolingSpeedRatio(SpeedNum);
   10749            0 :                         state.dataHVACGlobal->MSHPMassFlowRateLow = thisFurnace.CoolMassFlowRate(1);
   10750            0 :                         state.dataHVACGlobal->MSHPMassFlowRateHigh = thisFurnace.CoolMassFlowRate(1);
   10751            0 :                     } else if (SpeedNum > 1) {
   10752            0 :                         state.dataFurnaces->CompOnMassFlow =
   10753            0 :                             SpeedRatio * thisFurnace.CoolMassFlowRate(SpeedNum) + (1.0 - SpeedRatio) * thisFurnace.CoolMassFlowRate(SpeedNum - 1);
   10754            0 :                         state.dataFurnaces->CompOnFlowRatio = SpeedRatio * thisFurnace.MSCoolingSpeedRatio(SpeedNum) +
   10755            0 :                                                               (1.0 - SpeedRatio) * thisFurnace.MSCoolingSpeedRatio(SpeedNum - 1);
   10756            0 :                         state.dataHVACGlobal->MSHPMassFlowRateLow = thisFurnace.CoolMassFlowRate(SpeedNum - 1);
   10757            0 :                         state.dataHVACGlobal->MSHPMassFlowRateHigh = thisFurnace.CoolMassFlowRate(SpeedNum);
   10758              :                     }
   10759              :                 }
   10760              :             }
   10761              : 
   10762              :             // Set up fan flow rate during compressor off time
   10763            0 :             if (thisFurnace.fanOp == HVAC::FanOp::Continuous && present(SpeedNum)) {
   10764            0 :                 if (thisFurnace.AirFlowControl == AirFlowControlConstFan::UseCompressorOnFlow && state.dataFurnaces->CompOnMassFlow > 0.0) {
   10765            0 :                     if (SpeedNum == 1) { // LOWEST SPEED USE IDLE FLOW
   10766            0 :                         state.dataFurnaces->CompOffMassFlow = thisFurnace.IdleMassFlowRate;
   10767            0 :                         state.dataFurnaces->CompOffFlowRatio = thisFurnace.IdleSpeedRatio;
   10768            0 :                     } else if (thisFurnace.LastMode == Furnaces::ModeOfOperation::HeatingMode) {
   10769            0 :                         state.dataFurnaces->CompOffMassFlow = thisFurnace.HeatMassFlowRate(SpeedNum);
   10770            0 :                         state.dataFurnaces->CompOffFlowRatio = thisFurnace.MSHeatingSpeedRatio(SpeedNum);
   10771              :                     } else {
   10772            0 :                         state.dataFurnaces->CompOffMassFlow = thisFurnace.CoolMassFlowRate(SpeedNum);
   10773            0 :                         state.dataFurnaces->CompOffFlowRatio = thisFurnace.MSCoolingSpeedRatio(SpeedNum);
   10774              :                     }
   10775              :                 }
   10776              :             }
   10777              : 
   10778            0 :             if (present(SpeedNum)) {
   10779            0 :                 if (SpeedNum > 1) {
   10780            0 :                     AverageUnitMassFlow = state.dataFurnaces->CompOnMassFlow;
   10781            0 :                     state.dataFurnaces->FanSpeedRatio = state.dataFurnaces->CompOnFlowRatio;
   10782              :                 } else {
   10783            0 :                     AverageUnitMassFlow =
   10784            0 :                         (PartLoadRatio * state.dataFurnaces->CompOnMassFlow) + ((1 - PartLoadRatio) * state.dataFurnaces->CompOffMassFlow);
   10785            0 :                     if (state.dataFurnaces->CompOffFlowRatio > 0.0) {
   10786            0 :                         state.dataFurnaces->FanSpeedRatio =
   10787            0 :                             (PartLoadRatio * state.dataFurnaces->CompOnFlowRatio) + ((1 - PartLoadRatio) * state.dataFurnaces->CompOffFlowRatio);
   10788              :                     } else {
   10789            0 :                         state.dataFurnaces->FanSpeedRatio = state.dataFurnaces->CompOnFlowRatio;
   10790              :                     }
   10791              :                 }
   10792              :             } else {
   10793            0 :                 AverageUnitMassFlow =
   10794            0 :                     (PartLoadRatio * state.dataFurnaces->CompOnMassFlow) + ((1 - PartLoadRatio) * state.dataFurnaces->CompOffMassFlow);
   10795            0 :                 if (state.dataFurnaces->CompOffFlowRatio > 0.0) {
   10796            0 :                     state.dataFurnaces->FanSpeedRatio =
   10797            0 :                         (PartLoadRatio * state.dataFurnaces->CompOnFlowRatio) + ((1 - PartLoadRatio) * state.dataFurnaces->CompOffFlowRatio);
   10798              :                 } else {
   10799            0 :                     state.dataFurnaces->FanSpeedRatio = state.dataFurnaces->CompOnFlowRatio;
   10800              :                 }
   10801              :             }
   10802              :         }
   10803              : 
   10804           17 :         if ((thisFurnace.availSched->getCurrentVal() == 0.0) || state.dataHVACGlobal->TurnFansOff ||
   10805            8 :             (thisFurnace.fanAvailSched->getCurrentVal() == 0.0 && !state.dataHVACGlobal->TurnFansOn)) {
   10806            1 :             state.dataLoopNodes->Node(thisFurnace.FurnaceInletNodeNum).MassFlowRate = 0.0;
   10807            1 :             OnOffAirFlowRatio = 0.0;
   10808              :         } else {
   10809            8 :             state.dataLoopNodes->Node(thisFurnace.FurnaceInletNodeNum).MassFlowRate = AverageUnitMassFlow;
   10810            8 :             state.dataLoopNodes->Node(thisFurnace.FurnaceInletNodeNum).MassFlowRateMaxAvail = AverageUnitMassFlow;
   10811            8 :             if (AverageUnitMassFlow > 0.0) {
   10812            8 :                 OnOffAirFlowRatio = state.dataFurnaces->CompOnMassFlow / AverageUnitMassFlow;
   10813              :             } else {
   10814            0 :                 OnOffAirFlowRatio = 0.0;
   10815              :             }
   10816              :         }
   10817              : 
   10818            9 :         state.dataLoopNodes->Node(thisFurnace.FurnaceOutletNodeNum).MassFlowRate =
   10819            9 :             state.dataLoopNodes->Node(thisFurnace.FurnaceInletNodeNum).MassFlowRate;
   10820            9 :     }
   10821              : 
   10822            7 :     void SetMinOATCompressor(EnergyPlusData &state,
   10823              :                              int const FurnaceNum,                    // index to furnace
   10824              :                              std::string const &cCurrentModuleObject, // type of furnace
   10825              :                              bool &ErrorsFound                        // GetInput logical that errors were found
   10826              :     )
   10827              :     {
   10828            7 :         bool errFlag = false;
   10829            7 :         auto &thisFurnace = state.dataFurnaces->Furnace(FurnaceNum);
   10830              : 
   10831              :         // Set minimum OAT for heat pump compressor operation in heating mode
   10832            7 :         if (thisFurnace.CoolingCoilType_Num == HVAC::CoilDX_CoolingSingleSpeed) {
   10833            5 :             thisFurnace.MinOATCompressorCooling = DXCoils::GetMinOATCompressor(state, thisFurnace.CoolingCoilIndex, errFlag);
   10834            2 :         } else if (thisFurnace.CoolingCoilType_Num == HVAC::CoilDX_CoolingHXAssisted) {
   10835            1 :             std::string ChildCoolingCoilType = state.dataHVACAssistedCC->HXAssistedCoil(thisFurnace.CoolingCoilIndex).CoolingCoilType;
   10836            1 :             std::string ChildCoolingCoilName = state.dataHVACAssistedCC->HXAssistedCoil(thisFurnace.CoolingCoilIndex).CoolingCoilName;
   10837              : 
   10838            1 :             if (Util::SameString(ChildCoolingCoilType, "COIL:COOLING:DX")) {
   10839            1 :                 int childCCIndex_DX = CoilCoolingDX::factory(state, ChildCoolingCoilName);
   10840            1 :                 if (childCCIndex_DX < 0) {
   10841            0 :                     ShowContinueError(state, format("Occurs in {} = {}", cCurrentModuleObject, thisFurnace.Name));
   10842            0 :                     errFlag = true;
   10843            0 :                     ErrorsFound = true;
   10844              :                 }
   10845            1 :                 auto const &newCoil = state.dataCoilCoolingDX->coilCoolingDXs[childCCIndex_DX];
   10846            1 :                 thisFurnace.MinOATCompressorCooling = newCoil.performance.minOutdoorDrybulb;
   10847            0 :             } else if (Util::SameString(ChildCoolingCoilType, "Coil:Cooling:DX:VariableSpeed")) {
   10848            0 :                 int childCCIndex_VS = state.dataHVACAssistedCC->HXAssistedCoil(thisFurnace.CoolingCoilIndex).CoolingCoilIndex;
   10849            0 :                 thisFurnace.MinOATCompressorCooling = VariableSpeedCoils::GetVSCoilMinOATCompressor(state, childCCIndex_VS, errFlag);
   10850              :             } else { // Single speed
   10851            0 :                 int childCCIndex_SP = state.dataHVACAssistedCC->HXAssistedCoil(thisFurnace.CoolingCoilIndex).CoolingCoilIndex;
   10852            0 :                 thisFurnace.MinOATCompressorCooling = DXCoils::GetMinOATCompressor(state, childCCIndex_SP, errFlag);
   10853              :             }
   10854            2 :         } else if (thisFurnace.CoolingCoilType_Num == HVAC::Coil_CoolingAirToAirVariableSpeed) {
   10855            1 :             thisFurnace.MinOATCompressorCooling = VariableSpeedCoils::GetVSCoilMinOATCompressor(state, thisFurnace.CoolingCoilIndex, errFlag);
   10856              :         } else {
   10857            0 :             thisFurnace.MinOATCompressorCooling = -1000.0;
   10858              :         }
   10859            7 :         if (errFlag) {
   10860            0 :             ShowContinueError(state, format("...occurs in {} = {}", cCurrentModuleObject, thisFurnace.Name));
   10861            0 :             ErrorsFound = true;
   10862              :         }
   10863              : 
   10864              :         // Set minimum OAT for heat pump compressor operation in heating mode
   10865            7 :         errFlag = false;
   10866            7 :         if (thisFurnace.HeatingCoilType_Num == HVAC::Coil_HeatingAirToAirVariableSpeed) {
   10867            1 :             thisFurnace.MinOATCompressorHeating = VariableSpeedCoils::GetVSCoilMinOATCompressor(state, thisFurnace.HeatingCoilIndex, errFlag);
   10868            6 :         } else if (thisFurnace.HeatingCoilType_Num == HVAC::CoilDX_HeatingEmpirical) {
   10869            3 :             thisFurnace.MinOATCompressorHeating = DXCoils::GetMinOATCompressor(state, thisFurnace.HeatingCoilIndex, errFlag);
   10870              :         } else {
   10871            3 :             thisFurnace.MinOATCompressorHeating = -1000.0;
   10872              :         }
   10873            7 :         if (errFlag) {
   10874            0 :             ShowContinueError(state, format("...occurs in {} = {}", cCurrentModuleObject, thisFurnace.Name));
   10875            0 :             ErrorsFound = true;
   10876              :         }
   10877            7 :     }
   10878              : 
   10879              : } // namespace Furnaces
   10880              : 
   10881              : } // namespace EnergyPlus
        

Generated by: LCOV version 2.0-1