LCOV - code coverage report
Current view: top level - EnergyPlus - HeatingCoils.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 65.6 % 1665 1092
Test Date: 2025-05-22 16:09:37 Functions: 88.0 % 25 22

            Line data    Source code
       1              : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
       2              : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
       3              : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
       4              : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
       5              : // contributors. All rights reserved.
       6              : //
       7              : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
       8              : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
       9              : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
      10              : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
      11              : // derivative works, and perform publicly and display publicly, and to permit others to do so.
      12              : //
      13              : // Redistribution and use in source and binary forms, with or without modification, are permitted
      14              : // provided that the following conditions are met:
      15              : //
      16              : // (1) Redistributions of source code must retain the above copyright notice, this list of
      17              : //     conditions and the following disclaimer.
      18              : //
      19              : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
      20              : //     conditions and the following disclaimer in the documentation and/or other materials
      21              : //     provided with the distribution.
      22              : //
      23              : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
      24              : //     the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
      25              : //     used to endorse or promote products derived from this software without specific prior
      26              : //     written permission.
      27              : //
      28              : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
      29              : //     without changes from the version obtained under this License, or (ii) Licensee makes a
      30              : //     reference solely to the software portion of its product, Licensee must refer to the
      31              : //     software as "EnergyPlus version X" software, where "X" is the version number Licensee
      32              : //     obtained under this License and may not use a different name for the software. Except as
      33              : //     specifically required in this Section (4), Licensee shall not use in a company name, a
      34              : //     product name, in advertising, publicity, or other promotional activities any name, trade
      35              : //     name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
      36              : //     similar designation, without the U.S. Department of Energy's prior written consent.
      37              : //
      38              : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
      39              : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
      40              : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
      41              : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      42              : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      43              : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      44              : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      45              : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      46              : // POSSIBILITY OF SUCH DAMAGE.
      47              : 
      48              : // C++ Headers
      49              : #include <cmath>
      50              : 
      51              : // ObjexxFCL Headers
      52              : #include <ObjexxFCL/Array.functions.hh>
      53              : #include <ObjexxFCL/Fmath.hh>
      54              : 
      55              : // EnergyPlus Headers
      56              : #include <EnergyPlus/Autosizing/All_Simple_Sizing.hh>
      57              : #include <EnergyPlus/Autosizing/HeatingCapacitySizing.hh>
      58              : #include <EnergyPlus/BranchNodeConnections.hh>
      59              : #include <EnergyPlus/Coils/CoilCoolingDX.hh>
      60              : #include <EnergyPlus/CurveManager.hh>
      61              : #include <EnergyPlus/DXCoils.hh>
      62              : #include <EnergyPlus/Data/EnergyPlusData.hh>
      63              : #include <EnergyPlus/DataContaminantBalance.hh>
      64              : #include <EnergyPlus/DataEnvironment.hh>
      65              : #include <EnergyPlus/DataGlobalConstants.hh>
      66              : #include <EnergyPlus/DataHVACGlobals.hh>
      67              : #include <EnergyPlus/DataHeatBalance.hh>
      68              : #include <EnergyPlus/DataLoopNode.hh>
      69              : #include <EnergyPlus/DataSizing.hh>
      70              : #include <EnergyPlus/EMSManager.hh>
      71              : #include <EnergyPlus/FaultsManager.hh>
      72              : #include <EnergyPlus/General.hh>
      73              : #include <EnergyPlus/GlobalNames.hh>
      74              : #include <EnergyPlus/HeatingCoils.hh>
      75              : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      76              : #include <EnergyPlus/NodeInputManager.hh>
      77              : #include <EnergyPlus/OutputProcessor.hh>
      78              : #include <EnergyPlus/OutputReportPredefined.hh>
      79              : #include <EnergyPlus/Psychrometrics.hh>
      80              : #include <EnergyPlus/RefrigeratedCase.hh>
      81              : #include <EnergyPlus/ScheduleManager.hh>
      82              : #include <EnergyPlus/UtilityRoutines.hh>
      83              : #include <EnergyPlus/VariableSpeedCoils.hh>
      84              : 
      85              : namespace EnergyPlus { // NOLINT(modernize-concat-nested-namespaces) // TODO: Take out this lint when we want to apply formatting for nested
      86              :                        // namespacing
      87              : 
      88              : namespace HeatingCoils {
      89              :     // Module containing the HeatingCoil simulation routines other than the Water coils
      90              : 
      91              :     // MODULE INFORMATION:
      92              :     //       AUTHOR         Richard J. Liesen
      93              :     //       DATE WRITTEN   May 2000
      94              :     //       MODIFIED       Therese Stovall June 2008 to add references to refrigeration condensers
      95              : 
      96              :     // PURPOSE OF THIS MODULE:
      97              :     // To encapsulate the data and algorithms required to
      98              :     // manage the HeatingCoil System Component
      99              : 
     100       233160 :     void SimulateHeatingCoilComponents(EnergyPlusData &state,
     101              :                                        std::string_view CompName,
     102              :                                        bool const FirstHVACIteration,
     103              :                                        ObjexxFCL::Optional<Real64 const> QCoilReq, // coil load to be met
     104              :                                        ObjexxFCL::Optional_int CompIndex,
     105              :                                        ObjexxFCL::Optional<Real64> QCoilActual, // coil load actually delivered returned to calling component
     106              :                                        ObjexxFCL::Optional_bool_const SuppHeat, // True if current heating coil is a supplemental heating coil
     107              :                                        ObjexxFCL::Optional<HVAC::FanOp const> fanOpMode, // fan operating mode, FanOp::Cycling or FanOp::Continuous
     108              :                                        ObjexxFCL::Optional<Real64 const> PartLoadRatio,  // part-load ratio of heating coil
     109              :                                        ObjexxFCL::Optional_int StageNum,
     110              :                                        ObjexxFCL::Optional<Real64 const> SpeedRatio // Speed ratio of MultiStage heating coil
     111              :     )
     112              :     {
     113              : 
     114              :         // SUBROUTINE INFORMATION:
     115              :         //       AUTHOR         Richard Liesen
     116              :         //       DATE WRITTEN   May 2000
     117              : 
     118              :         // PURPOSE OF THIS SUBROUTINE:
     119              :         // This subroutine manages HeatingCoil component simulation.
     120              : 
     121              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     122       233160 :         int CoilNum(0);       // The HeatingCoil that you are currently loading input into
     123              :         Real64 QCoilActual2;  // coil load actually delivered returned from specific coil
     124              :         HVAC::FanOp fanOp;    // fan operating mode
     125              :         Real64 PartLoadFrac;  // part-load fraction of heating coil
     126              :         Real64 QCoilRequired; // local variable for optional argument
     127              : 
     128              :         // Obtains and Allocates HeatingCoil related parameters from input file
     129       233160 :         if (state.dataHeatingCoils->GetCoilsInputFlag) { // First time subroutine has been entered
     130           21 :             GetHeatingCoilInput(state);
     131           21 :             state.dataHeatingCoils->GetCoilsInputFlag = false;
     132              :         }
     133              : 
     134              :         // Find the correct HeatingCoilNumber with the Coil Name
     135       233160 :         if (present(CompIndex)) {
     136       233160 :             if (CompIndex == 0) {
     137        81878 :                 CoilNum = Util::FindItemInList(CompName, state.dataHeatingCoils->HeatingCoil);
     138        81878 :                 if (CoilNum == 0) {
     139            0 :                     ShowFatalError(state, format("SimulateHeatingCoilComponents: Coil not found={}", CompName));
     140              :                 }
     141              :                 //    CompIndex=CoilNum
     142              :             } else {
     143       151282 :                 CoilNum = CompIndex;
     144       151282 :                 if (CoilNum > state.dataHeatingCoils->NumHeatingCoils || CoilNum < 1) {
     145            0 :                     ShowFatalError(state,
     146            0 :                                    format("SimulateHeatingCoilComponents: Invalid CompIndex passed={}, Number of Heating Coils={}, Coil name={}",
     147              :                                           CoilNum,
     148            0 :                                           state.dataHeatingCoils->NumHeatingCoils,
     149              :                                           CompName));
     150              :                 }
     151       151282 :                 if (state.dataHeatingCoils->CheckEquipName(CoilNum)) {
     152           76 :                     if (!CompName.empty() && CompName != state.dataHeatingCoils->HeatingCoil(CoilNum).Name) {
     153            0 :                         ShowFatalError(
     154              :                             state,
     155            0 :                             format("SimulateHeatingCoilComponents: Invalid CompIndex passed={}, Coil name={}, stored Coil Name for that index={}",
     156              :                                    CoilNum,
     157              :                                    CompName,
     158            0 :                                    state.dataHeatingCoils->HeatingCoil(CoilNum).Name));
     159              :                     }
     160           76 :                     state.dataHeatingCoils->CheckEquipName(CoilNum) = false;
     161              :                 }
     162              :             }
     163              :         } else {
     164            0 :             ShowSevereError(state, "SimulateHeatingCoilComponents: CompIndex argument not used.");
     165            0 :             ShowContinueError(state, format("..CompName = {}", CompName));
     166            0 :             ShowFatalError(state, "Preceding conditions cause termination.");
     167              :         }
     168              : 
     169       233160 :         if (present(SuppHeat)) {
     170       138362 :             state.dataHeatingCoils->CoilIsSuppHeater = SuppHeat;
     171              :         } else {
     172        94798 :             state.dataHeatingCoils->CoilIsSuppHeater = false;
     173              :         }
     174              : 
     175       233160 :         if (present(fanOpMode)) {
     176       138934 :             fanOp = fanOpMode;
     177              :         } else {
     178        94226 :             fanOp = HVAC::FanOp::Continuous;
     179              :         }
     180              : 
     181       233160 :         if (present(PartLoadRatio)) {
     182        67273 :             PartLoadFrac = PartLoadRatio;
     183              :         } else {
     184       165887 :             PartLoadFrac = 1.0;
     185              :         }
     186              : 
     187       233160 :         if (present(QCoilReq)) {
     188       167678 :             QCoilRequired = QCoilReq;
     189              :         } else {
     190        65482 :             QCoilRequired = DataLoopNode::SensedLoadFlagValue;
     191              :         }
     192              : 
     193              :         // With the correct CoilNum Initialize
     194       233160 :         InitHeatingCoil(state, CoilNum, FirstHVACIteration, QCoilRequired); // Initialize all HeatingCoil related parameters
     195              : 
     196              :         // Calculate the Correct HeatingCoil Model with the current CoilNum
     197       233160 :         switch (state.dataHeatingCoils->HeatingCoil(CoilNum).HCoilType_Num) {
     198        73698 :         case HVAC::Coil_HeatingElectric: {
     199        73698 :             CalcElectricHeatingCoil(state, CoilNum, QCoilRequired, QCoilActual2, fanOp, PartLoadFrac);
     200        73698 :         } break;
     201          217 :         case HVAC::Coil_HeatingElectric_MultiStage: {
     202          217 :             CalcMultiStageElectricHeatingCoil(
     203              :                 state,
     204              :                 CoilNum,
     205              :                 SpeedRatio,
     206              :                 PartLoadRatio,
     207              :                 StageNum,
     208              :                 fanOp,
     209              :                 QCoilActual2,
     210          217 :                 state.dataHeatingCoils->CoilIsSuppHeater); // Autodesk:OPTIONAL SpeedRatio, PartLoadRatio, StageNum used without PRESENT check
     211          217 :         } break;
     212       159191 :         case HVAC::Coil_HeatingGasOrOtherFuel: {
     213       159191 :             CalcFuelHeatingCoil(state, CoilNum, QCoilRequired, QCoilActual2, fanOp, PartLoadFrac);
     214       159191 :         } break;
     215           50 :         case HVAC::Coil_HeatingGas_MultiStage: {
     216           50 :             CalcMultiStageGasHeatingCoil(state,
     217              :                                          CoilNum,
     218              :                                          SpeedRatio,
     219              :                                          PartLoadRatio,
     220              :                                          StageNum,
     221              :                                          fanOp); // Autodesk:OPTIONAL SpeedRatio, PartLoadRatio, StageNum used without PRESENT check
     222           50 :         } break;
     223            4 :         case HVAC::Coil_HeatingDesuperheater: {
     224            4 :             CalcDesuperheaterHeatingCoil(state, CoilNum, QCoilRequired, QCoilActual2);
     225            4 :         } break;
     226            0 :         default:
     227            0 :             QCoilActual2 = 0.0;
     228            0 :             break;
     229              :         }
     230              : 
     231              :         // Update the current HeatingCoil to the outlet nodes
     232       233160 :         UpdateHeatingCoil(state, CoilNum);
     233              : 
     234              :         // Report the current HeatingCoil
     235       233160 :         ReportHeatingCoil(state, CoilNum, state.dataHeatingCoils->CoilIsSuppHeater);
     236              : 
     237       233160 :         if (present(QCoilActual)) {
     238       126147 :             QCoilActual = QCoilActual2;
     239              :         }
     240       233160 :     }
     241              : 
     242          123 :     void GetHeatingCoilInput(EnergyPlusData &state)
     243              :     {
     244              : 
     245              :         // SUBROUTINE INFORMATION:
     246              :         //       AUTHOR         Richard Liesen
     247              :         //       DATE WRITTEN   May 2000
     248              : 
     249              :         // PURPOSE OF THIS SUBROUTINE:
     250              :         // Obtains input data for coils and stores it in coil data structures
     251              : 
     252              :         // METHODOLOGY EMPLOYED:
     253              :         // Uses "Get" routines to read in data.
     254              : 
     255              :         // SUBROUTINE PARAMETER DEFINITIONS:
     256              :         static constexpr std::string_view RoutineName = "GetHeatingCoilInput: "; // include trailing blank space
     257              :         static constexpr std::string_view routineName = "GetHeatingCoilInput";
     258              : 
     259              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     260          123 :         std::string CurrentModuleObject; // for ease in getting objects
     261          123 :         Array1D_string Alphas;           // Alpha input items for object
     262          123 :         Array1D_string cAlphaFields;     // Alpha field names
     263          123 :         Array1D_string cNumericFields;   // Numeric field names
     264          123 :         Array1D<Real64> Numbers;         // Numeric input items for object
     265          123 :         Array1D_bool lAlphaBlanks;       // Logical array, alpha field input BLANK = .TRUE.
     266          123 :         Array1D_bool lNumericBlanks;     // Logical array, numeric field input BLANK = .TRUE.
     267              :         int NumAlphas;
     268              :         int NumNums;
     269              :         int IOStat;
     270              :         int StageNum;
     271              :         bool DXCoilErrFlag; // Used in GetDXCoil mining functions
     272              :         bool errFlag;
     273              : 
     274          123 :         state.dataHeatingCoils->NumElecCoil = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Coil:Heating:Electric");
     275          246 :         state.dataHeatingCoils->NumElecCoilMultiStage =
     276          123 :             state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Coil:Heating:Electric:MultiStage");
     277          123 :         state.dataHeatingCoils->NumFuelCoil = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Coil:Heating:Fuel");
     278          246 :         state.dataHeatingCoils->NumGasCoilMultiStage =
     279          123 :             state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Coil:Heating:Gas:MultiStage");
     280          246 :         state.dataHeatingCoils->NumDesuperheaterCoil =
     281          123 :             state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Coil:Heating:Desuperheater");
     282          123 :         state.dataHeatingCoils->NumHeatingCoils = state.dataHeatingCoils->NumElecCoil + state.dataHeatingCoils->NumElecCoilMultiStage +
     283          123 :                                                   state.dataHeatingCoils->NumFuelCoil + state.dataHeatingCoils->NumGasCoilMultiStage +
     284          123 :                                                   state.dataHeatingCoils->NumDesuperheaterCoil;
     285          123 :         if (state.dataHeatingCoils->NumHeatingCoils > 0) {
     286          123 :             state.dataHeatingCoils->HeatingCoil.allocate(state.dataHeatingCoils->NumHeatingCoils);
     287          123 :             state.dataHeatingCoils->HeatingCoilNumericFields.allocate(state.dataHeatingCoils->NumHeatingCoils);
     288          123 :             state.dataHeatingCoils->ValidSourceType.dimension(state.dataHeatingCoils->NumHeatingCoils, false);
     289          123 :             state.dataHeatingCoils->CheckEquipName.dimension(state.dataHeatingCoils->NumHeatingCoils, true);
     290              :         }
     291              : 
     292          246 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(
     293          123 :             state, "Coil:Heating:Electric", state.dataHeatingCoils->TotalArgs, NumAlphas, NumNums);
     294          123 :         state.dataHeatingCoils->MaxNums = max(state.dataHeatingCoils->MaxNums, NumNums);
     295          123 :         state.dataHeatingCoils->MaxAlphas = max(state.dataHeatingCoils->MaxAlphas, NumAlphas);
     296          246 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(
     297          123 :             state, "Coil:Heating:Electric:MultiStage", state.dataHeatingCoils->TotalArgs, NumAlphas, NumNums);
     298          123 :         state.dataHeatingCoils->MaxNums = max(state.dataHeatingCoils->MaxNums, NumNums);
     299          123 :         state.dataHeatingCoils->MaxAlphas = max(state.dataHeatingCoils->MaxAlphas, NumAlphas);
     300          246 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(
     301          123 :             state, "Coil:Heating:Fuel", state.dataHeatingCoils->TotalArgs, NumAlphas, NumNums);
     302          123 :         state.dataHeatingCoils->MaxNums = max(state.dataHeatingCoils->MaxNums, NumNums);
     303          123 :         state.dataHeatingCoils->MaxAlphas = max(state.dataHeatingCoils->MaxAlphas, NumAlphas);
     304          246 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(
     305          123 :             state, "Coil:Heating:Gas:MultiStage", state.dataHeatingCoils->TotalArgs, NumAlphas, NumNums);
     306          123 :         state.dataHeatingCoils->MaxNums = max(state.dataHeatingCoils->MaxNums, NumNums);
     307          123 :         state.dataHeatingCoils->MaxAlphas = max(state.dataHeatingCoils->MaxAlphas, NumAlphas);
     308          246 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(
     309          123 :             state, "Coil:Heating:Desuperheater", state.dataHeatingCoils->TotalArgs, NumAlphas, NumNums);
     310          123 :         state.dataHeatingCoils->MaxNums = max(state.dataHeatingCoils->MaxNums, NumNums);
     311          123 :         state.dataHeatingCoils->MaxAlphas = max(state.dataHeatingCoils->MaxAlphas, NumAlphas);
     312              : 
     313          123 :         Alphas.allocate(state.dataHeatingCoils->MaxAlphas);
     314          123 :         cAlphaFields.allocate(state.dataHeatingCoils->MaxAlphas);
     315          123 :         cNumericFields.allocate(state.dataHeatingCoils->MaxNums);
     316          123 :         Numbers.dimension(state.dataHeatingCoils->MaxNums, 0.0);
     317          123 :         lAlphaBlanks.dimension(state.dataHeatingCoils->MaxAlphas, true);
     318          123 :         lNumericBlanks.dimension(state.dataHeatingCoils->MaxNums, true);
     319              : 
     320              :         // Get the data for electric heating coils
     321          181 :         for (int ElecCoilNum = 1; ElecCoilNum <= state.dataHeatingCoils->NumElecCoil; ++ElecCoilNum) {
     322              : 
     323           58 :             auto &heatingCoil = state.dataHeatingCoils->HeatingCoil(ElecCoilNum);
     324           58 :             auto &heatingCoilNumericFields = state.dataHeatingCoils->HeatingCoilNumericFields(ElecCoilNum);
     325              : 
     326           58 :             CurrentModuleObject = "Coil:Heating:Electric";
     327           58 :             heatingCoil.FuelType = Constant::eFuel::Electricity;
     328              : 
     329           58 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     330              :                                                                      CurrentModuleObject,
     331              :                                                                      ElecCoilNum,
     332              :                                                                      Alphas,
     333              :                                                                      NumAlphas,
     334              :                                                                      Numbers,
     335              :                                                                      NumNums,
     336              :                                                                      IOStat,
     337              :                                                                      lNumericBlanks,
     338              :                                                                      lAlphaBlanks,
     339              :                                                                      cAlphaFields,
     340              :                                                                      cNumericFields);
     341              : 
     342           58 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
     343           58 :             heatingCoilNumericFields.FieldNames.allocate(state.dataHeatingCoils->MaxNums);
     344           58 :             heatingCoilNumericFields.FieldNames = cNumericFields;
     345              : 
     346              :             // InputErrorsFound will be set to True if problem was found, left untouched otherwise
     347           58 :             GlobalNames::VerifyUniqueCoilName(
     348           58 :                 state, CurrentModuleObject, Alphas(1), state.dataHeatingCoils->InputErrorsFound, CurrentModuleObject + " Name");
     349              : 
     350           58 :             heatingCoil.Name = Alphas(1);
     351           58 :             if (lAlphaBlanks(2)) {
     352           18 :                 heatingCoil.availSched = Sched::GetScheduleAlwaysOn(state);
     353           40 :             } else if ((heatingCoil.availSched = Sched::GetSchedule(state, Alphas(2))) == nullptr) {
     354            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(2), Alphas(2));
     355            0 :                 state.dataHeatingCoils->InputErrorsFound = true;
     356              :             }
     357              : 
     358           58 :             heatingCoil.HeatingCoilType = "Heating";
     359           58 :             heatingCoil.HeatingCoilModel = "Electric";
     360           58 :             heatingCoil.HCoilType_Num = HVAC::Coil_HeatingElectric;
     361              : 
     362           58 :             heatingCoil.Efficiency = Numbers(1);
     363           58 :             heatingCoil.NominalCapacity = Numbers(2);
     364           58 :             errFlag = false;
     365           58 :             heatingCoil.AirInletNodeNum = GetOnlySingleNode(state,
     366           58 :                                                             Alphas(3),
     367              :                                                             errFlag,
     368              :                                                             DataLoopNode::ConnectionObjectType::CoilHeatingElectric,
     369           58 :                                                             Alphas(1),
     370              :                                                             DataLoopNode::NodeFluidType::Air,
     371              :                                                             DataLoopNode::ConnectionType::Inlet,
     372              :                                                             NodeInputManager::CompFluidStream::Primary,
     373              :                                                             DataLoopNode::ObjectIsNotParent);
     374           58 :             state.dataHeatingCoils->InputErrorsFound = errFlag || state.dataHeatingCoils->InputErrorsFound;
     375           58 :             errFlag = false;
     376           58 :             heatingCoil.AirOutletNodeNum = GetOnlySingleNode(state,
     377           58 :                                                              Alphas(4),
     378              :                                                              errFlag,
     379              :                                                              DataLoopNode::ConnectionObjectType::CoilHeatingElectric,
     380           58 :                                                              Alphas(1),
     381              :                                                              DataLoopNode::NodeFluidType::Air,
     382              :                                                              DataLoopNode::ConnectionType::Outlet,
     383              :                                                              NodeInputManager::CompFluidStream::Primary,
     384              :                                                              DataLoopNode::ObjectIsNotParent);
     385           58 :             state.dataHeatingCoils->InputErrorsFound = errFlag || state.dataHeatingCoils->InputErrorsFound;
     386              : 
     387           58 :             BranchNodeConnections::TestCompSet(state, CurrentModuleObject, Alphas(1), Alphas(3), Alphas(4), "Air Nodes");
     388              : 
     389           58 :             errFlag = false;
     390           58 :             heatingCoil.TempSetPointNodeNum = GetOnlySingleNode(state,
     391           58 :                                                                 Alphas(5),
     392              :                                                                 errFlag,
     393              :                                                                 DataLoopNode::ConnectionObjectType::CoilHeatingElectric,
     394           58 :                                                                 Alphas(1),
     395              :                                                                 DataLoopNode::NodeFluidType::Air,
     396              :                                                                 DataLoopNode::ConnectionType::Sensor,
     397              :                                                                 NodeInputManager::CompFluidStream::Primary,
     398              :                                                                 DataLoopNode::ObjectIsNotParent);
     399           58 :             state.dataHeatingCoils->InputErrorsFound = errFlag || state.dataHeatingCoils->InputErrorsFound;
     400              : 
     401              :             // Setup Report variables for the Electric Coils
     402              :             // CurrentModuleObject = "Coil:Heating:Electric"
     403          116 :             SetupOutputVariable(state,
     404              :                                 "Heating Coil Heating Energy",
     405              :                                 Constant::Units::J,
     406           58 :                                 heatingCoil.HeatingCoilLoad,
     407              :                                 OutputProcessor::TimeStepType::System,
     408              :                                 OutputProcessor::StoreType::Sum,
     409           58 :                                 heatingCoil.Name,
     410              :                                 Constant::eResource::EnergyTransfer,
     411              :                                 OutputProcessor::Group::HVAC,
     412              :                                 OutputProcessor::EndUseCat::HeatingCoils);
     413          116 :             SetupOutputVariable(state,
     414              :                                 "Heating Coil Heating Rate",
     415              :                                 Constant::Units::W,
     416           58 :                                 heatingCoil.HeatingCoilRate,
     417              :                                 OutputProcessor::TimeStepType::System,
     418              :                                 OutputProcessor::StoreType::Average,
     419           58 :                                 heatingCoil.Name);
     420          116 :             SetupOutputVariable(state,
     421              :                                 "Heating Coil Electricity Energy",
     422              :                                 Constant::Units::J,
     423           58 :                                 heatingCoil.ElecUseLoad,
     424              :                                 OutputProcessor::TimeStepType::System,
     425              :                                 OutputProcessor::StoreType::Sum,
     426           58 :                                 heatingCoil.Name,
     427              :                                 Constant::eResource::Electricity,
     428              :                                 OutputProcessor::Group::HVAC,
     429              :                                 OutputProcessor::EndUseCat::Heating);
     430          116 :             SetupOutputVariable(state,
     431              :                                 "Heating Coil Electricity Rate",
     432              :                                 Constant::Units::W,
     433           58 :                                 heatingCoil.ElecUseRate,
     434              :                                 OutputProcessor::TimeStepType::System,
     435              :                                 OutputProcessor::StoreType::Average,
     436           58 :                                 heatingCoil.Name);
     437              :         }
     438              : 
     439              :         // Get the data for electric heating coils
     440          132 :         for (int ElecCoilNum = 1; ElecCoilNum <= state.dataHeatingCoils->NumElecCoilMultiStage; ++ElecCoilNum) {
     441              : 
     442            9 :             int CoilNum = state.dataHeatingCoils->NumElecCoil + ElecCoilNum;
     443            9 :             auto &heatingCoil = state.dataHeatingCoils->HeatingCoil(CoilNum);
     444            9 :             auto &heatingCoilNumericFields = state.dataHeatingCoils->HeatingCoilNumericFields(CoilNum);
     445              : 
     446            9 :             CurrentModuleObject = "Coil:Heating:Electric:MultiStage";
     447            9 :             heatingCoil.FuelType = Constant::eFuel::Electricity;
     448              : 
     449            9 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     450              :                                                                      CurrentModuleObject,
     451              :                                                                      ElecCoilNum,
     452              :                                                                      Alphas,
     453              :                                                                      NumAlphas,
     454              :                                                                      Numbers,
     455              :                                                                      NumNums,
     456              :                                                                      IOStat,
     457              :                                                                      lNumericBlanks,
     458              :                                                                      lAlphaBlanks,
     459              :                                                                      cAlphaFields,
     460              :                                                                      cNumericFields);
     461              : 
     462            9 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
     463            9 :             heatingCoilNumericFields.FieldNames.allocate(state.dataHeatingCoils->MaxNums);
     464            9 :             heatingCoilNumericFields.FieldNames = cNumericFields;
     465              : 
     466              :             // InputErrorsFound will be set to True if problem was found, left untouched otherwise
     467            9 :             GlobalNames::VerifyUniqueCoilName(
     468            9 :                 state, CurrentModuleObject, Alphas(1), state.dataHeatingCoils->InputErrorsFound, CurrentModuleObject + " Name");
     469            9 :             heatingCoil.Name = Alphas(1);
     470            9 :             if (lAlphaBlanks(2)) {
     471            0 :                 heatingCoil.availSched = Sched::GetScheduleAlwaysOn(state);
     472            9 :             } else if ((heatingCoil.availSched = Sched::GetSchedule(state, Alphas(2))) == nullptr) {
     473            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(2), Alphas(2));
     474            0 :                 state.dataHeatingCoils->InputErrorsFound = true;
     475              :             }
     476              : 
     477            9 :             heatingCoil.HeatingCoilType = "Heating";
     478            9 :             heatingCoil.HeatingCoilModel = "Electric:MultiStage";
     479            9 :             heatingCoil.HCoilType_Num = HVAC::Coil_HeatingElectric_MultiStage;
     480              : 
     481            9 :             heatingCoil.NumOfStages = static_cast<int>(Numbers(1));
     482              : 
     483            9 :             heatingCoil.MSEfficiency.allocate(heatingCoil.NumOfStages);
     484            9 :             heatingCoil.MSNominalCapacity.allocate(heatingCoil.NumOfStages);
     485              : 
     486           27 :             for (StageNum = 1; StageNum <= heatingCoil.NumOfStages; ++StageNum) {
     487              : 
     488           18 :                 heatingCoil.MSEfficiency(StageNum) = Numbers(StageNum * 2);
     489           18 :                 heatingCoil.MSNominalCapacity(StageNum) = Numbers(StageNum * 2 + 1);
     490              :             }
     491              : 
     492            9 :             errFlag = false;
     493            9 :             heatingCoil.AirInletNodeNum = GetOnlySingleNode(state,
     494            9 :                                                             Alphas(3),
     495              :                                                             errFlag,
     496              :                                                             DataLoopNode::ConnectionObjectType::CoilHeatingElectricMultiStage,
     497            9 :                                                             Alphas(1),
     498              :                                                             DataLoopNode::NodeFluidType::Air,
     499              :                                                             DataLoopNode::ConnectionType::Inlet,
     500              :                                                             NodeInputManager::CompFluidStream::Primary,
     501              :                                                             DataLoopNode::ObjectIsNotParent);
     502            9 :             state.dataHeatingCoils->InputErrorsFound = errFlag || state.dataHeatingCoils->InputErrorsFound;
     503            9 :             errFlag = false;
     504            9 :             heatingCoil.AirOutletNodeNum = GetOnlySingleNode(state,
     505            9 :                                                              Alphas(4),
     506              :                                                              errFlag,
     507              :                                                              DataLoopNode::ConnectionObjectType::CoilHeatingElectricMultiStage,
     508            9 :                                                              Alphas(1),
     509              :                                                              DataLoopNode::NodeFluidType::Air,
     510              :                                                              DataLoopNode::ConnectionType::Outlet,
     511              :                                                              NodeInputManager::CompFluidStream::Primary,
     512              :                                                              DataLoopNode::ObjectIsNotParent);
     513            9 :             state.dataHeatingCoils->InputErrorsFound = errFlag || state.dataHeatingCoils->InputErrorsFound;
     514              : 
     515            9 :             BranchNodeConnections::TestCompSet(state, CurrentModuleObject, Alphas(1), Alphas(3), Alphas(4), "Air Nodes");
     516              : 
     517            9 :             errFlag = false;
     518            9 :             heatingCoil.TempSetPointNodeNum = GetOnlySingleNode(state,
     519            9 :                                                                 Alphas(5),
     520              :                                                                 errFlag,
     521              :                                                                 DataLoopNode::ConnectionObjectType::CoilHeatingElectricMultiStage,
     522            9 :                                                                 Alphas(1),
     523              :                                                                 DataLoopNode::NodeFluidType::Air,
     524              :                                                                 DataLoopNode::ConnectionType::Sensor,
     525              :                                                                 NodeInputManager::CompFluidStream::Primary,
     526              :                                                                 DataLoopNode::ObjectIsNotParent);
     527            9 :             state.dataHeatingCoils->InputErrorsFound = errFlag || state.dataHeatingCoils->InputErrorsFound;
     528              : 
     529              :             // Setup Report variables for the Electric Coils
     530              :             // CurrentModuleObject = "Coil:Heating:Electric:MultiStage"
     531           18 :             SetupOutputVariable(state,
     532              :                                 "Heating Coil Heating Energy",
     533              :                                 Constant::Units::J,
     534            9 :                                 heatingCoil.HeatingCoilLoad,
     535              :                                 OutputProcessor::TimeStepType::System,
     536              :                                 OutputProcessor::StoreType::Sum,
     537            9 :                                 heatingCoil.Name,
     538              :                                 Constant::eResource::EnergyTransfer,
     539              :                                 OutputProcessor::Group::HVAC,
     540              :                                 OutputProcessor::EndUseCat::HeatingCoils);
     541           18 :             SetupOutputVariable(state,
     542              :                                 "Heating Coil Heating Rate",
     543              :                                 Constant::Units::W,
     544            9 :                                 heatingCoil.HeatingCoilRate,
     545              :                                 OutputProcessor::TimeStepType::System,
     546              :                                 OutputProcessor::StoreType::Average,
     547            9 :                                 heatingCoil.Name);
     548           18 :             SetupOutputVariable(state,
     549              :                                 "Heating Coil Electricity Energy",
     550              :                                 Constant::Units::J,
     551            9 :                                 heatingCoil.ElecUseLoad,
     552              :                                 OutputProcessor::TimeStepType::System,
     553              :                                 OutputProcessor::StoreType::Sum,
     554            9 :                                 heatingCoil.Name,
     555              :                                 Constant::eResource::Electricity,
     556              :                                 OutputProcessor::Group::HVAC,
     557              :                                 OutputProcessor::EndUseCat::Heating);
     558           18 :             SetupOutputVariable(state,
     559              :                                 "Heating Coil Electricity Rate",
     560              :                                 Constant::Units::W,
     561            9 :                                 heatingCoil.ElecUseRate,
     562              :                                 OutputProcessor::TimeStepType::System,
     563              :                                 OutputProcessor::StoreType::Average,
     564            9 :                                 heatingCoil.Name);
     565              :         }
     566              : 
     567              :         // Get the data for for fuel heating coils
     568          230 :         for (int FuelCoilNum = 1; FuelCoilNum <= state.dataHeatingCoils->NumFuelCoil; ++FuelCoilNum) {
     569              : 
     570          107 :             int CoilNum = state.dataHeatingCoils->NumElecCoil + state.dataHeatingCoils->NumElecCoilMultiStage + FuelCoilNum;
     571          107 :             auto &heatingCoil = state.dataHeatingCoils->HeatingCoil(CoilNum);
     572          107 :             auto &heatingCoilNumericFields = state.dataHeatingCoils->HeatingCoilNumericFields(CoilNum);
     573              : 
     574          107 :             CurrentModuleObject = "Coil:Heating:Fuel";
     575              : 
     576          107 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     577              :                                                                      CurrentModuleObject,
     578              :                                                                      FuelCoilNum,
     579              :                                                                      Alphas,
     580              :                                                                      NumAlphas,
     581              :                                                                      Numbers,
     582              :                                                                      NumNums,
     583              :                                                                      IOStat,
     584              :                                                                      lNumericBlanks,
     585              :                                                                      lAlphaBlanks,
     586              :                                                                      cAlphaFields,
     587              :                                                                      cNumericFields);
     588              : 
     589          107 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
     590          107 :             heatingCoilNumericFields.FieldNames.allocate(state.dataHeatingCoils->MaxNums);
     591          107 :             heatingCoilNumericFields.FieldNames = cNumericFields;
     592              : 
     593              :             // InputErrorsFound will be set to True if problem was found, left untouched otherwise
     594          107 :             GlobalNames::VerifyUniqueCoilName(
     595          107 :                 state, CurrentModuleObject, Alphas(1), state.dataHeatingCoils->InputErrorsFound, CurrentModuleObject + " Name");
     596          107 :             heatingCoil.Name = Alphas(1);
     597          107 :             if (lAlphaBlanks(2)) {
     598           13 :                 heatingCoil.availSched = Sched::GetScheduleAlwaysOn(state);
     599           94 :             } else if ((heatingCoil.availSched = Sched::GetSchedule(state, Alphas(2))) == nullptr) {
     600            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(2), Alphas(2));
     601            0 :                 state.dataHeatingCoils->InputErrorsFound = true;
     602              :             }
     603              : 
     604          107 :             heatingCoil.HeatingCoilType = "Heating";
     605          107 :             heatingCoil.HeatingCoilModel = "Fuel";
     606          107 :             heatingCoil.HCoilType_Num = HVAC::Coil_HeatingGasOrOtherFuel;
     607              : 
     608          107 :             heatingCoil.FuelType = static_cast<Constant::eFuel>(getEnumValue(Constant::eFuelNamesUC, Alphas(3)));
     609          107 :             if (!(heatingCoil.FuelType == Constant::eFuel::NaturalGas || heatingCoil.FuelType == Constant::eFuel::Propane ||
     610            3 :                   heatingCoil.FuelType == Constant::eFuel::Diesel || heatingCoil.FuelType == Constant::eFuel::Gasoline ||
     611            3 :                   heatingCoil.FuelType == Constant::eFuel::FuelOilNo1 || heatingCoil.FuelType == Constant::eFuel::FuelOilNo2 ||
     612            3 :                   heatingCoil.FuelType == Constant::eFuel::OtherFuel1 || heatingCoil.FuelType == Constant::eFuel::OtherFuel2 ||
     613            2 :                   heatingCoil.FuelType == Constant::eFuel::Coal)) {
     614            2 :                 ShowSevereError(state,
     615            2 :                                 format("{}{}: Invalid {} entered ={} for {}={}",
     616              :                                        RoutineName,
     617              :                                        CurrentModuleObject,
     618              :                                        cAlphaFields(3),
     619              :                                        Alphas(3),
     620              :                                        cAlphaFields(1),
     621              :                                        Alphas(1)));
     622            1 :                 state.dataHeatingCoils->InputErrorsFound = true;
     623              :             }
     624          107 :             std::string const sFuelType(Constant::eFuelNames[static_cast<int>(heatingCoil.FuelType)]);
     625              : 
     626          107 :             heatingCoil.Efficiency = Numbers(1);
     627          107 :             heatingCoil.NominalCapacity = Numbers(2);
     628          107 :             errFlag = false;
     629          107 :             heatingCoil.AirInletNodeNum = GetOnlySingleNode(state,
     630          107 :                                                             Alphas(4),
     631              :                                                             errFlag,
     632              :                                                             DataLoopNode::ConnectionObjectType::CoilHeatingFuel,
     633          107 :                                                             Alphas(1),
     634              :                                                             DataLoopNode::NodeFluidType::Air,
     635              :                                                             DataLoopNode::ConnectionType::Inlet,
     636              :                                                             NodeInputManager::CompFluidStream::Primary,
     637              :                                                             DataLoopNode::ObjectIsNotParent);
     638          107 :             state.dataHeatingCoils->InputErrorsFound = errFlag || state.dataHeatingCoils->InputErrorsFound;
     639          107 :             errFlag = false;
     640          107 :             heatingCoil.AirOutletNodeNum = GetOnlySingleNode(state,
     641          107 :                                                              Alphas(5),
     642              :                                                              errFlag,
     643              :                                                              DataLoopNode::ConnectionObjectType::CoilHeatingFuel,
     644          107 :                                                              Alphas(1),
     645              :                                                              DataLoopNode::NodeFluidType::Air,
     646              :                                                              DataLoopNode::ConnectionType::Outlet,
     647              :                                                              NodeInputManager::CompFluidStream::Primary,
     648              :                                                              DataLoopNode::ObjectIsNotParent);
     649          107 :             state.dataHeatingCoils->InputErrorsFound = errFlag || state.dataHeatingCoils->InputErrorsFound;
     650              : 
     651          107 :             BranchNodeConnections::TestCompSet(state, CurrentModuleObject, Alphas(1), Alphas(4), Alphas(5), "Air Nodes");
     652              : 
     653          107 :             errFlag = false;
     654          107 :             heatingCoil.TempSetPointNodeNum = GetOnlySingleNode(state,
     655          107 :                                                                 Alphas(6),
     656              :                                                                 errFlag,
     657              :                                                                 DataLoopNode::ConnectionObjectType::CoilHeatingFuel,
     658          107 :                                                                 Alphas(1),
     659              :                                                                 DataLoopNode::NodeFluidType::Air,
     660              :                                                                 DataLoopNode::ConnectionType::Sensor,
     661              :                                                                 NodeInputManager::CompFluidStream::Primary,
     662              :                                                                 DataLoopNode::ObjectIsNotParent);
     663          107 :             state.dataHeatingCoils->InputErrorsFound = errFlag || state.dataHeatingCoils->InputErrorsFound;
     664              : 
     665              :             // parasitic electric load associated with the fuel heating coil
     666          107 :             heatingCoil.ParasiticElecLoad = Numbers(3);
     667              : 
     668          107 :             heatingCoil.PLFCurveIndex = Curve::GetCurveIndex(state, Alphas(7)); // convert curve name to number
     669              : 
     670              :             // parasitic fuel load associated with the gas heating coil (standing pilot light)
     671          107 :             heatingCoil.ParasiticFuelCapacity = Numbers(4);
     672              : 
     673              :             // Setup Report variables for the Fuel Coils
     674              :             // CurrentModuleObject = "Coil:Heating:OtherFuel"
     675              : 
     676          214 :             SetupOutputVariable(state,
     677              :                                 "Heating Coil Heating Energy",
     678              :                                 Constant::Units::J,
     679          107 :                                 heatingCoil.HeatingCoilLoad,
     680              :                                 OutputProcessor::TimeStepType::System,
     681              :                                 OutputProcessor::StoreType::Sum,
     682          107 :                                 heatingCoil.Name,
     683              :                                 Constant::eResource::EnergyTransfer,
     684              :                                 OutputProcessor::Group::HVAC,
     685              :                                 OutputProcessor::EndUseCat::HeatingCoils);
     686          214 :             SetupOutputVariable(state,
     687              :                                 "Heating Coil Heating Rate",
     688              :                                 Constant::Units::W,
     689          107 :                                 heatingCoil.HeatingCoilRate,
     690              :                                 OutputProcessor::TimeStepType::System,
     691              :                                 OutputProcessor::StoreType::Average,
     692          107 :                                 heatingCoil.Name);
     693          321 :             SetupOutputVariable(state,
     694          214 :                                 format("Heating Coil {} Energy", sFuelType),
     695              :                                 Constant::Units::J,
     696          107 :                                 heatingCoil.FuelUseLoad,
     697              :                                 OutputProcessor::TimeStepType::System,
     698              :                                 OutputProcessor::StoreType::Sum,
     699          107 :                                 heatingCoil.Name,
     700          107 :                                 Constant::eFuel2eResource[(int)heatingCoil.FuelType],
     701              :                                 OutputProcessor::Group::HVAC,
     702              :                                 OutputProcessor::EndUseCat::Heating);
     703          321 :             SetupOutputVariable(state,
     704          214 :                                 format("Heating Coil {} Rate", sFuelType),
     705              :                                 Constant::Units::W,
     706          107 :                                 heatingCoil.FuelUseRate,
     707              :                                 OutputProcessor::TimeStepType::System,
     708              :                                 OutputProcessor::StoreType::Average,
     709          107 :                                 heatingCoil.Name);
     710          214 :             SetupOutputVariable(state,
     711              :                                 "Heating Coil Electricity Energy",
     712              :                                 Constant::Units::J,
     713          107 :                                 heatingCoil.ElecUseLoad,
     714              :                                 OutputProcessor::TimeStepType::System,
     715              :                                 OutputProcessor::StoreType::Sum,
     716          107 :                                 heatingCoil.Name,
     717              :                                 Constant::eResource::Electricity,
     718              :                                 OutputProcessor::Group::HVAC,
     719              :                                 OutputProcessor::EndUseCat::Heating);
     720          214 :             SetupOutputVariable(state,
     721              :                                 "Heating Coil Electricity Rate",
     722              :                                 Constant::Units::W,
     723          107 :                                 heatingCoil.ElecUseRate,
     724              :                                 OutputProcessor::TimeStepType::System,
     725              :                                 OutputProcessor::StoreType::Average,
     726          107 :                                 heatingCoil.Name);
     727          214 :             SetupOutputVariable(state,
     728              :                                 "Heating Coil Runtime Fraction",
     729              :                                 Constant::Units::None,
     730          107 :                                 heatingCoil.RTF,
     731              :                                 OutputProcessor::TimeStepType::System,
     732              :                                 OutputProcessor::StoreType::Average,
     733          107 :                                 heatingCoil.Name);
     734          321 :             SetupOutputVariable(state,
     735          214 :                                 "Heating Coil Ancillary " + sFuelType + " Rate",
     736              :                                 Constant::Units::W,
     737          107 :                                 heatingCoil.ParasiticFuelRate,
     738              :                                 OutputProcessor::TimeStepType::System,
     739              :                                 OutputProcessor::StoreType::Average,
     740          107 :                                 heatingCoil.Name);
     741          321 :             SetupOutputVariable(state,
     742          214 :                                 "Heating Coil Ancillary " + sFuelType + " Energy",
     743              :                                 Constant::Units::J,
     744          107 :                                 heatingCoil.ParasiticFuelConsumption,
     745              :                                 OutputProcessor::TimeStepType::System,
     746              :                                 OutputProcessor::StoreType::Sum,
     747          107 :                                 heatingCoil.Name,
     748          107 :                                 Constant::eFuel2eResource[(int)heatingCoil.FuelType],
     749              :                                 OutputProcessor::Group::HVAC,
     750              :                                 OutputProcessor::EndUseCat::Heating);
     751          107 :         }
     752              : 
     753              :         // Get the data for for gas multistage heating coils
     754          126 :         for (int FuelCoilNum = 1; FuelCoilNum <= state.dataHeatingCoils->NumGasCoilMultiStage; ++FuelCoilNum) {
     755              : 
     756            3 :             int CoilNum = state.dataHeatingCoils->NumElecCoil + state.dataHeatingCoils->NumElecCoilMultiStage + state.dataHeatingCoils->NumFuelCoil +
     757            3 :                           FuelCoilNum;
     758            3 :             auto &heatingCoil = state.dataHeatingCoils->HeatingCoil(CoilNum);
     759            3 :             auto &heatingCoilNumericFields = state.dataHeatingCoils->HeatingCoilNumericFields(CoilNum);
     760            3 :             CurrentModuleObject = "Coil:Heating:Gas:MultiStage";
     761            3 :             heatingCoil.FuelType = Constant::eFuel::NaturalGas;
     762              : 
     763            3 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     764              :                                                                      CurrentModuleObject,
     765              :                                                                      FuelCoilNum,
     766              :                                                                      Alphas,
     767              :                                                                      NumAlphas,
     768              :                                                                      Numbers,
     769              :                                                                      NumNums,
     770              :                                                                      IOStat,
     771              :                                                                      lNumericBlanks,
     772              :                                                                      lAlphaBlanks,
     773              :                                                                      cAlphaFields,
     774              :                                                                      cNumericFields);
     775              : 
     776            3 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
     777              : 
     778            3 :             heatingCoilNumericFields.FieldNames.allocate(state.dataHeatingCoils->MaxNums);
     779            3 :             heatingCoilNumericFields.FieldNames = cNumericFields;
     780              : 
     781              :             // InputErrorsFound will be set to True if problem was found, left untouched otherwise
     782            3 :             GlobalNames::VerifyUniqueCoilName(
     783            3 :                 state, CurrentModuleObject, Alphas(1), state.dataHeatingCoils->InputErrorsFound, CurrentModuleObject + " Name");
     784            3 :             heatingCoil.Name = Alphas(1);
     785              : 
     786            3 :             if (lAlphaBlanks(2)) {
     787            0 :                 heatingCoil.availSched = Sched::GetScheduleAlwaysOn(state);
     788            3 :             } else if ((heatingCoil.availSched = Sched::GetSchedule(state, Alphas(2))) == nullptr) {
     789            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(2), Alphas(2));
     790            0 :                 state.dataHeatingCoils->InputErrorsFound = true;
     791              :             }
     792              : 
     793            3 :             heatingCoil.HeatingCoilType = "Heating";
     794            3 :             heatingCoil.HeatingCoilModel = "Gas:MultiStage";
     795            3 :             heatingCoil.HCoilType_Num = HVAC::Coil_HeatingGas_MultiStage;
     796              : 
     797            3 :             heatingCoil.ParasiticFuelCapacity = Numbers(1);
     798              : 
     799            3 :             heatingCoil.NumOfStages = static_cast<int>(Numbers(2));
     800              : 
     801            3 :             heatingCoil.MSEfficiency.allocate(heatingCoil.NumOfStages);
     802            3 :             heatingCoil.MSNominalCapacity.allocate(heatingCoil.NumOfStages);
     803            3 :             heatingCoil.MSParasiticElecLoad.allocate(heatingCoil.NumOfStages);
     804              : 
     805            8 :             for (StageNum = 1; StageNum <= heatingCoil.NumOfStages; ++StageNum) {
     806              : 
     807            5 :                 heatingCoil.MSEfficiency(StageNum) = Numbers(StageNum * 3);
     808            5 :                 heatingCoil.MSNominalCapacity(StageNum) = Numbers(StageNum * 3 + 1);
     809            5 :                 heatingCoil.MSParasiticElecLoad(StageNum) = Numbers(StageNum * 3 + 2);
     810              :             }
     811              : 
     812            3 :             errFlag = false;
     813            3 :             heatingCoil.AirInletNodeNum = GetOnlySingleNode(state,
     814            3 :                                                             Alphas(3),
     815              :                                                             errFlag,
     816              :                                                             DataLoopNode::ConnectionObjectType::CoilHeatingGasMultiStage,
     817            3 :                                                             Alphas(1),
     818              :                                                             DataLoopNode::NodeFluidType::Air,
     819              :                                                             DataLoopNode::ConnectionType::Inlet,
     820              :                                                             NodeInputManager::CompFluidStream::Primary,
     821              :                                                             DataLoopNode::ObjectIsNotParent);
     822            3 :             state.dataHeatingCoils->InputErrorsFound = errFlag || state.dataHeatingCoils->InputErrorsFound;
     823            3 :             errFlag = false;
     824            3 :             heatingCoil.AirOutletNodeNum = GetOnlySingleNode(state,
     825            3 :                                                              Alphas(4),
     826              :                                                              errFlag,
     827              :                                                              DataLoopNode::ConnectionObjectType::CoilHeatingGasMultiStage,
     828            3 :                                                              Alphas(1),
     829              :                                                              DataLoopNode::NodeFluidType::Air,
     830              :                                                              DataLoopNode::ConnectionType::Outlet,
     831              :                                                              NodeInputManager::CompFluidStream::Primary,
     832              :                                                              DataLoopNode::ObjectIsNotParent);
     833            3 :             state.dataHeatingCoils->InputErrorsFound = errFlag || state.dataHeatingCoils->InputErrorsFound;
     834              : 
     835            3 :             BranchNodeConnections::TestCompSet(state, CurrentModuleObject, Alphas(1), Alphas(3), Alphas(4), "Air Nodes");
     836              : 
     837            3 :             errFlag = false;
     838            3 :             heatingCoil.TempSetPointNodeNum = GetOnlySingleNode(state,
     839            3 :                                                                 Alphas(5),
     840              :                                                                 errFlag,
     841              :                                                                 DataLoopNode::ConnectionObjectType::CoilHeatingGasMultiStage,
     842            3 :                                                                 Alphas(1),
     843              :                                                                 DataLoopNode::NodeFluidType::Air,
     844              :                                                                 DataLoopNode::ConnectionType::Sensor,
     845              :                                                                 NodeInputManager::CompFluidStream::Primary,
     846              :                                                                 DataLoopNode::ObjectIsNotParent);
     847            3 :             state.dataHeatingCoils->InputErrorsFound = errFlag || state.dataHeatingCoils->InputErrorsFound;
     848              : 
     849              :             // parasitic electric load associated with the gas heating coil
     850            3 :             heatingCoil.ParasiticElecLoad = Numbers(10);
     851              : 
     852            3 :             heatingCoil.PLFCurveIndex = Curve::GetCurveIndex(state, Alphas(6)); // convert curve name to number
     853              : 
     854              :             // parasitic gas load associated with the gas heating coil (standing pilot light)
     855              : 
     856              :             // Setup Report variables for the Gas Coils
     857              :             // CurrentModuleObject = "Coil:Heating:Gas:MultiStage"
     858            6 :             SetupOutputVariable(state,
     859              :                                 "Heating Coil Heating Energy",
     860              :                                 Constant::Units::J,
     861            3 :                                 heatingCoil.HeatingCoilLoad,
     862              :                                 OutputProcessor::TimeStepType::System,
     863              :                                 OutputProcessor::StoreType::Sum,
     864            3 :                                 heatingCoil.Name,
     865              :                                 Constant::eResource::EnergyTransfer,
     866              :                                 OutputProcessor::Group::HVAC,
     867              :                                 OutputProcessor::EndUseCat::HeatingCoils);
     868            6 :             SetupOutputVariable(state,
     869              :                                 "Heating Coil Heating Rate",
     870              :                                 Constant::Units::W,
     871            3 :                                 heatingCoil.HeatingCoilRate,
     872              :                                 OutputProcessor::TimeStepType::System,
     873              :                                 OutputProcessor::StoreType::Average,
     874            3 :                                 heatingCoil.Name);
     875            6 :             SetupOutputVariable(state,
     876              :                                 "Heating Coil NaturalGas Energy",
     877              :                                 Constant::Units::J,
     878            3 :                                 heatingCoil.FuelUseLoad,
     879              :                                 OutputProcessor::TimeStepType::System,
     880              :                                 OutputProcessor::StoreType::Sum,
     881            3 :                                 heatingCoil.Name,
     882              :                                 Constant::eResource::NaturalGas,
     883              :                                 OutputProcessor::Group::HVAC,
     884              :                                 OutputProcessor::EndUseCat::Heating);
     885            6 :             SetupOutputVariable(state,
     886              :                                 "Heating Coil NaturalGas Rate",
     887              :                                 Constant::Units::W,
     888            3 :                                 heatingCoil.FuelUseRate,
     889              :                                 OutputProcessor::TimeStepType::System,
     890              :                                 OutputProcessor::StoreType::Average,
     891            3 :                                 heatingCoil.Name);
     892            6 :             SetupOutputVariable(state,
     893              :                                 "Heating Coil Electricity Energy",
     894              :                                 Constant::Units::J,
     895            3 :                                 heatingCoil.ElecUseLoad,
     896              :                                 OutputProcessor::TimeStepType::System,
     897              :                                 OutputProcessor::StoreType::Sum,
     898            3 :                                 heatingCoil.Name,
     899              :                                 Constant::eResource::Electricity,
     900              :                                 OutputProcessor::Group::HVAC,
     901              :                                 OutputProcessor::EndUseCat::Heating);
     902            6 :             SetupOutputVariable(state,
     903              :                                 "Heating Coil Electricity Rate",
     904              :                                 Constant::Units::W,
     905            3 :                                 heatingCoil.ElecUseRate,
     906              :                                 OutputProcessor::TimeStepType::System,
     907              :                                 OutputProcessor::StoreType::Average,
     908            3 :                                 heatingCoil.Name);
     909            6 :             SetupOutputVariable(state,
     910              :                                 "Heating Coil Runtime Fraction",
     911              :                                 Constant::Units::None,
     912            3 :                                 heatingCoil.RTF,
     913              :                                 OutputProcessor::TimeStepType::System,
     914              :                                 OutputProcessor::StoreType::Average,
     915            3 :                                 heatingCoil.Name);
     916            6 :             SetupOutputVariable(state,
     917              :                                 "Heating Coil Ancillary NaturalGas Rate",
     918              :                                 Constant::Units::W,
     919            3 :                                 heatingCoil.ParasiticFuelRate,
     920              :                                 OutputProcessor::TimeStepType::System,
     921              :                                 OutputProcessor::StoreType::Average,
     922            3 :                                 heatingCoil.Name);
     923            6 :             SetupOutputVariable(state,
     924              :                                 "Heating Coil Ancillary NaturalGas Energy",
     925              :                                 Constant::Units::J,
     926            3 :                                 heatingCoil.ParasiticFuelConsumption,
     927              :                                 OutputProcessor::TimeStepType::System,
     928              :                                 OutputProcessor::StoreType::Sum,
     929            3 :                                 heatingCoil.Name,
     930              :                                 Constant::eResource::NaturalGas,
     931              :                                 OutputProcessor::Group::HVAC,
     932              :                                 OutputProcessor::EndUseCat::Heating);
     933              :         }
     934              : 
     935              :         // Get the data for for desuperheater heating coils
     936          124 :         for (int DesuperheaterCoilNum = 1; DesuperheaterCoilNum <= state.dataHeatingCoils->NumDesuperheaterCoil; ++DesuperheaterCoilNum) {
     937              : 
     938            1 :             int CoilNum = state.dataHeatingCoils->NumElecCoil + state.dataHeatingCoils->NumElecCoilMultiStage + state.dataHeatingCoils->NumFuelCoil +
     939            1 :                           state.dataHeatingCoils->NumGasCoilMultiStage + DesuperheaterCoilNum;
     940            1 :             auto &heatingCoil = state.dataHeatingCoils->HeatingCoil(CoilNum);
     941            1 :             auto &heatingCoilNumericFields = state.dataHeatingCoils->HeatingCoilNumericFields(CoilNum);
     942            1 :             CurrentModuleObject = "Coil:Heating:Desuperheater";
     943            1 :             heatingCoil.FuelType = Constant::eFuel::Electricity;
     944              : 
     945            1 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     946              :                                                                      CurrentModuleObject,
     947              :                                                                      DesuperheaterCoilNum,
     948              :                                                                      Alphas,
     949              :                                                                      NumAlphas,
     950              :                                                                      Numbers,
     951              :                                                                      NumNums,
     952              :                                                                      IOStat,
     953              :                                                                      lNumericBlanks,
     954              :                                                                      lAlphaBlanks,
     955              :                                                                      cAlphaFields,
     956              :                                                                      cNumericFields);
     957              : 
     958            1 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
     959            1 :             heatingCoilNumericFields.FieldNames.allocate(state.dataHeatingCoils->MaxNums);
     960            1 :             heatingCoilNumericFields.FieldNames = cNumericFields;
     961              : 
     962              :             // InputErrorsFound will be set to True if problem was found, left untouched otherwise
     963            1 :             GlobalNames::VerifyUniqueCoilName(
     964            1 :                 state, CurrentModuleObject, Alphas(1), state.dataHeatingCoils->InputErrorsFound, CurrentModuleObject + " Name");
     965            1 :             heatingCoil.Name = Alphas(1);
     966            1 :             if (lAlphaBlanks(2)) {
     967            0 :                 heatingCoil.availSched = Sched::GetScheduleAlwaysOn(state);
     968            1 :             } else if ((heatingCoil.availSched = Sched::GetSchedule(state, Alphas(2))) == nullptr) {
     969            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(2), Alphas(2));
     970            0 :                 state.dataHeatingCoils->InputErrorsFound = true;
     971            1 :             } else if (!heatingCoil.availSched->checkMinMaxVals(state, Clusive::In, 0.0, Clusive::In, 1.0)) {
     972            0 :                 Sched::ShowSevereBadMinMax(state, eoh, cAlphaFields(2), Alphas(2), Clusive::In, 0.0, Clusive::In, 1.0);
     973            0 :                 state.dataHeatingCoils->InputErrorsFound = true;
     974              :             }
     975              : 
     976            1 :             heatingCoil.HeatingCoilType = "Heating";
     977            1 :             heatingCoil.HeatingCoilModel = "Desuperheater";
     978            1 :             heatingCoil.HCoilType_Num = HVAC::Coil_HeatingDesuperheater;
     979              : 
     980              :             // HeatingCoil(CoilNum)%Efficiency       = Numbers(1)
     981              :             //(Numbers(1)) error limits checked and defaults applied on efficiency after
     982              :             //       identifying souce type.
     983              : 
     984            1 :             errFlag = false;
     985            1 :             heatingCoil.AirInletNodeNum = GetOnlySingleNode(state,
     986            1 :                                                             Alphas(3),
     987              :                                                             errFlag,
     988              :                                                             DataLoopNode::ConnectionObjectType::CoilHeatingDesuperheater,
     989            1 :                                                             Alphas(1),
     990              :                                                             DataLoopNode::NodeFluidType::Air,
     991              :                                                             DataLoopNode::ConnectionType::Inlet,
     992              :                                                             NodeInputManager::CompFluidStream::Primary,
     993              :                                                             DataLoopNode::ObjectIsNotParent);
     994            1 :             state.dataHeatingCoils->InputErrorsFound = errFlag || state.dataHeatingCoils->InputErrorsFound;
     995            1 :             errFlag = false;
     996            1 :             heatingCoil.AirOutletNodeNum = GetOnlySingleNode(state,
     997            1 :                                                              Alphas(4),
     998              :                                                              errFlag,
     999              :                                                              DataLoopNode::ConnectionObjectType::CoilHeatingDesuperheater,
    1000            1 :                                                              Alphas(1),
    1001              :                                                              DataLoopNode::NodeFluidType::Air,
    1002              :                                                              DataLoopNode::ConnectionType::Outlet,
    1003              :                                                              NodeInputManager::CompFluidStream::Primary,
    1004              :                                                              DataLoopNode::ObjectIsNotParent);
    1005            1 :             state.dataHeatingCoils->InputErrorsFound = errFlag || state.dataHeatingCoils->InputErrorsFound;
    1006              : 
    1007            1 :             BranchNodeConnections::TestCompSet(state, CurrentModuleObject, Alphas(1), Alphas(3), Alphas(4), "Air Nodes");
    1008              : 
    1009            2 :             if ((Util::SameString(Alphas(5), "Refrigeration:Condenser:AirCooled")) ||
    1010            2 :                 (Util::SameString(Alphas(5), "Refrigeration:Condenser:EvaporativeCooled")) ||
    1011            2 :                 (Util::SameString(Alphas(5), "Refrigeration:Condenser:WaterCooled"))) {
    1012            0 :                 if (lNumericBlanks(1)) {
    1013            0 :                     heatingCoil.Efficiency = 0.8;
    1014              :                 } else {
    1015            0 :                     heatingCoil.Efficiency = Numbers(1);
    1016            0 :                     if (Numbers(1) < 0.0 || Numbers(1) > 0.9) {
    1017            0 :                         ShowSevereError(
    1018              :                             state,
    1019            0 :                             format("{}, \"{}\" heat reclaim recovery efficiency must be >= 0 and <=0.9", CurrentModuleObject, heatingCoil.Name));
    1020            0 :                         state.dataHeatingCoils->InputErrorsFound = true;
    1021              :                     }
    1022              :                 }
    1023              :             } else {
    1024            1 :                 if (lNumericBlanks(1)) {
    1025            0 :                     heatingCoil.Efficiency = 0.25;
    1026              :                 } else {
    1027            1 :                     heatingCoil.Efficiency = Numbers(1);
    1028            1 :                     if (Numbers(1) < 0.0 || Numbers(1) > 0.3) {
    1029            0 :                         ShowSevereError(
    1030              :                             state,
    1031            0 :                             format("{}, \"{}\" heat reclaim recovery efficiency must be >= 0 and <=0.3", CurrentModuleObject, heatingCoil.Name));
    1032            0 :                         state.dataHeatingCoils->InputErrorsFound = true;
    1033              :                     }
    1034              :                 }
    1035              :             }
    1036              : 
    1037              :             // Find the DX equipment index associated with the desuperheater heating coil.
    1038              :             // The CoilNum may not be found here when zone heating equip. exists. Check again in InitHeatingCoil.
    1039              :             // (when zone equipment heating coils are included in the input, the air loop DX equipment has not yet been read in)
    1040            1 :             if (Util::SameString(Alphas(5), "Refrigeration:CompressorRack")) {
    1041            1 :                 heatingCoil.ReclaimHeatingSource = HeatObjTypes::COMPRESSORRACK_REFRIGERATEDCASE;
    1042            2 :                 RefrigeratedCase::GetRefrigeratedRackIndex(
    1043            1 :                     state, Alphas(6), heatingCoil.ReclaimHeatingSourceIndexNum, DataHeatBalance::RefrigSystemType::Rack, DXCoilErrFlag, Alphas(5));
    1044            1 :                 if (heatingCoil.ReclaimHeatingSourceIndexNum > 0) {
    1045            1 :                     if (allocated(state.dataHeatBal->HeatReclaimRefrigeratedRack)) {
    1046              :                         DataHeatBalance::HeatReclaimDataBase &HeatReclaim =
    1047            1 :                             state.dataHeatBal->HeatReclaimRefrigeratedRack(heatingCoil.ReclaimHeatingSourceIndexNum);
    1048            1 :                         if (!allocated(HeatReclaim.HVACDesuperheaterReclaimedHeat)) {
    1049            1 :                             HeatReclaim.HVACDesuperheaterReclaimedHeat.allocate(state.dataHeatingCoils->NumDesuperheaterCoil);
    1050            1 :                             std::fill(HeatReclaim.HVACDesuperheaterReclaimedHeat.begin(), HeatReclaim.HVACDesuperheaterReclaimedHeat.end(), 0.0);
    1051              :                         }
    1052            1 :                         HeatReclaim.ReclaimEfficiencyTotal += heatingCoil.Efficiency;
    1053            1 :                         if (HeatReclaim.ReclaimEfficiencyTotal > 0.3) {
    1054            0 :                             ShowSevereError(
    1055              :                                 state,
    1056            0 :                                 format("{}, \"{}\" sum of heat reclaim recovery efficiencies from the same source coil: \"{} \" cannot be over 0.3",
    1057              :                                        HVAC::cAllCoilTypes(heatingCoil.HCoilType_Num),
    1058            0 :                                        heatingCoil.Name,
    1059            0 :                                        heatingCoil.ReclaimHeatingCoilName));
    1060              :                         }
    1061            1 :                         state.dataHeatingCoils->ValidSourceType(CoilNum) = true;
    1062              :                     }
    1063              :                 }
    1064            0 :             } else if ((Util::SameString(Alphas(5), "Refrigeration:Condenser:AirCooled")) ||
    1065            0 :                        (Util::SameString(Alphas(5), "Refrigeration:Condenser:EvaporativeCooled")) ||
    1066            0 :                        (Util::SameString(Alphas(5), "Refrigeration:Condenser:WaterCooled"))) {
    1067            0 :                 heatingCoil.ReclaimHeatingSource = HeatObjTypes::CONDENSER_REFRIGERATION;
    1068            0 :                 RefrigeratedCase::GetRefrigeratedRackIndex(state,
    1069            0 :                                                            Alphas(6),
    1070            0 :                                                            heatingCoil.ReclaimHeatingSourceIndexNum,
    1071              :                                                            DataHeatBalance::RefrigSystemType::Detailed,
    1072              :                                                            DXCoilErrFlag,
    1073            0 :                                                            Alphas(5));
    1074            0 :                 if (heatingCoil.ReclaimHeatingSourceIndexNum > 0) {
    1075            0 :                     if (allocated(state.dataHeatBal->HeatReclaimRefrigCondenser)) {
    1076              :                         DataHeatBalance::HeatReclaimDataBase &HeatReclaim =
    1077            0 :                             state.dataHeatBal->HeatReclaimRefrigCondenser(heatingCoil.ReclaimHeatingSourceIndexNum);
    1078            0 :                         if (!allocated(HeatReclaim.HVACDesuperheaterReclaimedHeat)) {
    1079            0 :                             HeatReclaim.HVACDesuperheaterReclaimedHeat.allocate(state.dataHeatingCoils->NumDesuperheaterCoil);
    1080            0 :                             std::fill(HeatReclaim.HVACDesuperheaterReclaimedHeat.begin(), HeatReclaim.HVACDesuperheaterReclaimedHeat.end(), 0.0);
    1081              :                         }
    1082            0 :                         HeatReclaim.ReclaimEfficiencyTotal += heatingCoil.Efficiency;
    1083            0 :                         if (HeatReclaim.ReclaimEfficiencyTotal > 0.9) {
    1084            0 :                             ShowSevereError(
    1085              :                                 state,
    1086            0 :                                 format("{}, \"{}\" sum of heat reclaim recovery efficiencies from the same source coil: \"{} \" cannot be over 0.9",
    1087              :                                        HVAC::cAllCoilTypes(heatingCoil.HCoilType_Num),
    1088            0 :                                        heatingCoil.Name,
    1089            0 :                                        heatingCoil.ReclaimHeatingCoilName));
    1090              :                         }
    1091            0 :                         state.dataHeatingCoils->ValidSourceType(CoilNum) = true;
    1092              :                     }
    1093              :                 }
    1094            0 :             } else if (Util::SameString(Alphas(5), "Coil:Cooling:DX:SingleSpeed")) {
    1095            0 :                 heatingCoil.ReclaimHeatingSource = HeatObjTypes::COIL_DX_COOLING;
    1096            0 :                 DXCoils::GetDXCoilIndex(state, Alphas(6), heatingCoil.ReclaimHeatingSourceIndexNum, DXCoilErrFlag, Alphas(5));
    1097            0 :                 if (heatingCoil.ReclaimHeatingSourceIndexNum > 0) {
    1098            0 :                     if (allocated(state.dataHeatBal->HeatReclaimDXCoil)) {
    1099              :                         DataHeatBalance::HeatReclaimDataBase &HeatReclaim =
    1100            0 :                             state.dataHeatBal->HeatReclaimDXCoil(heatingCoil.ReclaimHeatingSourceIndexNum);
    1101            0 :                         if (!allocated(HeatReclaim.HVACDesuperheaterReclaimedHeat)) {
    1102            0 :                             HeatReclaim.HVACDesuperheaterReclaimedHeat.allocate(state.dataHeatingCoils->NumDesuperheaterCoil);
    1103            0 :                             std::fill(HeatReclaim.HVACDesuperheaterReclaimedHeat.begin(), HeatReclaim.HVACDesuperheaterReclaimedHeat.end(), 0.0);
    1104              :                         }
    1105            0 :                         HeatReclaim.ReclaimEfficiencyTotal += heatingCoil.Efficiency;
    1106            0 :                         if (HeatReclaim.ReclaimEfficiencyTotal > 0.3) {
    1107            0 :                             ShowSevereError(
    1108              :                                 state,
    1109            0 :                                 format("{}, \"{}\" sum of heat reclaim recovery efficiencies from the same source coil: \"{} \" cannot be over 0.3",
    1110              :                                        HVAC::cAllCoilTypes(heatingCoil.HCoilType_Num),
    1111            0 :                                        heatingCoil.Name,
    1112            0 :                                        heatingCoil.ReclaimHeatingCoilName));
    1113              :                         }
    1114            0 :                         state.dataHeatingCoils->ValidSourceType(CoilNum) = true;
    1115              :                     }
    1116              :                 }
    1117            0 :                 if (heatingCoil.ReclaimHeatingSourceIndexNum > 0) state.dataHeatingCoils->ValidSourceType(CoilNum) = true;
    1118            0 :             } else if (Util::SameString(Alphas(5), "Coil:Cooling:DX:VariableSpeed")) {
    1119            0 :                 heatingCoil.ReclaimHeatingSource = HeatObjTypes::COIL_DX_VARIABLE_COOLING;
    1120            0 :                 heatingCoil.ReclaimHeatingSourceIndexNum = VariableSpeedCoils::GetCoilIndexVariableSpeed(state, Alphas(5), Alphas(6), DXCoilErrFlag);
    1121            0 :                 if (heatingCoil.ReclaimHeatingSourceIndexNum > 0) {
    1122            0 :                     if (allocated(state.dataHeatBal->HeatReclaimVS_Coil)) {
    1123              :                         DataHeatBalance::HeatReclaimDataBase &HeatReclaim =
    1124            0 :                             state.dataHeatBal->HeatReclaimVS_Coil(heatingCoil.ReclaimHeatingSourceIndexNum);
    1125            0 :                         if (!allocated(HeatReclaim.HVACDesuperheaterReclaimedHeat)) {
    1126            0 :                             HeatReclaim.HVACDesuperheaterReclaimedHeat.allocate(state.dataHeatingCoils->NumDesuperheaterCoil);
    1127            0 :                             std::fill(HeatReclaim.HVACDesuperheaterReclaimedHeat.begin(), HeatReclaim.HVACDesuperheaterReclaimedHeat.end(), 0.0);
    1128              :                         }
    1129            0 :                         HeatReclaim.ReclaimEfficiencyTotal += heatingCoil.Efficiency;
    1130            0 :                         if (HeatReclaim.ReclaimEfficiencyTotal > 0.3) {
    1131            0 :                             ShowSevereError(
    1132              :                                 state,
    1133            0 :                                 format("{}, \"{}\" sum of heat reclaim recovery efficiencies from the same source coil: \"{} \" cannot be over 0.3",
    1134              :                                        HVAC::cAllCoilTypes(heatingCoil.HCoilType_Num),
    1135            0 :                                        heatingCoil.Name,
    1136            0 :                                        heatingCoil.ReclaimHeatingCoilName));
    1137              :                         }
    1138            0 :                         state.dataHeatingCoils->ValidSourceType(CoilNum) = true;
    1139              :                     }
    1140              :                 }
    1141            0 :             } else if (Util::SameString(Alphas(5), "Coil:Cooling:DX:TwoSpeed")) {
    1142            0 :                 heatingCoil.ReclaimHeatingSource = HeatObjTypes::COIL_DX_MULTISPEED;
    1143            0 :                 DXCoils::GetDXCoilIndex(state, Alphas(6), heatingCoil.ReclaimHeatingSourceIndexNum, DXCoilErrFlag, Alphas(5));
    1144            0 :                 if (heatingCoil.ReclaimHeatingSourceIndexNum > 0) {
    1145            0 :                     if (allocated(state.dataHeatBal->HeatReclaimDXCoil)) {
    1146              :                         DataHeatBalance::HeatReclaimDataBase &HeatReclaim =
    1147            0 :                             state.dataHeatBal->HeatReclaimDXCoil(heatingCoil.ReclaimHeatingSourceIndexNum);
    1148            0 :                         if (!allocated(HeatReclaim.HVACDesuperheaterReclaimedHeat)) {
    1149            0 :                             HeatReclaim.HVACDesuperheaterReclaimedHeat.allocate(state.dataHeatingCoils->NumDesuperheaterCoil);
    1150            0 :                             std::fill(HeatReclaim.HVACDesuperheaterReclaimedHeat.begin(), HeatReclaim.HVACDesuperheaterReclaimedHeat.end(), 0.0);
    1151              :                         }
    1152            0 :                         HeatReclaim.ReclaimEfficiencyTotal += heatingCoil.Efficiency;
    1153            0 :                         if (HeatReclaim.ReclaimEfficiencyTotal > 0.3) {
    1154            0 :                             ShowSevereError(
    1155              :                                 state,
    1156            0 :                                 format("{}, \"{}\" sum of heat reclaim recovery efficiencies from the same source coil: \"{} \" cannot be over 0.3",
    1157              :                                        HVAC::cAllCoilTypes(heatingCoil.HCoilType_Num),
    1158            0 :                                        heatingCoil.Name,
    1159            0 :                                        heatingCoil.ReclaimHeatingCoilName));
    1160              :                         }
    1161            0 :                         state.dataHeatingCoils->ValidSourceType(CoilNum) = true;
    1162              :                     }
    1163              :                 }
    1164            0 :             } else if (Util::SameString(Alphas(5), "Coil:Cooling:DX:TwoStageWithHumidityControlMode")) {
    1165            0 :                 heatingCoil.ReclaimHeatingSource = HeatObjTypes::COIL_DX_MULTIMODE;
    1166            0 :                 DXCoils::GetDXCoilIndex(state, Alphas(6), heatingCoil.ReclaimHeatingSourceIndexNum, DXCoilErrFlag, Alphas(5));
    1167            0 :                 if (heatingCoil.ReclaimHeatingSourceIndexNum > 0) {
    1168            0 :                     if (allocated(state.dataHeatBal->HeatReclaimDXCoil)) {
    1169              :                         DataHeatBalance::HeatReclaimDataBase &HeatReclaim =
    1170            0 :                             state.dataHeatBal->HeatReclaimDXCoil(heatingCoil.ReclaimHeatingSourceIndexNum);
    1171            0 :                         if (!allocated(HeatReclaim.HVACDesuperheaterReclaimedHeat)) {
    1172            0 :                             HeatReclaim.HVACDesuperheaterReclaimedHeat.allocate(state.dataHeatingCoils->NumDesuperheaterCoil);
    1173            0 :                             std::fill(HeatReclaim.HVACDesuperheaterReclaimedHeat.begin(), HeatReclaim.HVACDesuperheaterReclaimedHeat.end(), 0.0);
    1174              :                         }
    1175            0 :                         HeatReclaim.ReclaimEfficiencyTotal += heatingCoil.Efficiency;
    1176            0 :                         if (HeatReclaim.ReclaimEfficiencyTotal > 0.3) {
    1177            0 :                             ShowSevereError(
    1178              :                                 state,
    1179            0 :                                 format(R"({}, "{}" sum of heat reclaim recovery efficiencies from the same source coil: "{} " cannot be over 0.3)",
    1180              :                                        HVAC::cAllCoilTypes(heatingCoil.HCoilType_Num),
    1181            0 :                                        heatingCoil.Name,
    1182            0 :                                        heatingCoil.ReclaimHeatingCoilName));
    1183              :                         }
    1184            0 :                         state.dataHeatingCoils->ValidSourceType(CoilNum) = true;
    1185              :                     }
    1186              :                 }
    1187            0 :             } else if (Util::SameString(Alphas(5), "Coil:Cooling:DX")) {
    1188            0 :                 heatingCoil.ReclaimHeatingSource = HeatObjTypes::COIL_COOLING_DX_NEW;
    1189            0 :                 heatingCoil.ReclaimHeatingSourceIndexNum = CoilCoolingDX::factory(state, Alphas(6));
    1190            0 :                 if (heatingCoil.ReclaimHeatingSourceIndexNum < 0) {
    1191            0 :                     ShowSevereError(
    1192            0 :                         state, format("{}={}, could not find desuperheater coil {}={}", CurrentModuleObject, heatingCoil.Name, Alphas(5), Alphas(6)));
    1193            0 :                     state.dataHeatingCoils->InputErrorsFound = true;
    1194              :                 }
    1195              :                 DataHeatBalance::HeatReclaimDataBase &HeatReclaim =
    1196            0 :                     state.dataCoilCoolingDX->coilCoolingDXs[heatingCoil.ReclaimHeatingSourceIndexNum].reclaimHeat;
    1197            0 :                 if (!allocated(HeatReclaim.HVACDesuperheaterReclaimedHeat)) {
    1198            0 :                     HeatReclaim.HVACDesuperheaterReclaimedHeat.allocate(state.dataHeatingCoils->NumDesuperheaterCoil);
    1199            0 :                     std::fill(HeatReclaim.HVACDesuperheaterReclaimedHeat.begin(), HeatReclaim.HVACDesuperheaterReclaimedHeat.end(), 0.0);
    1200              :                 }
    1201            0 :                 HeatReclaim.ReclaimEfficiencyTotal += heatingCoil.Efficiency;
    1202            0 :                 if (HeatReclaim.ReclaimEfficiencyTotal > 0.3) {
    1203            0 :                     ShowSevereError(
    1204              :                         state,
    1205            0 :                         format("{}, \"{}\" sum of heat reclaim recovery efficiencies from the same source coil: \"{}\" cannot be over 0.3",
    1206              :                                HVAC::cAllCoilTypes(heatingCoil.HCoilType_Num),
    1207            0 :                                heatingCoil.Name,
    1208            0 :                                heatingCoil.ReclaimHeatingCoilName));
    1209              :                 }
    1210            0 :                 state.dataHeatingCoils->ValidSourceType(CoilNum) = true;
    1211              :             } else {
    1212            0 :                 ShowSevereError(
    1213              :                     state,
    1214            0 :                     format("{}, \"{}\" valid desuperheater heat source object type not found: {}", CurrentModuleObject, heatingCoil.Name, Alphas(5)));
    1215            0 :                 ShowContinueError(state, "Valid desuperheater heat source objects are:");
    1216            0 :                 ShowContinueError(state,
    1217              :                                   "Refrigeration:CompressorRack, Coil:Cooling:DX:SingleSpeed, Refrigeration:Condenser:AirCooled, "
    1218              :                                   "Refrigeration:Condenser:EvaporativeCooled, Refrigeration:Condenser:WaterCooled,Coil:Cooling:DX:TwoSpeed, and "
    1219              :                                   "Coil:Cooling:DX:TwoStageWithHumidityControlMode");
    1220            0 :                 state.dataHeatingCoils->InputErrorsFound = true;
    1221              :             }
    1222              : 
    1223            1 :             heatingCoil.ReclaimHeatingCoilName = Alphas(6);
    1224              : 
    1225            1 :             errFlag = false;
    1226            1 :             heatingCoil.TempSetPointNodeNum = GetOnlySingleNode(state,
    1227            1 :                                                                 Alphas(7),
    1228              :                                                                 errFlag,
    1229              :                                                                 DataLoopNode::ConnectionObjectType::CoilHeatingDesuperheater,
    1230            1 :                                                                 Alphas(1),
    1231              :                                                                 DataLoopNode::NodeFluidType::Air,
    1232              :                                                                 DataLoopNode::ConnectionType::Sensor,
    1233              :                                                                 NodeInputManager::CompFluidStream::Primary,
    1234              :                                                                 DataLoopNode::ObjectIsNotParent);
    1235            1 :             state.dataHeatingCoils->InputErrorsFound = errFlag || state.dataHeatingCoils->InputErrorsFound;
    1236              : 
    1237              :             // parasitic electric load associated with the desuperheater heating coil
    1238            1 :             heatingCoil.ParasiticElecLoad = Numbers(2);
    1239              : 
    1240            1 :             if (Numbers(2) < 0.0) {
    1241            0 :                 ShowSevereError(state, format("{}, \"{}\" parasitic electric load must be >= 0", CurrentModuleObject, heatingCoil.Name));
    1242            0 :                 state.dataHeatingCoils->InputErrorsFound = true;
    1243              :             }
    1244              : 
    1245              :             // Setup Report variables for the Desuperheater Heating Coils
    1246              :             // CurrentModuleObject = "Coil:Heating:Desuperheater"
    1247            2 :             SetupOutputVariable(state,
    1248              :                                 "Heating Coil Heating Energy",
    1249              :                                 Constant::Units::J,
    1250            1 :                                 heatingCoil.HeatingCoilLoad,
    1251              :                                 OutputProcessor::TimeStepType::System,
    1252              :                                 OutputProcessor::StoreType::Sum,
    1253            1 :                                 heatingCoil.Name,
    1254              :                                 Constant::eResource::EnergyTransfer,
    1255              :                                 OutputProcessor::Group::HVAC,
    1256              :                                 OutputProcessor::EndUseCat::HeatingCoils);
    1257            2 :             SetupOutputVariable(state,
    1258              :                                 "Heating Coil Heating Rate",
    1259              :                                 Constant::Units::W,
    1260            1 :                                 heatingCoil.HeatingCoilRate,
    1261              :                                 OutputProcessor::TimeStepType::System,
    1262              :                                 OutputProcessor::StoreType::Average,
    1263            1 :                                 heatingCoil.Name);
    1264            2 :             SetupOutputVariable(state,
    1265              :                                 "Heating Coil Electricity Energy",
    1266              :                                 Constant::Units::J,
    1267            1 :                                 heatingCoil.ElecUseLoad,
    1268              :                                 OutputProcessor::TimeStepType::System,
    1269              :                                 OutputProcessor::StoreType::Sum,
    1270            1 :                                 heatingCoil.Name,
    1271              :                                 Constant::eResource::Electricity,
    1272              :                                 OutputProcessor::Group::HVAC,
    1273              :                                 OutputProcessor::EndUseCat::Heating);
    1274            2 :             SetupOutputVariable(state,
    1275              :                                 "Heating Coil Electricity Rate",
    1276              :                                 Constant::Units::W,
    1277            1 :                                 heatingCoil.ElecUseRate,
    1278              :                                 OutputProcessor::TimeStepType::System,
    1279              :                                 OutputProcessor::StoreType::Average,
    1280            1 :                                 heatingCoil.Name);
    1281            2 :             SetupOutputVariable(state,
    1282              :                                 "Heating Coil Runtime Fraction",
    1283              :                                 Constant::Units::None,
    1284            1 :                                 heatingCoil.RTF,
    1285              :                                 OutputProcessor::TimeStepType::System,
    1286              :                                 OutputProcessor::StoreType::Average,
    1287            1 :                                 heatingCoil.Name);
    1288              :         }
    1289              : 
    1290          123 :         if (state.dataHeatingCoils->InputErrorsFound) {
    1291            2 :             ShowFatalError(state, format("{}Errors found in input.  Program terminates.", RoutineName));
    1292              :         }
    1293              : 
    1294          122 :         Alphas.deallocate();
    1295          122 :         cAlphaFields.deallocate();
    1296          122 :         cNumericFields.deallocate();
    1297          122 :         Numbers.deallocate();
    1298          122 :         lAlphaBlanks.deallocate();
    1299          122 :         lNumericBlanks.deallocate();
    1300          129 :     }
    1301              : 
    1302       233160 :     void InitHeatingCoil(EnergyPlusData &state, int const CoilNum, bool const FirstHVACIteration, Real64 const QCoilRequired)
    1303              :     {
    1304              : 
    1305              :         // SUBROUTINE INFORMATION:
    1306              :         //       AUTHOR         Richard J. Liesen
    1307              :         //       DATE WRITTEN   May 2000
    1308              :         //       MODIFIED       B. Griffith, May 2009 added EMS setpoint check
    1309              : 
    1310              :         // PURPOSE OF THIS SUBROUTINE:
    1311              :         // This subroutine is for initializations of the HeatingCoil Components.
    1312              : 
    1313              :         // METHODOLOGY EMPLOYED:
    1314              :         // Uses the status flags to trigger initializations.
    1315              : 
    1316       233160 :         auto &heatingCoil = state.dataHeatingCoils->HeatingCoil(CoilNum);
    1317              : 
    1318       233160 :         if (state.dataHeatingCoils->MyOneTimeFlag) {
    1319              :             // initialize the environment and sizing flags
    1320           94 :             Real64 numHeatingCoils = state.dataHeatingCoils->NumHeatingCoils;
    1321           94 :             state.dataHeatingCoils->MyEnvrnFlag.allocate(numHeatingCoils);
    1322           94 :             state.dataHeatingCoils->MySizeFlag.allocate(numHeatingCoils);
    1323           94 :             state.dataHeatingCoils->ShowSingleWarning.allocate(numHeatingCoils);
    1324           94 :             state.dataHeatingCoils->MySPTestFlag.allocate(numHeatingCoils);
    1325           94 :             state.dataHeatingCoils->MyEnvrnFlag = true;
    1326           94 :             state.dataHeatingCoils->MySizeFlag = true;
    1327           94 :             state.dataHeatingCoils->ShowSingleWarning = true;
    1328           94 :             state.dataHeatingCoils->MyOneTimeFlag = false;
    1329           94 :             state.dataHeatingCoils->MySPTestFlag = true;
    1330              :         }
    1331              : 
    1332       233160 :         if (!state.dataGlobal->SysSizingCalc && state.dataHeatingCoils->MySizeFlag(CoilNum)) {
    1333              :             // for each coil, do the sizing once.
    1334           98 :             SizeHeatingCoil(state, CoilNum);
    1335              : 
    1336           98 :             state.dataHeatingCoils->MySizeFlag(CoilNum) = false;
    1337              :         }
    1338              : 
    1339              :         // Do the following initializations (every time step): This should be the info from
    1340              :         // the previous components outlets or the node data in this section.
    1341              :         // First set the conditions for the air into the coil model
    1342       233160 :         int AirOutletNodeNum = heatingCoil.AirOutletNodeNum;
    1343       233160 :         int ControlNodeNum = heatingCoil.TempSetPointNodeNum;
    1344       233160 :         auto const &airInletNode = state.dataLoopNodes->Node(heatingCoil.AirInletNodeNum);
    1345       233160 :         auto const &airOutletNode = state.dataLoopNodes->Node(AirOutletNodeNum);
    1346       233160 :         heatingCoil.InletAirMassFlowRate = airInletNode.MassFlowRate;
    1347       233160 :         heatingCoil.InletAirTemp = airInletNode.Temp;
    1348       233160 :         heatingCoil.InletAirHumRat = airInletNode.HumRat;
    1349       233160 :         heatingCoil.InletAirEnthalpy = airInletNode.Enthalpy;
    1350              : 
    1351              :         // Set the reporting variables to zero at each timestep.
    1352       233160 :         heatingCoil.HeatingCoilLoad = 0.0;
    1353       233160 :         heatingCoil.FuelUseLoad = 0.0;
    1354       233160 :         heatingCoil.ElecUseLoad = 0.0;
    1355       233160 :         heatingCoil.RTF = 0.0;
    1356              : 
    1357              :         // If a temperature setpoint controlled coil must set the desired outlet temp everytime
    1358       233160 :         if (ControlNodeNum == 0) {
    1359       167841 :             heatingCoil.DesiredOutletTemp = 0.0;
    1360              :         } else {
    1361        65319 :             auto const &controlNode = state.dataLoopNodes->Node(ControlNodeNum);
    1362        65319 :             heatingCoil.DesiredOutletTemp =
    1363        65319 :                 controlNode.TempSetPoint - ((ControlNodeNum == AirOutletNodeNum) ? 0 : (controlNode.Temp - airOutletNode.Temp));
    1364              :         }
    1365              : 
    1366        65486 :         if (QCoilRequired == DataLoopNode::SensedLoadFlagValue && state.dataHeatingCoils->MySPTestFlag(CoilNum) &&
    1367       298646 :             heatingCoil.HCoilType_Num != HVAC::Coil_HeatingElectric_MultiStage && heatingCoil.HCoilType_Num != HVAC::Coil_HeatingGas_MultiStage) {
    1368              : 
    1369              :             //   If the coil is temperature controlled (QCoilReq == -999.0), both a control node and setpoint are required.
    1370           77 :             if (!state.dataGlobal->SysSizingCalc && state.dataHVACGlobal->DoSetPointTest) {
    1371              :                 //     3 possibilities here:
    1372              :                 //     1) TempSetPointNodeNum .GT. 0 and TempSetPoint /= SensedNodeFlagValue, this is correct
    1373              :                 //     2) TempSetPointNodeNum .EQ. 0, this is not correct, control node is required
    1374              :                 //     3) TempSetPointNodeNum .GT. 0 and TempSetPoint == SensedNodeFlagValue, this is not correct, missing temperature setpoint
    1375              :                 //     test 2) here (fatal message)
    1376           15 :                 if (ControlNodeNum == 0) {
    1377            0 :                     ShowSevereError(state, format("{} \"{}\"", HVAC::cAllCoilTypes(heatingCoil.HCoilType_Num), heatingCoil.Name));
    1378            0 :                     ShowContinueError(state, "... Missing control node for heating coil.");
    1379            0 :                     ShowContinueError(state, "... enter a control node name in the coil temperature setpoint node field for this heating coil.");
    1380            0 :                     ShowContinueError(state, "... use a Setpoint Manager to establish a setpoint at the coil temperature setpoint node.");
    1381            0 :                     state.dataHeatingCoils->HeatingCoilFatalError = true;
    1382              :                     //     test 3) here (fatal message)
    1383              :                 } else { // IF(ControlNode .GT. 0)THEN
    1384           15 :                     auto const &controlNode = state.dataLoopNodes->Node(ControlNodeNum);
    1385           15 :                     if (controlNode.TempSetPoint == DataLoopNode::SensedNodeFlagValue) {
    1386            0 :                         if (!state.dataGlobal->AnyEnergyManagementSystemInModel) {
    1387            0 :                             ShowSevereError(state, format("{} \"{}\"", HVAC::cAllCoilTypes(heatingCoil.HCoilType_Num), heatingCoil.Name));
    1388            0 :                             ShowContinueError(state, "... Missing temperature setpoint for heating coil.");
    1389            0 :                             ShowContinueError(state, "... use a Setpoint Manager to establish a setpoint at the coil temperature setpoint node.");
    1390            0 :                             state.dataHeatingCoils->HeatingCoilFatalError = true;
    1391              :                         } else {
    1392            0 :                             EMSManager::CheckIfNodeSetPointManagedByEMS(
    1393            0 :                                 state, ControlNodeNum, HVAC::CtrlVarType::Temp, state.dataHeatingCoils->HeatingCoilFatalError);
    1394            0 :                             if (state.dataHeatingCoils->HeatingCoilFatalError) {
    1395            0 :                                 ShowSevereError(state, format("{} \"{}\"", HVAC::cAllCoilTypes(heatingCoil.HCoilType_Num), heatingCoil.Name));
    1396            0 :                                 ShowContinueError(state, "... Missing temperature setpoint for heating coil.");
    1397            0 :                                 ShowContinueError(state, "... use a Setpoint Manager to establish a setpoint at the coil temperature setpoint node.");
    1398            0 :                                 ShowContinueError(state, "... or use an EMS Actuator to establish a setpoint at the coil temperature setpoint node.");
    1399              :                             }
    1400              :                         }
    1401              :                     }
    1402              :                 }
    1403           15 :                 state.dataHeatingCoils->MySPTestFlag(CoilNum) = false;
    1404              :             }
    1405       233083 :         } else if (state.dataHeatingCoils->MySPTestFlag(CoilNum)) {
    1406              :             //  If QCoilReq /= SensedLoadFlagValue, the coil is load controlled and does not require a control node
    1407              :             //   4 possibilities here:
    1408              :             //   1) TempSetPointNodeNum .EQ. 0 and TempSetPoint == SensedNodeFlagValue, this is correct
    1409              :             //   2) TempSetPointNodeNum .EQ. 0 and TempSetPoint /= SensedNodeFlagValue, this may be correct,
    1410              :             //      (if no control node specified and SP on heating coil outlet do not show warning, other SP managers may be using SP)
    1411              :             //   3) TempSetPointNodeNum .GT. 0 and TempSetPoint == SensedNodeFlagValue, control node not required if load based control
    1412              :             //   4) TempSetPointNodeNum .GT. 0 and TempSetPoint /= SensedNodeFlagValue, control node not required if load based control
    1413              :             //   test 3) and 4) here (warning only)
    1414          106 :             if (ControlNodeNum > 0) {
    1415            4 :                 ShowWarningError(state, format("{} \"{}\"", HVAC::cAllCoilTypes(heatingCoil.HCoilType_Num), heatingCoil.Name));
    1416            8 :                 ShowContinueError(state, " The \"Temperature Setpoint Node Name\" input is not required for this heating coil.");
    1417           12 :                 ShowContinueError(state, " Leaving the input field \"Temperature Setpoint Node Name\" blank will eliminate this warning.");
    1418              :             }
    1419          106 :             state.dataHeatingCoils->MySPTestFlag(CoilNum) = false;
    1420              :         }
    1421              : 
    1422              :         // delay fatal error until all coils are called
    1423       233160 :         if (!FirstHVACIteration && state.dataHeatingCoils->HeatingCoilFatalError) {
    1424            0 :             ShowFatalError(state, "... errors found in heating coil input.");
    1425              :         }
    1426              : 
    1427              :         // Find the heating source index for the desuperheater heating coil if not already found. This occurs when zone heating
    1428              :         // equip. exists. (when zone equipment heating coils are included in the input, the air loop DX equipment has not yet been read)
    1429              :         // Issue a single warning if the coil is not found and continue the simulation
    1430       233160 :         if (!state.dataHeatingCoils->ValidSourceType(CoilNum) && (heatingCoil.HCoilType_Num == HVAC::Coil_HeatingDesuperheater) &&
    1431            0 :             state.dataHeatingCoils->ShowSingleWarning(CoilNum)) {
    1432            0 :             ++state.dataHeatingCoils->ValidSourceTypeCounter;
    1433            0 :             switch (heatingCoil.ReclaimHeatingSource) {
    1434            0 :             case HeatObjTypes::COMPRESSORRACK_REFRIGERATEDCASE: {
    1435            0 :                 for (int RackNum = 1; RackNum <= state.dataRefrigCase->NumRefrigeratedRacks; ++RackNum) {
    1436            0 :                     if (!Util::SameString(state.dataHeatBal->HeatReclaimRefrigeratedRack(RackNum).Name, heatingCoil.ReclaimHeatingCoilName)) continue;
    1437            0 :                     heatingCoil.ReclaimHeatingSourceIndexNum = RackNum;
    1438            0 :                     if (allocated(state.dataHeatBal->HeatReclaimRefrigeratedRack)) {
    1439              :                         DataHeatBalance::HeatReclaimDataBase &HeatReclaim =
    1440            0 :                             state.dataHeatBal->HeatReclaimRefrigeratedRack(heatingCoil.ReclaimHeatingSourceIndexNum);
    1441            0 :                         if (!allocated(HeatReclaim.HVACDesuperheaterReclaimedHeat)) {
    1442            0 :                             HeatReclaim.HVACDesuperheaterReclaimedHeat.allocate(state.dataHeatingCoils->NumDesuperheaterCoil);
    1443            0 :                             std::fill(HeatReclaim.HVACDesuperheaterReclaimedHeat.begin(), HeatReclaim.HVACDesuperheaterReclaimedHeat.end(), 0.0);
    1444            0 :                             HeatReclaim.ReclaimEfficiencyTotal += heatingCoil.Efficiency;
    1445            0 :                             if (HeatReclaim.ReclaimEfficiencyTotal > 0.3) {
    1446            0 :                                 ShowSevereError(
    1447              :                                     state,
    1448            0 :                                     format(R"({}, "{}" sum of heat reclaim recovery efficiencies from the same source coil: "{}" cannot be over 0.3)",
    1449              :                                            HVAC::cAllCoilTypes(heatingCoil.HCoilType_Num),
    1450            0 :                                            heatingCoil.Name,
    1451            0 :                                            heatingCoil.ReclaimHeatingCoilName));
    1452              :                             }
    1453              :                         }
    1454            0 :                         state.dataHeatingCoils->ValidSourceType(CoilNum) = true;
    1455              :                     }
    1456            0 :                     break;
    1457              :                 }
    1458            0 :             } break;
    1459            0 :             case HeatObjTypes::CONDENSER_REFRIGERATION: {
    1460            0 :                 for (int CondNum = 1; CondNum <= state.dataRefrigCase->NumRefrigCondensers; ++CondNum) {
    1461            0 :                     if (!Util::SameString(state.dataHeatBal->HeatReclaimRefrigCondenser(CondNum).Name, heatingCoil.ReclaimHeatingCoilName)) continue;
    1462            0 :                     heatingCoil.ReclaimHeatingSourceIndexNum = CondNum;
    1463            0 :                     if (allocated(state.dataHeatBal->HeatReclaimRefrigCondenser)) {
    1464              :                         DataHeatBalance::HeatReclaimDataBase &HeatReclaim =
    1465            0 :                             state.dataHeatBal->HeatReclaimRefrigCondenser(heatingCoil.ReclaimHeatingSourceIndexNum);
    1466            0 :                         if (!allocated(HeatReclaim.HVACDesuperheaterReclaimedHeat)) {
    1467            0 :                             HeatReclaim.HVACDesuperheaterReclaimedHeat.allocate(state.dataHeatingCoils->NumDesuperheaterCoil);
    1468            0 :                             std::fill(HeatReclaim.HVACDesuperheaterReclaimedHeat.begin(), HeatReclaim.HVACDesuperheaterReclaimedHeat.end(), 0.0);
    1469            0 :                             HeatReclaim.ReclaimEfficiencyTotal += heatingCoil.Efficiency;
    1470            0 :                             if (HeatReclaim.ReclaimEfficiencyTotal > 0.9) {
    1471            0 :                                 ShowSevereError(
    1472              :                                     state,
    1473            0 :                                     format(R"({}, "{}" sum of heat reclaim recovery efficiencies from the same source coil: "{}" cannot be over 0.9)",
    1474              :                                            HVAC::cAllCoilTypes(heatingCoil.HCoilType_Num),
    1475            0 :                                            heatingCoil.Name,
    1476            0 :                                            heatingCoil.ReclaimHeatingCoilName));
    1477              :                             }
    1478              :                         }
    1479            0 :                         state.dataHeatingCoils->ValidSourceType(CoilNum) = true;
    1480              :                     }
    1481            0 :                     break;
    1482              :                 }
    1483            0 :             } break;
    1484            0 :             case HeatObjTypes::COIL_DX_COOLING:
    1485              :             case HeatObjTypes::COIL_DX_MULTISPEED:
    1486              :             case HeatObjTypes::COIL_DX_MULTIMODE: {
    1487            0 :                 for (int DXCoilNum = 1; DXCoilNum <= state.dataDXCoils->NumDXCoils; ++DXCoilNum) {
    1488            0 :                     if (!Util::SameString(state.dataHeatBal->HeatReclaimDXCoil(DXCoilNum).Name, heatingCoil.ReclaimHeatingCoilName)) continue;
    1489            0 :                     heatingCoil.ReclaimHeatingSourceIndexNum = DXCoilNum;
    1490            0 :                     if (allocated(state.dataHeatBal->HeatReclaimDXCoil)) {
    1491              :                         DataHeatBalance::HeatReclaimDataBase &HeatReclaim =
    1492            0 :                             state.dataHeatBal->HeatReclaimDXCoil(heatingCoil.ReclaimHeatingSourceIndexNum);
    1493            0 :                         if (!allocated(HeatReclaim.HVACDesuperheaterReclaimedHeat)) {
    1494            0 :                             HeatReclaim.HVACDesuperheaterReclaimedHeat.allocate(state.dataHeatingCoils->NumDesuperheaterCoil);
    1495            0 :                             std::fill(HeatReclaim.HVACDesuperheaterReclaimedHeat.begin(), HeatReclaim.HVACDesuperheaterReclaimedHeat.end(), 0.0);
    1496            0 :                             HeatReclaim.ReclaimEfficiencyTotal += heatingCoil.Efficiency;
    1497            0 :                             if (HeatReclaim.ReclaimEfficiencyTotal > 0.3) {
    1498            0 :                                 ShowSevereError(
    1499              :                                     state,
    1500            0 :                                     format(R"({}, "{}" sum of heat reclaim recovery efficiencies from the same source coil: "{}" cannot be over 0.3)",
    1501              :                                            HVAC::cAllCoilTypes(heatingCoil.HCoilType_Num),
    1502            0 :                                            heatingCoil.Name,
    1503            0 :                                            heatingCoil.ReclaimHeatingCoilName));
    1504              :                             }
    1505              :                         }
    1506            0 :                         state.dataHeatingCoils->ValidSourceType(CoilNum) = true;
    1507              :                     }
    1508            0 :                     break;
    1509              :                 }
    1510            0 :             } break;
    1511            0 :             case HeatObjTypes::COIL_DX_VARIABLE_COOLING: {
    1512            0 :                 for (int DXCoilNum = 1; DXCoilNum <= state.dataVariableSpeedCoils->NumVarSpeedCoils; ++DXCoilNum) {
    1513            0 :                     if (!Util::SameString(state.dataHeatBal->HeatReclaimVS_Coil(DXCoilNum).Name, heatingCoil.ReclaimHeatingCoilName)) continue;
    1514            0 :                     heatingCoil.ReclaimHeatingSourceIndexNum = DXCoilNum;
    1515            0 :                     if (allocated(state.dataHeatBal->HeatReclaimVS_Coil)) {
    1516              :                         DataHeatBalance::HeatReclaimDataBase &HeatReclaim =
    1517            0 :                             state.dataHeatBal->HeatReclaimVS_Coil(heatingCoil.ReclaimHeatingSourceIndexNum);
    1518            0 :                         if (!allocated(HeatReclaim.HVACDesuperheaterReclaimedHeat)) {
    1519            0 :                             HeatReclaim.HVACDesuperheaterReclaimedHeat.allocate(state.dataHeatingCoils->NumDesuperheaterCoil);
    1520            0 :                             std::fill(HeatReclaim.HVACDesuperheaterReclaimedHeat.begin(), HeatReclaim.HVACDesuperheaterReclaimedHeat.end(), 0.0);
    1521            0 :                             HeatReclaim.ReclaimEfficiencyTotal += heatingCoil.Efficiency;
    1522            0 :                             if (HeatReclaim.ReclaimEfficiencyTotal > 0.3) {
    1523            0 :                                 ShowSevereError(
    1524              :                                     state,
    1525            0 :                                     format(R"({}, "{}" sum of heat reclaim recovery efficiencies from the same source coil: "{}" cannot be over 0.3)",
    1526              :                                            HVAC::cAllCoilTypes(heatingCoil.HCoilType_Num),
    1527            0 :                                            heatingCoil.Name,
    1528            0 :                                            heatingCoil.ReclaimHeatingCoilName));
    1529              :                             }
    1530              :                         }
    1531            0 :                         state.dataHeatingCoils->ValidSourceType(CoilNum) = true;
    1532              :                     }
    1533            0 :                     break;
    1534              :                 }
    1535              :             case HeatObjTypes::COIL_COOLING_DX_NEW:
    1536              :                 DataHeatBalance::HeatReclaimDataBase &HeatReclaim =
    1537            0 :                     state.dataCoilCoolingDX->coilCoolingDXs[heatingCoil.ReclaimHeatingSourceIndexNum].reclaimHeat;
    1538            0 :                 if (!allocated(HeatReclaim.HVACDesuperheaterReclaimedHeat)) {
    1539            0 :                     HeatReclaim.HVACDesuperheaterReclaimedHeat.allocate(state.dataHeatingCoils->NumDesuperheaterCoil);
    1540            0 :                     std::fill(HeatReclaim.HVACDesuperheaterReclaimedHeat.begin(), HeatReclaim.HVACDesuperheaterReclaimedHeat.end(), 0.0);
    1541            0 :                     HeatReclaim.ReclaimEfficiencyTotal += heatingCoil.Efficiency;
    1542            0 :                     if (HeatReclaim.ReclaimEfficiencyTotal > 0.3) {
    1543            0 :                         ShowSevereError(
    1544              :                             state,
    1545            0 :                             format("{}, \"{}\" sum of heat reclaim recovery efficiencies from the same source coil: \"{}\" cannot be over 0.3",
    1546              :                                    HVAC::cAllCoilTypes(heatingCoil.HCoilType_Num),
    1547            0 :                                    heatingCoil.Name,
    1548            0 :                                    heatingCoil.ReclaimHeatingCoilName));
    1549              :                     }
    1550              :                 }
    1551            0 :                 state.dataHeatingCoils->ValidSourceType(CoilNum) = true;
    1552            0 :                 break;
    1553              :             } break;
    1554            0 :             default:
    1555            0 :                 break;
    1556              :             }
    1557            0 :             if ((state.dataHeatingCoils->ValidSourceTypeCounter > state.dataHeatingCoils->NumDesuperheaterCoil * 2) &&
    1558            0 :                 state.dataHeatingCoils->ShowSingleWarning(CoilNum) && !state.dataHeatingCoils->ValidSourceType(CoilNum)) {
    1559            0 :                 ShowWarningError(state,
    1560            0 :                                  format("Coil:Heating:Desuperheater, \"{}\" desuperheater heat source object name not found: {}",
    1561            0 :                                         heatingCoil.Name,
    1562            0 :                                         heatingCoil.ReclaimHeatingCoilName));
    1563            0 :                 ShowContinueError(state, " Desuperheater heating coil is not modeled and simulation continues.");
    1564            0 :                 state.dataHeatingCoils->ShowSingleWarning(CoilNum) = false;
    1565              :             }
    1566              :         }
    1567       233160 :     }
    1568              : 
    1569           98 :     void SizeHeatingCoil(EnergyPlusData &state, int const CoilNum)
    1570              :     {
    1571              : 
    1572              :         // SUBROUTINE INFORMATION:
    1573              :         //       AUTHOR         Fred Buhl
    1574              :         //       DATE WRITTEN   January 2002
    1575              :         //       MODIFIED       August 2013 Daeho Kang, add component sizing table entries
    1576              :         //       RE-ENGINEERED  Mar 2014 FSEC, moved calculations to common routine in BaseSizer
    1577              : 
    1578              :         // PURPOSE OF THIS SUBROUTINE:
    1579              :         // This subroutine is for sizing Heating Coil Components for which nominal capcities have not been
    1580              :         // specified in the input.
    1581              : 
    1582              :         // METHODOLOGY EMPLOYED:
    1583              :         // Obtains heating capacities from the zone or system sizing arrays or parent object as necessary.
    1584              :         // heating coil or other routine sets up any required data variables (e.g., DataCoilIsSuppHeater, TermUnitPIU, etc.),
    1585              :         // sizing variable (e.g., HeatingCoil( CoilNum ).NominalCapacity in this routine since it can be multi-staged and new routine
    1586              :         // currently only handles single values) and associated string representing that sizing variable.
    1587              :         // Sizer functions handles the actual sizing and reporting.
    1588              : 
    1589              :         // SUBROUTINE PARAMETER DEFINITIONS:
    1590              :         static constexpr std::string_view RoutineName("SizeHeatingCoil: "); // include trailing blank space
    1591              : 
    1592              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1593           98 :         std::string CompName;       // component name
    1594           98 :         std::string CompType;       // component type
    1595           98 :         std::string SizingString;   // input field sizing description (e.g., Nominal Capacity)
    1596           98 :         bool bPRINT = true;         // TRUE if sizing is reported to output (eio)
    1597              :         Real64 NominalCapacityDes;  // Autosized nominal capacity for reporting
    1598              :         Real64 NominalCapacityUser; // Hardsized nominal capacity for reporting
    1599              :         Real64 TempCap;             // autosized capacity of heating coil [W]
    1600           98 :         int FieldNum = 2;           // IDD numeric field number where input field description is found
    1601           98 :         int NumCoilsSized = 0;      // counter used to deallocate temporary string array after all coils have been sized
    1602              : 
    1603           98 :         auto &heatingCoil = state.dataHeatingCoils->HeatingCoil(CoilNum);
    1604              : 
    1605           98 :         if (heatingCoil.HCoilType_Num == HVAC::Coil_HeatingElectric_MultiStage) {
    1606            9 :             FieldNum = 1 + (heatingCoil.NumOfStages * 2);
    1607            9 :             TempCap = heatingCoil.MSNominalCapacity(heatingCoil.NumOfStages);
    1608           89 :         } else if (heatingCoil.HCoilType_Num == HVAC::Coil_HeatingGas_MultiStage) {
    1609            3 :             FieldNum = 1 + (heatingCoil.NumOfStages * 3);
    1610            3 :             TempCap = heatingCoil.MSNominalCapacity(heatingCoil.NumOfStages);
    1611           86 :         } else if (heatingCoil.HCoilType_Num == HVAC::Coil_HeatingDesuperheater) {
    1612            1 :             return; // no autosizable inputs for desupterheater
    1613              :         } else {
    1614           85 :             FieldNum = 2;
    1615           85 :             TempCap = heatingCoil.NominalCapacity;
    1616              :         }
    1617           97 :         SizingString = state.dataHeatingCoils->HeatingCoilNumericFields(CoilNum).FieldNames(FieldNum) + " [W]";
    1618           97 :         CompType = "Coil:" + heatingCoil.HeatingCoilType + ':' + heatingCoil.HeatingCoilModel;
    1619           97 :         CompName = heatingCoil.Name;
    1620           97 :         state.dataSize->DataCoilIsSuppHeater = state.dataHeatingCoils->CoilIsSuppHeater; // set global instead of using optional argument
    1621           97 :         state.dataSize->DataCoolCoilCap =
    1622              :             0.0; // global only used for heat pump heating coils, non-HP heating coils are sized with other global variables
    1623              : 
    1624           97 :         if (TempCap == DataSizing::AutoSize) {
    1625           42 :             if (heatingCoil.DesiccantRegenerationCoil) {
    1626            3 :                 state.dataSize->DataDesicRegCoil = true;
    1627            3 :                 bPRINT = false;
    1628            3 :                 state.dataSize->DataDesicDehumNum = heatingCoil.DesiccantDehumNum;
    1629            3 :                 HeatingCoilDesAirInletTempSizer sizerHeatingDesInletTemp;
    1630            3 :                 bool ErrorsFound = false;
    1631            3 :                 sizerHeatingDesInletTemp.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
    1632            3 :                 state.dataSize->DataDesInletAirTemp = sizerHeatingDesInletTemp.size(state, DataSizing::AutoSize, ErrorsFound);
    1633              : 
    1634            3 :                 HeatingCoilDesAirOutletTempSizer sizerHeatingDesOutletTemp;
    1635            3 :                 ErrorsFound = false;
    1636            3 :                 sizerHeatingDesOutletTemp.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
    1637            3 :                 state.dataSize->DataDesOutletAirTemp = sizerHeatingDesOutletTemp.size(state, DataSizing::AutoSize, ErrorsFound);
    1638              : 
    1639            3 :                 if (state.dataSize->CurOASysNum > 0) {
    1640            1 :                     auto &OASysEqSizing(state.dataSize->OASysEqSizing(state.dataSize->CurOASysNum));
    1641            1 :                     OASysEqSizing.AirFlow = true;
    1642            1 :                     OASysEqSizing.AirVolFlow = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesOutAirVolFlow;
    1643              :                 }
    1644            3 :                 state.dataSize->DataDesicDehumNum = 0;
    1645            3 :                 bPRINT = true;
    1646            3 :             }
    1647              :         }
    1648           97 :         bool errorsFound = false;
    1649           97 :         HeatingCapacitySizer sizerHeatingCapacity;
    1650           97 :         sizerHeatingCapacity.overrideSizingString(SizingString);
    1651           97 :         sizerHeatingCapacity.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
    1652           97 :         TempCap = sizerHeatingCapacity.size(state, TempCap, errorsFound);
    1653           97 :         state.dataSize->DataCoilIsSuppHeater = false; // reset global to false so other heating coils are not affected
    1654           97 :         state.dataSize->DataDesicRegCoil = false;     // reset global to false so other heating coils are not affected
    1655           97 :         state.dataSize->DataDesInletAirTemp = 0.0;    // reset global data to zero so other heating coils are not
    1656           97 :         state.dataSize->DataDesOutletAirTemp = 0.0;   // reset global data to zero so other heating coils are not affected
    1657              : 
    1658           97 :         if (heatingCoil.HCoilType_Num == HVAC::Coil_HeatingElectric_MultiStage || heatingCoil.HCoilType_Num == HVAC::Coil_HeatingGas_MultiStage) {
    1659           12 :             heatingCoil.MSNominalCapacity(heatingCoil.NumOfStages) = TempCap;
    1660           12 :             bool IsAutoSize = false;
    1661              :             int NumOfStages; // total number of stages of multi-stage heating coil
    1662           12 :             if (any_eq(heatingCoil.MSNominalCapacity, DataSizing::AutoSize)) {
    1663            3 :                 IsAutoSize = true;
    1664              :             }
    1665           12 :             if (IsAutoSize) {
    1666            3 :                 NumOfStages = heatingCoil.NumOfStages;
    1667            6 :                 for (int StageNum = NumOfStages - 1; StageNum >= 1; --StageNum) {
    1668            3 :                     bool ThisStageAutoSize = false;
    1669            3 :                     FieldNum = 1 + StageNum * ((heatingCoil.HCoilType_Num == HVAC::Coil_HeatingElectric_MultiStage) ? 2 : 3);
    1670            3 :                     SizingString = state.dataHeatingCoils->HeatingCoilNumericFields(CoilNum).FieldNames(FieldNum) + " [W]";
    1671            3 :                     if (heatingCoil.MSNominalCapacity(StageNum) == DataSizing::AutoSize) {
    1672            3 :                         ThisStageAutoSize = true;
    1673              :                     }
    1674            3 :                     NominalCapacityDes = TempCap * StageNum / NumOfStages;
    1675            3 :                     if (ThisStageAutoSize) {
    1676            3 :                         heatingCoil.MSNominalCapacity(StageNum) = NominalCapacityDes;
    1677            3 :                         BaseSizer::reportSizerOutput(state, CompType, CompName, "Design Size " + SizingString, NominalCapacityDes);
    1678              :                     } else {
    1679            0 :                         if (heatingCoil.MSNominalCapacity(StageNum) > 0.0 && NominalCapacityDes > 0.0) {
    1680            0 :                             NominalCapacityUser = TempCap * StageNum / NumOfStages; // HeatingCoil( CoilNum ).MSNominalCapacity( StageNum );
    1681            0 :                             BaseSizer::reportSizerOutput(state,
    1682              :                                                          CompType,
    1683              :                                                          CompName,
    1684            0 :                                                          "Design Size " + SizingString,
    1685              :                                                          NominalCapacityDes,
    1686            0 :                                                          "User-Specified " + SizingString,
    1687              :                                                          NominalCapacityUser);
    1688            0 :                             if (state.dataGlobal->DisplayExtraWarnings) {
    1689            0 :                                 if ((std::abs(NominalCapacityDes - NominalCapacityUser) / NominalCapacityUser) >
    1690            0 :                                     state.dataSize->AutoVsHardSizingThreshold) {
    1691            0 :                                     ShowMessage(state,
    1692            0 :                                                 format("SizeHeatingCoil: Potential issue with equipment sizing for {}, {}", CompType, CompName));
    1693            0 :                                     ShowContinueError(state, format("User-Specified Nominal Capacity of {:.2R} [W]", NominalCapacityUser));
    1694            0 :                                     ShowContinueError(state, format("differs from Design Size Nominal Capacity of {:.2R} [W]", NominalCapacityDes));
    1695            0 :                                     ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
    1696            0 :                                     ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
    1697              :                                 }
    1698              :                             }
    1699              :                         }
    1700              :                     }
    1701              :                 }
    1702              :             } else { // No autosize
    1703            9 :                 NumOfStages = heatingCoil.NumOfStages;
    1704           17 :                 for (int StageNum = NumOfStages - 1; StageNum >= 1; --StageNum) {
    1705            8 :                     if (heatingCoil.MSNominalCapacity(StageNum) > 0.0) {
    1706           24 :                         BaseSizer::reportSizerOutput(
    1707           16 :                             state, CompType, CompName, "User-Specified " + SizingString, heatingCoil.MSNominalCapacity(StageNum));
    1708              :                     }
    1709              :                 }
    1710              :             }
    1711              :             // Ensure capacity at lower Stage must be lower or equal to the capacity at higher Stage.
    1712           23 :             for (int StageNum = 1; StageNum <= heatingCoil.NumOfStages - 1; ++StageNum) {
    1713           11 :                 if (heatingCoil.MSNominalCapacity(StageNum) > heatingCoil.MSNominalCapacity(StageNum + 1)) {
    1714            0 :                     ShowSevereError(state,
    1715            0 :                                     format("SizeHeatingCoil: {} {}, Stage {} Nominal Capacity ({:.2R} W) must be less than or equal to Stage {} "
    1716              :                                            "Nominal Capacity ({:.2R} W).",
    1717            0 :                                            heatingCoil.HeatingCoilType,
    1718            0 :                                            heatingCoil.Name,
    1719              :                                            StageNum,
    1720              :                                            heatingCoil.MSNominalCapacity(StageNum),
    1721            0 :                                            StageNum + 1,
    1722              :                                            heatingCoil.MSNominalCapacity(StageNum + 1)));
    1723            0 :                     ShowFatalError(state, "Preceding conditions cause termination.");
    1724              :                 }
    1725              :             }
    1726           12 :         } else { // not a multi-speed coil
    1727           85 :             heatingCoil.NominalCapacity = TempCap;
    1728              :         }
    1729              : 
    1730           97 :         if (++NumCoilsSized == state.dataHeatingCoils->NumHeatingCoils)
    1731           44 :             state.dataHeatingCoils->HeatingCoilNumericFields.deallocate(); // remove temporary array for field names at end of sizing
    1732              : 
    1733              :         // create predefined report entries
    1734           97 :         switch (heatingCoil.HCoilType_Num) {
    1735           39 :         case HVAC::Coil_HeatingElectric: {
    1736           39 :             OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchHeatCoilType, heatingCoil.Name, "Coil:Heating:Electric");
    1737           78 :             OutputReportPredefined::PreDefTableEntry(
    1738           39 :                 state, state.dataOutRptPredefined->pdchHeatCoilNomCap, heatingCoil.Name, heatingCoil.NominalCapacity);
    1739           39 :             OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchHeatCoilNomEff, heatingCoil.Name, heatingCoil.Efficiency);
    1740           39 :         } break;
    1741            9 :         case HVAC::Coil_HeatingElectric_MultiStage: {
    1742           18 :             OutputReportPredefined::PreDefTableEntry(
    1743            9 :                 state, state.dataOutRptPredefined->pdchHeatCoilType, heatingCoil.Name, "Coil:Heating:Electric:MultiStage");
    1744           18 :             OutputReportPredefined::PreDefTableEntry(
    1745            9 :                 state, state.dataOutRptPredefined->pdchHeatCoilNomCap, heatingCoil.Name, heatingCoil.MSNominalCapacity(heatingCoil.NumOfStages));
    1746           18 :             OutputReportPredefined::PreDefTableEntry(
    1747            9 :                 state, state.dataOutRptPredefined->pdchHeatCoilNomEff, heatingCoil.Name, heatingCoil.MSEfficiency(heatingCoil.NumOfStages));
    1748            9 :         } break;
    1749           46 :         case HVAC::Coil_HeatingGasOrOtherFuel: {
    1750           46 :             OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchHeatCoilType, heatingCoil.Name, "Coil:Heating:Fuel");
    1751           92 :             OutputReportPredefined::PreDefTableEntry(
    1752           46 :                 state, state.dataOutRptPredefined->pdchHeatCoilNomCap, heatingCoil.Name, heatingCoil.NominalCapacity);
    1753           46 :             OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchHeatCoilNomEff, heatingCoil.Name, heatingCoil.Efficiency);
    1754           46 :         } break;
    1755            3 :         case HVAC::Coil_HeatingGas_MultiStage: {
    1756            6 :             OutputReportPredefined::PreDefTableEntry(
    1757            3 :                 state, state.dataOutRptPredefined->pdchHeatCoilType, heatingCoil.Name, "Coil:Heating:Gas:MultiStage");
    1758            6 :             OutputReportPredefined::PreDefTableEntry(
    1759            3 :                 state, state.dataOutRptPredefined->pdchHeatCoilNomCap, heatingCoil.Name, heatingCoil.MSNominalCapacity(heatingCoil.NumOfStages));
    1760            6 :             OutputReportPredefined::PreDefTableEntry(
    1761            3 :                 state, state.dataOutRptPredefined->pdchHeatCoilNomEff, heatingCoil.Name, heatingCoil.MSEfficiency(heatingCoil.NumOfStages));
    1762            3 :         } break;
    1763            0 :         case HVAC::Coil_HeatingDesuperheater: {
    1764            0 :             OutputReportPredefined::PreDefTableEntry(
    1765            0 :                 state, state.dataOutRptPredefined->pdchHeatCoilType, heatingCoil.Name, "Coil:Heating:Desuperheater");
    1766            0 :             OutputReportPredefined::PreDefTableEntry(
    1767            0 :                 state, state.dataOutRptPredefined->pdchHeatCoilNomCap, heatingCoil.Name, heatingCoil.NominalCapacity);
    1768            0 :             OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchHeatCoilNomEff, heatingCoil.Name, heatingCoil.Efficiency);
    1769            0 :         } break;
    1770            0 :         default:
    1771            0 :             break;
    1772              :         }
    1773              : 
    1774              :         // std 229 heating coils existing table adding new variables:
    1775              :         // pdchHeatCoilUsedAsSupHeat is now reported at coil selection report
    1776              :         // pdchHeatCoilAirloopName is now reported at coil selection report
    1777              :         // std 229 Coil Connections New table: now all reported at coil selection report
    1778          100 :     }
    1779              : 
    1780        73698 :     void CalcElectricHeatingCoil(EnergyPlusData &state,
    1781              :                                  int const CoilNum, // index to heating coil
    1782              :                                  Real64 &QCoilReq,
    1783              :                                  Real64 &QCoilActual,       // coil load actually delivered (W)
    1784              :                                  HVAC::FanOp const fanOp,   // fan operating mode
    1785              :                                  Real64 const PartLoadRatio // part-load ratio of heating coil
    1786              :     )
    1787              :     {
    1788              :         // SUBROUTINE INFORMATION:
    1789              :         //       AUTHOR         Rich Liesen
    1790              :         //       DATE WRITTEN   May 2000
    1791              :         //       MODIFIED       Jul. 2016, R. Zhang, Applied the coil supply air temperature sensor offset
    1792              : 
    1793              :         // PURPOSE OF THIS SUBROUTINE:
    1794              :         // Simulates a simple Electric heating coil with an efficiency
    1795              : 
    1796              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1797              :         Real64 AirMassFlow; // [kg/sec]
    1798              :         Real64 TempAirOut;  // [C]
    1799              :         Real64 HeatingCoilLoad;
    1800              :         Real64 QCoilCap;
    1801              : 
    1802        73698 :         auto &heatingCoil = state.dataHeatingCoils->HeatingCoil(CoilNum);
    1803              : 
    1804        73698 :         Real64 Effic = heatingCoil.Efficiency;
    1805        73698 :         Real64 TempAirIn = heatingCoil.InletAirTemp;
    1806        73698 :         Real64 Win = heatingCoil.InletAirHumRat;
    1807        73698 :         Real64 TempSetPoint = heatingCoil.DesiredOutletTemp;
    1808              : 
    1809              :         // If there is a fault of coil SAT Sensor
    1810        73698 :         if (heatingCoil.FaultyCoilSATFlag && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) &&
    1811            0 :             (!state.dataGlobal->KickOffSimulation)) {
    1812              :             // calculate the sensor offset using fault information
    1813            0 :             int FaultIndex = heatingCoil.FaultyCoilSATIndex;
    1814            0 :             heatingCoil.FaultyCoilSATOffset = state.dataFaultsMgr->FaultsCoilSATSensor(FaultIndex).CalFaultOffsetAct(state);
    1815              :             // update the TempSetPoint
    1816            0 :             TempSetPoint -= heatingCoil.FaultyCoilSATOffset;
    1817              :         }
    1818              : 
    1819              :         //  adjust mass flow rates for cycling fan cycling coil operation
    1820        73698 :         if (fanOp == HVAC::FanOp::Cycling) {
    1821        61853 :             if (PartLoadRatio > 0.0) {
    1822        61465 :                 AirMassFlow = heatingCoil.InletAirMassFlowRate / PartLoadRatio;
    1823        61465 :                 QCoilReq /= PartLoadRatio;
    1824              :             } else {
    1825          388 :                 AirMassFlow = 0.0;
    1826              :             }
    1827              :         } else {
    1828        11845 :             AirMassFlow = heatingCoil.InletAirMassFlowRate;
    1829              :         }
    1830              : 
    1831        73698 :         Real64 CapacitanceAir = Psychrometrics::PsyCpAirFnW(Win) * AirMassFlow;
    1832              : 
    1833              :         // If the coil is operating there should be some heating capacitance
    1834              :         //  across the coil, so do the simulation. If not set outlet to inlet and no load.
    1835              :         //  Also the coil has to be scheduled to be available.
    1836              : 
    1837              :         // Control output to meet load QCoilReq (QCoilReq is passed in if load controlled, otherwise QCoilReq=-999)
    1838        73698 :         if ((AirMassFlow > 0.0 && heatingCoil.NominalCapacity > 0.0) && (heatingCoil.availSched->getCurrentVal() > 0.0) && (QCoilReq > 0.0)) {
    1839              : 
    1840              :             // check to see if the Required heating capacity is greater than the user specified capacity.
    1841         3697 :             if (QCoilReq > heatingCoil.NominalCapacity) {
    1842            2 :                 QCoilCap = heatingCoil.NominalCapacity;
    1843              :             } else {
    1844         3695 :                 QCoilCap = QCoilReq;
    1845              :             }
    1846              : 
    1847         3697 :             TempAirOut = TempAirIn + QCoilCap / CapacitanceAir;
    1848         3697 :             HeatingCoilLoad = QCoilCap;
    1849              : 
    1850              :             // The HeatingCoilLoad is the change in the enthalpy of the Heating
    1851         3697 :             heatingCoil.ElecUseLoad = HeatingCoilLoad / Effic;
    1852              : 
    1853              :             // Control coil output to meet a setpoint temperature.
    1854        50320 :         } else if ((AirMassFlow > 0.0 && heatingCoil.NominalCapacity > 0.0) && (heatingCoil.availSched->getCurrentVal() > 0.0) &&
    1855       120321 :                    (QCoilReq == DataLoopNode::SensedLoadFlagValue) && (std::abs(TempSetPoint - TempAirIn) > HVAC::TempControlTol)) {
    1856              : 
    1857         1926 :             QCoilCap = CapacitanceAir * (TempSetPoint - TempAirIn);
    1858              :             // check to see if setpoint above enetering temperature. If not, set
    1859              :             // output to zero.
    1860         1926 :             if (QCoilCap <= 0.0) {
    1861          129 :                 QCoilCap = 0.0;
    1862          129 :                 TempAirOut = TempAirIn;
    1863              :                 // check to see if the Required heating capacity is greater than the user
    1864              :                 // specified capacity.
    1865         1797 :             } else if (QCoilCap > heatingCoil.NominalCapacity) {
    1866          100 :                 QCoilCap = heatingCoil.NominalCapacity;
    1867          100 :                 TempAirOut = TempAirIn + QCoilCap / CapacitanceAir;
    1868              :             } else {
    1869         1697 :                 TempAirOut = TempSetPoint;
    1870              :             }
    1871              : 
    1872         1926 :             HeatingCoilLoad = QCoilCap;
    1873              : 
    1874              :             // The HeatingCoilLoad is the change in the enthalpy of the Heating
    1875         1926 :             heatingCoil.ElecUseLoad = HeatingCoilLoad / Effic;
    1876              : 
    1877              :         } else { // If not running Conditions do not change across coil from inlet to outlet
    1878              : 
    1879        68075 :             TempAirOut = TempAirIn;
    1880        68075 :             HeatingCoilLoad = 0.0;
    1881        68075 :             heatingCoil.ElecUseLoad = 0.0;
    1882              :         }
    1883              : 
    1884        73698 :         if (fanOp == HVAC::FanOp::Cycling) {
    1885        61853 :             heatingCoil.ElecUseLoad *= PartLoadRatio;
    1886        61853 :             HeatingCoilLoad *= PartLoadRatio;
    1887              :         }
    1888              : 
    1889        73698 :         heatingCoil.HeatingCoilLoad = HeatingCoilLoad;
    1890              : 
    1891              :         // Set the outlet conditions
    1892        73698 :         heatingCoil.OutletAirTemp = TempAirOut;
    1893              : 
    1894              :         // This HeatingCoil does not change the moisture or Mass Flow across the component
    1895        73698 :         heatingCoil.OutletAirHumRat = heatingCoil.InletAirHumRat;
    1896        73698 :         heatingCoil.OutletAirMassFlowRate = heatingCoil.InletAirMassFlowRate;
    1897              :         // Set the outlet enthalpys for air and Heating
    1898        73698 :         heatingCoil.OutletAirEnthalpy = Psychrometrics::PsyHFnTdbW(heatingCoil.OutletAirTemp, heatingCoil.OutletAirHumRat);
    1899              : 
    1900        73698 :         QCoilActual = HeatingCoilLoad;
    1901        73698 :         if (std::abs(heatingCoil.NominalCapacity) < 1.e-8) {
    1902           21 :             if (heatingCoil.AirLoopNum > 0) {
    1903            0 :                 state.dataAirLoop->AirLoopAFNInfo(heatingCoil.AirLoopNum).AFNLoopHeatingCoilMaxRTF =
    1904            0 :                     max(state.dataAirLoop->AirLoopAFNInfo(heatingCoil.AirLoopNum).AFNLoopHeatingCoilMaxRTF, 0.0);
    1905              :             }
    1906              :         } else {
    1907        73677 :             if (heatingCoil.AirLoopNum > 0) {
    1908        61404 :                 state.dataAirLoop->AirLoopAFNInfo(heatingCoil.AirLoopNum).AFNLoopHeatingCoilMaxRTF =
    1909        61404 :                     max(state.dataAirLoop->AirLoopAFNInfo(heatingCoil.AirLoopNum).AFNLoopHeatingCoilMaxRTF,
    1910        61404 :                         HeatingCoilLoad / heatingCoil.NominalCapacity);
    1911              :             }
    1912              :         }
    1913              : 
    1914              :         // set outlet node temp so parent objects can call calc directly without have to simulate entire model
    1915        73698 :         state.dataLoopNodes->Node(heatingCoil.AirOutletNodeNum).Temp = heatingCoil.OutletAirTemp;
    1916        73698 :     }
    1917              : 
    1918          247 :     void CalcMultiStageElectricHeatingCoil(EnergyPlusData &state,
    1919              :                                            int const CoilNum,       // the number of the electric heating coil to be simulated
    1920              :                                            Real64 const SpeedRatio, // SpeedRatio varies between 1.0 (maximum speed) and 0.0 (minimum speed)
    1921              :                                            Real64 const CycRatio,   // cycling part load ratio
    1922              :                                            int const StageNum,      // Stage number
    1923              :                                            HVAC::FanOp const fanOp, // Fan operation mode
    1924              :                                            Real64 &QCoilActual,     // coil load actually delivered (W)
    1925              :                                            bool const SuppHeat)
    1926              :     {
    1927              : 
    1928              :         // SUBROUTINE INFORMATION:
    1929              :         //       AUTHOR         Chandan Sharma, FSEC
    1930              :         //       DATE WRITTEN   January 2013
    1931              : 
    1932              :         // PURPOSE OF THIS SUBROUTINE:
    1933              :         // Calculates the air-side performance and electrical energy use of multistage electric heating coil.
    1934              : 
    1935              :         // METHODOLOGY EMPLOYED:
    1936              :         // Uses the same methodology as the single stage electric heating unit model (SUBROUTINE CalcelectricHeatingCoil).
    1937              :         // In addition it assumes that the unit performance is obtained by interpolating between
    1938              :         // the performance at high stage and that at low stage. If the output needed is below
    1939              :         // that produced at low stage, the coil cycles between off and low stage.
    1940              : 
    1941              :         // SUBROUTINE PARAMETER DEFINITIONS:
    1942              :         static constexpr std::string_view RoutineName = "CalcMultiStageElectricHeatingCoil";
    1943              :         static constexpr std::string_view RoutineNameAverageLoad = "CalcMultiStageElectricHeatingCoil:Averageload";
    1944              :         static constexpr std::string_view RoutineNameFullLoad = "CalcMultiStageElectricHeatingCoil:fullload";
    1945              : 
    1946              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1947              :         Real64 OutletAirEnthalpy;    // outlet air enthalpy [J/kg]
    1948              :         Real64 OutletAirHumRat;      // outlet air humidity ratio [kg/kg]
    1949              :         Real64 TotCapHS;             // total capacity at high stage [W]
    1950              :         Real64 TotCapLS;             // total capacity at low stage [W]
    1951              :         Real64 TotCap;               // total capacity at current stage [W]
    1952              :         Real64 EffHS;                // total capacity at high stage [W]
    1953              :         Real64 EffLS;                // total capacity at low stage [W]
    1954              :         int StageNumHS;              // High stage number
    1955              :         int StageNumLS;              // Low stage number
    1956              :         Real64 FullLoadOutAirEnth;   // Outlet full load enthalpy
    1957              :         Real64 FullLoadOutAirHumRat; // Outlet humidity ratio at full load
    1958              :         Real64 FullLoadOutAirTemp;   // Outlet temperature at full load
    1959              :         Real64 FullLoadOutAirRH;     // Outler relative humidity at full load
    1960              :         Real64 OutletAirTemp;        // Supply ari temperature
    1961              :         Real64 LSElecHeatingPower;   // Full load power at low stage
    1962              :         Real64 HSElecHeatingPower;   // Full load power at high stage
    1963              :         Real64 PartLoadRat;          // part load ratio
    1964              : 
    1965          247 :         auto &heatingCoil = state.dataHeatingCoils->HeatingCoil(CoilNum);
    1966          247 :         if (StageNum > 1) {
    1967           87 :             StageNumLS = StageNum - 1;
    1968           87 :             StageNumHS = StageNum;
    1969           87 :             if (StageNum > heatingCoil.NumOfStages) {
    1970            0 :                 StageNumLS = heatingCoil.NumOfStages - 1;
    1971            0 :                 StageNumHS = heatingCoil.NumOfStages;
    1972              :             }
    1973              :         } else {
    1974          160 :             StageNumLS = 1;
    1975          160 :             StageNumHS = 1;
    1976              :         }
    1977              : 
    1978          247 :         Real64 AirMassFlow = heatingCoil.InletAirMassFlowRate;
    1979          247 :         Real64 InletAirDryBulbTemp = heatingCoil.InletAirTemp;
    1980          247 :         Real64 InletAirEnthalpy = heatingCoil.InletAirEnthalpy;
    1981          247 :         Real64 InletAirHumRat = heatingCoil.InletAirHumRat;
    1982              : 
    1983          247 :         Real64 OutdoorPressure = state.dataEnvrn->OutBaroPress;
    1984              : 
    1985          247 :         if ((AirMassFlow > 0.0) && (heatingCoil.availSched->getCurrentVal() > 0.0) && ((CycRatio > 0.0) || (SpeedRatio > 0.0))) {
    1986              : 
    1987          137 :             if (StageNum > 1) {
    1988              : 
    1989           85 :                 TotCapLS = heatingCoil.MSNominalCapacity(StageNumLS);
    1990           85 :                 TotCapHS = heatingCoil.MSNominalCapacity(StageNumHS);
    1991              : 
    1992           85 :                 EffLS = heatingCoil.MSEfficiency(StageNumLS);
    1993           85 :                 EffHS = heatingCoil.MSEfficiency(StageNumHS);
    1994              : 
    1995              :                 // Get full load output and power
    1996           85 :                 LSElecHeatingPower = TotCapLS / EffLS;
    1997           85 :                 HSElecHeatingPower = TotCapHS / EffHS;
    1998           85 :                 OutletAirHumRat = InletAirHumRat;
    1999              : 
    2000              :                 // if cycling fan, send coil part-load fraction to on/off fan via HVACDataGlobals
    2001              :                 // IF (FanOpMode .EQ. FanOp::Cycling) OnOffFanPartLoadFraction = 1.0d0
    2002              : 
    2003              :                 // Power calculation
    2004           85 :                 heatingCoil.ElecUseLoad = SpeedRatio * HSElecHeatingPower + (1.0 - SpeedRatio) * LSElecHeatingPower;
    2005              : 
    2006           85 :                 heatingCoil.HeatingCoilLoad = TotCapHS * SpeedRatio + TotCapLS * (1.0 - SpeedRatio);
    2007              : 
    2008           85 :                 OutletAirEnthalpy = InletAirEnthalpy + heatingCoil.HeatingCoilLoad / heatingCoil.InletAirMassFlowRate;
    2009           85 :                 OutletAirTemp = Psychrometrics::PsyTdbFnHW(OutletAirEnthalpy, OutletAirHumRat);
    2010           85 :                 FullLoadOutAirRH = Psychrometrics::PsyRhFnTdbWPb(state, OutletAirTemp, OutletAirHumRat, OutdoorPressure, RoutineNameAverageLoad);
    2011              : 
    2012           85 :                 if (FullLoadOutAirRH > 1.0) { // Limit to saturated conditions at FullLoadOutAirEnth
    2013            0 :                     OutletAirTemp = Psychrometrics::PsyTsatFnHPb(state, OutletAirEnthalpy, OutdoorPressure, RoutineName);
    2014            0 :                     OutletAirHumRat = Psychrometrics::PsyWFnTdbH(state, OutletAirTemp, OutletAirEnthalpy, RoutineName);
    2015              :                 }
    2016              : 
    2017           85 :                 heatingCoil.OutletAirTemp = OutletAirTemp;
    2018           85 :                 heatingCoil.OutletAirHumRat = OutletAirHumRat;
    2019           85 :                 heatingCoil.OutletAirEnthalpy = OutletAirEnthalpy;
    2020           85 :                 heatingCoil.OutletAirMassFlowRate = heatingCoil.InletAirMassFlowRate;
    2021              : 
    2022              :                 // Stage 1
    2023           52 :             } else if (CycRatio > 0.0) {
    2024              : 
    2025           50 :                 PartLoadRat = min(1.0, CycRatio);
    2026              : 
    2027              :                 // for cycling fan, reset mass flow to full on rate
    2028           50 :                 if (fanOp == HVAC::FanOp::Cycling)
    2029           20 :                     AirMassFlow /= PartLoadRat;
    2030           30 :                 else if (fanOp == HVAC::FanOp::Continuous) {
    2031           30 :                     if (!SuppHeat) {
    2032           24 :                         AirMassFlow = state.dataHVACGlobal->MSHPMassFlowRateLow;
    2033              :                     }
    2034              :                 }
    2035              : 
    2036           50 :                 TotCap = heatingCoil.MSNominalCapacity(StageNumLS);
    2037              : 
    2038              :                 // Calculate full load outlet conditions
    2039           50 :                 FullLoadOutAirEnth = InletAirEnthalpy + TotCap / AirMassFlow;
    2040           50 :                 FullLoadOutAirHumRat = InletAirHumRat;
    2041           50 :                 FullLoadOutAirTemp = Psychrometrics::PsyTdbFnHW(FullLoadOutAirEnth, FullLoadOutAirHumRat);
    2042              :                 FullLoadOutAirRH =
    2043           50 :                     Psychrometrics::PsyRhFnTdbWPb(state, FullLoadOutAirTemp, FullLoadOutAirHumRat, OutdoorPressure, RoutineNameFullLoad);
    2044              : 
    2045           50 :                 if (FullLoadOutAirRH > 1.0) { // Limit to saturated conditions at FullLoadOutAirEnth
    2046            0 :                     FullLoadOutAirTemp = Psychrometrics::PsyTsatFnHPb(state, FullLoadOutAirEnth, OutdoorPressure, RoutineName);
    2047              :                     //  Eventually inlet air conditions will be used in electric Coil, these lines are commented out and marked with this comment
    2048              :                     //  line FullLoadOutAirTemp = PsyTsatFnHPb(FullLoadOutAirEnth,InletAirPressure)
    2049            0 :                     FullLoadOutAirHumRat = Psychrometrics::PsyWFnTdbH(state, FullLoadOutAirTemp, FullLoadOutAirEnth, RoutineName);
    2050              :                 }
    2051              : 
    2052              :                 // Set outlet conditions from the full load calculation
    2053           50 :                 if (fanOp == HVAC::FanOp::Cycling) {
    2054           20 :                     OutletAirEnthalpy = FullLoadOutAirEnth;
    2055           20 :                     OutletAirHumRat = FullLoadOutAirHumRat;
    2056           20 :                     OutletAirTemp = FullLoadOutAirTemp;
    2057              :                 } else {
    2058           30 :                     OutletAirEnthalpy = PartLoadRat * FullLoadOutAirEnth + (1.0 - PartLoadRat) * InletAirEnthalpy;
    2059           30 :                     OutletAirHumRat = PartLoadRat * FullLoadOutAirHumRat + (1.0 - PartLoadRat) * InletAirHumRat;
    2060           30 :                     OutletAirTemp = PartLoadRat * FullLoadOutAirTemp + (1.0 - PartLoadRat) * InletAirDryBulbTemp;
    2061              :                 }
    2062              : 
    2063           50 :                 EffLS = heatingCoil.MSEfficiency(StageNumLS);
    2064              : 
    2065              :                 //    HeatingCoil(CoilNum)%HeatingCoilLoad = TotCap
    2066              :                 //   This would require a CR to change
    2067           50 :                 heatingCoil.HeatingCoilLoad = TotCap * PartLoadRat;
    2068              : 
    2069           50 :                 heatingCoil.ElecUseLoad = heatingCoil.HeatingCoilLoad / EffLS;
    2070              : 
    2071           50 :                 heatingCoil.OutletAirTemp = OutletAirTemp;
    2072           50 :                 heatingCoil.OutletAirHumRat = OutletAirHumRat;
    2073           50 :                 heatingCoil.OutletAirEnthalpy = OutletAirEnthalpy;
    2074           50 :                 heatingCoil.OutletAirMassFlowRate = heatingCoil.InletAirMassFlowRate;
    2075              :                 // this would require a CR to correct (i.e., calculate outputs when coil is off)
    2076              :                 //  ELSE
    2077              :                 //    ! electric coil is off; just pass through conditions
    2078              :                 //    HeatingCoil(CoilNum)%OutletAirEnthalpy = HeatingCoil(CoilNum)%InletAirEnthalpy
    2079              :                 //    HeatingCoil(CoilNum)%OutletAirHumRat   = HeatingCoil(CoilNum)%InletAirHumRat
    2080              :                 //    HeatingCoil(CoilNum)%OutletAirTemp     = HeatingCoil(CoilNum)%InletAirTemp
    2081              :                 //    HeatingCoil(CoilNum)%OutletAirMassFlowRate = HeatingCoil(CoilNum)%InletAirMassFlowRate
    2082              :                 //    HeatingCoil(CoilNum)%ElecUseLoad      = 0.0
    2083              :                 //    HeatingCoil(CoilNum)%HeatingCoilLoad  = 0.0
    2084              :                 //    ElecHeatingCoilPower                  = 0.0
    2085              :             }
    2086              : 
    2087              :         } else {
    2088              : 
    2089              :             // electric coil is off; just pass through conditions
    2090          110 :             heatingCoil.OutletAirEnthalpy = heatingCoil.InletAirEnthalpy;
    2091          110 :             heatingCoil.OutletAirHumRat = heatingCoil.InletAirHumRat;
    2092          110 :             heatingCoil.OutletAirTemp = heatingCoil.InletAirTemp;
    2093          110 :             heatingCoil.OutletAirMassFlowRate = heatingCoil.InletAirMassFlowRate;
    2094              : 
    2095              :             // some of these are reset in Init, can be removed to speed up code
    2096          110 :             heatingCoil.ElecUseLoad = 0.0;
    2097          110 :             heatingCoil.HeatingCoilLoad = 0.0;
    2098              : 
    2099              :         } // end of on/off if - else
    2100              : 
    2101              :         // set outlet node temp so parent objects can call calc directly without have to simulate entire model
    2102          247 :         state.dataLoopNodes->Node(heatingCoil.AirOutletNodeNum).Temp = heatingCoil.OutletAirTemp;
    2103              : 
    2104          247 :         QCoilActual = heatingCoil.HeatingCoilLoad;
    2105          247 :     }
    2106              : 
    2107       159191 :     void CalcFuelHeatingCoil(EnergyPlusData &state,
    2108              :                              int const CoilNum, // index to heating coil
    2109              :                              Real64 const QCoilReq,
    2110              :                              Real64 &QCoilActual,                        // coil load actually delivered (W)
    2111              :                              HVAC::FanOp const fanOp,                    // fan operating mode
    2112              :                              [[maybe_unused]] Real64 const PartLoadRatio // part-load ratio of heating coil
    2113              :     )
    2114              :     {
    2115              :         // SUBROUTINE INFORMATION:
    2116              :         //       AUTHOR         Rich Liesen
    2117              :         //       DATE WRITTEN   May 2000
    2118              :         //       MODIFIED       Jul. 2016, R. Zhang, Applied the coil supply air temperature sensor offset
    2119              : 
    2120              :         // PURPOSE OF THIS SUBROUTINE:
    2121              :         // Simulates a simple Gas heating coil with a burner efficiency
    2122              : 
    2123              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2124              :         Real64 TempAirOut; // [C]
    2125              :         Real64 HeatingCoilLoad;
    2126              :         Real64 QCoilCap;
    2127              :         Real64 PartLoadRat;
    2128              :         Real64 PLF;
    2129              : 
    2130       159191 :         auto &heatingCoil = state.dataHeatingCoils->HeatingCoil(CoilNum);
    2131              : 
    2132       159191 :         Real64 Effic = heatingCoil.Efficiency;
    2133       159191 :         Real64 TempAirIn = heatingCoil.InletAirTemp;
    2134       159191 :         Real64 Win = heatingCoil.InletAirHumRat;
    2135       159191 :         Real64 TempSetPoint = heatingCoil.DesiredOutletTemp;
    2136       159191 :         Real64 AirMassFlow = heatingCoil.InletAirMassFlowRate;
    2137              : 
    2138       159191 :         Real64 CapacitanceAir = Psychrometrics::PsyCpAirFnW(Win) * AirMassFlow;
    2139              : 
    2140              :         // If there is a fault of coil SAT Sensor
    2141       159191 :         if (heatingCoil.FaultyCoilSATFlag && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) &&
    2142            0 :             (!state.dataGlobal->KickOffSimulation)) {
    2143              :             // calculate the sensor offset using fault information
    2144            0 :             int FaultIndex = heatingCoil.FaultyCoilSATIndex;
    2145            0 :             heatingCoil.FaultyCoilSATOffset = state.dataFaultsMgr->FaultsCoilSATSensor(FaultIndex).CalFaultOffsetAct(state);
    2146              :             // update the TempSetPoint
    2147            0 :             TempSetPoint -= heatingCoil.FaultyCoilSATOffset;
    2148              :         }
    2149              : 
    2150              :         // If the coil is operating there should be some heating capacitance
    2151              :         //  across the coil, so do the simulation. If not set outlet to inlet and no load.
    2152              :         //  Also the coil has to be scheduled to be available.
    2153              : 
    2154              :         // Control output to meet load QCoilReq (QCoilReq is passed in if load controlled, otherwise QCoilReq=-999)
    2155       159191 :         if ((AirMassFlow > 0.0 && heatingCoil.NominalCapacity > 0.0) && (heatingCoil.availSched->getCurrentVal() > 0.0) && (QCoilReq > 0.0)) {
    2156              : 
    2157              :             // check to see if the Required heating capacity is greater than the user specified capacity.
    2158        12652 :             if (QCoilReq > heatingCoil.NominalCapacity) {
    2159         2680 :                 QCoilCap = heatingCoil.NominalCapacity;
    2160              :             } else {
    2161         9972 :                 QCoilCap = QCoilReq;
    2162              :             }
    2163              : 
    2164        12652 :             TempAirOut = TempAirIn + QCoilCap / CapacitanceAir;
    2165        12652 :             HeatingCoilLoad = QCoilCap;
    2166              : 
    2167        12652 :             PartLoadRat = HeatingCoilLoad / heatingCoil.NominalCapacity;
    2168              : 
    2169              :             // The HeatingCoilLoad is the change in the enthalpy of the Heating
    2170        12652 :             heatingCoil.FuelUseLoad = HeatingCoilLoad / Effic;
    2171        12652 :             heatingCoil.ElecUseLoad = heatingCoil.ParasiticElecLoad * PartLoadRat;
    2172        12652 :             heatingCoil.ParasiticFuelRate = heatingCoil.ParasiticFuelCapacity * (1.0 - PartLoadRat);
    2173              : 
    2174              :             // Control coil output to meet a setpoint temperature.
    2175       112994 :         } else if ((AirMassFlow > 0.0 && heatingCoil.NominalCapacity > 0.0) && (heatingCoil.availSched->getCurrentVal() > 0.0) &&
    2176       259533 :                    (QCoilReq == DataLoopNode::SensedLoadFlagValue) && (std::abs(TempSetPoint - TempAirIn) > HVAC::TempControlTol)) {
    2177              : 
    2178        15405 :             QCoilCap = CapacitanceAir * (TempSetPoint - TempAirIn);
    2179              :             // check to see if setpoint above entering temperature. If not, set
    2180              :             // output to zero.
    2181        15405 :             if (QCoilCap <= 0.0) {
    2182           43 :                 QCoilCap = 0.0;
    2183           43 :                 TempAirOut = TempAirIn;
    2184              :                 // check to see if the Required heating capacity is greater than the user
    2185              :                 // specified capacity.
    2186        15362 :             } else if (QCoilCap > heatingCoil.NominalCapacity) {
    2187        10429 :                 QCoilCap = heatingCoil.NominalCapacity;
    2188        10429 :                 TempAirOut = TempAirIn + QCoilCap / CapacitanceAir;
    2189              :             } else {
    2190         4933 :                 TempAirOut = TempSetPoint;
    2191              :             }
    2192              : 
    2193        15405 :             HeatingCoilLoad = QCoilCap;
    2194              : 
    2195        15405 :             PartLoadRat = HeatingCoilLoad / heatingCoil.NominalCapacity;
    2196              : 
    2197              :             // The HeatingCoilLoad is the change in the enthalpy of the Heating
    2198        15405 :             heatingCoil.FuelUseLoad = HeatingCoilLoad / Effic;
    2199        15405 :             heatingCoil.ElecUseLoad = heatingCoil.ParasiticElecLoad * PartLoadRat;
    2200        15405 :             heatingCoil.ParasiticFuelRate = heatingCoil.ParasiticFuelCapacity * (1.0 - PartLoadRat);
    2201              : 
    2202              :         } else { // If not running Conditions do not change across coil from inlet to outlet
    2203              : 
    2204       131134 :             TempAirOut = TempAirIn;
    2205       131134 :             HeatingCoilLoad = 0.0;
    2206       131134 :             PartLoadRat = 0.0;
    2207       131134 :             heatingCoil.FuelUseLoad = 0.0;
    2208       131134 :             heatingCoil.ElecUseLoad = 0.0;
    2209       131134 :             heatingCoil.ParasiticFuelRate = heatingCoil.ParasiticFuelCapacity;
    2210              :         }
    2211              : 
    2212       159191 :         heatingCoil.RTF = PartLoadRat;
    2213              : 
    2214              :         // If the PLF curve is defined the gas usage needs to be modified
    2215       159191 :         if (heatingCoil.PLFCurveIndex > 0) {
    2216           90 :             if (PartLoadRat == 0) {
    2217           90 :                 heatingCoil.FuelUseLoad = 0.0;
    2218              :             } else {
    2219            0 :                 PLF = Curve::CurveValue(state, heatingCoil.PLFCurveIndex, PartLoadRat);
    2220            0 :                 if (PLF < 0.7) {
    2221            0 :                     if (heatingCoil.PLFErrorCount < 1) {
    2222            0 :                         ++heatingCoil.PLFErrorCount;
    2223            0 :                         ShowWarningError(state,
    2224            0 :                                          format("CalcFuelHeatingCoil: {}=\"{}\", PLF curve values",
    2225              :                                                 HVAC::cAllCoilTypes(heatingCoil.HCoilType_Num),
    2226            0 :                                                 heatingCoil.Name));
    2227            0 :                         ShowContinueError(state, format("The PLF curve value = {:.5T} for part-load ratio = {:.5T}", PLF, PartLoadRat));
    2228            0 :                         ShowContinueError(state, "PLF curve values must be >= 0.7. PLF has been reset to 0.7 and the simulation continues...");
    2229            0 :                         ShowContinueError(state, "Check the IO reference manual for PLF curve guidance [Coil:Heating:Fuel].");
    2230              :                     } else {
    2231            0 :                         ShowRecurringWarningErrorAtEnd(
    2232            0 :                             state, heatingCoil.Name + ", Heating coil PLF curve < 0.7 warning continues... ", heatingCoil.PLFErrorIndex, PLF, PLF);
    2233              :                     }
    2234            0 :                     PLF = 0.7;
    2235              :                 }
    2236              :                 // Modify the Gas Coil Consumption and parasitic loads based on PLF curve
    2237            0 :                 heatingCoil.RTF = PartLoadRat / PLF;
    2238            0 :                 if (heatingCoil.RTF > 1.0 && std::abs(heatingCoil.RTF - 1.0) > 0.001) {
    2239            0 :                     if (heatingCoil.RTFErrorCount < 1) {
    2240            0 :                         ++heatingCoil.RTFErrorCount;
    2241            0 :                         ShowWarningError(state,
    2242            0 :                                          format("CalcFuelHeatingCoil: {}=\"{}\", runtime fraction",
    2243              :                                                 HVAC::cAllCoilTypes(heatingCoil.HCoilType_Num),
    2244            0 :                                                 heatingCoil.Name));
    2245            0 :                         ShowContinueError(state, format("The runtime fraction exceeded 1.0. [{:.4T}].", heatingCoil.RTF));
    2246            0 :                         ShowContinueError(state, "Runtime fraction is set to 1.0 and the simulation continues...");
    2247            0 :                         ShowContinueError(state, "Check the IO reference manual for PLF curve guidance [Coil:Heating:Fuel].");
    2248              :                     } else {
    2249            0 :                         ShowRecurringWarningErrorAtEnd(state,
    2250            0 :                                                        format("{}, Heating coil runtime fraction > 1.0 warning continues... ", heatingCoil.Name),
    2251            0 :                                                        heatingCoil.RTFErrorIndex,
    2252            0 :                                                        heatingCoil.RTF,
    2253            0 :                                                        heatingCoil.RTF);
    2254              :                     }
    2255            0 :                     heatingCoil.RTF = 1.0; // Reset coil runtime fraction to 1.0
    2256            0 :                 } else if (heatingCoil.RTF > 1.0) {
    2257            0 :                     heatingCoil.RTF = 1.0; // Reset coil runtime fraction to 1.0
    2258              :                 }
    2259            0 :                 heatingCoil.ElecUseLoad = heatingCoil.ParasiticElecLoad * heatingCoil.RTF;
    2260            0 :                 heatingCoil.FuelUseLoad = heatingCoil.NominalCapacity / Effic * heatingCoil.RTF;
    2261            0 :                 heatingCoil.ParasiticFuelRate = heatingCoil.ParasiticFuelCapacity * (1.0 - heatingCoil.RTF);
    2262              :                 // Fan power will also be modified by the heating coil's part load fraction
    2263              :                 // OnOffFanPartLoadFraction passed to fan via DataHVACGlobals (cycling fan only)
    2264            0 :                 if (fanOp == HVAC::FanOp::Cycling) {
    2265            0 :                     state.dataHVACGlobal->OnOffFanPartLoadFraction = PLF;
    2266              :                 }
    2267              :             }
    2268              :         }
    2269              : 
    2270              :         // Set the outlet conditions
    2271       159191 :         heatingCoil.HeatingCoilLoad = HeatingCoilLoad;
    2272       159191 :         heatingCoil.OutletAirTemp = TempAirOut;
    2273              : 
    2274              :         // This HeatingCoil does not change the moisture or Mass Flow across the component
    2275       159191 :         heatingCoil.OutletAirHumRat = heatingCoil.InletAirHumRat;
    2276       159191 :         heatingCoil.OutletAirMassFlowRate = heatingCoil.InletAirMassFlowRate;
    2277              :         // Set the outlet enthalpys for air and Heating
    2278       159191 :         heatingCoil.OutletAirEnthalpy = Psychrometrics::PsyHFnTdbW(heatingCoil.OutletAirTemp, heatingCoil.OutletAirHumRat);
    2279              : 
    2280       159191 :         QCoilActual = HeatingCoilLoad;
    2281       159191 :         if (heatingCoil.AirLoopNum > 0) {
    2282            0 :             state.dataAirLoop->AirLoopAFNInfo(heatingCoil.AirLoopNum).AFNLoopHeatingCoilMaxRTF =
    2283            0 :                 max(state.dataAirLoop->AirLoopAFNInfo(heatingCoil.AirLoopNum).AFNLoopHeatingCoilMaxRTF, heatingCoil.RTF);
    2284              :         }
    2285       159191 :         state.dataHVACGlobal->ElecHeatingCoilPower = heatingCoil.ElecUseLoad;
    2286              : 
    2287              :         // set outlet node temp so parent objects can call calc directly without have to simulate entire model
    2288       159191 :         state.dataLoopNodes->Node(heatingCoil.AirOutletNodeNum).Temp = heatingCoil.OutletAirTemp;
    2289       159191 :     }
    2290              : 
    2291           65 :     void CalcMultiStageGasHeatingCoil(EnergyPlusData &state,
    2292              :                                       int const CoilNum,       // the number of the Gas heating coil to be simulated
    2293              :                                       Real64 const SpeedRatio, // SpeedRatio varies between 1.0 (maximum speed) and 0.0 (minimum speed)
    2294              :                                       Real64 const CycRatio,   // cycling part load ratio
    2295              :                                       int const StageNum,      // Speed number
    2296              :                                       HVAC::FanOp const fanOp  // Fan operation mode
    2297              :     )
    2298              :     {
    2299              : 
    2300              :         // SUBROUTINE INFORMATION:
    2301              :         //       AUTHOR         Chandan Sharma, FSEC
    2302              :         //       DATE WRITTEN   January 2013
    2303              : 
    2304              :         // PURPOSE OF THIS SUBROUTINE:
    2305              :         // Calculates the air-side performance and energy use of a multi stage gas heating coil.
    2306              : 
    2307              :         // METHODOLOGY EMPLOYED:
    2308              :         // Uses the same methodology as the single speed Gas heating unit model (SUBROUTINE CalcFuelHeatingCoil).
    2309              :         // In addition it assumes that the unit performance is obtained by interpolating between
    2310              :         // the performance at high stage and that at low stage. If the output needed is below
    2311              :         // that produced at low stage, the coil cycles between off and low stage.
    2312              : 
    2313           65 :         Real64 const MSHPMassFlowRateHigh = state.dataHVACGlobal->MSHPMassFlowRateHigh;
    2314           65 :         Real64 const MSHPMassFlowRateLow = state.dataHVACGlobal->MSHPMassFlowRateLow;
    2315              : 
    2316              :         // SUBROUTINE PARAMETER DEFINITIONS:
    2317              :         static constexpr std::string_view RoutineName("CalcMultiStageGasHeatingCoil");
    2318              :         static constexpr std::string_view RoutineNameAverageLoad("CalcMultiStageGasHeatingCoil:Averageload");
    2319              :         static constexpr std::string_view RoutineNameFullLoad("CalcMultiStageGasHeatingCoil:fullload");
    2320              : 
    2321              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2322              :         Real64 OutletAirEnthalpy;    // outlet air enthalpy [J/kg]
    2323              :         Real64 OutletAirHumRat;      // outlet air humidity ratio [kg/kg]
    2324              :         Real64 TotCapHS;             // total capacity at high stage [W]
    2325              :         Real64 TotCapLS;             // total capacity at low stage [W]
    2326              :         Real64 TotCap;               // total capacity at current stage [W]
    2327              :         Real64 EffHS;                // efficiency at high stage
    2328           65 :         Real64 EffLS(0.0);           // efficiency at low stage
    2329              :         Real64 EffAvg;               // average efficiency
    2330              :         int StageNumHS;              // High stage number
    2331              :         int StageNumLS;              // Low stage number
    2332              :         Real64 FullLoadOutAirEnth;   // Outlet full load enthalpy
    2333              :         Real64 FullLoadOutAirHumRat; // Outlet humidity ratio at full load
    2334              :         Real64 FullLoadOutAirTemp;   // Outlet temperature at full load
    2335              :         Real64 FullLoadOutAirRH;     // Outler relative humidity at full load
    2336              :         Real64 OutletAirTemp;        // Supply ari temperature
    2337              :         Real64 LSFullLoadOutAirEnth; // Outlet full load enthalpy at low stage
    2338              :         Real64 HSFullLoadOutAirEnth; // Outlet full load enthalpy at high stage
    2339              :         Real64 LSGasHeatingPower;    // Full load power at low stage
    2340              :         Real64 HSGasHeatingPower;    // Full load power at high stage
    2341           65 :         Real64 PartLoadRat(0.0);     // part load ratio
    2342              :         Real64 PLF;                  // part load factor used to calculate RTF
    2343              : 
    2344           65 :         auto &heatingCoil = state.dataHeatingCoils->HeatingCoil(CoilNum);
    2345              : 
    2346           65 :         if (StageNum > 1) {
    2347           14 :             StageNumLS = StageNum - 1;
    2348           14 :             StageNumHS = StageNum;
    2349           14 :             if (StageNum > heatingCoil.NumOfStages) {
    2350            0 :                 StageNumLS = heatingCoil.NumOfStages - 1;
    2351            0 :                 StageNumHS = heatingCoil.NumOfStages;
    2352              :             }
    2353              :         } else {
    2354           51 :             StageNumLS = 1;
    2355           51 :             StageNumHS = 1;
    2356              :         }
    2357              : 
    2358           65 :         Real64 AirMassFlow = heatingCoil.InletAirMassFlowRate;
    2359           65 :         Real64 InletAirEnthalpy = heatingCoil.InletAirEnthalpy;
    2360           65 :         Real64 InletAirHumRat = heatingCoil.InletAirHumRat;
    2361           65 :         Real64 OutdoorPressure = state.dataEnvrn->OutBaroPress;
    2362              : 
    2363           65 :         if ((AirMassFlow > 0.0) && (heatingCoil.availSched->getCurrentVal() > 0.0) && ((CycRatio > 0.0) || (SpeedRatio > 0.0))) {
    2364              : 
    2365           34 :             if (StageNum > 1) {
    2366              : 
    2367           14 :                 TotCapLS = heatingCoil.MSNominalCapacity(StageNumLS);
    2368           14 :                 TotCapHS = heatingCoil.MSNominalCapacity(StageNumHS);
    2369              : 
    2370           14 :                 EffLS = heatingCoil.MSEfficiency(StageNumLS);
    2371           14 :                 EffHS = heatingCoil.MSEfficiency(StageNumHS);
    2372              : 
    2373           14 :                 PartLoadRat = min(1.0, SpeedRatio);
    2374           14 :                 heatingCoil.RTF = 1.0;
    2375              : 
    2376              :                 // Get full load output and power
    2377           14 :                 LSFullLoadOutAirEnth = InletAirEnthalpy + TotCapLS / MSHPMassFlowRateLow;
    2378           14 :                 HSFullLoadOutAirEnth = InletAirEnthalpy + TotCapHS / MSHPMassFlowRateHigh;
    2379           14 :                 LSGasHeatingPower = TotCapLS / EffLS;
    2380           14 :                 HSGasHeatingPower = TotCapHS / EffHS;
    2381           14 :                 OutletAirHumRat = InletAirHumRat;
    2382              : 
    2383              :                 // if cycling fan, send coil part-load fraction to on/off fan via HVACDataGlobals
    2384              :                 // IF (FanOpMode .EQ. FanOp::Cycling) OnOffFanPartLoadFraction = 1.0d0
    2385              : 
    2386              :                 // Power calculation. If PartLoadRat (SpeedRatio) = 0, operate at LS the whole time step
    2387           14 :                 heatingCoil.ElecUseLoad =
    2388           14 :                     PartLoadRat * heatingCoil.MSParasiticElecLoad(StageNumHS) + (1.0 - PartLoadRat) * heatingCoil.MSParasiticElecLoad(StageNumLS);
    2389              : 
    2390           14 :                 state.dataHVACGlobal->ElecHeatingCoilPower = heatingCoil.ElecUseLoad;
    2391           14 :                 heatingCoil.HeatingCoilLoad = MSHPMassFlowRateHigh * (HSFullLoadOutAirEnth - InletAirEnthalpy) * PartLoadRat +
    2392           14 :                                               MSHPMassFlowRateLow * (LSFullLoadOutAirEnth - InletAirEnthalpy) * (1.0 - PartLoadRat);
    2393           14 :                 EffAvg = (EffHS * PartLoadRat) + (EffLS * (1.0 - PartLoadRat));
    2394           14 :                 heatingCoil.FuelUseLoad = heatingCoil.HeatingCoilLoad / EffAvg;
    2395           14 :                 heatingCoil.ParasiticFuelRate = 0.0;
    2396              : 
    2397           14 :                 OutletAirEnthalpy = InletAirEnthalpy + heatingCoil.HeatingCoilLoad / heatingCoil.InletAirMassFlowRate;
    2398           14 :                 OutletAirTemp = Psychrometrics::PsyTdbFnHW(OutletAirEnthalpy, OutletAirHumRat);
    2399           14 :                 FullLoadOutAirRH = Psychrometrics::PsyRhFnTdbWPb(state, OutletAirTemp, OutletAirHumRat, OutdoorPressure, RoutineNameAverageLoad);
    2400              : 
    2401           14 :                 if (FullLoadOutAirRH > 1.0) { // Limit to saturated conditions at FullLoadOutAirEnth
    2402            0 :                     OutletAirTemp = Psychrometrics::PsyTsatFnHPb(state, OutletAirEnthalpy, OutdoorPressure, RoutineName);
    2403            0 :                     OutletAirHumRat = Psychrometrics::PsyWFnTdbH(state, OutletAirTemp, OutletAirEnthalpy, RoutineName);
    2404              :                 }
    2405              : 
    2406           14 :                 heatingCoil.OutletAirTemp = OutletAirTemp;
    2407           14 :                 heatingCoil.OutletAirHumRat = OutletAirHumRat;
    2408           14 :                 heatingCoil.OutletAirEnthalpy = OutletAirEnthalpy;
    2409           14 :                 heatingCoil.OutletAirMassFlowRate = heatingCoil.InletAirMassFlowRate;
    2410              : 
    2411              :                 // Stage 1
    2412           20 :             } else if (CycRatio > 0.0) {
    2413              : 
    2414              :                 // for cycling fan, reset mass flow to full on rate
    2415           20 :                 if (fanOp == HVAC::FanOp::Cycling)
    2416            2 :                     AirMassFlow /= CycRatio;
    2417           18 :                 else if (fanOp == HVAC::FanOp::Continuous)
    2418           18 :                     AirMassFlow = MSHPMassFlowRateLow;
    2419              : 
    2420           20 :                 TotCap = heatingCoil.MSNominalCapacity(StageNumLS);
    2421              : 
    2422           20 :                 PartLoadRat = min(1.0, CycRatio);
    2423           20 :                 heatingCoil.RTF = PartLoadRat;
    2424              : 
    2425              :                 // Calculate full load outlet conditions
    2426           20 :                 FullLoadOutAirEnth = InletAirEnthalpy + TotCap / AirMassFlow;
    2427           20 :                 FullLoadOutAirHumRat = InletAirHumRat;
    2428           20 :                 FullLoadOutAirTemp = Psychrometrics::PsyTdbFnHW(FullLoadOutAirEnth, FullLoadOutAirHumRat);
    2429              :                 FullLoadOutAirRH =
    2430           20 :                     Psychrometrics::PsyRhFnTdbWPb(state, FullLoadOutAirTemp, FullLoadOutAirHumRat, OutdoorPressure, RoutineNameFullLoad);
    2431              : 
    2432           20 :                 if (FullLoadOutAirRH > 1.0) { // Limit to saturated conditions at FullLoadOutAirEnth
    2433            0 :                     FullLoadOutAirTemp = Psychrometrics::PsyTsatFnHPb(state, FullLoadOutAirEnth, OutdoorPressure, RoutineName);
    2434              :                     //  Eventually inlet air conditions will be used in Gas Coil, these lines are commented out and marked with this comment line
    2435              :                     //  FullLoadOutAirTemp = PsyTsatFnHPb(FullLoadOutAirEnth,InletAirPressure)
    2436            0 :                     FullLoadOutAirHumRat = Psychrometrics::PsyWFnTdbH(state, FullLoadOutAirTemp, FullLoadOutAirEnth, RoutineName);
    2437              :                 }
    2438              : 
    2439              :                 // Set outlet conditions from the full load calculation
    2440           20 :                 if (fanOp == HVAC::FanOp::Cycling) {
    2441            2 :                     OutletAirEnthalpy = FullLoadOutAirEnth;
    2442            2 :                     OutletAirHumRat = FullLoadOutAirHumRat;
    2443            2 :                     OutletAirTemp = FullLoadOutAirTemp;
    2444              :                 } else {
    2445           18 :                     OutletAirEnthalpy =
    2446           18 :                         PartLoadRat * AirMassFlow / heatingCoil.InletAirMassFlowRate * (FullLoadOutAirEnth - InletAirEnthalpy) + InletAirEnthalpy;
    2447           18 :                     OutletAirHumRat =
    2448           18 :                         PartLoadRat * AirMassFlow / heatingCoil.InletAirMassFlowRate * (FullLoadOutAirHumRat - InletAirHumRat) + InletAirHumRat;
    2449           18 :                     OutletAirTemp = Psychrometrics::PsyTdbFnHW(OutletAirEnthalpy, OutletAirHumRat);
    2450              :                 }
    2451              : 
    2452           20 :                 EffLS = heatingCoil.MSEfficiency(StageNumLS);
    2453              : 
    2454           20 :                 heatingCoil.HeatingCoilLoad = TotCap * PartLoadRat;
    2455              : 
    2456           20 :                 heatingCoil.FuelUseLoad = heatingCoil.HeatingCoilLoad / EffLS;
    2457              :                 //   parasitics are calculated when the coil is off (1-PLR)
    2458           20 :                 heatingCoil.ElecUseLoad = heatingCoil.MSParasiticElecLoad(StageNumLS) * (1.0 - PartLoadRat);
    2459           20 :                 heatingCoil.ParasiticFuelRate = heatingCoil.ParasiticFuelCapacity * (1.0 - PartLoadRat);
    2460           20 :                 state.dataHVACGlobal->ElecHeatingCoilPower = heatingCoil.ElecUseLoad;
    2461              : 
    2462           20 :                 heatingCoil.OutletAirTemp = OutletAirTemp;
    2463           20 :                 heatingCoil.OutletAirHumRat = OutletAirHumRat;
    2464           20 :                 heatingCoil.OutletAirEnthalpy = OutletAirEnthalpy;
    2465           20 :                 heatingCoil.OutletAirMassFlowRate = heatingCoil.InletAirMassFlowRate;
    2466              :             }
    2467              : 
    2468              :             // This requires a CR to correct (i.e., calculate outputs when coil is off)
    2469              :         } else {
    2470              : 
    2471              :             // Gas coil is off; just pass through conditions
    2472           31 :             heatingCoil.OutletAirEnthalpy = heatingCoil.InletAirEnthalpy;
    2473           31 :             heatingCoil.OutletAirHumRat = heatingCoil.InletAirHumRat;
    2474           31 :             heatingCoil.OutletAirTemp = heatingCoil.InletAirTemp;
    2475           31 :             heatingCoil.OutletAirMassFlowRate = heatingCoil.InletAirMassFlowRate;
    2476              : 
    2477              :             // some of these are reset in Init, can be removed to speed up code
    2478           31 :             heatingCoil.ElecUseLoad = 0.0;
    2479           31 :             heatingCoil.HeatingCoilLoad = 0.0;
    2480           31 :             heatingCoil.FuelUseLoad = 0.0;
    2481           31 :             heatingCoil.ParasiticFuelRate = heatingCoil.ParasiticFuelCapacity;
    2482           31 :             state.dataHVACGlobal->ElecHeatingCoilPower = 0.0;
    2483           31 :             PartLoadRat = 0.0;
    2484              : 
    2485              :         } // end of on/off if - else
    2486              : 
    2487              :         // If the PLF curve is defined the gas usage needs to be modified.
    2488              :         // The PLF curve is only used when the coil cycles.
    2489           65 :         if (heatingCoil.PLFCurveIndex > 0) {
    2490           62 :             if (PartLoadRat > 0.0 && StageNum < 2) {
    2491           18 :                 PLF = Curve::CurveValue(state, heatingCoil.PLFCurveIndex, PartLoadRat);
    2492           18 :                 if (PLF < 0.7) {
    2493            0 :                     if (heatingCoil.PLFErrorCount < 1) {
    2494            0 :                         ++heatingCoil.PLFErrorCount;
    2495            0 :                         ShowWarningError(state,
    2496            0 :                                          format("CalcFuelHeatingCoil: {}=\"{}\", PLF curve values",
    2497              :                                                 HVAC::cAllCoilTypes(heatingCoil.HCoilType_Num),
    2498            0 :                                                 heatingCoil.Name));
    2499            0 :                         ShowContinueError(state, format("The PLF curve value = {:.5T} for part-load ratio = {:.5T}", PLF, PartLoadRat));
    2500            0 :                         ShowContinueError(state, "PLF curve values must be >= 0.7. PLF has been reset to 0.7 and the simulation continues...");
    2501            0 :                         ShowContinueError(state, "Check the IO reference manual for PLF curve guidance [Coil:Heating:Fuel].");
    2502              :                     } else {
    2503            0 :                         ShowRecurringWarningErrorAtEnd(state,
    2504            0 :                                                        format("{}, Heating coil PLF curve < 0.7 warning continues... ", heatingCoil.Name),
    2505            0 :                                                        heatingCoil.PLFErrorIndex,
    2506              :                                                        PLF,
    2507              :                                                        PLF);
    2508              :                     }
    2509            0 :                     PLF = 0.7;
    2510              :                 }
    2511              :                 // Modify the Gas Coil Consumption and parasitic loads based on PLF curve
    2512           18 :                 heatingCoil.RTF = PartLoadRat / PLF;
    2513           18 :                 if (heatingCoil.RTF > 1.0 && std::abs(heatingCoil.RTF - 1.0) > 0.001) {
    2514            0 :                     if (heatingCoil.RTFErrorCount < 1) {
    2515            0 :                         ++heatingCoil.RTFErrorCount;
    2516            0 :                         ShowWarningError(state,
    2517            0 :                                          format("CalcFuelHeatingCoil: {}=\"{}\", runtime fraction",
    2518              :                                                 HVAC::cAllCoilTypes(heatingCoil.HCoilType_Num),
    2519            0 :                                                 heatingCoil.Name));
    2520            0 :                         ShowContinueError(state, format("The runtime fraction exceeded 1.0. [{:.4T}].", heatingCoil.RTF));
    2521            0 :                         ShowContinueError(state, "Runtime fraction is set to 1.0 and the simulation continues...");
    2522            0 :                         ShowContinueError(state, "Check the IO reference manual for PLF curve guidance [Coil:Heating:Fuel].");
    2523              :                     } else {
    2524            0 :                         ShowRecurringWarningErrorAtEnd(state,
    2525            0 :                                                        format("{}, Heating coil runtime fraction > 1.0 warning continues... ", heatingCoil.Name),
    2526            0 :                                                        heatingCoil.RTFErrorIndex,
    2527            0 :                                                        heatingCoil.RTF,
    2528            0 :                                                        heatingCoil.RTF);
    2529              :                     }
    2530            0 :                     heatingCoil.RTF = 1.0; // Reset coil runtime fraction to 1.0
    2531           18 :                 } else if (heatingCoil.RTF > 1.0) {
    2532            0 :                     heatingCoil.RTF = 1.0; // Reset coil runtime fraction to 1.0
    2533              :                 }
    2534           18 :                 heatingCoil.ElecUseLoad = heatingCoil.MSParasiticElecLoad(StageNum) * heatingCoil.RTF;
    2535           18 :                 heatingCoil.FuelUseLoad = (heatingCoil.MSNominalCapacity(StageNum) / EffLS) * heatingCoil.RTF;
    2536           18 :                 heatingCoil.ParasiticFuelRate = heatingCoil.ParasiticFuelCapacity * (1.0 - heatingCoil.RTF);
    2537              :                 // Fan power will also be modified by the heating coil's part load fraction
    2538              :                 // OnOffFanPartLoadFraction passed to fan via DataHVACGlobals (cycling fan only)
    2539           18 :                 if (fanOp == HVAC::FanOp::Cycling) {
    2540            2 :                     state.dataHVACGlobal->OnOffFanPartLoadFraction = PLF;
    2541              :                 }
    2542              :             }
    2543              :         }
    2544              : 
    2545              :         // set outlet node temp so parent objects can call calc directly without have to simulate entire model
    2546           65 :         state.dataLoopNodes->Node(heatingCoil.AirOutletNodeNum).Temp = heatingCoil.OutletAirTemp;
    2547           65 :     }
    2548              : 
    2549            4 :     void CalcDesuperheaterHeatingCoil(EnergyPlusData &state,
    2550              :                                       int const CoilNum,     // index to desuperheater heating coil
    2551              :                                       Real64 const QCoilReq, // load requested by the simulation for load based control [W]
    2552              :                                       Real64 &QCoilActual    // coil load actually delivered
    2553              :     )
    2554              :     {
    2555              :         // SUBROUTINE INFORMATION:
    2556              :         //       AUTHOR         Richard Raustad
    2557              :         //       DATE WRITTEN   January 2005
    2558              :         //       MODIFIED       Jul. 2016, R. Zhang, Applied the coil supply air temperature sensor offset
    2559              : 
    2560              :         // PURPOSE OF THIS SUBROUTINE:
    2561              :         // Simulates a simple desuperheater heating coil with a heat reclaim efficiency
    2562              :         // (eff = ratio of condenser waste heat reclaimed to total condenser waste heat rejected)
    2563              : 
    2564              :         // METHODOLOGY EMPLOYED:
    2565              :         // The available capacity of the desuperheater heating coil is determined by the
    2566              :         // amount of heat rejected at the heating source condenser multiplied by the
    2567              :         // desuperheater heat reclaim efficiency. This capacity is either applied towards
    2568              :         // a requested load (load based control) or applied to the air stream to meet a
    2569              :         // heating setpoint (temperature based control). This subroutine is similar to
    2570              :         // the electric or gas heating coil except that the NominalCapacity is variable
    2571              :         // and based on the runtime fraction and heat rejection of the heat source object.
    2572              : 
    2573              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2574              :         Real64 AvailTemp;       // Lowest temperature available from desuperheater (~T condensing)[C]
    2575              :         Real64 TempAirOut;      // temperature of the air leaving the desuperheater heating coil [C]
    2576              :         Real64 HeatingCoilLoad; // actual load delivered by the desuperheater heating coil [W]
    2577              :         Real64 QCoilCap;        // available capacity of the desuperheater heating coil [W]
    2578              :         int SourceID;           // waste heat source id number
    2579              : 
    2580            4 :         auto &heatingCoil = state.dataHeatingCoils->HeatingCoil(CoilNum);
    2581              : 
    2582            4 :         Real64 Effic = heatingCoil.Efficiency;
    2583            4 :         Real64 AirMassFlow = heatingCoil.InletAirMassFlowRate;
    2584            4 :         Real64 TempAirIn = heatingCoil.InletAirTemp;
    2585            4 :         Real64 Win = heatingCoil.InletAirHumRat;
    2586            4 :         Real64 CapacitanceAir = Psychrometrics::PsyCpAirFnW(Win) * AirMassFlow;
    2587            4 :         Real64 TempSetPoint = heatingCoil.DesiredOutletTemp;
    2588              : 
    2589              :         // If there is a fault of coil SAT Sensor
    2590            4 :         if (heatingCoil.FaultyCoilSATFlag && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) &&
    2591            0 :             (!state.dataGlobal->KickOffSimulation)) {
    2592              :             // calculate the sensor offset using fault information
    2593            0 :             int FaultIndex = heatingCoil.FaultyCoilSATIndex;
    2594            0 :             heatingCoil.FaultyCoilSATOffset = state.dataFaultsMgr->FaultsCoilSATSensor(FaultIndex).CalFaultOffsetAct(state);
    2595              :             // update the TempSetPoint
    2596            0 :             TempSetPoint -= heatingCoil.FaultyCoilSATOffset;
    2597              :         }
    2598              : 
    2599              :         // Access the appropriate structure to find the available heating capacity of the desuperheater heating coil
    2600              :         // The nominal capacity of the desuperheater heating coil varies based on the amount of heat rejected by the source
    2601              :         // Stovall 2011, add comparison to available temperature of heat reclaim source
    2602            4 :         if (state.dataHeatingCoils->ValidSourceType(CoilNum)) {
    2603            4 :             SourceID = heatingCoil.ReclaimHeatingSourceIndexNum;
    2604            4 :             switch (heatingCoil.ReclaimHeatingSource) {
    2605            4 :             case HeatObjTypes::COMPRESSORRACK_REFRIGERATEDCASE:
    2606              :                 // Added last term to available energy equations to avoid double counting reclaimed energy
    2607              :                 // because refrigeration systems are solved outside the hvac time step iterations
    2608            4 :                 heatingCoil.RTF = 1.0;
    2609            4 :                 heatingCoil.NominalCapacity = state.dataHeatBal->HeatReclaimRefrigeratedRack(SourceID).AvailCapacity * Effic -
    2610            4 :                                               state.dataHeatBal->HeatReclaimRefrigeratedRack(SourceID).WaterHeatingDesuperheaterReclaimedHeatTotal;
    2611            4 :                 break;
    2612            0 :             case HeatObjTypes::CONDENSER_REFRIGERATION:
    2613            0 :                 AvailTemp = state.dataHeatBal->HeatReclaimRefrigCondenser(SourceID).AvailTemperature;
    2614            0 :                 heatingCoil.RTF = 1.0;
    2615            0 :                 if (AvailTemp <= TempAirIn) {
    2616            0 :                     heatingCoil.NominalCapacity = 0.0;
    2617            0 :                     ShowRecurringWarningErrorAtEnd(
    2618              :                         state,
    2619            0 :                         format("Coil:Heating:Desuperheater {} - Waste heat source temperature was too low to be useful.", heatingCoil.Name),
    2620            0 :                         heatingCoil.InsuffTemperatureWarn);
    2621              :                 } else {
    2622            0 :                     heatingCoil.NominalCapacity = state.dataHeatBal->HeatReclaimRefrigCondenser(SourceID).AvailCapacity * Effic -
    2623            0 :                                                   state.dataHeatBal->HeatReclaimRefrigCondenser(SourceID).WaterHeatingDesuperheaterReclaimedHeatTotal;
    2624              :                 }
    2625            0 :                 break;
    2626            0 :             case HeatObjTypes::COIL_DX_COOLING:
    2627              :             case HeatObjTypes::COIL_DX_MULTISPEED:
    2628              :             case HeatObjTypes::COIL_DX_MULTIMODE:
    2629            0 :                 heatingCoil.RTF = state.dataDXCoils->DXCoil(SourceID).CoolingCoilRuntimeFraction;
    2630            0 :                 heatingCoil.NominalCapacity = state.dataHeatBal->HeatReclaimDXCoil(SourceID).AvailCapacity * Effic -
    2631            0 :                                               state.dataHeatBal->HeatReclaimDXCoil(SourceID).WaterHeatingDesuperheaterReclaimedHeatTotal;
    2632            0 :                 break;
    2633            0 :             case HeatObjTypes::COIL_DX_VARIABLE_COOLING:
    2634              :                 // condenser heat rejection
    2635            0 :                 heatingCoil.RTF = state.dataVariableSpeedCoils->VarSpeedCoil(SourceID).RunFrac;
    2636            0 :                 heatingCoil.NominalCapacity = state.dataHeatBal->HeatReclaimVS_Coil(SourceID).AvailCapacity * Effic -
    2637            0 :                                               state.dataHeatBal->HeatReclaimVS_Coil(SourceID).WaterHeatingDesuperheaterReclaimedHeatTotal;
    2638            0 :                 break;
    2639            0 :             case HeatObjTypes::COIL_COOLING_DX_NEW:
    2640              :                 // get RTF and NominalCapacity from Coil:CoolingDX
    2641              :                 {
    2642            0 :                     auto const &thisCoolingCoil = state.dataCoilCoolingDX->coilCoolingDXs[SourceID];
    2643            0 :                     heatingCoil.RTF = thisCoolingCoil.runTimeFraction;
    2644            0 :                     heatingCoil.NominalCapacity =
    2645            0 :                         thisCoolingCoil.reclaimHeat.AvailCapacity * Effic - thisCoolingCoil.reclaimHeat.WaterHeatingDesuperheaterReclaimedHeatTotal;
    2646              :                 }
    2647            0 :                 break;
    2648            0 :             default:
    2649            0 :                 assert(false);
    2650              :             }
    2651              : 
    2652              :         } else {
    2653            0 :             heatingCoil.NominalCapacity = 0.0;
    2654              :         }
    2655              : 
    2656              :         // Control output to meet load (QCoilReq)
    2657            4 :         if ((AirMassFlow > 0.0) && (heatingCoil.availSched->getCurrentVal() > 0.0) && (QCoilReq > 0.0)) {
    2658              : 
    2659              :             // check to see if the Required heating capacity is greater than the available heating capacity.
    2660            2 :             if (QCoilReq > heatingCoil.NominalCapacity) {
    2661            0 :                 QCoilCap = heatingCoil.NominalCapacity;
    2662              :             } else {
    2663            2 :                 QCoilCap = QCoilReq;
    2664              :             }
    2665              : 
    2666              :             // report the runtime fraction of the desuperheater heating coil
    2667            2 :             if (heatingCoil.NominalCapacity > 0.0) {
    2668            2 :                 heatingCoil.RTF *= (QCoilCap / heatingCoil.NominalCapacity);
    2669            2 :                 TempAirOut = TempAirIn + QCoilCap / CapacitanceAir;
    2670            2 :                 HeatingCoilLoad = QCoilCap;
    2671              :             } else {
    2672            0 :                 heatingCoil.RTF = 0.0;
    2673            0 :                 TempAirOut = TempAirIn;
    2674            0 :                 HeatingCoilLoad = 0.0;
    2675              :             }
    2676              : 
    2677              :             // Control coil output to meet a setpoint temperature.
    2678            1 :         } else if ((AirMassFlow > 0.0 && heatingCoil.NominalCapacity > 0.0) && (heatingCoil.availSched->getCurrentVal() > 0.0) &&
    2679            3 :                    (QCoilReq == DataLoopNode::SensedLoadFlagValue) && (std::abs(TempSetPoint - TempAirIn) > HVAC::TempControlTol)) {
    2680              : 
    2681            0 :             QCoilCap = CapacitanceAir * (TempSetPoint - TempAirIn);
    2682              :             // check to see if setpoint is above entering air temperature. If not, set output to zero.
    2683            0 :             if (QCoilCap <= 0.0) {
    2684            0 :                 QCoilCap = 0.0;
    2685            0 :                 TempAirOut = TempAirIn;
    2686              :                 // check to see if the required heating capacity is greater than the available capacity.
    2687            0 :             } else if (QCoilCap > heatingCoil.NominalCapacity) {
    2688            0 :                 QCoilCap = heatingCoil.NominalCapacity;
    2689            0 :                 TempAirOut = TempAirIn + QCoilCap / CapacitanceAir;
    2690              :             } else {
    2691            0 :                 TempAirOut = TempSetPoint;
    2692              :             }
    2693              : 
    2694            0 :             HeatingCoilLoad = QCoilCap;
    2695              :             //     report the runtime fraction of the desuperheater heating coil
    2696            0 :             heatingCoil.RTF *= (QCoilCap / heatingCoil.NominalCapacity);
    2697              : 
    2698              :         } else { // If not running, conditions do not change across heating coil from inlet to outlet
    2699              : 
    2700            2 :             TempAirOut = TempAirIn;
    2701            2 :             HeatingCoilLoad = 0.0;
    2702            2 :             heatingCoil.ElecUseLoad = 0.0;
    2703            2 :             heatingCoil.RTF = 0.0;
    2704              :         }
    2705              : 
    2706              :         // Set the outlet conditions
    2707            4 :         heatingCoil.HeatingCoilLoad = HeatingCoilLoad;
    2708            4 :         heatingCoil.OutletAirTemp = TempAirOut;
    2709              : 
    2710              :         // This HeatingCoil does not change the moisture or Mass Flow across the component
    2711            4 :         heatingCoil.OutletAirHumRat = heatingCoil.InletAirHumRat;
    2712            4 :         heatingCoil.OutletAirMassFlowRate = heatingCoil.InletAirMassFlowRate;
    2713              :         // Set the outlet enthalpy
    2714            4 :         heatingCoil.OutletAirEnthalpy = Psychrometrics::PsyHFnTdbW(heatingCoil.OutletAirTemp, heatingCoil.OutletAirHumRat);
    2715              : 
    2716            4 :         heatingCoil.ElecUseLoad = heatingCoil.ParasiticElecLoad * heatingCoil.RTF;
    2717            4 :         QCoilActual = HeatingCoilLoad;
    2718              : 
    2719              :         // Update remaining waste heat (just in case multiple users of waste heat use same source)
    2720            4 :         if (state.dataHeatingCoils->ValidSourceType(CoilNum)) {
    2721            4 :             SourceID = heatingCoil.ReclaimHeatingSourceIndexNum;
    2722              :             //   Refrigerated cases are simulated at the zone time step, do not decrement available capacity
    2723              :             //   (the heat reclaim available capacity will not get reinitialized as the air loop iterates)
    2724            4 :             int DesuperheaterNum = CoilNum - state.dataHeatingCoils->NumElecCoil - state.dataHeatingCoils->NumElecCoilMultiStage -
    2725            4 :                                    state.dataHeatingCoils->NumFuelCoil - state.dataHeatingCoils->NumGasCoilMultiStage;
    2726            4 :             switch (heatingCoil.ReclaimHeatingSource) {
    2727            4 :             case HeatObjTypes::COMPRESSORRACK_REFRIGERATEDCASE: {
    2728            4 :                 state.dataHeatBal->HeatReclaimRefrigeratedRack(SourceID).HVACDesuperheaterReclaimedHeat(DesuperheaterNum) = HeatingCoilLoad;
    2729            4 :                 state.dataHeatBal->HeatReclaimRefrigeratedRack(SourceID).HVACDesuperheaterReclaimedHeatTotal = 0.0;
    2730            8 :                 for (auto const &num : state.dataHeatBal->HeatReclaimRefrigeratedRack(SourceID).HVACDesuperheaterReclaimedHeat)
    2731            4 :                     state.dataHeatBal->HeatReclaimRefrigeratedRack(SourceID).HVACDesuperheaterReclaimedHeatTotal += num;
    2732            4 :             } break;
    2733            0 :             case HeatObjTypes::CONDENSER_REFRIGERATION: {
    2734            0 :                 state.dataHeatBal->HeatReclaimRefrigCondenser(SourceID).HVACDesuperheaterReclaimedHeat(DesuperheaterNum) = HeatingCoilLoad;
    2735            0 :                 state.dataHeatBal->HeatReclaimRefrigCondenser(SourceID).HVACDesuperheaterReclaimedHeatTotal = 0.0;
    2736            0 :                 for (auto const &num : state.dataHeatBal->HeatReclaimRefrigCondenser(SourceID).HVACDesuperheaterReclaimedHeat)
    2737            0 :                     state.dataHeatBal->HeatReclaimRefrigCondenser(SourceID).HVACDesuperheaterReclaimedHeatTotal += num;
    2738            0 :             } break;
    2739            0 :             case HeatObjTypes::COIL_DX_COOLING:
    2740              :             case HeatObjTypes::COIL_DX_MULTISPEED:
    2741              :             case HeatObjTypes::COIL_DX_MULTIMODE: {
    2742            0 :                 state.dataHeatBal->HeatReclaimDXCoil(SourceID).HVACDesuperheaterReclaimedHeat(DesuperheaterNum) = HeatingCoilLoad;
    2743            0 :                 state.dataHeatBal->HeatReclaimDXCoil(SourceID).HVACDesuperheaterReclaimedHeatTotal = 0.0;
    2744            0 :                 for (auto const &num : state.dataHeatBal->HeatReclaimDXCoil(SourceID).HVACDesuperheaterReclaimedHeat)
    2745            0 :                     state.dataHeatBal->HeatReclaimDXCoil(SourceID).HVACDesuperheaterReclaimedHeatTotal += num;
    2746            0 :             } break;
    2747            0 :             case HeatObjTypes::COIL_DX_VARIABLE_COOLING: {
    2748            0 :                 state.dataHeatBal->HeatReclaimVS_Coil(SourceID).HVACDesuperheaterReclaimedHeat(DesuperheaterNum) = HeatingCoilLoad;
    2749            0 :                 state.dataHeatBal->HeatReclaimVS_Coil(SourceID).HVACDesuperheaterReclaimedHeatTotal = 0.0;
    2750            0 :                 for (auto const &num : state.dataHeatBal->HeatReclaimVS_Coil(SourceID).HVACDesuperheaterReclaimedHeat)
    2751            0 :                     state.dataHeatBal->HeatReclaimVS_Coil(SourceID).HVACDesuperheaterReclaimedHeatTotal += num;
    2752            0 :             } break;
    2753            0 :             default:
    2754            0 :                 break;
    2755              :             }
    2756              :         }
    2757            4 :     }
    2758              : 
    2759       233160 :     void UpdateHeatingCoil(EnergyPlusData &state, int const CoilNum)
    2760              :     {
    2761              :         // SUBROUTINE INFORMATION:
    2762              :         //       AUTHOR         Richard Liesen
    2763              :         //       DATE WRITTEN   May 2000
    2764              : 
    2765              :         // PURPOSE OF THIS SUBROUTINE:
    2766              :         // This subroutine updates the coil outlet nodes.
    2767              : 
    2768              :         // METHODOLOGY EMPLOYED:
    2769              :         // Data is moved from the coil data structure to the coil outlet nodes.
    2770              : 
    2771              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2772       233160 :         auto const &heatingCoil = state.dataHeatingCoils->HeatingCoil(CoilNum);
    2773       233160 :         auto const &airInletNode = state.dataLoopNodes->Node(heatingCoil.AirInletNodeNum);
    2774       233160 :         auto &airOuletNode = state.dataLoopNodes->Node(heatingCoil.AirOutletNodeNum);
    2775              : 
    2776              :         // Set the outlet air nodes of the HeatingCoil
    2777       233160 :         airOuletNode.MassFlowRate = heatingCoil.OutletAirMassFlowRate;
    2778       233160 :         airOuletNode.Temp = heatingCoil.OutletAirTemp;
    2779       233160 :         airOuletNode.HumRat = heatingCoil.OutletAirHumRat;
    2780       233160 :         airOuletNode.Enthalpy = heatingCoil.OutletAirEnthalpy;
    2781              : 
    2782              :         // Set the outlet nodes for properties that just pass through & not used
    2783       233160 :         airOuletNode.Quality = airInletNode.Quality;
    2784       233160 :         airOuletNode.Press = airInletNode.Press;
    2785       233160 :         airOuletNode.MassFlowRateMin = airInletNode.MassFlowRateMin;
    2786       233160 :         airOuletNode.MassFlowRateMax = airInletNode.MassFlowRateMax;
    2787       233160 :         airOuletNode.MassFlowRateMinAvail = airInletNode.MassFlowRateMinAvail;
    2788       233160 :         airOuletNode.MassFlowRateMaxAvail = airInletNode.MassFlowRateMaxAvail;
    2789              : 
    2790       233160 :         if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    2791            0 :             airOuletNode.CO2 = airInletNode.CO2;
    2792              :         }
    2793              : 
    2794       233160 :         if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    2795            0 :             airOuletNode.GenContam = airInletNode.GenContam;
    2796              :         }
    2797       233160 :     }
    2798              : 
    2799       233160 :     void ReportHeatingCoil(EnergyPlusData &state, int const CoilNum, bool const coilIsSuppHeater)
    2800              :     {
    2801              : 
    2802              :         // SUBROUTINE INFORMATION:
    2803              :         //       AUTHOR         Richard Liesen
    2804              :         //       DATE WRITTEN   May 2000
    2805              : 
    2806              :         // PURPOSE OF THIS SUBROUTINE:
    2807              :         // This subroutine updates the report variable for the coils.
    2808              : 
    2809              :         // Using/Aliasing
    2810       233160 :         Real64 TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
    2811       233160 :         auto &heatingCoil = state.dataHeatingCoils->HeatingCoil(CoilNum);
    2812              : 
    2813              :         // report the HeatingCoil energy from this component
    2814       233160 :         heatingCoil.HeatingCoilRate = heatingCoil.HeatingCoilLoad;
    2815       233160 :         heatingCoil.HeatingCoilLoad *= TimeStepSysSec;
    2816              : 
    2817       233160 :         heatingCoil.FuelUseRate = heatingCoil.FuelUseLoad;
    2818       233160 :         heatingCoil.ElecUseRate = heatingCoil.ElecUseLoad;
    2819       233160 :         if (coilIsSuppHeater) {
    2820       137752 :             state.dataHVACGlobal->SuppHeatingCoilPower = heatingCoil.ElecUseLoad;
    2821              :         } else {
    2822        95408 :             state.dataHVACGlobal->ElecHeatingCoilPower = heatingCoil.ElecUseLoad;
    2823              :         }
    2824       233160 :         heatingCoil.FuelUseLoad *= TimeStepSysSec;
    2825       233160 :         heatingCoil.ElecUseLoad *= TimeStepSysSec;
    2826              : 
    2827       233160 :         heatingCoil.ParasiticFuelConsumption = heatingCoil.ParasiticFuelRate * TimeStepSysSec;
    2828              : 
    2829       233160 :         std::string coilObjClassName;
    2830       233160 :         switch (heatingCoil.HCoilType_Num) {
    2831        73698 :         case HVAC::Coil_HeatingElectric: {
    2832        73698 :             coilObjClassName = "Coil:Heating:Electric";
    2833        73698 :         } break;
    2834          217 :         case HVAC::Coil_HeatingElectric_MultiStage: {
    2835          217 :             coilObjClassName = "Coil:Heating:Electric:MultiStage";
    2836          217 :         } break;
    2837       159191 :         case HVAC::Coil_HeatingGasOrOtherFuel: {
    2838       159191 :             coilObjClassName = "Coil:Heating:Fuel";
    2839       159191 :         } break;
    2840           50 :         case HVAC::Coil_HeatingGas_MultiStage: {
    2841           50 :             coilObjClassName = "Coil:Heating:Gas:MultiStage";
    2842           50 :         } break;
    2843            4 :         case HVAC::Coil_HeatingDesuperheater: {
    2844            4 :             coilObjClassName = "Coil:Heating:Desuperheater";
    2845            4 :         } break;
    2846            0 :         default:
    2847            0 :             break;
    2848              :         }
    2849       233160 :         if (heatingCoil.reportCoilFinalSizes) {
    2850        56127 :             if (!state.dataGlobal->WarmupFlag && !state.dataGlobal->DoingHVACSizingSimulations && !state.dataGlobal->DoingSizing) {
    2851          117 :                 state.dataRptCoilSelection->coilSelectionReportObj->setCoilFinalSizes(
    2852          117 :                     state, heatingCoil.Name, coilObjClassName, heatingCoil.NominalCapacity, heatingCoil.NominalCapacity, -999.0, -999.0);
    2853          117 :                 heatingCoil.reportCoilFinalSizes = false;
    2854              :             }
    2855              :         }
    2856       233160 :     }
    2857              : 
    2858              :     //        End of Reporting subroutines for the HeatingCoil Module
    2859              : 
    2860           84 :     void GetCoilIndex(EnergyPlusData &state, std::string const &HeatingCoilName, int &HeatingCoilIndex, bool &ErrorsFound)
    2861              :     {
    2862              : 
    2863              :         // SUBROUTINE INFORMATION:
    2864              :         //       AUTHOR         Richard Raustad
    2865              :         //       DATE WRITTEN   March 2005
    2866              : 
    2867              :         // PURPOSE OF THIS SUBROUTINE:
    2868              :         // This subroutine sets an index for a given DX Coil -- issues error message if that
    2869              :         // DX Coil is not a legal DX Coil.
    2870              : 
    2871              :         // Obtains and Allocates HeatingCoil related parameters from input file
    2872           84 :         if (state.dataHeatingCoils->GetCoilsInputFlag) { // First time subroutine has been entered
    2873           36 :             GetHeatingCoilInput(state);
    2874           36 :             state.dataHeatingCoils->GetCoilsInputFlag = false;
    2875              :         }
    2876              : 
    2877           84 :         HeatingCoilIndex = Util::FindItem(HeatingCoilName, state.dataHeatingCoils->HeatingCoil);
    2878           84 :         if (HeatingCoilIndex == 0) {
    2879            0 :             ShowSevereError(state, format("GetCoilIndex: Heating coil not found={}", HeatingCoilName));
    2880            0 :             ErrorsFound = true;
    2881              :         }
    2882           84 :     }
    2883              : 
    2884            2 :     void CheckHeatingCoilSchedule(EnergyPlusData &state,
    2885              :                                   std::string const &CompType, // unused1208
    2886              :                                   std::string_view CompName,
    2887              :                                   Real64 &Value,
    2888              :                                   int &CompIndex)
    2889              :     {
    2890              : 
    2891              :         // SUBROUTINE INFORMATION:
    2892              :         //       AUTHOR         Linda Lawrie
    2893              :         //       DATE WRITTEN   October 2005
    2894              : 
    2895              :         // PURPOSE OF THIS SUBROUTINE:
    2896              :         // This routine provides a method for outside routines to check if
    2897              :         // the heating coil is scheduled to be on.
    2898              : 
    2899              :         // Obtains and Allocates HeatingCoil related parameters from input file
    2900            2 :         if (state.dataHeatingCoils->GetCoilsInputFlag) { // First time subroutine has been entered
    2901            2 :             GetHeatingCoilInput(state);
    2902            2 :             state.dataHeatingCoils->GetCoilsInputFlag = false;
    2903              :         }
    2904              : 
    2905              :         // Find the correct Coil number
    2906            2 :         if (CompIndex == 0) {
    2907            2 :             int CoilNum = Util::FindItem(CompName, state.dataHeatingCoils->HeatingCoil);
    2908            2 :             if (CoilNum == 0) {
    2909            0 :                 ShowFatalError(state, format("CheckHeatingCoilSchedule: Coil not found=\"{}\".", CompName));
    2910              :             }
    2911            2 :             if (!Util::SameString(CompType, HVAC::cAllCoilTypes(state.dataHeatingCoils->HeatingCoil(CoilNum).HCoilType_Num))) {
    2912            0 :                 ShowSevereError(state, format("CheckHeatingCoilSchedule: Coil=\"{}\"", CompName));
    2913            0 :                 ShowContinueError(state,
    2914            0 :                                   format("...expected type=\"{}\", actual type=\"{}\".",
    2915              :                                          CompType,
    2916            0 :                                          HVAC::cAllCoilTypes(state.dataHeatingCoils->HeatingCoil(CoilNum).HCoilType_Num)));
    2917            0 :                 ShowFatalError(state, "Program terminates due to preceding conditions.");
    2918              :             }
    2919            2 :             CompIndex = CoilNum;
    2920            2 :             Value = state.dataHeatingCoils->HeatingCoil(CoilNum).availSched->getCurrentVal(); // not scheduled?
    2921              :         } else {
    2922            0 :             int CoilNum = CompIndex;
    2923            0 :             if (CoilNum > state.dataHeatingCoils->NumHeatingCoils || CoilNum < 1) {
    2924            0 :                 ShowFatalError(state,
    2925            0 :                                format("CheckHeatingCoilSchedule: Invalid CompIndex passed={}, Number of Heating Coils={}, Coil name={}",
    2926              :                                       CoilNum,
    2927            0 :                                       state.dataHeatingCoils->NumHeatingCoils,
    2928              :                                       CompName));
    2929              :             }
    2930            0 :             if (CompName != state.dataHeatingCoils->HeatingCoil(CoilNum).Name) {
    2931            0 :                 ShowSevereError(state,
    2932            0 :                                 format("CheckHeatingCoilSchedule: Invalid CompIndex passed={}, Coil name={}, stored Coil Name for that index={}",
    2933              :                                        CoilNum,
    2934              :                                        CompName,
    2935            0 :                                        state.dataHeatingCoils->HeatingCoil(CoilNum).Name));
    2936            0 :                 ShowContinueError(state,
    2937            0 :                                   format("...expected type=\"{}\", actual type=\"{}\".",
    2938              :                                          CompType,
    2939            0 :                                          HVAC::cAllCoilTypes(state.dataHeatingCoils->HeatingCoil(CoilNum).HCoilType_Num)));
    2940            0 :                 ShowFatalError(state, "Program terminates due to preceding conditions.");
    2941              :             }
    2942            0 :             Value = state.dataHeatingCoils->HeatingCoil(CoilNum).availSched->getCurrentVal(); // not scheduled?
    2943              :         }
    2944            2 :     }
    2945              : 
    2946           22 :     Real64 GetCoilCapacity(EnergyPlusData &state,
    2947              :                            std::string const &CoilType, // must match coil types in this module
    2948              :                            std::string const &CoilName, // must match coil names for the coil type
    2949              :                            bool &ErrorsFound            // set to true if problem
    2950              :     )
    2951              :     {
    2952              : 
    2953              :         // FUNCTION INFORMATION:
    2954              :         //       AUTHOR         Linda Lawrie
    2955              :         //       DATE WRITTEN   February 2006
    2956              : 
    2957              :         // PURPOSE OF THIS FUNCTION:
    2958              :         // This function looks up the coil capacity for the given coil and returns it.  If
    2959              :         // incorrect coil type or name is given, ErrorsFound is returned as true and capacity is returned
    2960              :         // as negative.
    2961              : 
    2962              :         // Return value
    2963              :         Real64 CoilCapacity; // returned capacity of matched coil
    2964              : 
    2965              :         // FUNCTION LOCAL VARIABLE DECLARATIONS:
    2966              :         int WhichCoil;
    2967              : 
    2968              :         // Obtains and Allocates HeatingCoil related parameters from input file
    2969           22 :         if (state.dataHeatingCoils->GetCoilsInputFlag) { // First time subroutine has been entered
    2970            0 :             GetHeatingCoilInput(state);
    2971            0 :             state.dataHeatingCoils->GetCoilsInputFlag = false;
    2972              :         }
    2973              : 
    2974           22 :         int FoundType = Util::FindItem(CoilType, HVAC::cAllCoilTypes, HVAC::NumAllCoilTypes);
    2975           22 :         if (FoundType == HVAC::Coil_HeatingElectric || FoundType == HVAC::Coil_HeatingGasOrOtherFuel ||
    2976              :             FoundType == HVAC::Coil_HeatingDesuperheater) {
    2977           22 :             WhichCoil = Util::FindItem(CoilName, state.dataHeatingCoils->HeatingCoil);
    2978           22 :             if (WhichCoil != 0) {
    2979           22 :                 CoilCapacity = state.dataHeatingCoils->HeatingCoil(WhichCoil).NominalCapacity;
    2980              :             }
    2981            0 :         } else if (FoundType == HVAC::Coil_HeatingElectric_MultiStage || FoundType == HVAC::Coil_HeatingGas_MultiStage) {
    2982            0 :             WhichCoil = Util::FindItem(CoilName, state.dataHeatingCoils->HeatingCoil);
    2983            0 :             if (WhichCoil != 0) {
    2984            0 :                 CoilCapacity =
    2985            0 :                     state.dataHeatingCoils->HeatingCoil(WhichCoil).MSNominalCapacity(state.dataHeatingCoils->HeatingCoil(WhichCoil).NumOfStages);
    2986              :             }
    2987              :         } else {
    2988            0 :             WhichCoil = 0;
    2989              :         }
    2990              : 
    2991           22 :         if (WhichCoil == 0) { // Autodesk:Return Reworked block to assure CoilCapacity is set before return
    2992            0 :             if (FoundType == 0) {
    2993            0 :                 ShowSevereError(state, format("GetCoilCapacity: Could not find Coil, Type=\"{}\" Name=\"{}\"", CoilType, CoilName));
    2994            0 :             } else if (FoundType > 0) {
    2995            0 :                 ShowSevereError(state, format("GetCoilCapacity: Invalid coil type for capacity, Type=\"{}\" Name=\"{}\"", CoilType, CoilName));
    2996            0 :                 ShowContinueError(state,
    2997            0 :                                   format("...only {}, {} or {} are valid in this context.",
    2998              :                                          HVAC::cAllCoilTypes(HVAC::Coil_HeatingElectric),
    2999              :                                          HVAC::cAllCoilTypes(HVAC::Coil_HeatingGasOrOtherFuel),
    3000              :                                          HVAC::cAllCoilTypes(HVAC::Coil_HeatingDesuperheater)));
    3001              :             }
    3002            0 :             ShowContinueError(state, "... returning Coil Capacity as -1000.");
    3003            0 :             ErrorsFound = true;
    3004            0 :             CoilCapacity = -1000.0;
    3005              :         }
    3006              : 
    3007           22 :         return CoilCapacity;
    3008              :     }
    3009              : 
    3010            0 :     Sched::Schedule *GetCoilAvailSched(EnergyPlusData &state,
    3011              :                                        std::string const &CoilType, // must match coil types in this module
    3012              :                                        std::string const &CoilName, // must match coil names for the coil type
    3013              :                                        bool &ErrorsFound            // set to true if problem
    3014              :     )
    3015              :     {
    3016              : 
    3017              :         // FUNCTION INFORMATION:
    3018              :         //       AUTHOR         Richard Raustad, FSEC
    3019              :         //       DATE WRITTEN   February 2013
    3020              : 
    3021              :         // PURPOSE OF THIS FUNCTION:
    3022              :         // This function looks up the given coil and returns the availability schedule index.  If
    3023              :         // incorrect coil type or name is given, ErrorsFound is returned as true and index is returned
    3024              :         // as zero.
    3025              : 
    3026              :         // Obtains and Allocates HeatingCoil related parameters from input file
    3027            0 :         if (state.dataHeatingCoils->GetCoilsInputFlag) { // First time subroutine has been entered
    3028            0 :             GetHeatingCoilInput(state);
    3029            0 :             state.dataHeatingCoils->GetCoilsInputFlag = false;
    3030              :         }
    3031              : 
    3032            0 :         int WhichCoil = 0;
    3033            0 :         int FoundType = Util::FindItem(CoilType, HVAC::cAllCoilTypes, HVAC::NumAllCoilTypes);
    3034            0 :         if (FoundType == HVAC::Coil_HeatingElectric || FoundType == HVAC::Coil_HeatingElectric_MultiStage ||
    3035            0 :             FoundType == HVAC::Coil_HeatingGasOrOtherFuel || FoundType == HVAC::Coil_HeatingGas_MultiStage ||
    3036              :             FoundType == HVAC::Coil_HeatingDesuperheater) {
    3037            0 :             WhichCoil = Util::FindItem(CoilName, state.dataHeatingCoils->HeatingCoil);
    3038            0 :             if (WhichCoil != 0) {
    3039            0 :                 return state.dataHeatingCoils->HeatingCoil(WhichCoil).availSched;
    3040              :             }
    3041              :         } else {
    3042            0 :             WhichCoil = 0;
    3043              :         }
    3044              : 
    3045            0 :         if (WhichCoil == 0) {
    3046            0 :             ShowSevereError(state, format("GetCoilAvailScheduleIndex: Could not find Coil, Type=\"{}\" Name=\"{}\"", CoilType, CoilName));
    3047            0 :             ErrorsFound = true;
    3048              :         }
    3049              : 
    3050            0 :         return nullptr;
    3051              :     }
    3052              : 
    3053           21 :     int GetCoilInletNode(EnergyPlusData &state,
    3054              :                          std::string_view CoilType,   // must match coil types in this module
    3055              :                          std::string const &CoilName, // must match coil names for the coil type
    3056              :                          bool &ErrorsFound            // set to true if problem
    3057              :     )
    3058              :     {
    3059              : 
    3060              :         // FUNCTION INFORMATION:
    3061              :         //       AUTHOR         Linda Lawrie
    3062              :         //       DATE WRITTEN   February 2006
    3063              : 
    3064              :         // PURPOSE OF THIS FUNCTION:
    3065              :         // This function looks up the given coil and returns the inlet node number.  If
    3066              :         // incorrect coil type or name is given, ErrorsFound is returned as true and node number is returned
    3067              :         // as zero.
    3068              : 
    3069              :         // Obtains and Allocates HeatingCoil related parameters from input file
    3070           21 :         if (state.dataHeatingCoils->GetCoilsInputFlag) { // First time subroutine has been entered
    3071            6 :             GetHeatingCoilInput(state);
    3072            6 :             state.dataHeatingCoils->GetCoilsInputFlag = false;
    3073              :         }
    3074              : 
    3075           21 :         int WhichCoil = 0;
    3076           21 :         int NodeNumber = 0;
    3077           21 :         int FoundType = Util::FindItem(CoilType, HVAC::cAllCoilTypes, HVAC::NumAllCoilTypes);
    3078           21 :         if (FoundType == HVAC::Coil_HeatingElectric || FoundType == HVAC::Coil_HeatingElectric_MultiStage ||
    3079            0 :             FoundType == HVAC::Coil_HeatingGasOrOtherFuel || FoundType == HVAC::Coil_HeatingGas_MultiStage ||
    3080              :             FoundType == HVAC::Coil_HeatingDesuperheater) {
    3081           21 :             WhichCoil = Util::FindItem(CoilName, state.dataHeatingCoils->HeatingCoil);
    3082           21 :             if (WhichCoil != 0) {
    3083           21 :                 NodeNumber = state.dataHeatingCoils->HeatingCoil(WhichCoil).AirInletNodeNum;
    3084              :             }
    3085              :         } else {
    3086            0 :             WhichCoil = 0;
    3087              :         }
    3088              : 
    3089           21 :         if (WhichCoil == 0) {
    3090            0 :             ShowSevereError(state, format("GetCoilInletNode: Could not find Coil, Type=\"{}\" Name=\"{}\"", CoilType, CoilName));
    3091            0 :             ErrorsFound = true;
    3092            0 :             NodeNumber = 0;
    3093              :         }
    3094              : 
    3095           21 :         return NodeNumber;
    3096              :     }
    3097              : 
    3098           24 :     int GetCoilOutletNode(EnergyPlusData &state,
    3099              :                           std::string_view CoilType,   // must match coil types in this module
    3100              :                           std::string const &CoilName, // must match coil names for the coil type
    3101              :                           bool &ErrorsFound            // set to true if problem
    3102              :     )
    3103              :     {
    3104              : 
    3105              :         // FUNCTION INFORMATION:
    3106              :         //       AUTHOR         Richard Raustad
    3107              :         //       DATE WRITTEN   August 2006
    3108              : 
    3109              :         // PURPOSE OF THIS FUNCTION:
    3110              :         // This function looks up the given coil and returns the outlet node number.  If
    3111              :         // incorrect coil type or name is given, ErrorsFound is returned as true and node number is returned
    3112              :         // as zero.
    3113              : 
    3114              :         // Obtains and Allocates HeatingCoil related parameters from input file
    3115           24 :         if (state.dataHeatingCoils->GetCoilsInputFlag) { // First time subroutine has been entered
    3116            2 :             GetHeatingCoilInput(state);
    3117            2 :             state.dataHeatingCoils->GetCoilsInputFlag = false;
    3118              :         }
    3119              : 
    3120           24 :         int WhichCoil = 0;
    3121           24 :         int NodeNumber = 0;
    3122           24 :         int FoundType = Util::FindItem(CoilType, HVAC::cAllCoilTypes, HVAC::NumAllCoilTypes);
    3123           24 :         if (FoundType == HVAC::Coil_HeatingElectric || FoundType == HVAC::Coil_HeatingElectric_MultiStage ||
    3124            0 :             FoundType == HVAC::Coil_HeatingGasOrOtherFuel || FoundType == HVAC::Coil_HeatingGas_MultiStage ||
    3125              :             FoundType == HVAC::Coil_HeatingDesuperheater) {
    3126           24 :             WhichCoil = Util::FindItem(CoilName, state.dataHeatingCoils->HeatingCoil);
    3127           24 :             if (WhichCoil != 0) {
    3128           24 :                 NodeNumber = state.dataHeatingCoils->HeatingCoil(WhichCoil).AirOutletNodeNum;
    3129              :             }
    3130              :         } else {
    3131            0 :             WhichCoil = 0;
    3132              :         }
    3133              : 
    3134           24 :         if (WhichCoil == 0) {
    3135            0 :             ShowSevereError(state, format("GetCoilOutletNode: Could not find Coil, Type=\"{}\" Name=\"{}\"", CoilType, CoilName));
    3136            0 :             ErrorsFound = true;
    3137            0 :             NodeNumber = 0;
    3138              :         }
    3139              : 
    3140           24 :         return NodeNumber;
    3141              :     }
    3142              : 
    3143            3 :     int GetHeatReclaimSourceIndex(EnergyPlusData &state,
    3144              :                                   std::string const &CoilType, // must match coil types in this module
    3145              :                                   std::string const &CoilName, // must match coil names for the coil type
    3146              :                                   bool &ErrorsFound            // set to true if problem
    3147              :     )
    3148              :     {
    3149              : 
    3150              :         // FUNCTION INFORMATION:
    3151              :         //       AUTHOR         Richard Raustad
    3152              :         //       DATE WRITTEN   June 2007
    3153              : 
    3154              :         // PURPOSE OF THIS FUNCTION:
    3155              :         // This function looks up the given coil and returns the heating coil index number if it is a desuperheating coil.
    3156              :         // If incorrect coil type or name is given, ErrorsFound is returned as true and index number is returned
    3157              :         // as zero.
    3158              : 
    3159              :         // FUNCTION LOCAL VARIABLE DECLARATIONS:
    3160              :         bool GetCoilErrFlag;
    3161              :         int NumCoil;
    3162            3 :         int CoilNum(0);
    3163              : 
    3164              :         // Obtains and Allocates HeatingCoil related parameters from input file
    3165            3 :         if (state.dataHeatingCoils->GetCoilsInputFlag) { // First time subroutine has been entered
    3166            1 :             GetHeatingCoilInput(state);
    3167            1 :             state.dataHeatingCoils->GetCoilsInputFlag = false;
    3168              :         }
    3169              : 
    3170            3 :         int CoilFound = 0;
    3171              : 
    3172              :         // note should eventually get rid of this string comparison
    3173            4 :         if (Util::SameString(CoilType, "COIL:COOLING:DX:SINGLESPEED") || Util::SameString(CoilType, "COIL:COOLING:DX:TWOSPEED") ||
    3174            4 :             Util::SameString(CoilType, "COIL:COOLING:DX:TWOSTAGEWITHHUMIDITYCONTROLMODE")) {
    3175            2 :             bool SuppressWarning = true;
    3176            2 :             DXCoils::GetDXCoilIndex(state, CoilName, CoilNum, GetCoilErrFlag, CoilType, SuppressWarning);
    3177            5 :             for (NumCoil = 1; NumCoil <= state.dataHeatingCoils->NumHeatingCoils; ++NumCoil) {
    3178            3 :                 if (state.dataHeatingCoils->HeatingCoil(NumCoil).ReclaimHeatingSource != HeatObjTypes::COIL_DX_COOLING &&
    3179            3 :                     state.dataHeatingCoils->HeatingCoil(NumCoil).ReclaimHeatingSource != HeatObjTypes::COIL_DX_MULTISPEED &&
    3180            9 :                     state.dataHeatingCoils->HeatingCoil(NumCoil).ReclaimHeatingSource != HeatObjTypes::COIL_DX_MULTIMODE &&
    3181            3 :                     state.dataHeatingCoils->HeatingCoil(NumCoil).ReclaimHeatingCoilName != CoilName)
    3182            3 :                     continue;
    3183            0 :                 CoilFound = CoilNum;
    3184            0 :                 break;
    3185              :             }
    3186            1 :         } else if (Util::SameString(CoilType, "COIL:COOLING:DX:VARIABLESPEED")) {
    3187            1 :             CoilNum = VariableSpeedCoils::GetCoilIndexVariableSpeed(state, CoilType, CoilName, GetCoilErrFlag);
    3188            3 :             for (NumCoil = 1; NumCoil <= state.dataHeatingCoils->NumHeatingCoils; ++NumCoil) {
    3189            4 :                 if (state.dataHeatingCoils->HeatingCoil(NumCoil).ReclaimHeatingSource != HeatObjTypes::COIL_DX_VARIABLE_COOLING &&
    3190            2 :                     state.dataHeatingCoils->HeatingCoil(NumCoil).ReclaimHeatingCoilName != CoilName)
    3191            2 :                     continue;
    3192            0 :                 CoilFound = CoilNum;
    3193            0 :                 break;
    3194              :             }
    3195              :         }
    3196              : 
    3197            3 :         if (CoilNum == 0) {
    3198            0 :             ErrorsFound = true;
    3199              :         }
    3200              : 
    3201            3 :         return CoilFound;
    3202              :     }
    3203              : 
    3204            3 :     int GetCoilControlNodeNum(EnergyPlusData &state,
    3205              :                               std::string const &CoilType, // must match coil types in this module
    3206              :                               std::string const &CoilName, // must match coil names for the coil type
    3207              :                               bool &ErrorsFound            // set to true if problem
    3208              :     )
    3209              :     {
    3210              : 
    3211              :         // FUNCTION INFORMATION:
    3212              :         //       AUTHOR         Richard Raustad
    3213              :         //       DATE WRITTEN   June 2007
    3214              : 
    3215              :         // PURPOSE OF THIS FUNCTION:
    3216              :         // This function looks up the given coil and returns the control node number.  If
    3217              :         // incorrect coil type or name is given, ErrorsFound is returned as true and node number is returned
    3218              :         // as zero.
    3219              : 
    3220              :         // Obtains and Allocates HeatingCoil related parameters from input file
    3221            3 :         if (state.dataHeatingCoils->GetCoilsInputFlag) { // First time subroutine has been entered
    3222            0 :             GetHeatingCoilInput(state);
    3223            0 :             state.dataHeatingCoils->GetCoilsInputFlag = false;
    3224              :         }
    3225              : 
    3226            3 :         int FoundType = Util::FindItem(CoilType, HVAC::cAllCoilTypes, HVAC::NumAllCoilTypes);
    3227            3 :         if (FoundType == HVAC::Coil_HeatingElectric || FoundType == HVAC::Coil_HeatingElectric_MultiStage ||
    3228            0 :             FoundType == HVAC::Coil_HeatingGasOrOtherFuel || FoundType == HVAC::Coil_HeatingGas_MultiStage ||
    3229              :             FoundType == HVAC::Coil_HeatingDesuperheater) {
    3230            3 :             int WhichCoil = Util::FindItem(CoilName, state.dataHeatingCoils->HeatingCoil);
    3231            3 :             if (WhichCoil != 0) {
    3232            3 :                 return state.dataHeatingCoils->HeatingCoil(WhichCoil).TempSetPointNodeNum;
    3233              :             }
    3234              :         }
    3235              : 
    3236            0 :         ShowSevereError(state, format("GetCoilControlNodeNum: Could not find Coil, Type=\"{}\" Name=\"{}\"", CoilType, CoilName));
    3237            0 :         ErrorsFound = true;
    3238            0 :         return 0;
    3239              :     }
    3240              : 
    3241           81 :     int GetHeatingCoilTypeNum(EnergyPlusData &state,
    3242              :                               std::string const &CoilType, // must match coil types in this module
    3243              :                               std::string const &CoilName, // must match coil names for the coil type
    3244              :                               bool &ErrorsFound            // set to true if problem
    3245              :     )
    3246              :     {
    3247              : 
    3248              :         // FUNCTION INFORMATION:
    3249              :         //       AUTHOR         Richard Raustad
    3250              :         //       DATE WRITTEN   August 2008
    3251              : 
    3252              :         // PURPOSE OF THIS FUNCTION:
    3253              :         // This function looks up the given coil and returns the type number.  If
    3254              :         // incorrect coil type or name is given, ErrorsFound is returned as true and type number is returned
    3255              :         // as zero.
    3256              : 
    3257              :         // Obtains and Allocates HeatingCoil related parameters from input file
    3258           81 :         if (state.dataHeatingCoils->GetCoilsInputFlag) { // First time subroutine has been entered
    3259           49 :             GetHeatingCoilInput(state);
    3260           49 :             state.dataHeatingCoils->GetCoilsInputFlag = false;
    3261              :         }
    3262              : 
    3263           81 :         int FoundType = Util::FindItem(CoilType, HVAC::cAllCoilTypes, HVAC::NumAllCoilTypes);
    3264           81 :         if (FoundType == HVAC::Coil_HeatingElectric || FoundType == HVAC::Coil_HeatingElectric_MultiStage ||
    3265            1 :             FoundType == HVAC::Coil_HeatingGasOrOtherFuel || FoundType == HVAC::Coil_HeatingGas_MultiStage ||
    3266              :             FoundType == HVAC::Coil_HeatingDesuperheater) {
    3267           81 :             int WhichCoil = Util::FindItem(CoilName, state.dataHeatingCoils->HeatingCoil);
    3268           81 :             if (WhichCoil != 0) {
    3269           81 :                 return state.dataHeatingCoils->HeatingCoil(WhichCoil).HCoilType_Num;
    3270              :             }
    3271              :         }
    3272              : 
    3273            0 :         ShowSevereError(state, format("GetHeatingCoilTypeNum: Could not find Coil, Type=\"{}\" Name=\"{}\"", CoilType, CoilName));
    3274            0 :         ErrorsFound = true;
    3275            0 :         return 0;
    3276              :     }
    3277              : 
    3278           37 :     int GetHeatingCoilIndex(EnergyPlusData &state,
    3279              :                             std::string const &CoilType, // must match coil types in this module
    3280              :                             std::string const &CoilName, // must match coil names for the coil type
    3281              :                             bool &ErrorsFound            // set to true if problem
    3282              :     )
    3283              :     {
    3284              : 
    3285              :         // FUNCTION INFORMATION:
    3286              :         //       AUTHOR         Linda Lawrie
    3287              :         //       DATE WRITTEN   February 2011
    3288              : 
    3289              :         // PURPOSE OF THIS FUNCTION:
    3290              :         // This function looks up the given coil and returns the index into the structure.  If
    3291              :         // incorrect coil type or name is given, ErrorsFound is returned as true and index is returned
    3292              :         // as zero.
    3293              : 
    3294              :         // Obtains and Allocates HeatingCoil related parameters from input file
    3295           37 :         if (state.dataHeatingCoils->GetCoilsInputFlag) { // First time subroutine has been entered
    3296            2 :             GetHeatingCoilInput(state);
    3297            2 :             state.dataHeatingCoils->GetCoilsInputFlag = false;
    3298              :         }
    3299              : 
    3300           37 :         int WhichCoil = 0;
    3301           37 :         int FoundType = Util::FindItem(CoilType, HVAC::cAllCoilTypes, HVAC::NumAllCoilTypes);
    3302           37 :         if (FoundType == HVAC::Coil_HeatingElectric || FoundType == HVAC::Coil_HeatingElectric_MultiStage ||
    3303            0 :             FoundType == HVAC::Coil_HeatingGasOrOtherFuel || FoundType == HVAC::Coil_HeatingGas_MultiStage ||
    3304              :             FoundType == HVAC::Coil_HeatingDesuperheater) {
    3305           37 :             WhichCoil = Util::FindItem(CoilName, state.dataHeatingCoils->HeatingCoil);
    3306              :         }
    3307              : 
    3308           37 :         if (WhichCoil == 0) {
    3309            0 :             ShowSevereError(state, format("GetHeatingCoilIndex: Could not find Coil, Type=\"{}\" Name=\"{}\"", CoilType, CoilName));
    3310            0 :             ErrorsFound = true;
    3311              :         }
    3312              : 
    3313           37 :         return WhichCoil;
    3314              :     }
    3315              : 
    3316            0 :     int GetHeatingCoilPLFCurveIndex(EnergyPlusData &state,
    3317              :                                     std::string const &CoilType, // must match coil types in this module
    3318              :                                     std::string const &CoilName, // must match coil names for the coil type
    3319              :                                     bool &ErrorsFound            // set to true if problem
    3320              :     )
    3321              :     {
    3322              : 
    3323              :         // FUNCTION INFORMATION:
    3324              :         //       AUTHOR         Richard Raustad
    3325              :         //       DATE WRITTEN   December 2008
    3326              : 
    3327              :         // PURPOSE OF THIS FUNCTION:
    3328              :         // This function looks up the given coil and returns the PLF curve index.  If
    3329              :         // incorrect coil name is given for gas or electric heating coils, ErrorsFound
    3330              :         // is returned as true and curve index is returned as zero.
    3331              :         // If not a gas or electric heating coil, ErrorsFound is unchanged and index is 0.
    3332              : 
    3333              :         // Obtains and Allocates HeatingCoil related parameters from input file
    3334            0 :         if (state.dataHeatingCoils->GetCoilsInputFlag) { // First time subroutine has been entered
    3335            0 :             GetHeatingCoilInput(state);
    3336            0 :             state.dataHeatingCoils->GetCoilsInputFlag = false;
    3337              :         }
    3338              : 
    3339            0 :         int FoundType = Util::FindItem(CoilType, HVAC::cAllCoilTypes, HVAC::NumAllCoilTypes);
    3340            0 :         if (FoundType == HVAC::Coil_HeatingElectric || FoundType == HVAC::Coil_HeatingElectric_MultiStage ||
    3341            0 :             FoundType == HVAC::Coil_HeatingGasOrOtherFuel || FoundType == HVAC::Coil_HeatingGas_MultiStage ||
    3342              :             FoundType == HVAC::Coil_HeatingDesuperheater) {
    3343            0 :             int WhichCoil = Util::FindItem(CoilName, state.dataHeatingCoils->HeatingCoil);
    3344            0 :             if (WhichCoil != 0) {
    3345            0 :                 return state.dataHeatingCoils->HeatingCoil(WhichCoil).PLFCurveIndex;
    3346              :             } else {
    3347            0 :                 ShowSevereError(state, format("GetHeatingCoilPLFCurveIndex: Could not find Coil, Type=\"{}\" Name=\"{}\"", CoilType, CoilName));
    3348            0 :                 ErrorsFound = true;
    3349            0 :                 return 0;
    3350              :             }
    3351              :         } else {
    3352            0 :             return 0;
    3353              :         }
    3354              :     }
    3355              : 
    3356            0 :     int GetHeatingCoilNumberOfStages(EnergyPlusData &state,
    3357              :                                      std::string const &CoilType, // must match coil types in this module
    3358              :                                      std::string const &CoilName, // must match coil names for the coil type
    3359              :                                      bool &ErrorsFound            // set to true if problem
    3360              :     )
    3361              :     {
    3362              : 
    3363              :         // FUNCTION INFORMATION:
    3364              :         //       AUTHOR         Chandan Sharma
    3365              :         //       DATE WRITTEN   February 2013
    3366              : 
    3367              :         // PURPOSE OF THIS FUNCTION:
    3368              :         // This function looks up the given coil and returns the number of speeds for multistage coils.
    3369              :         // If incorrect coil type or name is given, ErrorsFound is returned as true.
    3370              : 
    3371              :         // Obtains and Allocates HeatingCoils
    3372            0 :         if (state.dataHeatingCoils->GetCoilsInputFlag) { // First time subroutine has been entered
    3373            0 :             GetHeatingCoilInput(state);
    3374            0 :             state.dataHeatingCoils->GetCoilsInputFlag = false;
    3375              :         }
    3376              : 
    3377            0 :         int WhichCoil = Util::FindItemInList(CoilName, state.dataHeatingCoils->HeatingCoil);
    3378            0 :         if (WhichCoil != 0) {
    3379            0 :             return state.dataHeatingCoils->HeatingCoil(WhichCoil).NumOfStages;
    3380              :         } else {
    3381            0 :             ShowSevereError(state, format("GetHeatingCoilNumberOfSpeeds: Invalid Heating Coil Type=\"{}\" Name=\"{}\"", CoilType, CoilName));
    3382            0 :             ErrorsFound = true;
    3383            0 :             return 0;
    3384              :         }
    3385              :     }
    3386              : 
    3387            3 :     void SetHeatingCoilData(EnergyPlusData &state,
    3388              :                             int const CoilNum,                                  // Number of electric or gas heating Coil
    3389              :                             bool &ErrorsFound,                                  // Set to true if certain errors found
    3390              :                             ObjexxFCL::Optional_bool DesiccantRegenerationCoil, // Flag that this coil is used as regeneration air heating coil
    3391              :                             ObjexxFCL::Optional_int DesiccantDehumIndex         // Index for the desiccant dehum system where this coil is used
    3392              :     )
    3393              :     {
    3394              : 
    3395              :         // FUNCTION INFORMATION:
    3396              :         //       AUTHOR         Bereket Nigusse
    3397              :         //       DATE WRITTEN   February 2016
    3398              : 
    3399              :         // PURPOSE OF THIS FUNCTION:
    3400              :         // This function sets data to Heating Coil using the coil index and arguments passed
    3401              : 
    3402            3 :         auto &heatingCoil = state.dataHeatingCoils->HeatingCoil(CoilNum);
    3403            3 :         if (state.dataHeatingCoils->GetCoilsInputFlag) {
    3404            0 :             GetHeatingCoilInput(state);
    3405            0 :             state.dataHeatingCoils->GetCoilsInputFlag = false;
    3406              :         }
    3407              : 
    3408            3 :         if (CoilNum <= 0 || CoilNum > state.dataHeatingCoils->NumHeatingCoils) {
    3409            0 :             ShowSevereError(state,
    3410            0 :                             format("SetHeatingCoilData: called with heating coil Number out of range={} should be >0 and <{}",
    3411              :                                    CoilNum,
    3412            0 :                                    state.dataHeatingCoils->NumHeatingCoils));
    3413            0 :             ErrorsFound = true;
    3414            0 :             return;
    3415              :         }
    3416              : 
    3417            3 :         if (present(DesiccantRegenerationCoil)) {
    3418            3 :             heatingCoil.DesiccantRegenerationCoil = DesiccantRegenerationCoil;
    3419              :         }
    3420              : 
    3421            3 :         if (present(DesiccantDehumIndex)) {
    3422            3 :             heatingCoil.DesiccantDehumNum = DesiccantDehumIndex;
    3423              :         }
    3424              :     }
    3425              : 
    3426            3 :     void SetHeatingCoilAirLoopNumber(EnergyPlusData &state, std::string const &HeatingCoilName, int AirLoopNum, bool &ErrorsFound)
    3427              :     {
    3428              :         // SUBROUTINE INFORMATION:
    3429              :         //       AUTHOR         L.Gu
    3430              :         //       DATE WRITTEN   March 2018
    3431              : 
    3432              :         // PURPOSE OF THIS SUBROUTINE:
    3433              :         // This subroutine sets an AirLoopNum for a given heating Coil
    3434              : 
    3435              :         int HeatingCoilIndex;
    3436              : 
    3437            3 :         if (state.dataHeatingCoils->GetCoilsInputFlag) { // First time subroutine has been entered
    3438            0 :             GetHeatingCoilInput(state);
    3439            0 :             state.dataHeatingCoils->GetCoilsInputFlag = false;
    3440              :         }
    3441              : 
    3442            3 :         HeatingCoilIndex = Util::FindItem(HeatingCoilName, state.dataHeatingCoils->HeatingCoil);
    3443            3 :         if (HeatingCoilIndex == 0) {
    3444            0 :             ShowSevereError(state, format("GetCoilIndex: Heating coil not found={}", HeatingCoilName));
    3445            0 :             ErrorsFound = true;
    3446              :         } else {
    3447            3 :             state.dataHeatingCoils->HeatingCoil(HeatingCoilIndex).AirLoopNum = AirLoopNum;
    3448              :         }
    3449            3 :     }
    3450              : } // namespace HeatingCoils
    3451              : 
    3452              : } // namespace EnergyPlus
        

Generated by: LCOV version 2.0-1