LCOV - code coverage report
Current view: top level - EnergyPlus - SteamCoils.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 52.8 % 845 446
Test Date: 2025-06-02 12:03:30 Functions: 58.3 % 24 14

            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              : 
      54              : // EnergyPlus Headers
      55              : #include <EnergyPlus/Autosizing/All_Simple_Sizing.hh>
      56              : #include <EnergyPlus/Autosizing/HeatingAirFlowSizing.hh>
      57              : #include <EnergyPlus/BranchNodeConnections.hh>
      58              : #include <EnergyPlus/Data/EnergyPlusData.hh>
      59              : #include <EnergyPlus/DataContaminantBalance.hh>
      60              : #include <EnergyPlus/DataEnvironment.hh>
      61              : #include <EnergyPlus/DataHVACGlobals.hh>
      62              : #include <EnergyPlus/DataLoopNode.hh>
      63              : #include <EnergyPlus/DataSizing.hh>
      64              : #include <EnergyPlus/Fans.hh>
      65              : #include <EnergyPlus/FaultsManager.hh>
      66              : #include <EnergyPlus/FluidProperties.hh>
      67              : #include <EnergyPlus/GeneralRoutines.hh>
      68              : #include <EnergyPlus/GlobalNames.hh>
      69              : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      70              : #include <EnergyPlus/NodeInputManager.hh>
      71              : #include <EnergyPlus/OutputProcessor.hh>
      72              : #include <EnergyPlus/Plant/DataPlant.hh>
      73              : #include <EnergyPlus/PlantUtilities.hh>
      74              : #include <EnergyPlus/Psychrometrics.hh>
      75              : #include <EnergyPlus/ReportCoilSelection.hh>
      76              : #include <EnergyPlus/ScheduleManager.hh>
      77              : #include <EnergyPlus/SteamCoils.hh>
      78              : #include <EnergyPlus/UtilityRoutines.hh>
      79              : 
      80              : namespace EnergyPlus {
      81              : 
      82              : namespace SteamCoils {
      83              : 
      84              :     // Module containing the SteamCoil simulation routines
      85              : 
      86              :     // MODULE INFORMATION:
      87              :     //   AUTHOR         Rahul Chillar
      88              :     //   DATE WRITTEN   Jan 2005
      89              :     //   MODIFIED       na
      90              :     //   RE-ENGINEERED  na
      91              : 
      92              :     // PURPOSE OF THIS MODULE:
      93              :     // To encapsulate the data and algorithms required to
      94              :     // manage the SteamCoil System Component.
      95              : 
      96              :     using namespace DataLoopNode;
      97              :     using namespace Psychrometrics;
      98              : 
      99              :     using PlantUtilities::MyPlantSizingIndex;
     100              :     using PlantUtilities::ScanPlantLoopsForObject;
     101              : 
     102              :     constexpr std::array<std::string_view, static_cast<int>(CoilControlType::Num)> coilControlTypeNames = {"TEMPERATURESETPOINTCONTROL",
     103              :                                                                                                            "ZONELOADCONTROL"};
     104              : 
     105            3 :     void SimulateSteamCoilComponents(EnergyPlusData &state,
     106              :                                      std::string_view CompName,
     107              :                                      bool const FirstHVACIteration,
     108              :                                      int &CompIndex,
     109              :                                      ObjexxFCL::Optional<Real64 const> QCoilReq, // coil load to be met
     110              :                                      ObjexxFCL::Optional<Real64> QCoilActual,    // coil load actually delivered returned to calling component
     111              :                                      ObjexxFCL::Optional<HVAC::FanOp const> fanOpMode,
     112              :                                      ObjexxFCL::Optional<Real64 const> PartLoadRatio)
     113              :     {
     114              : 
     115              :         // SUBROUTINE INFORMATION:
     116              :         //   AUTHOR         Rahul Chillar
     117              :         //   DATE WRITTEN   Jan 2005
     118              :         //   MODIFIED       na
     119              :         //   RE-ENGINEERED  na
     120              : 
     121              :         // PURPOSE OF THIS SUBROUTINE:
     122              :         // This subroutine manages SteamCoil component simulation.
     123              : 
     124              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     125              :         Real64 QCoilActualTemp; // coil load actually delivered returned to calling component
     126              :         int CoilNum;            // The SteamCoil that you are currently loading input into
     127              :         HVAC::FanOp fanOp;      // fan operating mode
     128              :         Real64 PartLoadFrac;    // part-load fraction of heating coil
     129              :         Real64 QCoilReqLocal;   // local required heating load optional
     130              : 
     131              :         // Obtains and Allocates SteamCoil related parameters from input file
     132            3 :         if (state.dataSteamCoils->GetSteamCoilsInputFlag) { // First time subroutine has been entered
     133            0 :             GetSteamCoilInput(state);
     134            0 :             state.dataSteamCoils->GetSteamCoilsInputFlag = false;
     135              :         }
     136              : 
     137              :         // Find the correct SteamCoilNumber with the Coil Name
     138            3 :         if (CompIndex == 0) {
     139            0 :             CoilNum = Util::FindItemInList(CompName, state.dataSteamCoils->SteamCoil);
     140            0 :             if (CoilNum == 0) {
     141            0 :                 ShowFatalError(state, format("SimulateSteamCoilComponents: Coil not found={}", CompName));
     142              :             }
     143            0 :             CompIndex = CoilNum;
     144              :         } else {
     145            3 :             CoilNum = CompIndex;
     146            3 :             if (CoilNum > state.dataSteamCoils->NumSteamCoils || CoilNum < 1) {
     147            0 :                 ShowFatalError(state,
     148            0 :                                format("SimulateSteamCoilComponents: Invalid CompIndex passed={}, Number of Steam Coils={}, Coil name={}",
     149              :                                       CoilNum,
     150            0 :                                       state.dataSteamCoils->NumSteamCoils,
     151              :                                       CompName));
     152              :             }
     153            3 :             if (state.dataSteamCoils->CheckEquipName(CoilNum)) {
     154            2 :                 if (CompName != state.dataSteamCoils->SteamCoil(CoilNum).Name) {
     155            0 :                     ShowFatalError(
     156              :                         state,
     157            0 :                         format("SimulateSteamCoilComponents: Invalid CompIndex passed={}, Coil name={}, stored Coil Name for that index={}",
     158              :                                CoilNum,
     159              :                                CompName,
     160            0 :                                state.dataSteamCoils->SteamCoil(CoilNum).Name));
     161              :                 }
     162            2 :                 state.dataSteamCoils->CheckEquipName(CoilNum) = false;
     163              :             }
     164              :         }
     165              : 
     166              :         // With the correct CoilNum Initialize
     167            3 :         InitSteamCoil(state, CoilNum, FirstHVACIteration); // Initialize all SteamCoil related parameters
     168              : 
     169            3 :         if (present(fanOpMode)) {
     170            2 :             fanOp = fanOpMode;
     171              :         } else {
     172            1 :             fanOp = HVAC::FanOp::Continuous;
     173              :         }
     174            3 :         if (present(PartLoadRatio)) {
     175            2 :             PartLoadFrac = PartLoadRatio;
     176              :         } else {
     177            1 :             PartLoadFrac = 1.0;
     178              :         }
     179            3 :         if (present(QCoilReq)) {
     180            2 :             QCoilReqLocal = QCoilReq;
     181              :         } else {
     182            1 :             QCoilReqLocal = 0.0;
     183              :         }
     184              : 
     185            3 :         CalcSteamAirCoil(
     186              :             state, CoilNum, QCoilReqLocal, QCoilActualTemp, fanOp, PartLoadFrac); // Autodesk:OPTIONAL QCoilReq used without PRESENT check
     187            3 :         if (present(QCoilActual)) {
     188            2 :             QCoilActual = QCoilActualTemp;
     189              :         }
     190              : 
     191              :         // Update the current SteamCoil to the outlet nodes
     192            3 :         UpdateSteamCoil(state, CoilNum);
     193              : 
     194              :         // Report the current SteamCoil
     195            3 :         ReportSteamCoil(state, CoilNum);
     196            3 :     }
     197              : 
     198              :     // Get Input Section of the Module
     199              : 
     200            2 :     void GetSteamCoilInput(EnergyPlusData &state)
     201              :     {
     202              :         // SUBROUTINE INFORMATION:
     203              :         //   AUTHOR         Rahul Chillar
     204              :         //   DATE WRITTEN   Jan 2005
     205              :         //   MODIFIED       na
     206              :         //   RE-ENGINEERED  na
     207              : 
     208              :         // PURPOSE OF THIS SUBROUTINE:
     209              :         // Obtains input data for coils and stores it in coil data structures
     210              : 
     211              :         // METHODOLOGY EMPLOYED:
     212              :         // Uses "Get" routines to read in data.
     213              : 
     214              :         // Using/Aliasing
     215              :         using BranchNodeConnections::TestCompSet;
     216              :         using GlobalNames::VerifyUniqueCoilName;
     217              :         using NodeInputManager::GetOnlySingleNode;
     218              : 
     219              :         // SUBROUTINE PARAMETER DEFINITIONS:
     220              :         static constexpr std::string_view RoutineName("GetSteamCoilInput: "); // include trailing blank space
     221              :         static constexpr std::string_view routineName = "GetSteamCoilInput";
     222              : 
     223              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     224              :         int CoilNum; // The SteamCoil that you are currently loading input into
     225              :         int NumStmHeat;
     226              :         int StmHeatNum;
     227              :         int NumAlphas;
     228              :         int NumNums;
     229              :         int IOStat;
     230            2 :         bool ErrorsFound(false);         // If errors detected in input
     231            2 :         std::string CurrentModuleObject; // for ease in getting objects
     232            2 :         Array1D_string AlphArray;        // Alpha input items for object
     233            2 :         Array1D_string cAlphaFields;     // Alpha field names
     234            2 :         Array1D_string cNumericFields;   // Numeric field names
     235            2 :         Array1D<Real64> NumArray;        // Numeric input items for object
     236            2 :         Array1D_bool lAlphaBlanks;       // Logical array, alpha field input BLANK = .TRUE.
     237            2 :         Array1D_bool lNumericBlanks;     // Logical array, numeric field input BLANK = .TRUE.
     238            2 :         int TotalArgs(0);                // Total number of alpha and numeric arguments (max) for a
     239              :                                          //  certain object in the input file
     240              : 
     241            2 :         CurrentModuleObject = "Coil:Heating:Steam";
     242            2 :         NumStmHeat = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
     243            2 :         state.dataSteamCoils->NumSteamCoils = NumStmHeat;
     244            2 :         if (state.dataSteamCoils->NumSteamCoils > 0) {
     245            2 :             state.dataSteamCoils->SteamCoil.allocate(state.dataSteamCoils->NumSteamCoils);
     246            2 :             state.dataSteamCoils->CheckEquipName.dimension(state.dataSteamCoils->NumSteamCoils, true);
     247              :         }
     248              : 
     249            2 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, TotalArgs, NumAlphas, NumNums);
     250            2 :         AlphArray.allocate(NumAlphas);
     251            2 :         cAlphaFields.allocate(NumAlphas);
     252            2 :         cNumericFields.allocate(NumNums);
     253            2 :         NumArray.dimension(NumNums, 0.0);
     254            2 :         lAlphaBlanks.dimension(NumAlphas, true);
     255            2 :         lNumericBlanks.dimension(NumNums, true);
     256              : 
     257              :         // Get the data for steam heating coils
     258            4 :         for (StmHeatNum = 1; StmHeatNum <= NumStmHeat; ++StmHeatNum) {
     259              : 
     260            2 :             CoilNum = StmHeatNum;
     261              : 
     262            2 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     263              :                                                                      CurrentModuleObject,
     264              :                                                                      StmHeatNum,
     265              :                                                                      AlphArray,
     266              :                                                                      NumAlphas,
     267              :                                                                      NumArray,
     268              :                                                                      NumNums,
     269              :                                                                      IOStat,
     270              :                                                                      lNumericBlanks,
     271              :                                                                      lAlphaBlanks,
     272              :                                                                      cAlphaFields,
     273              :                                                                      cNumericFields);
     274              : 
     275            2 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, AlphArray(1)};
     276            2 :             Util::IsNameEmpty(state, AlphArray(1), CurrentModuleObject, ErrorsFound);
     277              : 
     278              :             // ErrorsFound will be set to True if problem was found, left untouched otherwise
     279            2 :             VerifyUniqueCoilName(state, CurrentModuleObject, AlphArray(1), ErrorsFound, CurrentModuleObject + " Name");
     280              : 
     281            2 :             state.dataSteamCoils->SteamCoil(CoilNum).Name = AlphArray(1);
     282              : 
     283            2 :             if (lAlphaBlanks(2)) {
     284            0 :                 state.dataSteamCoils->SteamCoil(CoilNum).availSched = Sched::GetScheduleAlwaysOn(state);
     285            2 :             } else if ((state.dataSteamCoils->SteamCoil(CoilNum).availSched = Sched::GetSchedule(state, AlphArray(2))) == nullptr) {
     286            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(2), AlphArray(2));
     287            0 :                 ErrorsFound = true;
     288              :             }
     289              : 
     290            2 :             state.dataSteamCoils->SteamCoil(CoilNum).SteamCoilTypeA = "Heating";
     291            2 :             state.dataSteamCoils->SteamCoil(CoilNum).CoilType = DataPlant::PlantEquipmentType::CoilSteamAirHeating;
     292            2 :             state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamVolFlowRate = NumArray(1);
     293            2 :             state.dataSteamCoils->SteamCoil(CoilNum).DegOfSubcooling = NumArray(2);
     294            2 :             state.dataSteamCoils->SteamCoil(CoilNum).LoopSubcoolReturn = NumArray(3);
     295              : 
     296            4 :             state.dataSteamCoils->SteamCoil(CoilNum).SteamInletNodeNum = GetOnlySingleNode(state,
     297            2 :                                                                                            AlphArray(3),
     298              :                                                                                            ErrorsFound,
     299              :                                                                                            DataLoopNode::ConnectionObjectType::CoilHeatingSteam,
     300            2 :                                                                                            AlphArray(1),
     301              :                                                                                            DataLoopNode::NodeFluidType::Steam,
     302              :                                                                                            DataLoopNode::ConnectionType::Inlet,
     303              :                                                                                            NodeInputManager::CompFluidStream::Secondary,
     304              :                                                                                            ObjectIsNotParent);
     305            4 :             state.dataSteamCoils->SteamCoil(CoilNum).SteamOutletNodeNum = GetOnlySingleNode(state,
     306            2 :                                                                                             AlphArray(4),
     307              :                                                                                             ErrorsFound,
     308              :                                                                                             DataLoopNode::ConnectionObjectType::CoilHeatingSteam,
     309            2 :                                                                                             AlphArray(1),
     310              :                                                                                             DataLoopNode::NodeFluidType::Steam,
     311              :                                                                                             DataLoopNode::ConnectionType::Outlet,
     312              :                                                                                             NodeInputManager::CompFluidStream::Secondary,
     313              :                                                                                             ObjectIsNotParent);
     314            4 :             state.dataSteamCoils->SteamCoil(CoilNum).AirInletNodeNum = GetOnlySingleNode(state,
     315            2 :                                                                                          AlphArray(5),
     316              :                                                                                          ErrorsFound,
     317              :                                                                                          DataLoopNode::ConnectionObjectType::CoilHeatingSteam,
     318            2 :                                                                                          AlphArray(1),
     319              :                                                                                          DataLoopNode::NodeFluidType::Air,
     320              :                                                                                          DataLoopNode::ConnectionType::Inlet,
     321              :                                                                                          NodeInputManager::CompFluidStream::Primary,
     322              :                                                                                          ObjectIsNotParent);
     323            4 :             state.dataSteamCoils->SteamCoil(CoilNum).AirOutletNodeNum = GetOnlySingleNode(state,
     324            2 :                                                                                           AlphArray(6),
     325              :                                                                                           ErrorsFound,
     326              :                                                                                           DataLoopNode::ConnectionObjectType::CoilHeatingSteam,
     327            2 :                                                                                           AlphArray(1),
     328              :                                                                                           DataLoopNode::NodeFluidType::Air,
     329              :                                                                                           DataLoopNode::ConnectionType::Outlet,
     330              :                                                                                           NodeInputManager::CompFluidStream::Primary,
     331              :                                                                                           ObjectIsNotParent);
     332              : 
     333            2 :             std::string controlMode = Util::makeUPPER(AlphArray(7));
     334            2 :             state.dataSteamCoils->SteamCoil(CoilNum).TypeOfCoil = static_cast<CoilControlType>(getEnumValue(coilControlTypeNames, controlMode));
     335              : 
     336            2 :             switch (state.dataSteamCoils->SteamCoil(CoilNum).TypeOfCoil) {
     337            0 :             case CoilControlType::TemperatureSetPoint:
     338            0 :                 state.dataSteamCoils->SteamCoil(CoilNum).TempSetPointNodeNum = GetOnlySingleNode(state,
     339            0 :                                                                                                  AlphArray(8),
     340              :                                                                                                  ErrorsFound,
     341              :                                                                                                  DataLoopNode::ConnectionObjectType::CoilHeatingSteam,
     342            0 :                                                                                                  AlphArray(1),
     343              :                                                                                                  DataLoopNode::NodeFluidType::Air,
     344              :                                                                                                  DataLoopNode::ConnectionType::Sensor,
     345              :                                                                                                  NodeInputManager::CompFluidStream::Primary,
     346              :                                                                                                  ObjectIsNotParent);
     347            0 :                 if (state.dataSteamCoils->SteamCoil(CoilNum).TempSetPointNodeNum == 0) {
     348            0 :                     ShowSevereError(state, format("{}{} not found for {} = {}", RoutineName, cAlphaFields(8), CurrentModuleObject, AlphArray(1)));
     349            0 :                     ShowContinueError(state, "..required for Temperature Setpoint Controlled Coils.");
     350            0 :                     ErrorsFound = true;
     351              :                 }
     352            0 :                 break;
     353            2 :             case CoilControlType::ZoneLoadControl:
     354            2 :                 if (!lAlphaBlanks(8)) {
     355            0 :                     ShowWarningError(state, format("{}ZoneLoad Controlled Coil, so {} not needed", RoutineName, cAlphaFields(8)));
     356            0 :                     ShowContinueError(state, format("for {} = {}", CurrentModuleObject, AlphArray(1)));
     357            0 :                     state.dataSteamCoils->SteamCoil(CoilNum).TempSetPointNodeNum = 0;
     358              :                 }
     359            2 :                 break;
     360            0 :             default:
     361            0 :                 ShowSevereError(
     362              :                     state,
     363            0 :                     format("{}Invalid {} [{}] specified for {} = {}", RoutineName, cAlphaFields(7), AlphArray(7), CurrentModuleObject, AlphArray(1)));
     364            0 :                 ErrorsFound = true;
     365              :             }
     366              : 
     367            4 :             TestCompSet(state, CurrentModuleObject, AlphArray(1), AlphArray(3), AlphArray(4), "Steam Nodes");
     368            2 :             TestCompSet(state, CurrentModuleObject, AlphArray(1), AlphArray(5), AlphArray(6), "Air Nodes");
     369              : 
     370            2 :             state.dataSteamCoils->SteamCoil(CoilNum).steam = Fluid::GetSteam(state);
     371            2 :             if (state.dataSteamCoils->SteamCoil(CoilNum).steam == nullptr && CoilNum == 1) {
     372            0 :                 ShowSevereError(state, format("{}Steam Properties for {} not found.", RoutineName, AlphArray(1)));
     373            0 :                 ShowContinueError(state, "Steam Fluid Properties should have been included in the input file.");
     374            0 :                 ErrorsFound = true;
     375              :             }
     376            2 :         }
     377              : 
     378            4 :         for (CoilNum = 1; CoilNum <= NumStmHeat; ++CoilNum) {
     379              : 
     380              :             // Setup the Simple Heating Coil reporting variables
     381              :             // CurrentModuleObject = "Coil:Heating:Steam"
     382            4 :             SetupOutputVariable(state,
     383              :                                 "Heating Coil Heating Energy",
     384              :                                 Constant::Units::J,
     385            2 :                                 state.dataSteamCoils->SteamCoil(CoilNum).TotSteamHeatingCoilEnergy,
     386              :                                 OutputProcessor::TimeStepType::System,
     387              :                                 OutputProcessor::StoreType::Sum,
     388            2 :                                 state.dataSteamCoils->SteamCoil(CoilNum).Name,
     389              :                                 Constant::eResource::EnergyTransfer,
     390              :                                 OutputProcessor::Group::HVAC,
     391              :                                 OutputProcessor::EndUseCat::HeatingCoils);
     392            4 :             SetupOutputVariable(state,
     393              :                                 "Heating Coil Heating Rate",
     394              :                                 Constant::Units::W,
     395            2 :                                 state.dataSteamCoils->SteamCoil(CoilNum).TotSteamHeatingCoilRate,
     396              :                                 OutputProcessor::TimeStepType::System,
     397              :                                 OutputProcessor::StoreType::Average,
     398            2 :                                 state.dataSteamCoils->SteamCoil(CoilNum).Name);
     399            4 :             SetupOutputVariable(state,
     400              :                                 "Heating Coil Steam Mass Flow Rate",
     401              :                                 Constant::Units::kg_s,
     402            2 :                                 state.dataSteamCoils->SteamCoil(CoilNum).OutletSteamMassFlowRate,
     403              :                                 OutputProcessor::TimeStepType::System,
     404              :                                 OutputProcessor::StoreType::Average,
     405            2 :                                 state.dataSteamCoils->SteamCoil(CoilNum).Name);
     406            4 :             SetupOutputVariable(state,
     407              :                                 "Heating Coil Steam Inlet Temperature",
     408              :                                 Constant::Units::C,
     409            2 :                                 state.dataSteamCoils->SteamCoil(CoilNum).InletSteamTemp,
     410              :                                 OutputProcessor::TimeStepType::System,
     411              :                                 OutputProcessor::StoreType::Average,
     412            2 :                                 state.dataSteamCoils->SteamCoil(CoilNum).Name);
     413            4 :             SetupOutputVariable(state,
     414              :                                 "Heating Coil Steam Outlet Temperature",
     415              :                                 Constant::Units::C,
     416            2 :                                 state.dataSteamCoils->SteamCoil(CoilNum).OutletSteamTemp,
     417              :                                 OutputProcessor::TimeStepType::System,
     418              :                                 OutputProcessor::StoreType::Average,
     419            2 :                                 state.dataSteamCoils->SteamCoil(CoilNum).Name);
     420            4 :             SetupOutputVariable(state,
     421              :                                 "Heating Coil Steam Trap Loss Rate",
     422              :                                 Constant::Units::W,
     423            2 :                                 state.dataSteamCoils->SteamCoil(CoilNum).LoopLoss,
     424              :                                 OutputProcessor::TimeStepType::System,
     425              :                                 OutputProcessor::StoreType::Average,
     426            2 :                                 state.dataSteamCoils->SteamCoil(CoilNum).Name);
     427              :         }
     428              : 
     429            2 :         if (ErrorsFound) {
     430            0 :             ShowFatalError(state, format("{}Errors found in getting input.", RoutineName));
     431              :         }
     432              : 
     433            2 :         AlphArray.deallocate();
     434            2 :         cAlphaFields.deallocate();
     435            2 :         cNumericFields.deallocate();
     436            2 :         NumArray.deallocate();
     437            2 :         lAlphaBlanks.deallocate();
     438            2 :         lNumericBlanks.deallocate();
     439            2 :     }
     440              : 
     441              :     // End of Get Input subroutines for the HB Module
     442              : 
     443              :     // Beginning Initialization Section of the Module
     444              : 
     445            3 :     void InitSteamCoil(EnergyPlusData &state, int const CoilNum, bool const FirstHVACIteration)
     446              :     {
     447              :         // SUBROUTINE INFORMATION:
     448              :         //   AUTHOR         Rahul Chillar
     449              :         //   DATE WRITTEN   Jan 2005
     450              :         //   MODIFIED       na
     451              :         //   RE-ENGINEERED  na
     452              : 
     453              :         // PURPOSE OF THIS SUBROUTINE:
     454              :         // This subroutine is for initializations of the SteamCoil Components.
     455              : 
     456              :         // METHODOLOGY EMPLOYED:
     457              :         // Uses the status flags to trigger initializations.
     458              : 
     459              :         // REFERENCES:
     460              :         // na
     461              : 
     462              :         // Using/Aliasing
     463              :         using PlantUtilities::InitComponentNodes;
     464              : 
     465              :         // Locals
     466              :         // SUBROUTINE ARGUMENT DEFINITIONS:
     467              : 
     468              :         // SUBROUTINE PARAMETER DEFINITIONS:
     469              :         static constexpr std::string_view RoutineName("InitSteamCoil");
     470              : 
     471              :         // INTERFACE BLOCK SPECIFICATIONS
     472              :         // na
     473              : 
     474              :         // DERIVED TYPE DEFINITIONS
     475              :         // na
     476              : 
     477              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     478              :         int AirInletNode;
     479              :         int SteamInletNode;
     480              :         int ControlNode;
     481              :         int AirOutletNode;
     482              :         Real64 SteamDensity;
     483              :         Real64 StartEnthSteam;
     484              :         bool errFlag;
     485              : 
     486            3 :         if (state.dataSteamCoils->MyOneTimeFlag) {
     487              :             // initialize the environment and sizing flags
     488            2 :             state.dataSteamCoils->MyEnvrnFlag.dimension(state.dataSteamCoils->NumSteamCoils, true);
     489            2 :             state.dataSteamCoils->MySizeFlag.dimension(state.dataSteamCoils->NumSteamCoils, true);
     490            2 :             state.dataSteamCoils->CoilWarningOnceFlag.dimension(state.dataSteamCoils->NumSteamCoils, true);
     491            2 :             state.dataSteamCoils->MyPlantScanFlag.dimension(state.dataSteamCoils->NumSteamCoils, true);
     492            2 :             state.dataSteamCoils->MyOneTimeFlag = false;
     493              :         }
     494              : 
     495            3 :         if (state.dataSteamCoils->MyPlantScanFlag(CoilNum) && allocated(state.dataPlnt->PlantLoop)) {
     496            2 :             errFlag = false;
     497            4 :             ScanPlantLoopsForObject(state,
     498            2 :                                     state.dataSteamCoils->SteamCoil(CoilNum).Name,
     499            2 :                                     state.dataSteamCoils->SteamCoil(CoilNum).CoilType,
     500            2 :                                     state.dataSteamCoils->SteamCoil(CoilNum).plantLoc,
     501              :                                     errFlag,
     502              :                                     _,
     503              :                                     _,
     504              :                                     _,
     505              :                                     _,
     506              :                                     _);
     507            2 :             if (errFlag) {
     508            0 :                 ShowFatalError(state, "InitSteamCoil: Program terminated for previous conditions.");
     509              :             }
     510            2 :             state.dataSteamCoils->MyPlantScanFlag(CoilNum) = false;
     511              :         }
     512              : 
     513            3 :         if (!state.dataGlobal->SysSizingCalc && state.dataSteamCoils->MySizeFlag(CoilNum)) {
     514              :             // for each coil, do the sizing once.
     515            1 :             SizeSteamCoil(state, CoilNum);
     516            1 :             state.dataSteamCoils->MySizeFlag(CoilNum) = false;
     517              :         }
     518              : 
     519              :         // Do the Begin Environment initializations
     520            3 :         if (state.dataGlobal->BeginEnvrnFlag && state.dataSteamCoils->MyEnvrnFlag(CoilNum)) {
     521              :             // Initialize all report variables to a known state at beginning of simulation
     522            2 :             state.dataSteamCoils->SteamCoil(CoilNum).TotSteamHeatingCoilEnergy = 0.0;
     523            2 :             state.dataSteamCoils->SteamCoil(CoilNum).TotSteamCoolingCoilEnergy = 0.0;
     524            2 :             state.dataSteamCoils->SteamCoil(CoilNum).SenSteamCoolingCoilEnergy = 0.0;
     525            2 :             state.dataSteamCoils->SteamCoil(CoilNum).TotSteamHeatingCoilRate = 0.0;
     526            2 :             state.dataSteamCoils->SteamCoil(CoilNum).TotSteamCoolingCoilRate = 0.0;
     527            2 :             state.dataSteamCoils->SteamCoil(CoilNum).SenSteamCoolingCoilRate = 0.0;
     528              :             // Initialize other module level variables
     529            2 :             state.dataSteamCoils->SteamCoil(CoilNum).InletAirMassFlowRate = 0.0;
     530            2 :             state.dataSteamCoils->SteamCoil(CoilNum).OutletAirMassFlowRate = 0.0;
     531            2 :             state.dataSteamCoils->SteamCoil(CoilNum).InletAirTemp = 0.0;
     532            2 :             state.dataSteamCoils->SteamCoil(CoilNum).OutletAirTemp = 0.0;
     533            2 :             state.dataSteamCoils->SteamCoil(CoilNum).InletAirHumRat = 0.0;
     534            2 :             state.dataSteamCoils->SteamCoil(CoilNum).OutletAirHumRat = 0.0;
     535            2 :             state.dataSteamCoils->SteamCoil(CoilNum).InletAirEnthalpy = 0.0;
     536            2 :             state.dataSteamCoils->SteamCoil(CoilNum).OutletAirEnthalpy = 0.0;
     537            2 :             state.dataSteamCoils->SteamCoil(CoilNum).TotSteamCoilLoad = 0.0;
     538            2 :             state.dataSteamCoils->SteamCoil(CoilNum).SenSteamCoilLoad = 0.0;
     539            2 :             state.dataSteamCoils->SteamCoil(CoilNum).LoopLoss = 0.0;
     540            2 :             state.dataSteamCoils->SteamCoil(CoilNum).LeavingRelHum = 0.0;
     541            2 :             state.dataSteamCoils->SteamCoil(CoilNum).DesiredOutletTemp = 0.0;
     542            2 :             state.dataSteamCoils->SteamCoil(CoilNum).DesiredOutletHumRat = 0.0;
     543            2 :             state.dataSteamCoils->SteamCoil(CoilNum).InletSteamTemp = 0.0;
     544            2 :             state.dataSteamCoils->SteamCoil(CoilNum).OutletSteamTemp = 0.0;
     545            2 :             state.dataSteamCoils->SteamCoil(CoilNum).InletSteamMassFlowRate = 0.0;
     546            2 :             state.dataSteamCoils->SteamCoil(CoilNum).OutletSteamMassFlowRate = 0.0;
     547            2 :             state.dataSteamCoils->SteamCoil(CoilNum).InletSteamEnthalpy = 0.0;
     548            2 :             state.dataSteamCoils->SteamCoil(CoilNum).OutletWaterEnthalpy = 0.0;
     549            2 :             state.dataSteamCoils->SteamCoil(CoilNum).InletSteamPress = 0.0;
     550            2 :             state.dataSteamCoils->SteamCoil(CoilNum).InletSteamQuality = 0.0;
     551            2 :             state.dataSteamCoils->SteamCoil(CoilNum).OutletSteamQuality = 0.0;
     552              : 
     553              :             // More Environment initializations
     554            2 :             AirInletNode = state.dataSteamCoils->SteamCoil(CoilNum).AirInletNodeNum;
     555            2 :             SteamInletNode = state.dataSteamCoils->SteamCoil(CoilNum).SteamInletNodeNum;
     556            2 :             ControlNode = state.dataSteamCoils->SteamCoil(CoilNum).TempSetPointNodeNum;
     557            2 :             AirOutletNode = state.dataSteamCoils->SteamCoil(CoilNum).AirOutletNodeNum;
     558              : 
     559            2 :             state.dataLoopNodes->Node(SteamInletNode).Temp = 100.0;
     560            2 :             state.dataLoopNodes->Node(SteamInletNode).Press = 101325.0;
     561            2 :             auto *steam = Fluid::GetSteam(state);
     562            2 :             SteamDensity = steam->getSatDensity(state, state.dataLoopNodes->Node(SteamInletNode).Temp, 1.0, RoutineName);
     563            2 :             StartEnthSteam = steam->getSatEnthalpy(state, state.dataLoopNodes->Node(SteamInletNode).Temp, 1.0, RoutineName);
     564            2 :             state.dataLoopNodes->Node(SteamInletNode).Enthalpy = StartEnthSteam;
     565            2 :             state.dataLoopNodes->Node(SteamInletNode).Quality = 1.0;
     566            2 :             state.dataLoopNodes->Node(SteamInletNode).HumRat = 0.0;
     567            2 :             state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamMassFlowRate =
     568            2 :                 SteamDensity * state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamVolFlowRate;
     569              :             //     Node(SteamInletNode)%MassFlowRate         = SteamCoil(CoilNum)%MaxSteamMassFlowRate
     570              :             //     Node(SteamInletNode)%MassFlowRateMinAvail = 0.0
     571              :             //     Node(SteamInletNode)%MassFlowRateMaxAvail = SteamCoil(CoilNum)%MaxSteamMassFlowRate
     572            6 :             InitComponentNodes(state,
     573              :                                0.0,
     574            2 :                                state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamMassFlowRate,
     575            2 :                                state.dataSteamCoils->SteamCoil(CoilNum).SteamInletNodeNum,
     576            2 :                                state.dataSteamCoils->SteamCoil(CoilNum).SteamOutletNodeNum);
     577            2 :             state.dataSteamCoils->MyEnvrnFlag(CoilNum) = false;
     578              :         } // End If for the Begin Environment initializations
     579              : 
     580            3 :         if (!state.dataGlobal->BeginEnvrnFlag) {
     581            0 :             state.dataSteamCoils->MyEnvrnFlag(CoilNum) = true;
     582              :         }
     583              : 
     584              :         // Do the Begin Day initializations
     585              :         // NONE
     586              : 
     587              :         // Do the begin HVAC time step initializations
     588              :         // NONE
     589              : 
     590              :         // Do the following initializations (every time step): This should be the info from
     591              :         // the previous components outlets or the node data in this section.
     592              : 
     593            3 :         AirInletNode = state.dataSteamCoils->SteamCoil(CoilNum).AirInletNodeNum;
     594            3 :         SteamInletNode = state.dataSteamCoils->SteamCoil(CoilNum).SteamInletNodeNum;
     595            3 :         ControlNode = state.dataSteamCoils->SteamCoil(CoilNum).TempSetPointNodeNum;
     596            3 :         AirOutletNode = state.dataSteamCoils->SteamCoil(CoilNum).AirOutletNodeNum;
     597              : 
     598              :         // First set the conditions for the air into the coil model
     599              : 
     600              :         // If a temperature setpoint controlled coil must set the desired outlet temp everytime
     601            3 :         if (ControlNode == 0) {
     602            3 :             state.dataSteamCoils->SteamCoil(CoilNum).DesiredOutletTemp = 0.0;
     603            0 :         } else if (ControlNode == AirOutletNode) {
     604            0 :             state.dataSteamCoils->SteamCoil(CoilNum).DesiredOutletTemp = state.dataLoopNodes->Node(ControlNode).TempSetPoint;
     605              :         } else {
     606            0 :             state.dataSteamCoils->SteamCoil(CoilNum).DesiredOutletTemp =
     607            0 :                 state.dataLoopNodes->Node(ControlNode).TempSetPoint -
     608            0 :                 (state.dataLoopNodes->Node(ControlNode).Temp - state.dataLoopNodes->Node(AirOutletNode).Temp);
     609              :         }
     610              : 
     611            3 :         state.dataSteamCoils->SteamCoil(CoilNum).InletAirMassFlowRate = state.dataLoopNodes->Node(AirInletNode).MassFlowRate;
     612            3 :         state.dataSteamCoils->SteamCoil(CoilNum).InletAirTemp = state.dataLoopNodes->Node(AirInletNode).Temp;
     613            3 :         state.dataSteamCoils->SteamCoil(CoilNum).InletAirHumRat = state.dataLoopNodes->Node(AirInletNode).HumRat;
     614            3 :         state.dataSteamCoils->SteamCoil(CoilNum).InletAirEnthalpy = state.dataLoopNodes->Node(AirInletNode).Enthalpy;
     615            3 :         if (FirstHVACIteration) {
     616            3 :             state.dataSteamCoils->SteamCoil(CoilNum).InletSteamMassFlowRate = state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamMassFlowRate;
     617              :         } else {
     618            0 :             state.dataSteamCoils->SteamCoil(CoilNum).InletSteamMassFlowRate = state.dataLoopNodes->Node(SteamInletNode).MassFlowRate;
     619              :         }
     620            3 :         state.dataSteamCoils->SteamCoil(CoilNum).InletSteamTemp = state.dataLoopNodes->Node(SteamInletNode).Temp;
     621            3 :         state.dataSteamCoils->SteamCoil(CoilNum).InletSteamEnthalpy = state.dataLoopNodes->Node(SteamInletNode).Enthalpy;
     622            3 :         state.dataSteamCoils->SteamCoil(CoilNum).InletSteamPress = state.dataLoopNodes->Node(SteamInletNode).Press;
     623            3 :         state.dataSteamCoils->SteamCoil(CoilNum).InletSteamQuality = state.dataLoopNodes->Node(SteamInletNode).Quality;
     624            3 :         state.dataSteamCoils->SteamCoil(CoilNum).TotSteamHeatingCoilRate = 0.0;
     625            3 :         state.dataSteamCoils->SteamCoil(CoilNum).TotSteamCoolingCoilRate = 0.0;
     626            3 :         state.dataSteamCoils->SteamCoil(CoilNum).SenSteamCoolingCoilRate = 0.0;
     627              :         //   Node(SteamInletNode)%MassFlowRateMaxAvail = MIN(Node(SteamInletNode)%MassFlowRateMaxAvail,&
     628              :         //                                                   SteamCoil(CoilNum)%MaxSteamMassFlowRate)
     629            3 :     }
     630              : 
     631            1 :     void SizeSteamCoil(EnergyPlusData &state, int const CoilNum)
     632              :     {
     633              :         // SUBROUTINE INFORMATION:
     634              :         //       AUTHOR         Rahul Chillar
     635              :         //       DATE WRITTEN   Jan 2005
     636              :         //       MODIFIED       na
     637              :         //       RE-ENGINEERED  na
     638              : 
     639              :         // PURPOSE OF THIS SUBROUTINE:
     640              :         // This subroutine is for sizing Steam Coil Components for which flow rates have not been
     641              :         // specified in the input.
     642              : 
     643              :         // METHODOLOGY EMPLOYED:
     644              :         // Obtains flow rates from the zone or system sizing arrays and plant sizing data.
     645              : 
     646              :         // Using/Aliasing
     647              :         using namespace DataSizing;
     648              :         using PlantUtilities::RegisterPlantCompDesignFlow;
     649              : 
     650              :         // SUBROUTINE PARAMETER DEFINITIONS:
     651              :         static constexpr std::string_view RoutineName("SizeSteamCoil");
     652              : 
     653              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     654              :         int PltSizNum;      // do loop index for plant sizing
     655              :         int PltSizSteamNum; // index of plant sizing object for 1st steam loop
     656              :         bool ErrorsFound;   // If errors detected in input
     657              :         Real64 CoilInTemp;
     658              :         Real64 CoilOutTemp;
     659              :         Real64 CoilOutHumRat;
     660              :         Real64 CoilInHumRat;
     661              :         Real64 DesCoilLoad;
     662              :         Real64 DesMassFlow;
     663              :         Real64 DesVolFlow;
     664              :         Real64 MinFlowFrac;
     665              :         Real64 OutAirFrac;
     666            1 :         Real64 TempSteamIn(100.0);
     667              :         Real64 EnthSteamInDry;
     668              :         Real64 EnthSteamOutWet;
     669              :         Real64 LatentHeatSteam;
     670              :         Real64 SteamDensity;
     671              :         Real64 RhoAirStd; // density of air at standard conditions
     672              :         Real64 CpAirStd;  // specific heat of air at std conditions
     673              :         Real64 CpWater;   // specific heat of water (condensed steam)
     674              : 
     675            1 :         std::string CompName;     // component name
     676            1 :         std::string CompType;     // component type
     677            1 :         std::string SizingString; // input field sizing description (e.g., Nominal Capacity)
     678            1 :         bool bPRINT = false;      // TRUE if sizing is reported to output (eio)
     679              :         Real64 TempSize;          // autosized value
     680              : 
     681            1 :         ErrorsFound = false;
     682            1 :         PltSizSteamNum = 0;
     683            1 :         PltSizNum = 0;
     684            1 :         CoilInTemp = 0.0;
     685            1 :         CoilInHumRat = 0.0;
     686            1 :         CoilOutTemp = 0.0;
     687            1 :         DesCoilLoad = 0.0;
     688            1 :         MinFlowFrac = 0.0;
     689            1 :         DesMassFlow = 0.0;
     690            1 :         DesVolFlow = 0.0;
     691            1 :         CpWater = 0.0;
     692            1 :         RhoAirStd = PsyRhoAirFnPbTdbW(state, state.dataEnvrn->StdBaroPress, 20.0, 0.0);
     693            1 :         CpAirStd = PsyCpAirFnW(0.0);
     694            1 :         bool coilWasAutosized(false); // coil report
     695              : 
     696            1 :         auto &OASysEqSizing = state.dataSize->OASysEqSizing;
     697            1 :         auto &TermUnitSizing = state.dataSize->TermUnitSizing;
     698              : 
     699              :         // If this is a steam coil
     700              :         // Find the appropriate steam Plant Sizing object
     701            1 :         if (state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamVolFlowRate == AutoSize) {
     702            1 :             coilWasAutosized = true; // coil report
     703            1 :             PltSizSteamNum = MyPlantSizingIndex(state,
     704              :                                                 "steam heating coil",
     705            1 :                                                 state.dataSteamCoils->SteamCoil(CoilNum).Name,
     706            1 :                                                 state.dataSteamCoils->SteamCoil(CoilNum).SteamInletNodeNum,
     707            1 :                                                 state.dataSteamCoils->SteamCoil(CoilNum).SteamOutletNodeNum,
     708              :                                                 ErrorsFound);
     709              :         }
     710              : 
     711            1 :         if (PltSizSteamNum > 0) {
     712              :             // If this is a central air system heating coil
     713            1 :             if (state.dataSize->CurSysNum > 0) {
     714            0 :                 auto &finalSysSizing = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum);
     715              : 
     716              :                 // If the coil water volume flow rate needs autosizing, then do it
     717            0 :                 if (state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamVolFlowRate == AutoSize) {
     718            0 :                     CheckSysSizing(state, "Coil:Heating:Steam", state.dataSteamCoils->SteamCoil(CoilNum).Name);
     719              : 
     720            0 :                     if (state.dataSteamCoils->SteamCoil(CoilNum).DesiccantRegenerationCoil) {
     721              : 
     722            0 :                         state.dataSize->DataDesicRegCoil = true;
     723            0 :                         state.dataSize->DataDesicDehumNum = state.dataSteamCoils->SteamCoil(CoilNum).DesiccantDehumNum;
     724            0 :                         CompType = state.dataSteamCoils->SteamCoil(CoilNum).SteamCoilType; // this is casting an int to a string
     725            0 :                         CompName = state.dataSteamCoils->SteamCoil(CoilNum).Name;
     726            0 :                         bPRINT = false;
     727            0 :                         HeatingCoilDesAirInletTempSizer sizerHeatingDesInletTemp;
     728            0 :                         bool ErrorsFound = false;
     729            0 :                         sizerHeatingDesInletTemp.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
     730            0 :                         state.dataSize->DataDesInletAirTemp = sizerHeatingDesInletTemp.size(state, DataSizing::AutoSize, ErrorsFound);
     731              : 
     732            0 :                         HeatingCoilDesAirOutletTempSizer sizerHeatingDesOutletTemp;
     733            0 :                         ErrorsFound = false;
     734            0 :                         sizerHeatingDesOutletTemp.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
     735            0 :                         state.dataSize->DataDesOutletAirTemp = sizerHeatingDesOutletTemp.size(state, DataSizing::AutoSize, ErrorsFound);
     736              : 
     737            0 :                         if (state.dataSize->CurOASysNum > 0) {
     738            0 :                             OASysEqSizing(state.dataSize->CurOASysNum).AirFlow = true;
     739            0 :                             OASysEqSizing(state.dataSize->CurOASysNum).AirVolFlow = finalSysSizing.DesOutAirVolFlow;
     740              :                         }
     741            0 :                         TempSize = AutoSize; // reset back
     742            0 :                     }
     743              : 
     744              :                     // Set the duct flow rate
     745            0 :                     switch (state.dataSize->CurDuctType) {
     746            0 :                     case HVAC::AirDuctType::Main:
     747            0 :                         DesVolFlow = finalSysSizing.SysAirMinFlowRat * finalSysSizing.DesMainVolFlow;
     748            0 :                         break;
     749            0 :                     case HVAC::AirDuctType::Cooling:
     750            0 :                         DesVolFlow = finalSysSizing.SysAirMinFlowRat * finalSysSizing.DesCoolVolFlow;
     751            0 :                         break;
     752            0 :                     case HVAC::AirDuctType::Heating:
     753            0 :                         DesVolFlow = finalSysSizing.DesHeatVolFlow;
     754            0 :                         break;
     755            0 :                     case HVAC::AirDuctType::Other:
     756            0 :                         DesVolFlow = finalSysSizing.DesMainVolFlow;
     757            0 :                         break;
     758            0 :                     default:
     759            0 :                         DesVolFlow = finalSysSizing.DesMainVolFlow;
     760              :                     }
     761            0 :                     if (state.dataSize->DataDesicRegCoil) {
     762            0 :                         bPRINT = false;
     763            0 :                         TempSize = AutoSize;
     764            0 :                         bool errorsFound = false;
     765            0 :                         HeatingAirFlowSizer sizingHeatingAirFlow;
     766            0 :                         sizingHeatingAirFlow.overrideSizingString(SizingString);
     767              :                         // sizingHeatingAirFlow.setHVACSizingIndexData(FanCoil(FanCoilNum).HVACSizingIndex);
     768            0 :                         sizingHeatingAirFlow.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
     769            0 :                         DesVolFlow = sizingHeatingAirFlow.size(state, TempSize, errorsFound);
     770            0 :                     }
     771            0 :                     DesMassFlow = RhoAirStd * DesVolFlow;
     772              :                     // get the outside air fraction
     773            0 :                     if (finalSysSizing.HeatOAOption == DataSizing::OAControl::MinOA) {
     774            0 :                         if (DesVolFlow > 0.0) {
     775            0 :                             OutAirFrac = finalSysSizing.DesOutAirVolFlow / DesVolFlow;
     776              :                         } else {
     777            0 :                             OutAirFrac = 1.0;
     778              :                         }
     779            0 :                         OutAirFrac = min(1.0, max(0.0, OutAirFrac));
     780              :                     } else {
     781            0 :                         OutAirFrac = 1.0;
     782              :                     }
     783              : 
     784            0 :                     if (state.dataSize->DataDesicRegCoil) {
     785            0 :                         DesCoilLoad = CpAirStd * DesMassFlow * (state.dataSize->DataDesOutletAirTemp - state.dataSize->DataDesInletAirTemp);
     786              :                     } else {
     787              :                         // mixed air temp
     788            0 :                         CoilInTemp = OutAirFrac * finalSysSizing.HeatOutTemp + (1.0 - OutAirFrac) * finalSysSizing.HeatRetTemp;
     789              :                         // coil load
     790            0 :                         DesCoilLoad = CpAirStd * DesMassFlow * (finalSysSizing.HeatSupTemp - CoilInTemp);
     791              :                     }
     792              :                     // AUTOSTEAMCOIL
     793            0 :                     if (DesCoilLoad >= HVAC::SmallLoad) {
     794              :                         // TempSteamIn=SteamCoil(CoilNum)%InletSteamTemp
     795              :                         // TempSteamIn=PlantSizData(PltSizSteamNum)%ExitTemp
     796            0 :                         TempSteamIn = 100.0; // Should be from the PlantSizing object (ExitTemp) instead of hardwired to 100?
     797              :                         // RefrigIndex is set during GetInput for this module
     798            0 :                         EnthSteamInDry = state.dataSteamCoils->SteamCoil(CoilNum).steam->getSatEnthalpy(state, TempSteamIn, 1.0, RoutineName);
     799            0 :                         EnthSteamOutWet = state.dataSteamCoils->SteamCoil(CoilNum).steam->getSatEnthalpy(state, TempSteamIn, 0.0, RoutineName);
     800            0 :                         LatentHeatSteam = EnthSteamInDry - EnthSteamOutWet;
     801            0 :                         SteamDensity = state.dataSteamCoils->SteamCoil(CoilNum).steam->getSatDensity(state, TempSteamIn, 1.0, RoutineName);
     802              :                         // SteamCoil(CoilNum)%MaxSteamVolFlowRate = DesCoilLoad/(SteamDensity * LatentHeatSteam)
     803              :                         //            CpWater  =  GetSpecificHeatGlycol('WATER',  &
     804              :                         //                                              TempSteamIn, &
     805              :                         //                                              PlantLoop(SteamCoil(CoilNum)%LoopNum)%FluidIndex, &
     806              :                         //                                             'SizeSteamCoil')
     807            0 :                         CpWater = state.dataSteamCoils->SteamCoil(CoilNum).steam->getSatSpecificHeat(state, TempSteamIn, 0.0, RoutineName);
     808              : 
     809            0 :                         state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamVolFlowRate =
     810            0 :                             DesCoilLoad / (SteamDensity * (LatentHeatSteam + state.dataSteamCoils->SteamCoil(CoilNum).DegOfSubcooling * CpWater));
     811              :                         //             PlantSizData(PltSizSteamNum)%DeltaT*CPHW(PlantSizData(PltSizSteamNum)%ExitTemp)))
     812              :                     } else {
     813            0 :                         state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamVolFlowRate = 0.0;
     814            0 :                         ShowWarningError(
     815            0 :                             state, format("The design coil load is zero for COIL:Heating:Steam {}", state.dataSteamCoils->SteamCoil(CoilNum).Name));
     816              :                     }
     817            0 :                     BaseSizer::reportSizerOutput(state,
     818              :                                                  "Coil:Heating:Steam",
     819            0 :                                                  state.dataSteamCoils->SteamCoil(CoilNum).Name,
     820              :                                                  "Maximum Steam Flow Rate [m3/s]",
     821            0 :                                                  state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamVolFlowRate);
     822              :                 }
     823            0 :                 state.dataSize->DataDesicRegCoil = false; // reset all globals to 0 to ensure correct sizing for other child components
     824              :                 // Coil report, set fan info for airloopnum
     825              : 
     826            0 :                 if (state.dataAirSystemsData->PrimaryAirSystems(state.dataSize->CurSysNum).supFanNum > 0) {
     827            0 :                     state.dataRptCoilSelection->coilSelectionReportObj->setCoilSupplyFanInfo(
     828              :                         state,
     829            0 :                         state.dataSteamCoils->SteamCoil(CoilNum).Name,
     830              :                         "Coil:Heating:Steam",
     831            0 :                         state.dataFans->fans(state.dataAirSystemsData->PrimaryAirSystems(state.dataSize->CurSysNum).supFanNum)->Name,
     832            0 :                         state.dataFans->fans(state.dataAirSystemsData->PrimaryAirSystems(state.dataSize->CurSysNum).supFanNum)->type,
     833            0 :                         state.dataAirSystemsData->PrimaryAirSystems(state.dataSize->CurSysNum).supFanNum);
     834              :                 }
     835              : 
     836              :                 // if this is a zone coil
     837            1 :             } else if (state.dataSize->CurZoneEqNum > 0) {
     838            1 :                 CheckZoneSizing(state, "Coil:Heating:Steam", state.dataSteamCoils->SteamCoil(CoilNum).Name);
     839              :                 // autosize the coil steam volume flow rate if needed
     840            1 :                 if (state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamVolFlowRate == AutoSize) {
     841              :                     // if coil is part of a terminal unit just use the terminal unit value
     842            1 :                     if (state.dataSize->TermUnitSingDuct || state.dataSize->TermUnitPIU || state.dataSize->TermUnitIU) {
     843            0 :                         if (state.dataSize->CurTermUnitSizingNum > 0) {
     844            0 :                             state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamVolFlowRate =
     845            0 :                                 TermUnitSizing(state.dataSize->CurTermUnitSizingNum).MaxSTVolFlow;
     846              :                         } else {
     847            0 :                             state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamVolFlowRate = 0.0;
     848              :                         }
     849              :                         // if coil is part of a zonal unit, calc coil load to get hot Steam flow rate
     850            0 :                         DesCoilLoad = TermUnitSizing(state.dataSize->CurTermUnitSizingNum).DesHeatingLoad; // coil report
     851            0 :                         DesVolFlow = TermUnitSizing(state.dataSize->CurTermUnitSizingNum).AirVolFlow *
     852            0 :                                      TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatAirFlowMult; // coil report
     853              :                     } else {
     854            1 :                         CoilInTemp = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).DesHeatCoilInTemp;
     855            1 :                         CoilOutTemp = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).HeatDesTemp;
     856            1 :                         CoilOutHumRat = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).HeatDesHumRat;
     857            1 :                         DesMassFlow = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).DesHeatMassFlow;
     858            1 :                         DesVolFlow = DesMassFlow / RhoAirStd;
     859            1 :                         DesCoilLoad = PsyCpAirFnW(CoilOutHumRat) * DesMassFlow * (CoilOutTemp - CoilInTemp);
     860            1 :                         if (DesCoilLoad >= HVAC::SmallLoad) {
     861            1 :                             TempSteamIn = 100.0;
     862              :                             // RefrigIndex is set during GetInput for this module
     863            1 :                             EnthSteamInDry = state.dataSteamCoils->SteamCoil(CoilNum).steam->getSatEnthalpy(state, TempSteamIn, 1.0, RoutineName);
     864            1 :                             EnthSteamOutWet = state.dataSteamCoils->SteamCoil(CoilNum).steam->getSatEnthalpy(state, TempSteamIn, 0.0, RoutineName);
     865            1 :                             LatentHeatSteam = EnthSteamInDry - EnthSteamOutWet;
     866            1 :                             SteamDensity = state.dataSteamCoils->SteamCoil(CoilNum).steam->getSatDensity(state, TempSteamIn, 1.0, RoutineName);
     867              :                             // SteamCoil(CoilNum)%MaxSteamVolFlowRate = DesCoilLoad/(SteamDensity * LatentHeatSteam)
     868              :                             //           CpWater  =  GetSpecificHeatGlycol('WATER',  &
     869              :                             //                                             TempSteamIn, &
     870              :                             //                                             PlantLoop(SteamCoil(CoilNum)%LoopNum)%FluidIndex, &
     871              :                             //                                            'SizeSteamCoil')
     872            1 :                             CpWater = state.dataSteamCoils->SteamCoil(CoilNum).steam->getSatSpecificHeat(state, TempSteamIn, 0.0, RoutineName);
     873              : 
     874            1 :                             state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamVolFlowRate =
     875            1 :                                 DesCoilLoad / (SteamDensity * (LatentHeatSteam + state.dataSteamCoils->SteamCoil(CoilNum).DegOfSubcooling * CpWater));
     876              :                             //             PlantSizData(PltSizSteamNum)%DeltaT*CPHW(PlantSizData(PltSizSteamNum)%ExitTemp)))
     877              :                         } else {
     878            0 :                             state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamVolFlowRate = 0.0;
     879              :                         }
     880              :                     }
     881              :                     // issue warning if hw coil has zero flow
     882            1 :                     if (state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamVolFlowRate == 0.0) {
     883            0 :                         ShowWarningError(
     884            0 :                             state, format("The design coil load is zero for COIL:Heating:Steam {}", state.dataSteamCoils->SteamCoil(CoilNum).Name));
     885            0 :                         ShowContinueError(state, "The autosize value for max Steam flow rate is zero");
     886              :                     }
     887            2 :                     BaseSizer::reportSizerOutput(state,
     888              :                                                  "Coil:Heating:Steam",
     889            1 :                                                  state.dataSteamCoils->SteamCoil(CoilNum).Name,
     890              :                                                  "Maximum Steam Flow Rate [m3/s]",
     891            1 :                                                  state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamVolFlowRate);
     892              :                 }
     893              :             } // end zone coil ELSE - IF
     894              : 
     895              :         } else {
     896              :             // if there is no heating Plant Sizing object and autosizng was requested, issue an error message
     897            0 :             if (state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamVolFlowRate == AutoSize) {
     898            0 :                 ShowSevereError(state, "Autosizing of Steam coil requires a heating loop Sizing:Plant object");
     899            0 :                 ShowContinueError(state, format("Occurs in Steam coil object= {}", state.dataSteamCoils->SteamCoil(CoilNum).Name));
     900            0 :                 ErrorsFound = true;
     901              :             }
     902              :         } // end of heating Plant Sizing existence IF - ELSE
     903              : 
     904              :         // save the design Steam volumetric flow rate for use by the Steam loop sizing algorithms
     905            2 :         RegisterPlantCompDesignFlow(
     906            1 :             state, state.dataSteamCoils->SteamCoil(CoilNum).SteamInletNodeNum, state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamVolFlowRate);
     907              : 
     908            4 :         state.dataRptCoilSelection->coilSelectionReportObj->setCoilHeatingCapacity(state,
     909            1 :                                                                                    state.dataSteamCoils->SteamCoil(CoilNum).Name,
     910              :                                                                                    "Coil:Heating:Steam",
     911              :                                                                                    DesCoilLoad,
     912              :                                                                                    coilWasAutosized,
     913            1 :                                                                                    state.dataSize->CurSysNum,
     914            1 :                                                                                    state.dataSize->CurZoneEqNum,
     915            1 :                                                                                    state.dataSize->CurOASysNum,
     916              :                                                                                    0.0,
     917              :                                                                                    1.0,
     918              :                                                                                    -999.0,
     919              :                                                                                    -999.0);
     920            3 :         state.dataRptCoilSelection->coilSelectionReportObj->setCoilWaterFlowNodeNums(state,
     921            1 :                                                                                      state.dataSteamCoils->SteamCoil(CoilNum).Name,
     922              :                                                                                      "Coil:Heating:Steam",
     923            1 :                                                                                      state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamVolFlowRate,
     924              :                                                                                      coilWasAutosized,
     925            1 :                                                                                      state.dataSteamCoils->SteamCoil(CoilNum).SteamInletNodeNum,
     926            1 :                                                                                      state.dataSteamCoils->SteamCoil(CoilNum).SteamOutletNodeNum,
     927            1 :                                                                                      state.dataSteamCoils->SteamCoil(CoilNum).plantLoc.loopNum);
     928            3 :         state.dataRptCoilSelection->coilSelectionReportObj->setCoilWaterHeaterCapacityNodeNums(
     929              :             state,
     930            1 :             state.dataSteamCoils->SteamCoil(CoilNum).Name,
     931              :             "Coil:Heating:Steam",
     932              :             DesCoilLoad,
     933              :             coilWasAutosized,
     934            1 :             state.dataSteamCoils->SteamCoil(CoilNum).SteamInletNodeNum,
     935            1 :             state.dataSteamCoils->SteamCoil(CoilNum).SteamOutletNodeNum,
     936            1 :             state.dataSteamCoils->SteamCoil(CoilNum).plantLoc.loopNum);
     937            3 :         state.dataRptCoilSelection->coilSelectionReportObj->setCoilEntWaterTemp(
     938            1 :             state, state.dataSteamCoils->SteamCoil(CoilNum).Name, "Coil:Heating:Steam", TempSteamIn); // coil  report
     939            3 :         state.dataRptCoilSelection->coilSelectionReportObj->setCoilLvgWaterTemp(
     940              :             state,
     941            1 :             state.dataSteamCoils->SteamCoil(CoilNum).Name,
     942              :             "Coil:Heating:Steam",
     943            1 :             TempSteamIn - state.dataSteamCoils->SteamCoil(CoilNum).DegOfSubcooling); // coil report
     944            3 :         state.dataRptCoilSelection->coilSelectionReportObj->setCoilWaterDeltaT(
     945              :             state,
     946            1 :             state.dataSteamCoils->SteamCoil(CoilNum).Name,
     947              :             "Coil:Heating:Steam",
     948            1 :             state.dataSteamCoils->SteamCoil(CoilNum).DegOfSubcooling); // coil report
     949            1 :         state.dataSteamCoils->SteamCoil(CoilNum).DesCoilCapacity = DesCoilLoad;
     950            1 :         state.dataSteamCoils->SteamCoil(CoilNum).DesAirVolFlow = DesVolFlow;
     951            1 :         if (ErrorsFound) {
     952            0 :             ShowFatalError(state, "Preceding Steam coil sizing errors cause program termination");
     953              :         }
     954              : 
     955              :         // There is no standard rating for heating coils at this point, so fill with dummy flag values
     956            3 :         state.dataRptCoilSelection->coilSelectionReportObj->setRatedCoilConditions(state,
     957            1 :                                                                                    state.dataSteamCoils->SteamCoil(CoilNum).Name,
     958              :                                                                                    "Coil:Heating:Steam",
     959              :                                                                                    -999.0,
     960              :                                                                                    -999.0,
     961              :                                                                                    -999.0,
     962              :                                                                                    -999.0,
     963              :                                                                                    -999.0,
     964              :                                                                                    -999.0,
     965              :                                                                                    -999.0,
     966              :                                                                                    -999.0,
     967              :                                                                                    -999.0,
     968              :                                                                                    -999.0,
     969              :                                                                                    -999.0,
     970              :                                                                                    -999.0,
     971              :                                                                                    -999.0);
     972            1 :     }
     973              : 
     974              :     // End Initialization Section of the Module
     975              : 
     976              :     // Begin Algorithm Section of the Module
     977              : 
     978            3 :     void CalcSteamAirCoil(EnergyPlusData &state,
     979              :                           int const CoilNum,
     980              :                           Real64 const QCoilRequested, // requested coil load
     981              :                           Real64 &QCoilActual,         // coil load actually delivered
     982              :                           HVAC::FanOp const fanOp,     // fan operating mode
     983              :                           Real64 const PartLoadRatio   // part-load ratio of heating coil
     984              :     )
     985              :     {
     986              :         // SUBROUTINE INFORMATION:
     987              :         //   AUTHOR         Rahul Chillar
     988              :         //   DATE WRITTEN   Jan 2005
     989              :         //   MODIFIED       Sep. 2012, B. Griffith, add calls to SetComponentFlowRate for plant interactions
     990              :         //                  Jul. 2016, R. Zhang, Applied the coil supply air temperature sensor offset fault model
     991              :         //   RE-ENGINEERED  na
     992              : 
     993              :         // PURPOSE OF THIS SUBROUTINE:
     994              :         // Simple Steam to air heat exchanger which,
     995              :         // serves as an interface for distributing heat from boiler to zones.
     996              : 
     997              :         // METHODOLOGY EMPLOYED:
     998              :         // Steam coils are different, All of steam condenses in heat exchanger
     999              :         // Steam traps allow only water to leave the coil,the degree of subcooling
    1000              :         // desired is input by the user, which is used to calculate water outlet temp.
    1001              :         // Heat exchange is = Latent Heat + Sensible heat,coil effectivness is 1.0
    1002              : 
    1003              :         using HVAC::TempControlTol;
    1004              :         using PlantUtilities::SetComponentFlowRate;
    1005              : 
    1006              :         static constexpr std::string_view RoutineName("CalcSteamAirCoil");
    1007              :         static constexpr std::string_view RoutineNameSizeSteamCoil("SizeSteamCoil");
    1008              : 
    1009            3 :         Real64 SteamMassFlowRate(0.0);
    1010            3 :         Real64 AirMassFlow(0.0); // [kg/sec]
    1011            3 :         Real64 TempAirIn(0.0);   // [C]
    1012            3 :         Real64 TempAirOut(0.0);  // [C]
    1013            3 :         Real64 Win(0.0);
    1014            3 :         Real64 TempSteamIn(0.0);
    1015            3 :         Real64 TempWaterOut(0.0);
    1016            3 :         Real64 CapacitanceAir(0.0);
    1017            3 :         Real64 HeatingCoilLoad(0.0);
    1018            3 :         Real64 CoilPress(0.0);
    1019            3 :         Real64 EnthSteamInDry(0.0);
    1020            3 :         Real64 EnthSteamOutWet(0.0);
    1021            3 :         Real64 LatentHeatSteam(0.0);
    1022            3 :         Real64 SubcoolDeltaTemp(0.0);
    1023            3 :         Real64 TempSetPoint(0.0);
    1024            3 :         Real64 QCoilReq(0.0);
    1025            3 :         Real64 QCoilCap(0.0);
    1026            3 :         Real64 QSteamCoilMaxHT(0.0);
    1027            3 :         Real64 TempWaterAtmPress(0.0);
    1028            3 :         Real64 TempLoopOutToPump(0.0);
    1029            3 :         Real64 EnergyLossToEnvironment(0.0);
    1030            3 :         Real64 EnthCoilOutlet(0.0);
    1031            3 :         Real64 EnthPumpInlet(0.0);
    1032            3 :         Real64 EnthAtAtmPress(0.0);
    1033            3 :         Real64 CpWater(0.0);
    1034              : 
    1035            3 :         QCoilReq = QCoilRequested;
    1036            3 :         TempAirIn = state.dataSteamCoils->SteamCoil(CoilNum).InletAirTemp;
    1037            3 :         Win = state.dataSteamCoils->SteamCoil(CoilNum).InletAirHumRat;
    1038            3 :         TempSteamIn = state.dataSteamCoils->SteamCoil(CoilNum).InletSteamTemp;
    1039            3 :         CoilPress = state.dataSteamCoils->SteamCoil(CoilNum).InletSteamPress;
    1040            3 :         SubcoolDeltaTemp = state.dataSteamCoils->SteamCoil(CoilNum).DegOfSubcooling;
    1041            3 :         TempSetPoint = state.dataSteamCoils->SteamCoil(CoilNum).DesiredOutletTemp;
    1042              : 
    1043              :         // If there is a fault of coil SAT Sensor
    1044            3 :         if (state.dataSteamCoils->SteamCoil(CoilNum).FaultyCoilSATFlag && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) &&
    1045            0 :             (!state.dataGlobal->KickOffSimulation)) {
    1046              :             // calculate the sensor offset using fault information
    1047            0 :             int FaultIndex = state.dataSteamCoils->SteamCoil(CoilNum).FaultyCoilSATIndex;
    1048            0 :             state.dataSteamCoils->SteamCoil(CoilNum).FaultyCoilSATOffset =
    1049            0 :                 state.dataFaultsMgr->FaultsCoilSATSensor(FaultIndex).CalFaultOffsetAct(state);
    1050              :             // update the TempSetPoint
    1051            0 :             TempSetPoint -= state.dataSteamCoils->SteamCoil(CoilNum).FaultyCoilSATOffset;
    1052              :         }
    1053              : 
    1054              :         //  adjust mass flow rates for cycling fan cycling coil operation
    1055            3 :         if (fanOp == HVAC::FanOp::Cycling) {
    1056            0 :             if (PartLoadRatio > 0.0) {
    1057            0 :                 AirMassFlow = state.dataSteamCoils->SteamCoil(CoilNum).InletAirMassFlowRate / PartLoadRatio;
    1058            0 :                 SteamMassFlowRate = min(state.dataSteamCoils->SteamCoil(CoilNum).InletSteamMassFlowRate / PartLoadRatio,
    1059            0 :                                         state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamMassFlowRate);
    1060            0 :                 QCoilReq /= PartLoadRatio;
    1061              :             } else {
    1062            0 :                 AirMassFlow = 0.0;
    1063            0 :                 SteamMassFlowRate = 0.0;
    1064              :             }
    1065              :         } else {
    1066            3 :             AirMassFlow = state.dataSteamCoils->SteamCoil(CoilNum).InletAirMassFlowRate;
    1067            3 :             SteamMassFlowRate = state.dataSteamCoils->SteamCoil(CoilNum).InletSteamMassFlowRate;
    1068              :         }
    1069              : 
    1070            3 :         if (AirMassFlow > 0.0) { // If the coil is operating
    1071            2 :             CapacitanceAir = PsyCpAirFnW(Win) * AirMassFlow;
    1072              :         } else {
    1073            1 :             CapacitanceAir = 0.0;
    1074              :         }
    1075              : 
    1076              :         // If the coil is operating there should be some heating capacitance
    1077              :         //  across the coil, so do the simulation. If not set outlet to inlet and no load.
    1078              :         //  Also the coil has to be scheduled to be available
    1079              :         //  Control output to meet load QCoilReq. Load Controlled Coil.
    1080            3 :         switch (state.dataSteamCoils->SteamCoil(CoilNum).TypeOfCoil) {
    1081              : 
    1082            3 :         case CoilControlType::ZoneLoadControl:
    1083            4 :             if ((CapacitanceAir > 0.0) && ((state.dataSteamCoils->SteamCoil(CoilNum).InletSteamMassFlowRate) > 0.0) &&
    1084            7 :                 (state.dataSteamCoils->SteamCoil(CoilNum).availSched->getCurrentVal() > 0.0 || state.dataSteamCoils->MySizeFlag(CoilNum)) &&
    1085              :                 (QCoilReq > 0.0)) {
    1086              : 
    1087              :                 // Steam heat exchangers would not have effectivness, since all of the steam is
    1088              :                 // converted to water and only then the steam trap allows it to leave the heat
    1089              :                 // exchanger, subsequently heat exchange is latent heat + subcooling.
    1090            2 :                 EnthSteamInDry = state.dataSteamCoils->SteamCoil(CoilNum).steam->getSatEnthalpy(state, TempSteamIn, 1.0, RoutineName);
    1091            2 :                 EnthSteamOutWet = state.dataSteamCoils->SteamCoil(CoilNum).steam->getSatEnthalpy(state, TempSteamIn, 0.0, RoutineName);
    1092              : 
    1093            2 :                 LatentHeatSteam = EnthSteamInDry - EnthSteamOutWet;
    1094              : 
    1095              :                 //          CpWater = GetSpecificHeatGlycol('WATER',  &
    1096              :                 //                                           TempSteamIn, &
    1097              :                 //                                           PlantLoop(SteamCoil(CoilNum)%LoopNum)%FluidIndex, &
    1098              :                 //                                           'CalcSteamAirCoil')
    1099              : 
    1100            2 :                 CpWater = state.dataSteamCoils->SteamCoil(CoilNum).steam->getSatSpecificHeat(state, TempSteamIn, 0.0, RoutineNameSizeSteamCoil);
    1101              : 
    1102              :                 // Max Heat Transfer
    1103            2 :                 QSteamCoilMaxHT = state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamMassFlowRate * (LatentHeatSteam + SubcoolDeltaTemp * CpWater);
    1104            2 :                 state.dataSteamCoils->SteamCoil(CoilNum).OperatingCapacity = QSteamCoilMaxHT;
    1105              : 
    1106              :                 // Determine the Max coil capacity and check for the same.
    1107            2 :                 if (QCoilReq > QSteamCoilMaxHT) {
    1108            1 :                     QCoilCap = QSteamCoilMaxHT;
    1109              :                 } else {
    1110            1 :                     QCoilCap = QCoilReq;
    1111              :                 }
    1112              : 
    1113              :                 // Steam Mass Flow Rate Required
    1114            2 :                 SteamMassFlowRate = QCoilCap / (LatentHeatSteam + SubcoolDeltaTemp * CpWater);
    1115              : 
    1116            4 :                 SetComponentFlowRate(state,
    1117              :                                      SteamMassFlowRate,
    1118            2 :                                      state.dataSteamCoils->SteamCoil(CoilNum).SteamInletNodeNum,
    1119            2 :                                      state.dataSteamCoils->SteamCoil(CoilNum).SteamOutletNodeNum,
    1120            2 :                                      state.dataSteamCoils->SteamCoil(CoilNum).plantLoc);
    1121              : 
    1122              :                 // recalculate if mass flow rate changed in previous call.
    1123            2 :                 QCoilCap = SteamMassFlowRate * (LatentHeatSteam + SubcoolDeltaTemp * CpWater);
    1124              : 
    1125              :                 // In practice Sensible & Superheated heat transfer is negligible compared to latent part.
    1126              :                 // This is required for outlet water temperature, otherwise it will be saturation temperature.
    1127              :                 // Steam Trap drains off all the Water formed.
    1128              :                 // Here Degree of Subcooling is used to calculate hot water return temperature.
    1129              : 
    1130              :                 // Calculating Water outlet temperature
    1131            2 :                 TempWaterOut = TempSteamIn - SubcoolDeltaTemp;
    1132              : 
    1133              :                 // Total Heat Transfer to air
    1134            2 :                 HeatingCoilLoad = QCoilCap;
    1135              : 
    1136              :                 // Temperature of air at outlet
    1137            2 :                 TempAirOut = TempAirIn + QCoilCap / (AirMassFlow * PsyCpAirFnW(Win));
    1138              : 
    1139            2 :                 state.dataSteamCoils->SteamCoil(CoilNum).OutletSteamMassFlowRate = SteamMassFlowRate;
    1140            2 :                 state.dataSteamCoils->SteamCoil(CoilNum).InletSteamMassFlowRate = SteamMassFlowRate;
    1141              : 
    1142              :                 //************************* Loop Losses *****************************
    1143              :                 // Loop pressure return considerations included in steam coil since the pipes are
    1144              :                 // perfect and do not account for losses.
    1145              :                 // Return water is condensate at atmoshperic pressure
    1146              :                 // Process is considered constant enthalpy expansion
    1147              :                 // No quality function in EnergyPlus hence no option left apart from
    1148              :                 // considering saturated state.
    1149              :                 //              StdBaroPress=101325
    1150              : 
    1151              :                 TempWaterAtmPress =
    1152            2 :                     state.dataSteamCoils->SteamCoil(CoilNum).steam->getSatTemperature(state, state.dataEnvrn->StdBaroPress, RoutineName);
    1153              : 
    1154              :                 // Point 4 at atm - loop delta subcool during return journery back to pump
    1155            2 :                 TempLoopOutToPump = TempWaterAtmPress - state.dataSteamCoils->SteamCoil(CoilNum).LoopSubcoolReturn;
    1156              : 
    1157              :                 // Actual Steam Coil Outlet Enthalpy
    1158            2 :                 EnthCoilOutlet =
    1159            2 :                     state.dataSteamCoils->SteamCoil(CoilNum).steam->getSatEnthalpy(state, TempSteamIn, 0.0, RoutineName) - CpWater * SubcoolDeltaTemp;
    1160              : 
    1161              :                 // Enthalpy at Point 4
    1162            2 :                 EnthAtAtmPress = state.dataSteamCoils->SteamCoil(CoilNum).steam->getSatEnthalpy(state, TempWaterAtmPress, 0.0, RoutineName);
    1163              : 
    1164              :                 // Reported value of coil outlet enthalpy at the node to match the node outlet temperature
    1165            2 :                 CpWater = state.dataSteamCoils->SteamCoil(CoilNum).steam->getSatSpecificHeat(state, TempLoopOutToPump, 0.0, RoutineNameSizeSteamCoil);
    1166              : 
    1167            2 :                 EnthPumpInlet = EnthAtAtmPress - CpWater * state.dataSteamCoils->SteamCoil(CoilNum).LoopSubcoolReturn;
    1168              : 
    1169            2 :                 state.dataSteamCoils->SteamCoil(CoilNum).OutletWaterEnthalpy = EnthPumpInlet;
    1170              : 
    1171              :                 // Point 3-Point 5,
    1172            2 :                 EnergyLossToEnvironment = SteamMassFlowRate * (EnthCoilOutlet - EnthPumpInlet);
    1173              : 
    1174              :                 // Loss to enviornment due to pressure drop
    1175            2 :                 state.dataSteamCoils->SteamCoil(CoilNum).LoopLoss = EnergyLossToEnvironment;
    1176              :                 //************************* Loop Losses *****************************
    1177              :             } else { // Coil is not running.
    1178              : 
    1179            1 :                 TempAirOut = TempAirIn;
    1180            1 :                 TempWaterOut = TempSteamIn;
    1181            1 :                 HeatingCoilLoad = 0.0;
    1182            1 :                 state.dataSteamCoils->SteamCoil(CoilNum).OutletWaterEnthalpy = state.dataSteamCoils->SteamCoil(CoilNum).InletSteamEnthalpy;
    1183            1 :                 state.dataSteamCoils->SteamCoil(CoilNum).OutletSteamMassFlowRate = 0.0;
    1184            1 :                 state.dataSteamCoils->SteamCoil(CoilNum).OutletSteamQuality = 0.0;
    1185            1 :                 state.dataSteamCoils->SteamCoil(CoilNum).LoopLoss = 0.0;
    1186            1 :                 TempLoopOutToPump = TempWaterOut;
    1187              :             }
    1188            3 :             break;
    1189            0 :         case CoilControlType::TemperatureSetPoint:
    1190              :             // Control coil output to meet a Setpoint Temperature.
    1191            0 :             if ((CapacitanceAir > 0.0) && ((state.dataSteamCoils->SteamCoil(CoilNum).InletSteamMassFlowRate) > 0.0) &&
    1192            0 :                 (state.dataSteamCoils->SteamCoil(CoilNum).availSched->getCurrentVal() > 0.0 || state.dataSteamCoils->MySizeFlag(CoilNum)) &&
    1193            0 :                 (std::abs(TempSetPoint - TempAirIn) > TempControlTol)) {
    1194              : 
    1195              :                 // Steam heat exchangers would not have effectivness, since all of the steam is
    1196              :                 // converted to water and only then the steam trap allows it to leave the heat
    1197              :                 // exchanger, subsequently heat exchange is latent heat + subcooling.
    1198            0 :                 EnthSteamInDry = state.dataSteamCoils->SteamCoil(CoilNum).steam->getSatEnthalpy(state, TempSteamIn, 1.0, RoutineName);
    1199            0 :                 EnthSteamOutWet = state.dataSteamCoils->SteamCoil(CoilNum).steam->getSatEnthalpy(state, TempSteamIn, 0.0, RoutineName);
    1200            0 :                 LatentHeatSteam = EnthSteamInDry - EnthSteamOutWet;
    1201              : 
    1202              :                 //          CpWater = GetSpecificHeatGlycol('WATER',  &
    1203              :                 //                                           TempSteamIn, &
    1204              :                 //                                           PlantLoop(SteamCoil(CoilNum)%LoopNum)%FluidIndex, &
    1205              :                 //                                           'CalcSteamAirCoil')
    1206            0 :                 CpWater = state.dataSteamCoils->SteamCoil(CoilNum).steam->getSatSpecificHeat(state, TempSteamIn, 0.0, RoutineNameSizeSteamCoil);
    1207              : 
    1208              :                 // Max Heat Transfer
    1209            0 :                 QSteamCoilMaxHT = state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamMassFlowRate * (LatentHeatSteam + SubcoolDeltaTemp * CpWater);
    1210              : 
    1211              :                 // Coil Load in case of temperature setpoint
    1212            0 :                 QCoilCap = CapacitanceAir * (TempSetPoint - TempAirIn);
    1213              : 
    1214              :                 // Check to see if setpoint above enetering temperature. If not, set
    1215              :                 // output to zero.
    1216            0 :                 if (QCoilCap <= 0.0) {
    1217            0 :                     QCoilCap = 0.0;
    1218            0 :                     TempAirOut = TempAirIn;
    1219              : 
    1220              :                     // Steam Mass Flow Rate Required
    1221            0 :                     SteamMassFlowRate = 0.0;
    1222            0 :                     SetComponentFlowRate(state,
    1223              :                                          SteamMassFlowRate,
    1224            0 :                                          state.dataSteamCoils->SteamCoil(CoilNum).SteamInletNodeNum,
    1225            0 :                                          state.dataSteamCoils->SteamCoil(CoilNum).SteamOutletNodeNum,
    1226            0 :                                          state.dataSteamCoils->SteamCoil(CoilNum).plantLoc);
    1227              :                     // Inlet equal to outlet when not required to run.
    1228            0 :                     TempWaterOut = TempSteamIn;
    1229              : 
    1230              :                     // Total Heat Transfer to air
    1231            0 :                     HeatingCoilLoad = QCoilCap;
    1232              : 
    1233              :                     // The HeatingCoilLoad is the change in the enthalpy of the water
    1234            0 :                     state.dataSteamCoils->SteamCoil(CoilNum).OutletWaterEnthalpy = state.dataSteamCoils->SteamCoil(CoilNum).InletSteamEnthalpy;
    1235              : 
    1236              :                     // Outlet flow rate set to inlet
    1237            0 :                     state.dataSteamCoils->SteamCoil(CoilNum).OutletSteamMassFlowRate = SteamMassFlowRate;
    1238            0 :                     state.dataSteamCoils->SteamCoil(CoilNum).InletSteamMassFlowRate = SteamMassFlowRate;
    1239              : 
    1240            0 :                 } else if (QCoilCap > QSteamCoilMaxHT) {
    1241              :                     // Setting to Maximum Coil Capacity
    1242            0 :                     QCoilCap = QSteamCoilMaxHT;
    1243              : 
    1244              :                     // Temperature of air at outlet
    1245            0 :                     TempAirOut = TempAirIn + QCoilCap / (AirMassFlow * PsyCpAirFnW(Win));
    1246              : 
    1247              :                     // In practice Sensible & Superheated heat transfer is negligible compared to latent part.
    1248              :                     // This is required for outlet water temperature, otherwise it will be saturation temperature.
    1249              :                     // Steam Trap drains off all the Water formed.
    1250              :                     // Here Degree of Subcooling is used to calculate hot water return temperature.
    1251              : 
    1252              :                     // Calculating Water outlet temperature
    1253            0 :                     TempWaterOut = TempSteamIn - SubcoolDeltaTemp;
    1254              : 
    1255              :                     // Steam Mass Flow Rate Required
    1256            0 :                     SteamMassFlowRate = QCoilCap / (LatentHeatSteam + SubcoolDeltaTemp * CpWater);
    1257            0 :                     SetComponentFlowRate(state,
    1258              :                                          SteamMassFlowRate,
    1259            0 :                                          state.dataSteamCoils->SteamCoil(CoilNum).SteamInletNodeNum,
    1260            0 :                                          state.dataSteamCoils->SteamCoil(CoilNum).SteamOutletNodeNum,
    1261            0 :                                          state.dataSteamCoils->SteamCoil(CoilNum).plantLoc);
    1262              : 
    1263              :                     // recalculate in case previous call changed mass flow rate
    1264            0 :                     QCoilCap = SteamMassFlowRate * (LatentHeatSteam + SubcoolDeltaTemp * CpWater);
    1265            0 :                     TempAirOut = TempAirIn + QCoilCap / (AirMassFlow * PsyCpAirFnW(Win));
    1266              : 
    1267              :                     // Total Heat Transfer to air
    1268            0 :                     HeatingCoilLoad = QCoilCap;
    1269              : 
    1270              :                     // The HeatingCoilLoad is the change in the enthalpy of the water
    1271            0 :                     state.dataSteamCoils->SteamCoil(CoilNum).OutletWaterEnthalpy =
    1272            0 :                         state.dataSteamCoils->SteamCoil(CoilNum).InletSteamEnthalpy - HeatingCoilLoad / SteamMassFlowRate;
    1273            0 :                     state.dataSteamCoils->SteamCoil(CoilNum).OutletSteamMassFlowRate = SteamMassFlowRate;
    1274            0 :                     state.dataSteamCoils->SteamCoil(CoilNum).InletSteamMassFlowRate = SteamMassFlowRate;
    1275              : 
    1276              :                 } else {
    1277              :                     // Temp air out is temperature Setpoint
    1278            0 :                     TempAirOut = TempSetPoint;
    1279              : 
    1280              :                     // In practice Sensible & Superheated heat transfer is negligible compared to latent part.
    1281              :                     // This is required for outlet water temperature, otherwise it will be saturation temperature.
    1282              :                     // Steam Trap drains off all the Water formed.
    1283              :                     // Here Degree of Subcooling is used to calculate hot water return temperature.
    1284              : 
    1285              :                     // Calculating Water outlet temperature
    1286            0 :                     TempWaterOut = TempSteamIn - SubcoolDeltaTemp;
    1287              : 
    1288              :                     // Steam Mass Flow Rate Required
    1289            0 :                     SteamMassFlowRate = QCoilCap / (LatentHeatSteam + SubcoolDeltaTemp * CpWater);
    1290            0 :                     SetComponentFlowRate(state,
    1291              :                                          SteamMassFlowRate,
    1292            0 :                                          state.dataSteamCoils->SteamCoil(CoilNum).SteamInletNodeNum,
    1293            0 :                                          state.dataSteamCoils->SteamCoil(CoilNum).SteamOutletNodeNum,
    1294            0 :                                          state.dataSteamCoils->SteamCoil(CoilNum).plantLoc);
    1295              : 
    1296              :                     // recalculate in case previous call changed mass flow rate
    1297            0 :                     QCoilCap = SteamMassFlowRate * (LatentHeatSteam + SubcoolDeltaTemp * CpWater);
    1298            0 :                     TempAirOut = TempAirIn + QCoilCap / (AirMassFlow * PsyCpAirFnW(Win));
    1299              : 
    1300              :                     // Total Heat Transfer to air
    1301            0 :                     HeatingCoilLoad = QCoilCap;
    1302              : 
    1303            0 :                     state.dataSteamCoils->SteamCoil(CoilNum).OutletSteamMassFlowRate = SteamMassFlowRate;
    1304            0 :                     state.dataSteamCoils->SteamCoil(CoilNum).InletSteamMassFlowRate = SteamMassFlowRate;
    1305              : 
    1306              :                     //************************* Loop Losses *****************************
    1307              :                     // Loop pressure return considerations included in steam coil since the pipes are
    1308              :                     // perfect and do not account for losses.
    1309              : 
    1310              :                     // Return water is condensate at atmoshperic pressure
    1311              :                     // Process is considered constant enthalpy expansion
    1312              :                     // No quality function in EnergyPlus hence no option left apart from
    1313              :                     // considering saturated state.
    1314              :                     //              StdBaroPress=101325
    1315              : 
    1316              :                     TempWaterAtmPress =
    1317            0 :                         state.dataSteamCoils->SteamCoil(CoilNum).steam->getSatTemperature(state, state.dataEnvrn->StdBaroPress, RoutineName);
    1318              : 
    1319              :                     // Point 4 at atm - loop delta subcool during return journery back to pump
    1320            0 :                     TempLoopOutToPump = TempWaterAtmPress - state.dataSteamCoils->SteamCoil(CoilNum).LoopSubcoolReturn;
    1321              : 
    1322              :                     // Actual Steam Coil Outlet Enthalpy
    1323            0 :                     EnthCoilOutlet = state.dataSteamCoils->SteamCoil(CoilNum).steam->getSatEnthalpy(state, TempSteamIn, 0.0, RoutineName) -
    1324            0 :                                      CpWater * SubcoolDeltaTemp;
    1325              : 
    1326              :                     // Enthalpy at Point 4
    1327            0 :                     EnthAtAtmPress = state.dataSteamCoils->SteamCoil(CoilNum).steam->getSatEnthalpy(state, TempWaterAtmPress, 0.0, RoutineName);
    1328              : 
    1329              :                     CpWater =
    1330            0 :                         state.dataSteamCoils->SteamCoil(CoilNum).steam->getSatSpecificHeat(state, TempLoopOutToPump, 0.0, RoutineNameSizeSteamCoil);
    1331              : 
    1332              :                     // Reported value of coil outlet enthalpy at the node to match the node outlet temperature
    1333            0 :                     EnthPumpInlet = EnthAtAtmPress - CpWater * state.dataSteamCoils->SteamCoil(CoilNum).LoopSubcoolReturn;
    1334              : 
    1335            0 :                     state.dataSteamCoils->SteamCoil(CoilNum).OutletWaterEnthalpy = EnthPumpInlet;
    1336              : 
    1337              :                     // Point 3-Point 5,
    1338            0 :                     EnergyLossToEnvironment = SteamMassFlowRate * (EnthCoilOutlet - EnthPumpInlet);
    1339              : 
    1340              :                     // Loss to enviornment due to pressure drop
    1341            0 :                     state.dataSteamCoils->SteamCoil(CoilNum).LoopLoss = EnergyLossToEnvironment;
    1342              :                     //************************* Loop Losses *****************************
    1343              :                 }
    1344              : 
    1345              :             } else { // If not running Conditions do not change across coil from inlet to outlet
    1346            0 :                 SteamMassFlowRate = 0.0;
    1347            0 :                 SetComponentFlowRate(state,
    1348              :                                      SteamMassFlowRate,
    1349            0 :                                      state.dataSteamCoils->SteamCoil(CoilNum).SteamInletNodeNum,
    1350            0 :                                      state.dataSteamCoils->SteamCoil(CoilNum).SteamOutletNodeNum,
    1351            0 :                                      state.dataSteamCoils->SteamCoil(CoilNum).plantLoc);
    1352            0 :                 TempAirOut = TempAirIn;
    1353            0 :                 TempWaterOut = TempSteamIn;
    1354            0 :                 HeatingCoilLoad = 0.0;
    1355            0 :                 state.dataSteamCoils->SteamCoil(CoilNum).OutletWaterEnthalpy = state.dataSteamCoils->SteamCoil(CoilNum).InletSteamEnthalpy;
    1356            0 :                 state.dataSteamCoils->SteamCoil(CoilNum).OutletSteamMassFlowRate = 0.0;
    1357            0 :                 state.dataSteamCoils->SteamCoil(CoilNum).OutletSteamQuality = 0.0;
    1358            0 :                 state.dataSteamCoils->SteamCoil(CoilNum).LoopLoss = 0.0;
    1359            0 :                 TempLoopOutToPump = TempWaterOut;
    1360              :             }
    1361            0 :             break;
    1362            0 :         default:
    1363            0 :             assert(false);
    1364              :         }
    1365              : 
    1366            3 :         if (fanOp == HVAC::FanOp::Cycling) {
    1367            0 :             HeatingCoilLoad *= PartLoadRatio;
    1368              :         }
    1369              : 
    1370              :         // Set the outlet conditions
    1371            3 :         state.dataSteamCoils->SteamCoil(CoilNum).TotSteamHeatingCoilRate = HeatingCoilLoad;
    1372            3 :         state.dataSteamCoils->SteamCoil(CoilNum).OutletAirTemp = TempAirOut;
    1373            3 :         state.dataSteamCoils->SteamCoil(CoilNum).OutletSteamTemp = TempLoopOutToPump;
    1374            3 :         state.dataSteamCoils->SteamCoil(CoilNum).OutletSteamQuality = 0.0;
    1375            3 :         QCoilActual = HeatingCoilLoad;
    1376              : 
    1377              :         // This SteamCoil does not change the moisture or Mass Flow across the component
    1378            3 :         state.dataSteamCoils->SteamCoil(CoilNum).OutletAirHumRat = state.dataSteamCoils->SteamCoil(CoilNum).InletAirHumRat;
    1379            3 :         state.dataSteamCoils->SteamCoil(CoilNum).OutletAirMassFlowRate = state.dataSteamCoils->SteamCoil(CoilNum).InletAirMassFlowRate;
    1380              :         // Set the outlet enthalpys for air and water
    1381            3 :         state.dataSteamCoils->SteamCoil(CoilNum).OutletAirEnthalpy =
    1382            3 :             PsyHFnTdbW(state.dataSteamCoils->SteamCoil(CoilNum).OutletAirTemp, state.dataSteamCoils->SteamCoil(CoilNum).OutletAirHumRat);
    1383            3 :     }
    1384              : 
    1385              :     // Beginning of Update subroutines for the SteamCoil Module
    1386              : 
    1387            3 :     void UpdateSteamCoil(EnergyPlusData &state, int const CoilNum)
    1388              :     {
    1389              :         // SUBROUTINE INFORMATION:
    1390              :         //   AUTHOR         Rahul Chillar
    1391              :         //   DATE WRITTEN   Jan 2005
    1392              :         //   MODIFIED       na
    1393              :         //   RE-ENGINEERED  na
    1394              : 
    1395              :         // PURPOSE OF THIS SUBROUTINE:
    1396              :         // This subroutine updates the coil outlet nodes.
    1397              : 
    1398              :         // METHODOLOGY EMPLOYED:
    1399              :         // Data is moved from the coil data structure to the coil outlet nodes.
    1400              : 
    1401              :         using PlantUtilities::SafeCopyPlantNode;
    1402              : 
    1403              :         int AirInletNode;
    1404              :         int SteamInletNode;
    1405              :         int AirOutletNode;
    1406              :         int SteamOutletNode;
    1407              : 
    1408            3 :         AirInletNode = state.dataSteamCoils->SteamCoil(CoilNum).AirInletNodeNum;
    1409            3 :         SteamInletNode = state.dataSteamCoils->SteamCoil(CoilNum).SteamInletNodeNum;
    1410            3 :         AirOutletNode = state.dataSteamCoils->SteamCoil(CoilNum).AirOutletNodeNum;
    1411            3 :         SteamOutletNode = state.dataSteamCoils->SteamCoil(CoilNum).SteamOutletNodeNum;
    1412              : 
    1413              :         // Set the outlet air nodes of the SteamCoil
    1414            3 :         state.dataLoopNodes->Node(AirOutletNode).MassFlowRate = state.dataSteamCoils->SteamCoil(CoilNum).OutletAirMassFlowRate;
    1415            3 :         state.dataLoopNodes->Node(AirOutletNode).Temp = state.dataSteamCoils->SteamCoil(CoilNum).OutletAirTemp;
    1416            3 :         state.dataLoopNodes->Node(AirOutletNode).HumRat = state.dataSteamCoils->SteamCoil(CoilNum).OutletAirHumRat;
    1417            3 :         state.dataLoopNodes->Node(AirOutletNode).Enthalpy = state.dataSteamCoils->SteamCoil(CoilNum).OutletAirEnthalpy;
    1418              : 
    1419            3 :         SafeCopyPlantNode(state, SteamInletNode, SteamOutletNode);
    1420              : 
    1421              :         // Set the outlet Steam nodes for the Coil
    1422              :         //   Node(SteamOutletNode)%MassFlowRate = SteamCoil(CoilNum)%OutletSteamMassFlowRate
    1423            3 :         state.dataLoopNodes->Node(SteamOutletNode).Temp = state.dataSteamCoils->SteamCoil(CoilNum).OutletSteamTemp;
    1424            3 :         state.dataLoopNodes->Node(SteamOutletNode).Enthalpy = state.dataSteamCoils->SteamCoil(CoilNum).OutletWaterEnthalpy;
    1425            3 :         state.dataLoopNodes->Node(SteamOutletNode).Quality = state.dataSteamCoils->SteamCoil(CoilNum).OutletSteamQuality;
    1426              :         // Node(SteamInletNode)%MassFlowRate  = SteamCoil(CoilNum)%OutletSteamMassFlowRate
    1427              : 
    1428              :         // Set the outlet nodes for properties that just pass through & not used
    1429            3 :         state.dataLoopNodes->Node(AirOutletNode).Quality = state.dataLoopNodes->Node(AirInletNode).Quality;
    1430            3 :         state.dataLoopNodes->Node(AirOutletNode).Press = state.dataLoopNodes->Node(AirInletNode).Press;
    1431            3 :         state.dataLoopNodes->Node(AirOutletNode).MassFlowRateMin = state.dataLoopNodes->Node(AirInletNode).MassFlowRateMin;
    1432            3 :         state.dataLoopNodes->Node(AirOutletNode).MassFlowRateMax = state.dataLoopNodes->Node(AirInletNode).MassFlowRateMax;
    1433            3 :         state.dataLoopNodes->Node(AirOutletNode).MassFlowRateMinAvail = state.dataLoopNodes->Node(AirInletNode).MassFlowRateMinAvail;
    1434            3 :         state.dataLoopNodes->Node(AirOutletNode).MassFlowRateMaxAvail = state.dataLoopNodes->Node(AirInletNode).MassFlowRateMaxAvail;
    1435              : 
    1436              :         // Set the outlet nodes for properties that just pass through & not used
    1437              : 
    1438              :         // Node(SteamOutletNode)%Press              = Node(SteamInletNode)%Press
    1439              :         //   Node(SteamOutletNode)%Press               = StdBaroPress  ! Water out at atm pressure
    1440              :         //   Node(SteamOutletNode)%HumRat              = Node(SteamInletNode)%HumRat
    1441              :         //   Node(SteamOutletNode)%MassFlowRateMin     = Node(SteamInletNode)%MassFlowRateMin
    1442              :         //   Node(SteamOutletNode)%MassFlowRateMax     = Node(SteamInletNode)%MassFlowRateMax
    1443              :         //   Node(SteamOutletNode)%MassFlowRateMinAvail= Node(SteamInletNode)%MassFlowRateMinAvail
    1444              :         //   Node(SteamOutletNode)%MassFlowRateMaxAvail= Node(SteamInletNode)%MassFlowRateMaxAvail
    1445              : 
    1446              :         //   IF (SteamCoil(CoilNum)%InletSteamMassFlowRate.EQ.0.0) THEN
    1447              :         //     Node(SteamInletNode)%MassFlowRate         = 0.0
    1448              :         //     Node(SteamInletNode)%MassFlowRateMinAvail = 0.0
    1449              :         //     Node(SteamOutletNode)%MassFlowRateMinAvail= 0.0
    1450              :         //   END IF
    1451              : 
    1452            3 :         if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    1453            0 :             state.dataLoopNodes->Node(AirOutletNode).CO2 = state.dataLoopNodes->Node(AirInletNode).CO2;
    1454              :         }
    1455            3 :         if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    1456            0 :             state.dataLoopNodes->Node(AirOutletNode).GenContam = state.dataLoopNodes->Node(AirInletNode).GenContam;
    1457              :         }
    1458            3 :     }
    1459              : 
    1460              :     // End of Update subroutines for the SteamCoil Module
    1461              : 
    1462              :     // Beginning of Reporting subroutines for the SteamCoil Module
    1463              : 
    1464            3 :     void ReportSteamCoil(EnergyPlusData &state, int const CoilNum)
    1465              :     {
    1466              :         // SUBROUTINE INFORMATION:
    1467              :         //   AUTHOR         Rahul Chillar
    1468              :         //   DATE WRITTEN   Jan 2005
    1469              :         //   MODIFIED       na
    1470              :         //   RE-ENGINEERED  na
    1471              : 
    1472              :         // PURPOSE OF THIS SUBROUTINE:
    1473              :         // This subroutine updates the report variable for the coils.
    1474              : 
    1475              :         // Report the SteamCoil energy from this component
    1476            3 :         state.dataSteamCoils->SteamCoil(CoilNum).TotSteamHeatingCoilEnergy =
    1477            3 :             state.dataSteamCoils->SteamCoil(CoilNum).TotSteamHeatingCoilRate * state.dataHVACGlobal->TimeStepSysSec;
    1478            3 :     }
    1479              : 
    1480              :     // End of Reporting subroutines for the SteamCoil Module
    1481              : 
    1482              :     // Utility subroutines for the SteamCoil Module
    1483              : 
    1484            2 :     int GetSteamCoilIndex(EnergyPlusData &state,
    1485              :                           std::string_view CoilType,   // must match coil types in this module
    1486              :                           std::string const &CoilName, // must match coil names for the coil type
    1487              :                           bool &ErrorsFound            // set to true if problem
    1488              :     )
    1489              :     {
    1490              : 
    1491              :         // FUNCTION INFORMATION:
    1492              :         //       AUTHOR         R. Raustad
    1493              :         //       DATE WRITTEN   August 2007
    1494              :         //       MODIFIED       na
    1495              :         //       RE-ENGINEERED  na
    1496              : 
    1497              :         // PURPOSE OF THIS FUNCTION:
    1498              :         // This function looks up the index for the given coil and returns it.  If
    1499              :         // incorrect coil type or name is given, ErrorsFound is returned as true and node number is returned
    1500              :         // as zero.
    1501              : 
    1502              :         // Return value
    1503              :         int IndexNum; // returned air inlet node number of matched coil
    1504              : 
    1505              :         // Obtains and Allocates SteamCoil related parameters from input file
    1506            2 :         if (state.dataSteamCoils->GetSteamCoilsInputFlag) { // First time subroutine has been entered
    1507            2 :             GetSteamCoilInput(state);
    1508            2 :             state.dataSteamCoils->GetSteamCoilsInputFlag = false;
    1509              :         }
    1510              : 
    1511            2 :         if (CoilType == "COIL:HEATING:STEAM") {
    1512            2 :             IndexNum = Util::FindItemInList(CoilName, state.dataSteamCoils->SteamCoil);
    1513              :         } else {
    1514            0 :             IndexNum = 0;
    1515              :         }
    1516              : 
    1517            2 :         if (IndexNum == 0) {
    1518            0 :             ShowSevereError(state, format(R"(GetSteamCoilIndex: Could not find CoilType="{}" with Name="{}")", CoilType, CoilName));
    1519            0 :             ErrorsFound = true;
    1520              :         }
    1521              : 
    1522            2 :         return IndexNum;
    1523              :     }
    1524              : 
    1525            0 :     int GetCompIndex(EnergyPlusData &state, std::string_view const coilName)
    1526              :     {
    1527            0 :         if (state.dataSteamCoils->GetSteamCoilsInputFlag) { // First time subroutine has been entered
    1528            0 :             GetSteamCoilInput(state);
    1529            0 :             state.dataSteamCoils->GetSteamCoilsInputFlag = false;
    1530              :         }
    1531              : 
    1532            0 :         int indexNum = Util::FindItemInList(coilName, state.dataSteamCoils->SteamCoil);
    1533              : 
    1534            0 :         if (indexNum == 0) { // may not find coil name
    1535            0 :             ShowSevereError(state, format("GetSteamCoilIndex: Could not find CoilType = Coil:Heating:Steam with Name = \"{}\"", coilName));
    1536              :         }
    1537              : 
    1538            0 :         return indexNum;
    1539              :     }
    1540              : 
    1541            0 :     void CheckSteamCoilSchedule(
    1542              :         EnergyPlusData &state, [[maybe_unused]] std::string const &CompType, std::string_view CompName, Real64 &Value, int &CompIndex)
    1543              :     {
    1544              : 
    1545              :         // SUBROUTINE INFORMATION:
    1546              :         //       AUTHOR         Linda Lawrie
    1547              :         //       DATE WRITTEN   March 2006
    1548              :         //       MODIFIED       na
    1549              :         //       RE-ENGINEERED  na
    1550              : 
    1551              :         // PURPOSE OF THIS SUBROUTINE:
    1552              :         // Gets the correct schedule value for this coil
    1553              : 
    1554              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1555              :         int CoilNum;
    1556              : 
    1557              :         // Obtains and Allocates SteamCoil related parameters from input file
    1558            0 :         if (state.dataSteamCoils->GetSteamCoilsInputFlag) { // First time subroutine has been entered
    1559            0 :             GetSteamCoilInput(state);
    1560            0 :             state.dataSteamCoils->GetSteamCoilsInputFlag = false;
    1561              :         }
    1562              : 
    1563              :         // Find the correct Coil number
    1564            0 :         if (CompIndex == 0) {
    1565            0 :             CoilNum = Util::FindItemInList(CompName, state.dataSteamCoils->SteamCoil);
    1566            0 :             if (CoilNum == 0) {
    1567            0 :                 ShowFatalError(state, format("CheckSteamCoilSchedule: Coil not found={}", CompName));
    1568              :             }
    1569            0 :             CompIndex = CoilNum;
    1570            0 :             Value = state.dataSteamCoils->SteamCoil(CoilNum).availSched->getCurrentVal(); // not scheduled?
    1571              :         } else {
    1572            0 :             CoilNum = CompIndex;
    1573            0 :             if (CoilNum > state.dataSteamCoils->NumSteamCoils || CoilNum < 1) {
    1574            0 :                 ShowFatalError(state,
    1575            0 :                                format("SimulateSteamCoilComponents: Invalid CompIndex passed={}, Number of Steam Coils={}, Coil name={}",
    1576              :                                       CoilNum,
    1577            0 :                                       state.dataSteamCoils->NumSteamCoils,
    1578              :                                       CompName));
    1579              :             }
    1580            0 :             if (CompName != state.dataSteamCoils->SteamCoil(CoilNum).Name) {
    1581            0 :                 ShowFatalError(state,
    1582            0 :                                format("SimulateSteamCoilComponents: Invalid CompIndex passed={}, Coil name={}, stored Coil Name for that index={}",
    1583              :                                       CoilNum,
    1584              :                                       CompName,
    1585            0 :                                       state.dataSteamCoils->SteamCoil(CoilNum).Name));
    1586              :             }
    1587            0 :             Value = state.dataSteamCoils->SteamCoil(CoilNum).availSched->getCurrentVal(); // not scheduled?
    1588              :         }
    1589            0 :     }
    1590              : 
    1591            0 :     Real64 GetCoilMaxWaterFlowRate(EnergyPlusData &state,
    1592              :                                    std::string const &CoilType, // must match coil types in this module
    1593              :                                    std::string const &CoilName, // must match coil names for the coil type
    1594              :                                    bool &ErrorsFound            // set to true if problem
    1595              :     )
    1596              :     {
    1597              : 
    1598              :         // FUNCTION INFORMATION:
    1599              :         //       AUTHOR         Linda Lawrie
    1600              :         //       DATE WRITTEN   November 2006
    1601              :         //       MODIFIED       na
    1602              :         //       RE-ENGINEERED  na
    1603              : 
    1604              :         // PURPOSE OF THIS FUNCTION:
    1605              :         // This function looks up the max water flow rate for the given coil and returns it.  If
    1606              :         // incorrect coil type or name is given, ErrorsFound is returned as true and capacity is returned
    1607              :         // as negative.
    1608              : 
    1609              :         // Return value
    1610              :         Real64 MaxWaterFlowRate; // returned max water flow rate of matched coil
    1611              : 
    1612              :         // FUNCTION LOCAL VARIABLE DECLARATIONS:
    1613              :         int WhichCoil;
    1614              : 
    1615              :         // Obtains and Allocates SteamCoil related parameters from input file
    1616            0 :         if (state.dataSteamCoils->GetSteamCoilsInputFlag) { // First time subroutine has been entered
    1617            0 :             GetSteamCoilInput(state);
    1618            0 :             state.dataSteamCoils->GetSteamCoilsInputFlag = false;
    1619              :         }
    1620              : 
    1621            0 :         if (Util::SameString(CoilType, "Coil:Heating:Steam")) {
    1622            0 :             WhichCoil = Util::FindItem(CoilName, state.dataSteamCoils->SteamCoil);
    1623            0 :             if (WhichCoil != 0) {
    1624              :                 // coil does not specify MaxWaterFlowRate
    1625            0 :                 MaxWaterFlowRate = 0.0;
    1626            0 :                 ShowRecurringWarningErrorAtEnd(state, "Requested Max Water Flow Rate from COIL:Heating:Steam N/A", state.dataSteamCoils->ErrCount);
    1627              :             }
    1628              :         } else {
    1629            0 :             WhichCoil = 0;
    1630              :         }
    1631              : 
    1632            0 :         if (WhichCoil == 0) {
    1633            0 :             ShowSevereError(state, format("GetCoilMaxWaterFlowRate: Could not find CoilType=\"{}\" with Name=\"{}\"", CoilType, CoilName));
    1634            0 :             ErrorsFound = true;
    1635            0 :             MaxWaterFlowRate = -1000.0;
    1636              :         }
    1637              : 
    1638            0 :         return MaxWaterFlowRate;
    1639              :     }
    1640              : 
    1641            3 :     Real64 GetCoilMaxSteamFlowRate(EnergyPlusData &state,
    1642              :                                    int const CoilIndex, // must match coil types in this module
    1643              :                                    bool &ErrorsFound    // set to true if problem
    1644              :     )
    1645              :     {
    1646              : 
    1647              :         // FUNCTION INFORMATION:
    1648              :         //       AUTHOR         R. Raustad
    1649              :         //       DATE WRITTEN   August 2007
    1650              :         //       MODIFIED       na
    1651              :         //       RE-ENGINEERED  na
    1652              : 
    1653              :         // PURPOSE OF THIS FUNCTION:
    1654              :         // This function looks up the max steam flow rate for the given coil and returns it.  If
    1655              :         // incorrect coil type or name is given, ErrorsFound is returned as true and flow rate is returned
    1656              :         // as zero.
    1657              : 
    1658              :         // Return value
    1659              :         Real64 MaxSteamFlowRate; // returned max steam flow rate of matched coil
    1660              : 
    1661              :         // Obtains and Allocates SteamCoil related parameters from input file
    1662            3 :         if (state.dataSteamCoils->GetSteamCoilsInputFlag) { // First time subroutine has been entered
    1663            0 :             GetSteamCoilInput(state);
    1664            0 :             state.dataSteamCoils->GetSteamCoilsInputFlag = false;
    1665              :         }
    1666              : 
    1667            3 :         if (CoilIndex == 0) {
    1668            0 :             ShowSevereError(state, "GetCoilMaxSteamFlowRate: Could not find CoilType = \"Coil:Heating:Steam\"");
    1669            0 :             ErrorsFound = true;
    1670            0 :             MaxSteamFlowRate = 0.0;
    1671              :         } else {
    1672            3 :             MaxSteamFlowRate = state.dataSteamCoils->SteamCoil(CoilIndex).MaxSteamVolFlowRate;
    1673              :         }
    1674              : 
    1675            3 :         return MaxSteamFlowRate;
    1676              :     }
    1677              : 
    1678            2 :     int GetCoilAirInletNode(EnergyPlusData &state,
    1679              :                             int const CoilIndex,         // must match coil types in this module
    1680              :                             std::string const &CoilName, // must match coil names for the coil type
    1681              :                             bool &ErrorsFound            // set to true if problem
    1682              :     )
    1683              :     {
    1684              : 
    1685              :         // FUNCTION INFORMATION:
    1686              :         //       AUTHOR         R. Raustad
    1687              :         //       DATE WRITTEN   July 2007
    1688              :         //       MODIFIED       na
    1689              :         //       RE-ENGINEERED  na
    1690              : 
    1691              :         // PURPOSE OF THIS FUNCTION:
    1692              :         // This function looks up the air inlet node number for the given coil and returns it.  If
    1693              :         // incorrect coil type or name is given, ErrorsFound is returned as true and node number is returned
    1694              :         // as zero.
    1695              : 
    1696              :         // Return value
    1697              :         int NodeNumber; // returned air inlet node number of matched coil
    1698              : 
    1699              :         // Obtains and Allocates SteamCoil related parameters from input file
    1700            2 :         if (state.dataSteamCoils->GetSteamCoilsInputFlag) { // First time subroutine has been entered
    1701            0 :             GetSteamCoilInput(state);
    1702            0 :             state.dataSteamCoils->GetSteamCoilsInputFlag = false;
    1703              :         }
    1704              : 
    1705            2 :         if (CoilIndex == 0) {
    1706            0 :             ShowSevereError(state, format("GetCoilAirInletNode: Could not find CoilType = \"Coil:Heating:Steam\" with Name = {}", CoilName));
    1707            0 :             ErrorsFound = true;
    1708            0 :             NodeNumber = 0;
    1709              :         } else {
    1710            2 :             NodeNumber = state.dataSteamCoils->SteamCoil(CoilIndex).AirInletNodeNum;
    1711              :         }
    1712              : 
    1713            2 :         return NodeNumber;
    1714              :     }
    1715              : 
    1716            2 :     int GetCoilAirOutletNode(EnergyPlusData &state,
    1717              :                              int const CoilIndex,         // must match coil types in this module
    1718              :                              std::string const &CoilName, // must match coil names for the coil type
    1719              :                              bool &ErrorsFound            // set to true if problem
    1720              :     )
    1721              :     {
    1722              : 
    1723              :         // FUNCTION INFORMATION:
    1724              :         //       AUTHOR         R. Raustad
    1725              :         //       DATE WRITTEN   July 2007
    1726              :         //       MODIFIED       na
    1727              :         //       RE-ENGINEERED  na
    1728              : 
    1729              :         // PURPOSE OF THIS FUNCTION:
    1730              :         // This function looks up the air outlet node number for the given coil and returns it.  If
    1731              :         // incorrect coil type or name is given, ErrorsFound is returned as true and node number is returned
    1732              :         // as zero.
    1733              : 
    1734              :         // METHODOLOGY EMPLOYED:
    1735              :         // na
    1736              : 
    1737              :         // REFERENCES:
    1738              :         // na
    1739              : 
    1740              :         // USE STATEMENTS:
    1741              :         // na
    1742              : 
    1743              :         // Return value
    1744              :         int NodeNumber; // returned air inlet node number of matched coil
    1745              : 
    1746              :         // Obtains and Allocates SteamCoil related parameters from input file
    1747            2 :         if (state.dataSteamCoils->GetSteamCoilsInputFlag) { // First time subroutine has been entered
    1748            0 :             GetSteamCoilInput(state);
    1749            0 :             state.dataSteamCoils->GetSteamCoilsInputFlag = false;
    1750              :         }
    1751              : 
    1752            2 :         if (CoilIndex == 0) {
    1753            0 :             ShowSevereError(state, format("GetCoilAirOutletNode: Could not find CoilType = \"Coil:Heating:Steam\" with Name = {}", CoilName));
    1754            0 :             ErrorsFound = true;
    1755            0 :             NodeNumber = 0;
    1756              :         } else {
    1757            2 :             NodeNumber = state.dataSteamCoils->SteamCoil(CoilIndex).AirOutletNodeNum;
    1758              :         }
    1759              : 
    1760            2 :         return NodeNumber;
    1761              :     }
    1762              : 
    1763            0 :     int GetCoilAirOutletNode(EnergyPlusData &state,
    1764              :                              std::string const &CoilType,       // must match coil types in this module
    1765              :                              std::string const &CoilName,       // must match coil names for the coil type
    1766              :                              [[maybe_unused]] bool &ErrorsFound // set to true if problem
    1767              :     )
    1768              :     {
    1769              : 
    1770              :         // FUNCTION INFORMATION:
    1771              :         //       AUTHOR         R. Raustad
    1772              :         //       DATE WRITTEN   July 2007
    1773              :         //       MODIFIED       na
    1774              :         //       RE-ENGINEERED  na
    1775              : 
    1776              :         // PURPOSE OF THIS FUNCTION:
    1777              :         // This function looks up the air outlet node number for the given coil and returns it.  If
    1778              :         // incorrect coil type or name is given, ErrorsFound is returned as true and node number is returned
    1779              :         // as zero.
    1780              : 
    1781              :         // Return value
    1782              :         int NodeNumber; // returned air inlet node number of matched coil
    1783              : 
    1784              :         // FUNCTION LOCAL VARIABLE DECLARATIONS:
    1785              :         int IndexNum; // returned air inlet node number of matched coil
    1786              : 
    1787              :         // Obtains and Allocates SteamCoil related parameters from input file
    1788            0 :         if (state.dataSteamCoils->GetSteamCoilsInputFlag) { // First time subroutine has been entered
    1789            0 :             GetSteamCoilInput(state);
    1790            0 :             state.dataSteamCoils->GetSteamCoilsInputFlag = false;
    1791              :         }
    1792              : 
    1793            0 :         if (Util::SameString(CoilType, "Coil:Heating:Steam")) {
    1794            0 :             IndexNum = Util::FindItem(CoilName, state.dataSteamCoils->SteamCoil);
    1795              :         } else {
    1796            0 :             IndexNum = 0;
    1797              :         }
    1798              : 
    1799            0 :         if (IndexNum == 0) {
    1800            0 :             NodeNumber = 0;
    1801              :         } else {
    1802            0 :             NodeNumber = state.dataSteamCoils->SteamCoil(IndexNum).AirOutletNodeNum;
    1803              :         }
    1804              : 
    1805            0 :         return NodeNumber;
    1806              :     }
    1807              : 
    1808            1 :     int GetCoilSteamInletNode(EnergyPlusData &state,
    1809              :                               int const CoilIndex,         // must match coil types in this module
    1810              :                               std::string const &CoilName, // must match coil names for the coil type
    1811              :                               bool &ErrorsFound            // set to true if problem
    1812              :     )
    1813              :     {
    1814              : 
    1815              :         // FUNCTION INFORMATION:
    1816              :         //       AUTHOR         R. Raustad
    1817              :         //       DATE WRITTEN   July 2007
    1818              :         //       MODIFIED       na
    1819              :         //       RE-ENGINEERED  na
    1820              : 
    1821              :         // PURPOSE OF THIS FUNCTION:
    1822              :         // This function looks up the steam inlet node number for the given coil and returns it.  If
    1823              :         // incorrect coil type or name is given, ErrorsFound is returned as true and node number is returned
    1824              :         // as zero.
    1825              : 
    1826              :         // Return value
    1827              :         int NodeNumber; // returned air inlet node number of matched coil
    1828              : 
    1829              :         // Obtains and Allocates SteamCoil related parameters from input file
    1830            1 :         if (state.dataSteamCoils->GetSteamCoilsInputFlag) { // First time subroutine has been entered
    1831            0 :             GetSteamCoilInput(state);
    1832            0 :             state.dataSteamCoils->GetSteamCoilsInputFlag = false;
    1833              :         }
    1834              : 
    1835            1 :         if (CoilIndex == 0) {
    1836            0 :             ShowSevereError(state, format("GetCoilSteamInletNode: Could not find CoilType = \"Coil:Heating:Steam\" with Name = {}", CoilName));
    1837            0 :             ErrorsFound = true;
    1838            0 :             NodeNumber = 0;
    1839              :         } else {
    1840            1 :             NodeNumber = state.dataSteamCoils->SteamCoil(CoilIndex).SteamInletNodeNum;
    1841              :         }
    1842              : 
    1843            1 :         return NodeNumber;
    1844              :     }
    1845              : 
    1846            1 :     int GetCoilSteamInletNode(EnergyPlusData &state,
    1847              :                               std::string const &CoilType, // must match coil types in this module
    1848              :                               std::string const &CoilName, // must match coil names for the coil type
    1849              :                               bool &ErrorsFound            // set to true if problem
    1850              :     )
    1851              :     {
    1852              : 
    1853              :         // FUNCTION INFORMATION:
    1854              :         //       AUTHOR         L. Lawrie (based on R. Raustad)
    1855              :         //       DATE WRITTEN   June 2008
    1856              :         //       MODIFIED       na
    1857              :         //       RE-ENGINEERED  na
    1858              : 
    1859              :         // PURPOSE OF THIS FUNCTION:
    1860              :         // This function looks up the steam inlet node number for the given coil and returns it.  If
    1861              :         // incorrect coil type or name is given, ErrorsFound is returned as true and node number is returned
    1862              :         // as zero.
    1863              : 
    1864              :         // Return value
    1865              :         int NodeNumber; // returned air inlet node number of matched coil
    1866              : 
    1867              :         // FUNCTION LOCAL VARIABLE DECLARATIONS:
    1868              :         int IndexNum; // returned air inlet node number of matched coil
    1869              : 
    1870              :         // Obtains and Allocates SteamCoil related parameters from input file
    1871            1 :         if (state.dataSteamCoils->GetSteamCoilsInputFlag) { // First time subroutine has been entered
    1872            0 :             GetSteamCoilInput(state);
    1873            0 :             state.dataSteamCoils->GetSteamCoilsInputFlag = false;
    1874              :         }
    1875              : 
    1876            1 :         if (Util::SameString(CoilType, "Coil:Heating:Steam")) {
    1877            1 :             IndexNum = Util::FindItem(CoilName, state.dataSteamCoils->SteamCoil);
    1878              :         } else {
    1879            0 :             IndexNum = 0;
    1880              :         }
    1881              : 
    1882            1 :         if (IndexNum == 0) {
    1883            0 :             ShowSevereError(state, format("GetCoilSteamInletNode: Could not find CoilType = \"Coil:Heating:Steam\" with Name = {}", CoilName));
    1884            0 :             ErrorsFound = true;
    1885            0 :             NodeNumber = 0;
    1886              :         } else {
    1887            1 :             NodeNumber = state.dataSteamCoils->SteamCoil(IndexNum).SteamInletNodeNum;
    1888              :         }
    1889              : 
    1890            1 :         return NodeNumber;
    1891              :     }
    1892              : 
    1893            0 :     int GetCoilSteamOutletNode(EnergyPlusData &state,
    1894              :                                int const CoilIndex,         // must match coil types in this module
    1895              :                                std::string const &CoilName, // must match coil names for the coil type
    1896              :                                bool &ErrorsFound            // set to true if problem
    1897              :     )
    1898              :     {
    1899              : 
    1900              :         // FUNCTION INFORMATION:
    1901              :         //       AUTHOR         R. Raustad
    1902              :         //       DATE WRITTEN   July 2007
    1903              :         //       MODIFIED       na
    1904              :         //       RE-ENGINEERED  na
    1905              : 
    1906              :         // PURPOSE OF THIS FUNCTION:
    1907              :         // This function looks up the steam inlet node number for the given coil and returns it.  If
    1908              :         // incorrect coil type or name is given, ErrorsFound is returned as true and node number is returned
    1909              :         // as zero.
    1910              : 
    1911              :         // Return value
    1912              :         int NodeNumber; // returned air inlet node number of matched coil
    1913              : 
    1914              :         // Obtains and Allocates SteamCoil related parameters from input file
    1915            0 :         if (state.dataSteamCoils->GetSteamCoilsInputFlag) { // First time subroutine has been entered
    1916            0 :             GetSteamCoilInput(state);
    1917            0 :             state.dataSteamCoils->GetSteamCoilsInputFlag = false;
    1918              :         }
    1919              : 
    1920            0 :         if (CoilIndex == 0) {
    1921            0 :             ShowSevereError(state, format("GetCoilSteamInletNode: Could not find CoilType = \"Coil:Heating:Steam\" with Name = {}", CoilName));
    1922            0 :             ErrorsFound = true;
    1923            0 :             NodeNumber = 0;
    1924              :         } else {
    1925            0 :             NodeNumber = state.dataSteamCoils->SteamCoil(CoilIndex).SteamOutletNodeNum;
    1926              :         }
    1927              : 
    1928            0 :         return NodeNumber;
    1929              :     }
    1930              : 
    1931            1 :     int GetCoilSteamOutletNode(EnergyPlusData &state,
    1932              :                                std::string_view CoilType,   // must match coil types in this module
    1933              :                                std::string const &CoilName, // must match coil names for the coil type
    1934              :                                bool &ErrorsFound            // set to true if problem
    1935              :     )
    1936              :     {
    1937              : 
    1938              :         // FUNCTION INFORMATION:
    1939              :         //       AUTHOR         L. Lawrie (based on R. Raustad)
    1940              :         //       DATE WRITTEN   June 2008
    1941              :         //       MODIFIED       na
    1942              :         //       RE-ENGINEERED  na
    1943              : 
    1944              :         // PURPOSE OF THIS FUNCTION:
    1945              :         // This function looks up the steam inlet node number for the given coil and returns it.  If
    1946              :         // incorrect coil type or name is given, ErrorsFound is returned as true and node number is returned
    1947              :         // as zero.
    1948              : 
    1949              :         // Return value
    1950              :         int NodeNumber; // returned air inlet node number of matched coil
    1951              : 
    1952              :         // FUNCTION LOCAL VARIABLE DECLARATIONS:
    1953              :         int IndexNum; // returned air inlet node number of matched coil
    1954              : 
    1955              :         // Obtains and Allocates SteamCoil related parameters from input file
    1956            1 :         if (state.dataSteamCoils->GetSteamCoilsInputFlag) { // First time subroutine has been entered
    1957            0 :             GetSteamCoilInput(state);
    1958            0 :             state.dataSteamCoils->GetSteamCoilsInputFlag = false;
    1959              :         }
    1960              : 
    1961            1 :         if (Util::SameString(CoilType, "Coil:Heating:Steam")) {
    1962            1 :             IndexNum = Util::FindItem(CoilName, state.dataSteamCoils->SteamCoil);
    1963              :         } else {
    1964            0 :             IndexNum = 0;
    1965              :         }
    1966              : 
    1967            1 :         if (IndexNum == 0) {
    1968            0 :             ShowSevereError(state, format("GetCoilSteamInletNode: Could not find CoilType = \"Coil:Heating:Steam\" with Name = {}", CoilName));
    1969            0 :             ErrorsFound = true;
    1970            0 :             NodeNumber = 0;
    1971              :         } else {
    1972            1 :             NodeNumber = state.dataSteamCoils->SteamCoil(IndexNum).SteamOutletNodeNum;
    1973              :         }
    1974              : 
    1975            1 :         return NodeNumber;
    1976              :     }
    1977              : 
    1978            0 :     Real64 GetCoilCapacity(EnergyPlusData &state,
    1979              :                            std::string const &CoilType, // must match coil types in this module
    1980              :                            std::string const &CoilName, // must match coil names for the coil type
    1981              :                            bool &ErrorsFound            // set to true if problem
    1982              :     )
    1983              :     {
    1984              : 
    1985              :         // FUNCTION INFORMATION:
    1986              :         //       AUTHOR         R. Raustad
    1987              :         //       DATE WRITTEN   July 2007
    1988              :         //       MODIFIED       na
    1989              :         //       RE-ENGINEERED  na
    1990              : 
    1991              :         // PURPOSE OF THIS FUNCTION:
    1992              :         // This function looks up the steam coils operating capacity and returns it.  If
    1993              :         // incorrect coil type or name is given, ErrorsFound is returned as true and node number is returned
    1994              :         // as zero.
    1995              : 
    1996              :         // Return value
    1997              :         Real64 Capacity; // returned operating capacity of matched coil (W)
    1998              : 
    1999              :         // FUNCTION LOCAL VARIABLE DECLARATIONS:
    2000              :         int WhichCoil;
    2001              : 
    2002              :         // Obtains and Allocates SteamCoil related parameters from input file
    2003            0 :         if (state.dataSteamCoils->GetSteamCoilsInputFlag) { // First time subroutine has been entered
    2004            0 :             GetSteamCoilInput(state);
    2005            0 :             state.dataSteamCoils->GetSteamCoilsInputFlag = false;
    2006              :         }
    2007              : 
    2008            0 :         if (Util::SameString(CoilType, "Coil:Heating:Steam")) {
    2009            0 :             WhichCoil = Util::FindItem(CoilName, state.dataSteamCoils->SteamCoil);
    2010            0 :             if (WhichCoil != 0) {
    2011              :                 // coil does not specify MaxWaterFlowRate
    2012            0 :                 Capacity = state.dataSteamCoils->SteamCoil(WhichCoil).OperatingCapacity;
    2013              :             }
    2014              :         } else {
    2015            0 :             WhichCoil = 0;
    2016              :         }
    2017              : 
    2018            0 :         if (WhichCoil == 0) {
    2019            0 :             ShowSevereError(state, format("GetCoilSteamInletNode: Could not find CoilType=\"{}\" with Name=\"{}\"", CoilType, CoilName));
    2020            0 :             ErrorsFound = true;
    2021            0 :             Capacity = 0.0;
    2022              :         }
    2023              : 
    2024            0 :         return Capacity;
    2025              :     }
    2026              : 
    2027            0 :     CoilControlType GetTypeOfCoil(EnergyPlusData &state,
    2028              :                                   int const CoilIndex,         // must match coil types in this module
    2029              :                                   std::string const &CoilName, // must match coil names for the coil type
    2030              :                                   bool &ErrorsFound            // set to true if problem
    2031              :     )
    2032              :     {
    2033              : 
    2034              :         // FUNCTION INFORMATION:
    2035              :         //       AUTHOR         R. Raustad
    2036              :         //       DATE WRITTEN   July 2007
    2037              :         //       MODIFIED       na
    2038              :         //       RE-ENGINEERED  na
    2039              : 
    2040              :         // PURPOSE OF THIS FUNCTION:
    2041              :         // This function looks up the steam coils operating capacity and returns it.  If
    2042              :         // incorrect coil type or name is given, ErrorsFound is returned as true and node number is returned
    2043              :         // as zero.
    2044              : 
    2045              :         // Obtains and Allocates SteamCoil related parameters from input file
    2046            0 :         if (state.dataSteamCoils->GetSteamCoilsInputFlag) { // First time subroutine has been entered
    2047            0 :             GetSteamCoilInput(state);
    2048            0 :             state.dataSteamCoils->GetSteamCoilsInputFlag = false;
    2049              :         }
    2050              : 
    2051            0 :         if (CoilIndex == 0) {
    2052            0 :             ShowSevereError(state, format("GetCoilSteamInletNode: Could not find CoilType = \"Coil:Heating:Steam\" with Name = {}", CoilName));
    2053            0 :             ErrorsFound = true;
    2054            0 :             return CoilControlType::Invalid;
    2055              :         } else {
    2056            0 :             return state.dataSteamCoils->SteamCoil(CoilIndex).TypeOfCoil;
    2057              :         }
    2058              :     }
    2059              : 
    2060            0 :     int GetSteamCoilControlNodeNum(EnergyPlusData &state,
    2061              :                                    std::string const &CoilType, // must match coil types in this module
    2062              :                                    std::string const &CoilName, // must match coil names for the coil type
    2063              :                                    bool &ErrorFlag              // set to true if problem
    2064              :     )
    2065              :     {
    2066              : 
    2067              :         // FUNCTION INFORMATION:
    2068              :         //       AUTHOR         B. Nigusse, FSEC
    2069              :         //       DATE WRITTEN   January 2012
    2070              :         //       MODIFIED       na
    2071              :         //       RE-ENGINEERED  na
    2072              : 
    2073              :         // PURPOSE OF THIS FUNCTION:
    2074              :         // This function looks up the steam coils and returns the steam control node number.  If
    2075              :         // incorrect coil type or name is given, ErrorsFound is returned as true and node number is returned
    2076              :         // as zero.
    2077              : 
    2078              :         // Return value
    2079              :         int NodeNumber; // returned node number of matched coil
    2080              : 
    2081              :         // FUNCTION LOCAL VARIABLE DECLARATIONS:
    2082              :         int WhichCoil;
    2083              : 
    2084              :         // Obtains and Allocates SteamCoil related parameters from input file
    2085            0 :         if (state.dataSteamCoils->GetSteamCoilsInputFlag) { // First time subroutine has been entered
    2086            0 :             GetSteamCoilInput(state);
    2087            0 :             state.dataSteamCoils->GetSteamCoilsInputFlag = false;
    2088              :         }
    2089              : 
    2090            0 :         WhichCoil = 0;
    2091            0 :         NodeNumber = 0;
    2092            0 :         if (Util::SameString(CoilType, "Coil:Heating:Steam")) {
    2093            0 :             WhichCoil = Util::FindItem(CoilName, state.dataSteamCoils->SteamCoil);
    2094            0 :             if (WhichCoil != 0) {
    2095            0 :                 NodeNumber = state.dataSteamCoils->SteamCoil(WhichCoil).TempSetPointNodeNum;
    2096              :             }
    2097              :         } else {
    2098            0 :             WhichCoil = 0;
    2099              :         }
    2100              : 
    2101            0 :         if (WhichCoil == 0) {
    2102            0 :             ShowSevereError(state, format("GetSteamCoilControlNodeNum: Could not find Coil, Type=\"{}\" Name=\"{}\"", CoilType, CoilName));
    2103            0 :             ErrorFlag = true;
    2104            0 :             NodeNumber = 0;
    2105              :         }
    2106              : 
    2107            0 :         return NodeNumber;
    2108              :     }
    2109              : 
    2110            0 :     int GetSteamCoilAvailScheduleIndex(EnergyPlusData &state,
    2111              :                                        std::string const &CoilType, // must match coil types in this module
    2112              :                                        std::string const &CoilName, // must match coil names for the coil type
    2113              :                                        bool &ErrorsFound            // set to true if problem
    2114              :     )
    2115              :     {
    2116              : 
    2117              :         // FUNCTION INFORMATION:
    2118              :         //       AUTHOR         Chandan Sharma, FSEC
    2119              :         //       DATE WRITTEN   February 2013
    2120              :         //       MODIFIED       na
    2121              :         //       RE-ENGINEERED  na
    2122              : 
    2123              :         // PURPOSE OF THIS FUNCTION:
    2124              :         // This function looks up the given coil and returns the availability schedule index.  If
    2125              :         // incorrect coil type or name is given, ErrorsFound is returned as true and index is returned
    2126              :         // as zero.
    2127              : 
    2128              :         // Return value
    2129              :         int AvailSchIndex; // returned availability schedule of matched coil
    2130              : 
    2131              :         // FUNCTION LOCAL VARIABLE DECLARATIONS:
    2132              :         int WhichCoil;
    2133              : 
    2134              :         // Obtains and Allocates HeatingCoil related parameters from input file
    2135            0 :         if (state.dataSteamCoils->GetSteamCoilsInputFlag) { // First time subroutine has been entered
    2136            0 :             GetSteamCoilInput(state);
    2137            0 :             state.dataSteamCoils->GetSteamCoilsInputFlag = false;
    2138              :         }
    2139              : 
    2140            0 :         WhichCoil = 0;
    2141            0 :         AvailSchIndex = 0;
    2142              : 
    2143            0 :         if (Util::SameString(CoilType, "Coil:Heating:Steam")) {
    2144            0 :             WhichCoil = Util::FindItem(CoilName, state.dataSteamCoils->SteamCoil);
    2145            0 :             if (WhichCoil != 0) {
    2146            0 :                 AvailSchIndex = state.dataSteamCoils->SteamCoil(WhichCoil).availSched->Num;
    2147              :             }
    2148              :         } else {
    2149            0 :             WhichCoil = 0;
    2150              :         }
    2151              : 
    2152            0 :         if (WhichCoil == 0) {
    2153            0 :             ShowSevereError(state, format("GetCoilAvailScheduleIndex: Could not find Coil, Type=\"{}\" Name=\"{}\"", CoilType, CoilName));
    2154            0 :             ErrorsFound = true;
    2155            0 :             AvailSchIndex = 0;
    2156              :         }
    2157              : 
    2158            0 :         return AvailSchIndex;
    2159              :     }
    2160              : 
    2161            0 :     void SetSteamCoilData(EnergyPlusData &state,
    2162              :                           int const CoilNum,                                  // Number of hot water heating Coil
    2163              :                           bool &ErrorsFound,                                  // Set to true if certain errors found
    2164              :                           ObjexxFCL::Optional_bool DesiccantRegenerationCoil, // Flag that this coil is used as regeneration air heating coil
    2165              :                           ObjexxFCL::Optional_int DesiccantDehumIndex         // Index for the desiccant dehum system where this caoil is used
    2166              :     )
    2167              :     {
    2168              : 
    2169              :         // FUNCTION INFORMATION:
    2170              :         //       AUTHOR         Bereket Nigusse
    2171              :         //       DATE WRITTEN   February 2016
    2172              :         //       MODIFIED       na
    2173              :         //       RE-ENGINEERED  na
    2174              : 
    2175              :         // PURPOSE OF THIS FUNCTION:
    2176              :         // This function sets data to water Heating Coil using the coil index and arguments passed
    2177              : 
    2178            0 :         if (state.dataSteamCoils->GetSteamCoilsInputFlag) {
    2179            0 :             GetSteamCoilInput(state);
    2180            0 :             state.dataSteamCoils->GetSteamCoilsInputFlag = false;
    2181              :         }
    2182              : 
    2183            0 :         if (CoilNum <= 0 || CoilNum > state.dataSteamCoils->NumSteamCoils) {
    2184            0 :             ShowSevereError(state,
    2185            0 :                             format("SetHeatingCoilData: called with heating coil Number out of range={} should be >0 and <{}",
    2186              :                                    CoilNum,
    2187            0 :                                    state.dataSteamCoils->NumSteamCoils));
    2188            0 :             ErrorsFound = true;
    2189            0 :             return;
    2190              :         }
    2191              : 
    2192            0 :         if (present(DesiccantRegenerationCoil)) {
    2193            0 :             state.dataSteamCoils->SteamCoil(CoilNum).DesiccantRegenerationCoil = DesiccantRegenerationCoil;
    2194              :         }
    2195              : 
    2196            0 :         if (present(DesiccantDehumIndex)) {
    2197            0 :             state.dataSteamCoils->SteamCoil(CoilNum).DesiccantDehumNum = DesiccantDehumIndex;
    2198              :         }
    2199              :     }
    2200              :     // End of Utility subroutines for the SteamCoil Module
    2201              : 
    2202              : } // namespace SteamCoils
    2203              : 
    2204              : } // namespace EnergyPlus
        

Generated by: LCOV version 2.0-1