LCOV - code coverage report
Current view: top level - EnergyPlus - SingleDuct.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 70.5 % 3182 2244
Test Date: 2025-06-02 07:23:51 Functions: 89.7 % 29 26

            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 <AirflowNetwork/Solver.hpp>
      56              : #include <EnergyPlus/Autosizing/Base.hh>
      57              : #include <EnergyPlus/BranchNodeConnections.hh>
      58              : #include <EnergyPlus/Data/EnergyPlusData.hh>
      59              : #include <EnergyPlus/DataContaminantBalance.hh>
      60              : #include <EnergyPlus/DataConvergParams.hh>
      61              : #include <EnergyPlus/DataDefineEquip.hh>
      62              : #include <EnergyPlus/DataEnvironment.hh>
      63              : #include <EnergyPlus/DataHVACGlobals.hh>
      64              : #include <EnergyPlus/DataHeatBalFanSys.hh>
      65              : #include <EnergyPlus/DataHeatBalance.hh>
      66              : #include <EnergyPlus/DataIPShortCuts.hh>
      67              : #include <EnergyPlus/DataLoopNode.hh>
      68              : #include <EnergyPlus/DataSizing.hh>
      69              : #include <EnergyPlus/DataZoneEnergyDemands.hh>
      70              : #include <EnergyPlus/DataZoneEquipment.hh>
      71              : #include <EnergyPlus/EMSManager.hh>
      72              : #include <EnergyPlus/Fans.hh>
      73              : #include <EnergyPlus/FluidProperties.hh>
      74              : #include <EnergyPlus/General.hh>
      75              : #include <EnergyPlus/GeneralRoutines.hh>
      76              : #include <EnergyPlus/GlobalNames.hh>
      77              : #include <EnergyPlus/HeatingCoils.hh>
      78              : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      79              : #include <EnergyPlus/NodeInputManager.hh>
      80              : #include <EnergyPlus/OutputProcessor.hh>
      81              : #include <EnergyPlus/OutputReportPredefined.hh>
      82              : #include <EnergyPlus/Plant/DataPlant.hh>
      83              : #include <EnergyPlus/PlantUtilities.hh>
      84              : #include <EnergyPlus/Psychrometrics.hh>
      85              : #include <EnergyPlus/ReportCoilSelection.hh>
      86              : #include <EnergyPlus/ScheduleManager.hh>
      87              : #include <EnergyPlus/SingleDuct.hh>
      88              : #include <EnergyPlus/SteamCoils.hh>
      89              : #include <EnergyPlus/UtilityRoutines.hh>
      90              : #include <EnergyPlus/WaterCoils.hh>
      91              : #include <EnergyPlus/ZoneAirLoopEquipmentManager.hh>
      92              : 
      93              : namespace EnergyPlus::SingleDuct {
      94              : 
      95              : // Module containing the Single Duct Systems as a single component/ or really a single driver
      96              : 
      97              : // MODULE INFORMATION:
      98              : //       AUTHOR         Richard J. Liesen
      99              : //       DATE WRITTEN   January 2000
     100              : 
     101              : // PURPOSE OF THIS MODULE:
     102              : // To encapsulate the data and algorithms required to
     103              : // simulate single duct systems as a single driver or inter-connecting controllers.
     104              : 
     105              : // Using/Aliasing
     106              : using namespace DataLoopNode;
     107              : using BranchNodeConnections::SetUpCompSets;
     108              : using BranchNodeConnections::TestCompSet;
     109              : using HVAC::SmallAirVolFlow;
     110              : using HVAC::SmallLoad;
     111              : using HVAC::SmallMassFlow;
     112              : using namespace DataSizing;
     113              : using Psychrometrics::PsyCpAirFnW;
     114              : using Psychrometrics::PsyRhoAirFnPbTdbW;
     115              : using namespace SteamCoils;
     116              : 
     117     37322114 : void SimulateSingleDuct(
     118              :     EnergyPlusData &state, std::string_view CompName, bool const FirstHVACIteration, int const ZoneNum, int const ZoneNodeNum, int &CompIndex)
     119              : {
     120              : 
     121              :     // SUBROUTINE INFORMATION:
     122              :     //       AUTHOR         Richard Liesen
     123              :     //       DATE WRITTEN   January 2000
     124              : 
     125              :     // PURPOSE OF THIS SUBROUTINE:
     126              :     // This subroutine manages Sys system simulation.
     127              :     // It is called from the ManageZoneEquip
     128              :     // at the system time step.
     129              : 
     130              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     131              :     int SysNum; // The Sys that you are currently loading input into
     132              : 
     133              :     // Obtains and Allocates Sys related parameters from input file
     134     37322114 :     if (state.dataSingleDuct->GetInputFlag) { // First time subroutine has been entered
     135          525 :         GetSysInput(state);
     136          525 :         state.dataSingleDuct->GetInputFlag = false;
     137              :     }
     138              : 
     139              :     // Find the correct SysNumber with the Component Name
     140     37322114 :     if (CompIndex == 0) {
     141         3607 :         SysNum = Util::FindItemInList(CompName, state.dataSingleDuct->sd_airterminal, &SingleDuctAirTerminal::SysName);
     142         3607 :         if (SysNum == 0) {
     143            0 :             ShowFatalError(state, format("SimulateSingleDuct: System not found={}", CompName));
     144              :         }
     145         3607 :         CompIndex = SysNum;
     146              :     } else {
     147     37318507 :         SysNum = CompIndex;
     148     37318507 :         if (SysNum > state.dataSingleDuct->NumSDAirTerminal || SysNum < 1) {
     149            0 :             ShowFatalError(state,
     150            0 :                            format("SimulateSingleDuct: Invalid CompIndex passed={}, Number of Systems={}, System name={}",
     151              :                                   CompIndex,
     152            0 :                                   state.dataSingleDuct->NumSDAirTerminal,
     153              :                                   CompName));
     154              :         }
     155     37318507 :         if (state.dataSingleDuct->CheckEquipName(SysNum)) {
     156         3602 :             if (CompName != state.dataSingleDuct->sd_airterminal(SysNum).SysName) {
     157            0 :                 ShowFatalError(state,
     158            0 :                                format("SimulateSingleDuct: Invalid CompIndex passed={}, System name={}, stored System Name for that index={}",
     159              :                                       CompIndex,
     160              :                                       CompName,
     161            0 :                                       state.dataSingleDuct->sd_airterminal(SysNum).SysName));
     162              :             }
     163         3602 :             state.dataSingleDuct->CheckEquipName(SysNum) = false;
     164              :         }
     165              :     }
     166              : 
     167     37322114 :     auto &thisATU(state.dataSingleDuct->sd_airterminal(SysNum));
     168              : 
     169     37322114 :     state.dataSize->TermUnitSingDuct = true;
     170     37322114 :     state.dataSize->CurTermUnitSizingNum = state.dataDefineEquipment->AirDistUnit(thisATU.ADUNum).TermUnitSizingNum;
     171              : 
     172              :     // With the correct SysNum Initialize the system
     173     37322114 :     thisATU.InitSys(state, FirstHVACIteration); // Initialize all Sys related parameters
     174              : 
     175              :     // Calculate the Correct Sys Model with the current SysNum
     176     37322114 :     switch (thisATU.SysType_Num) {
     177      1656582 :     case SysType::SingleDuctConstVolReheat: // AirTerminal:SingleDuct:ConstantVolume:Reheat
     178      1656582 :         thisATU.SimConstVol(state, FirstHVACIteration, ZoneNum, ZoneNodeNum);
     179      1656582 :         break;
     180      8544703 :     case SysType::SingleDuctConstVolNoReheat: // AirTerminal:SingleDuct:ConstantVolume:NoReheat
     181      8544703 :         thisATU.SimConstVolNoReheat(state);
     182      8544703 :         break;
     183     27022691 :     case SysType::SingleDuctVAVReheat:   // SINGLE DUCT:VAV:REHEAT
     184              :     case SysType::SingleDuctVAVNoReheat: // SINGLE DUCT:VAV:NOREHEAT
     185     27022691 :         thisATU.SimVAV(state, FirstHVACIteration, ZoneNum, ZoneNodeNum);
     186     27022691 :         break;
     187        30864 :     case SysType::SingleDuctVAVReheatVSFan: // SINGLE DUCT:VAV:REHEAT:VS FAN
     188        30864 :         thisATU.SimVAVVS(state, FirstHVACIteration, ZoneNum, ZoneNodeNum);
     189        30864 :         break;
     190        67274 :     case SysType::SingleDuctCBVAVReheat:   // SINGLE DUCT:VAVHEATANDCOOL:REHEAT
     191              :     case SysType::SingleDuctCBVAVNoReheat: // SINGLE DUCT:VAVHEATANDCOOL:NOREHEAT
     192        67274 :         thisATU.SimCBVAV(state, FirstHVACIteration, ZoneNum, ZoneNodeNum);
     193        67274 :         break;
     194            0 :     default:
     195              :         // assert(false);
     196            0 :         break;
     197              :     }
     198              : 
     199              :     // Report the current Sys
     200     37322114 :     thisATU.ReportSys(state);
     201              : 
     202     37322114 :     state.dataSize->TermUnitSingDuct = false;
     203     37322114 : }
     204              : 
     205              : // Get Input Section of the Module
     206              : //******************************************************************************
     207              : 
     208          525 : void GetSysInput(EnergyPlusData &state)
     209              : {
     210              : 
     211              :     // SUBROUTINE INFORMATION:
     212              :     //       AUTHOR         Richard Liesen
     213              :     //       DATE WRITTEN   April 1998
     214              : 
     215              :     // PURPOSE OF THIS SUBROUTINE:
     216              :     // This subroutine is the main routine to call other input routines and Get routines
     217              : 
     218              :     // METHODOLOGY EMPLOYED:
     219              :     // Uses the status flags to trigger events.
     220              : 
     221              :     // Using/Aliasing
     222              :     using NodeInputManager::GetOnlySingleNode;
     223              :     using SteamCoils::GetCoilAirOutletNode;
     224              :     using SteamCoils::GetCoilSteamInletNode;
     225              :     using SteamCoils::GetSteamCoilIndex;
     226              :     using WaterCoils::GetCoilOutletNode;
     227              :     using WaterCoils::GetCoilWaterInletNode;
     228          525 :     auto &GetHeatingCoilCapacity(HeatingCoils::GetCoilCapacity);
     229          525 :     auto &GetHeatingCoilOutletNode(HeatingCoils::GetCoilOutletNode);
     230              :     using namespace DataHeatBalance;
     231              : 
     232              :     // SUBROUTINE PARAMETER DEFINITIONS:
     233              :     static constexpr std::string_view RoutineName("GetSysInput: "); // include trailing blank
     234              :     static constexpr std::string_view routineName = "GetSysInput";
     235              : 
     236              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     237              : 
     238              :     int NumZoneSiz;
     239              :     int ZoneSizIndex;
     240              :     int IOStat;
     241          525 :     bool ErrorsFound(false);         // If errors detected in input
     242              :     bool IsNotOK;                    // Flag to verify name
     243              :     int CtrlZone;                    // controlled zone do loop index
     244              :     int SupAirIn;                    // controlled zone supply air inlet index
     245              :     int ADUNum;                      // air distribution unit index
     246          525 :     std::string CurrentModuleObject; // for ease in getting objects
     247          525 :     Array1D_string Alphas;           // Alpha input items for object
     248          525 :     Array1D_string cAlphaFields;     // Alpha field names
     249          525 :     Array1D_string cNumericFields;   // Numeric field names
     250          525 :     Array1D<Real64> Numbers;         // Numeric input items for object
     251          525 :     Array1D_bool lAlphaBlanks;       // Logical array, alpha field input BLANK = .TRUE.
     252          525 :     Array1D_bool lNumericBlanks;     // Logical array, numeric field input BLANK = .TRUE.
     253              : 
     254              :     //  certain object in the input file
     255          525 :     std::string AirTermSysInletNodeName;  // air terminal single duct system inlet node name
     256          525 :     std::string AirTermSysOutletNodeName; // air terminal single duct system outlet node name
     257              : 
     258          525 :     state.dataSingleDuct->NumVAVSysGSI = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "AirTerminal:SingleDuct:VAV:Reheat");
     259         1050 :     state.dataSingleDuct->NumNoRHVAVSysGSI =
     260          525 :         state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "AirTerminal:SingleDuct:VAV:NoReheat");
     261         1050 :     state.dataSingleDuct->NumConstVolSys =
     262          525 :         state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "AirTerminal:SingleDuct:ConstantVolume:Reheat");
     263         1050 :     state.dataSingleDuct->NumCVNoReheatSysGSI =
     264          525 :         state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "AirTerminal:SingleDuct:ConstantVolume:NoReheat");
     265         1050 :     state.dataSingleDuct->NumVAVVSGSI =
     266          525 :         state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "AirTerminal:SingleDuct:VAV:Reheat:VariableSpeedFan");
     267         1050 :     state.dataSingleDuct->NumCBVAVSysGSI =
     268          525 :         state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "AirTerminal:SingleDuct:VAV:HeatAndCool:Reheat");
     269         1050 :     state.dataSingleDuct->NumNoRHCBVAVSysGSI =
     270          525 :         state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "AirTerminal:SingleDuct:VAV:HeatAndCool:NoReheat");
     271          525 :     state.dataSingleDuct->NumSDAirTerminal = state.dataSingleDuct->NumVAVSysGSI + state.dataSingleDuct->NumConstVolSys +
     272          525 :                                              state.dataSingleDuct->NumCVNoReheatSysGSI + state.dataSingleDuct->NumNoRHVAVSysGSI +
     273          525 :                                              state.dataSingleDuct->NumVAVVSGSI + state.dataSingleDuct->NumCBVAVSysGSI +
     274          525 :                                              state.dataSingleDuct->NumNoRHCBVAVSysGSI;
     275              : 
     276          525 :     state.dataSingleDuct->sd_airterminal.allocate(state.dataSingleDuct->NumSDAirTerminal);
     277          525 :     state.dataSingleDuct->SysUniqueNames.reserve(static_cast<unsigned>(state.dataSingleDuct->NumSDAirTerminal));
     278          525 :     state.dataSingleDuct->CheckEquipName.dimension(state.dataSingleDuct->NumSDAirTerminal, true);
     279              : 
     280         1050 :     state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state,
     281              :                                                                    "AirTerminal:SingleDuct:VAV:Reheat",
     282          525 :                                                                    state.dataSingleDuct->TotalArgsGSI,
     283          525 :                                                                    state.dataSingleDuct->NumAlphasGSI,
     284          525 :                                                                    state.dataSingleDuct->NumNumsGSI);
     285          525 :     state.dataSingleDuct->MaxNumsGSI = max(state.dataSingleDuct->MaxNumsGSI, state.dataSingleDuct->NumNumsGSI);
     286          525 :     state.dataSingleDuct->MaxAlphasGSI = max(state.dataSingleDuct->MaxAlphasGSI, state.dataSingleDuct->NumAlphasGSI);
     287         1050 :     state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state,
     288              :                                                                    "AirTerminal:SingleDuct:VAV:NoReheat",
     289          525 :                                                                    state.dataSingleDuct->TotalArgsGSI,
     290          525 :                                                                    state.dataSingleDuct->NumAlphasGSI,
     291          525 :                                                                    state.dataSingleDuct->NumNumsGSI);
     292          525 :     state.dataSingleDuct->MaxNumsGSI = max(state.dataSingleDuct->MaxNumsGSI, state.dataSingleDuct->NumNumsGSI);
     293          525 :     state.dataSingleDuct->MaxAlphasGSI = max(state.dataSingleDuct->MaxAlphasGSI, state.dataSingleDuct->NumAlphasGSI);
     294         1050 :     state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state,
     295              :                                                                    "AirTerminal:SingleDuct:ConstantVolume:Reheat",
     296          525 :                                                                    state.dataSingleDuct->TotalArgsGSI,
     297          525 :                                                                    state.dataSingleDuct->NumAlphasGSI,
     298          525 :                                                                    state.dataSingleDuct->NumNumsGSI);
     299          525 :     state.dataSingleDuct->MaxNumsGSI = max(state.dataSingleDuct->MaxNumsGSI, state.dataSingleDuct->NumNumsGSI);
     300          525 :     state.dataSingleDuct->MaxAlphasGSI = max(state.dataSingleDuct->MaxAlphasGSI, state.dataSingleDuct->NumAlphasGSI);
     301         1050 :     state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state,
     302              :                                                                    "AirTerminal:SingleDuct:ConstantVolume:NoReheat",
     303          525 :                                                                    state.dataSingleDuct->TotalArgsGSI,
     304          525 :                                                                    state.dataSingleDuct->NumAlphasGSI,
     305          525 :                                                                    state.dataSingleDuct->NumNumsGSI);
     306          525 :     state.dataSingleDuct->MaxNumsGSI = max(state.dataSingleDuct->MaxNumsGSI, state.dataSingleDuct->NumNumsGSI);
     307          525 :     state.dataSingleDuct->MaxAlphasGSI = max(state.dataSingleDuct->MaxAlphasGSI, state.dataSingleDuct->NumAlphasGSI);
     308         1050 :     state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state,
     309              :                                                                    "AirTerminal:SingleDuct:VAV:Reheat:VariableSpeedFan",
     310          525 :                                                                    state.dataSingleDuct->TotalArgsGSI,
     311          525 :                                                                    state.dataSingleDuct->NumAlphasGSI,
     312          525 :                                                                    state.dataSingleDuct->NumNumsGSI);
     313          525 :     state.dataSingleDuct->MaxNumsGSI = max(state.dataSingleDuct->MaxNumsGSI, state.dataSingleDuct->NumNumsGSI);
     314          525 :     state.dataSingleDuct->MaxAlphasGSI = max(state.dataSingleDuct->MaxAlphasGSI, state.dataSingleDuct->NumAlphasGSI);
     315         1050 :     state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state,
     316              :                                                                    "AirTerminal:SingleDuct:VAV:HeatAndCool:Reheat",
     317          525 :                                                                    state.dataSingleDuct->TotalArgsGSI,
     318          525 :                                                                    state.dataSingleDuct->NumAlphasGSI,
     319          525 :                                                                    state.dataSingleDuct->NumNumsGSI);
     320          525 :     state.dataSingleDuct->MaxNumsGSI = max(state.dataSingleDuct->MaxNumsGSI, state.dataSingleDuct->NumNumsGSI);
     321          525 :     state.dataSingleDuct->MaxAlphasGSI = max(state.dataSingleDuct->MaxAlphasGSI, state.dataSingleDuct->NumAlphasGSI);
     322         1050 :     state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state,
     323              :                                                                    "AirTerminal:SingleDuct:VAV:HeatAndCool:NoReheat",
     324          525 :                                                                    state.dataSingleDuct->TotalArgsGSI,
     325          525 :                                                                    state.dataSingleDuct->NumAlphasGSI,
     326          525 :                                                                    state.dataSingleDuct->NumNumsGSI);
     327          525 :     state.dataSingleDuct->MaxNumsGSI = max(state.dataSingleDuct->MaxNumsGSI, state.dataSingleDuct->NumNumsGSI);
     328          525 :     state.dataSingleDuct->MaxAlphasGSI = max(state.dataSingleDuct->MaxAlphasGSI, state.dataSingleDuct->NumAlphasGSI);
     329              : 
     330          525 :     Alphas.allocate(state.dataSingleDuct->MaxAlphasGSI);
     331          525 :     cAlphaFields.allocate(state.dataSingleDuct->MaxAlphasGSI);
     332          525 :     cNumericFields.allocate(state.dataSingleDuct->MaxNumsGSI);
     333          525 :     Numbers.dimension(state.dataSingleDuct->MaxNumsGSI, 0.0);
     334          525 :     lAlphaBlanks.dimension(state.dataSingleDuct->MaxAlphasGSI, true);
     335          525 :     lNumericBlanks.dimension(state.dataSingleDuct->MaxNumsGSI, true);
     336              : 
     337              :     // Start Loading the System Input
     338         2760 :     for (state.dataSingleDuct->SysIndexGSI = 1; state.dataSingleDuct->SysIndexGSI <= state.dataSingleDuct->NumVAVSysGSI;
     339         2235 :          ++state.dataSingleDuct->SysIndexGSI) {
     340              : 
     341         2235 :         CurrentModuleObject = "AirTerminal:SingleDuct:VAV:Reheat";
     342              : 
     343         4470 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     344              :                                                                  CurrentModuleObject,
     345         2235 :                                                                  state.dataSingleDuct->SysIndexGSI,
     346              :                                                                  Alphas,
     347         2235 :                                                                  state.dataSingleDuct->NumAlphasGSI,
     348              :                                                                  Numbers,
     349         2235 :                                                                  state.dataSingleDuct->NumNumsGSI,
     350              :                                                                  IOStat,
     351              :                                                                  lNumericBlanks,
     352              :                                                                  lAlphaBlanks,
     353              :                                                                  cAlphaFields,
     354              :                                                                  cNumericFields);
     355              : 
     356         2235 :         ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
     357              : 
     358         2235 :         state.dataSingleDuct->SysNumGSI = state.dataSingleDuct->SysIndexGSI;
     359              : 
     360         2235 :         auto &airTerm = state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI);
     361         2235 :         airTerm.SysNum = state.dataSingleDuct->SysNumGSI;
     362         2235 :         GlobalNames::VerifyUniqueInterObjectName(
     363         4470 :             state, state.dataSingleDuct->SysUniqueNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
     364         2235 :         airTerm.SysName = Alphas(1);
     365         2235 :         airTerm.sysType = CurrentModuleObject;
     366         2235 :         airTerm.SysType_Num = SysType::SingleDuctVAVReheat;
     367              : 
     368         2235 :         airTerm.ReheatComp = Alphas(7);
     369         2235 :         if (Util::SameString(airTerm.ReheatComp, "Coil:Heating:Fuel")) {
     370           57 :             airTerm.ReheatComp_Num = HeatingCoilType::Gas;
     371         2178 :         } else if (Util::SameString(airTerm.ReheatComp, "Coil:Heating:Electric")) {
     372          259 :             airTerm.ReheatComp_Num = HeatingCoilType::Electric;
     373         1919 :         } else if (Util::SameString(airTerm.ReheatComp, "Coil:Heating:Water")) {
     374         1906 :             airTerm.ReheatComp_Num = HeatingCoilType::SimpleHeating;
     375         1906 :             airTerm.ReheatComp_PlantType = DataPlant::PlantEquipmentType::CoilWaterSimpleHeating;
     376           13 :         } else if (Util::SameString(airTerm.ReheatComp, "Coil:Heating:Steam")) {
     377           13 :             airTerm.ReheatComp_Num = HeatingCoilType::SteamAirHeating;
     378           13 :             airTerm.ReheatComp_PlantType = DataPlant::PlantEquipmentType::CoilSteamAirHeating;
     379            0 :         } else if (!airTerm.ReheatComp.empty()) {
     380            0 :             ShowSevereError(state, format("Illegal {} = {}.", cAlphaFields(8), airTerm.ReheatComp));
     381            0 :             ShowContinueError(state, format("Occurs in {} = {}", airTerm.sysType, airTerm.SysName));
     382            0 :             ErrorsFound = true;
     383              :         }
     384              : 
     385         2235 :         airTerm.ReheatName = Alphas(8);
     386         2235 :         if (airTerm.ReheatComp_Num == HeatingCoilType::Gas || airTerm.ReheatComp_Num == HeatingCoilType::Electric) {
     387          316 :             HeatingCoils::GetCoilIndex(state, airTerm.ReheatName, airTerm.ReheatComp_Index, ErrorsFound);
     388          316 :             if (airTerm.ReheatComp_Index == 0) {
     389            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(8), Alphas(8));
     390            0 :                 ErrorsFound = true;
     391              :             }
     392         1919 :         } else if (airTerm.ReheatComp_Num == HeatingCoilType::SimpleHeating) {
     393         1906 :             airTerm.ReheatComp_Index = WaterCoils::GetWaterCoilIndex(state, airTerm.ReheatComp, airTerm.ReheatName, ErrorsFound);
     394         1906 :             if (airTerm.ReheatComp_Index == 0) {
     395            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(8), Alphas(8));
     396            0 :                 ErrorsFound = true;
     397              :             }
     398           13 :         } else if (airTerm.ReheatComp_Num == HeatingCoilType::SteamAirHeating) {
     399           13 :             airTerm.ReheatComp_Index = SteamCoils::GetSteamCoilIndex(state, airTerm.ReheatComp, airTerm.ReheatName, ErrorsFound);
     400           13 :             if (airTerm.ReheatComp_Index == 0) {
     401            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(8), Alphas(8));
     402            0 :                 ErrorsFound = true;
     403              :             }
     404              :         }
     405              : 
     406         2235 :         if (lAlphaBlanks(2)) {
     407           23 :             airTerm.availSched = Sched::GetScheduleAlwaysOn(state);
     408         2212 :         } else if ((airTerm.availSched = Sched::GetSchedule(state, Alphas(2))) == nullptr) {
     409            0 :             ShowSevereItemNotFound(state, eoh, cAlphaFields(2), Alphas(2));
     410            0 :             ErrorsFound = true;
     411              :         }
     412              :         // For node connections, this object is both a parent and a non-parent, because the
     413              :         // VAV damper is not called out as a separate component, its nodes must be connected
     414              :         // as ObjectIsNotParent.  But for the reheat coil, the nodes are connected as ObjectIsParent
     415         6705 :         airTerm.OutletNodeNum = GetOnlySingleNode(state,
     416         2235 :                                                   Alphas(3),
     417              :                                                   ErrorsFound,
     418              :                                                   DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctVAVReheat,
     419         2235 :                                                   Alphas(1),
     420              :                                                   DataLoopNode::NodeFluidType::Air,
     421              :                                                   DataLoopNode::ConnectionType::Outlet,
     422              :                                                   NodeInputManager::CompFluidStream::Primary,
     423              :                                                   ObjectIsNotParent,
     424         2235 :                                                   cAlphaFields(3));
     425         6705 :         airTerm.InletNodeNum = GetOnlySingleNode(state,
     426         2235 :                                                  Alphas(4),
     427              :                                                  ErrorsFound,
     428              :                                                  DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctVAVReheat,
     429         2235 :                                                  Alphas(1),
     430              :                                                  DataLoopNode::NodeFluidType::Air,
     431              :                                                  DataLoopNode::ConnectionType::Inlet,
     432              :                                                  NodeInputManager::CompFluidStream::Primary,
     433              :                                                  ObjectIsNotParent,
     434         2235 :                                                  cAlphaFields(4));
     435         2235 :         airTerm.MaxAirVolFlowRate = Numbers(1);
     436              : 
     437         2235 :         if (Util::SameString(Alphas(5), "Constant")) {
     438         2197 :             airTerm.ZoneMinAirFracMethod = MinFlowFraction::Constant;
     439           38 :         } else if (Util::SameString(Alphas(5), "FixedFlowRate")) {
     440            3 :             airTerm.ZoneMinAirFracMethod = MinFlowFraction::Fixed;
     441           35 :         } else if (Util::SameString(Alphas(5), "Scheduled")) {
     442           35 :             airTerm.ZoneMinAirFracMethod = MinFlowFraction::Scheduled;
     443              :         } else {
     444            0 :             ShowSevereError(state, format("{} = {} not found.", cAlphaFields(5), Alphas(5)));
     445            0 :             ShowContinueError(state, format("Occurs in {} = {}", airTerm.sysType, airTerm.SysName));
     446            0 :             ErrorsFound = true;
     447              :         }
     448              : 
     449         2235 :         airTerm.ZoneMinAirFracDes = Numbers(2);
     450         2235 :         if (lNumericBlanks(2)) {
     451           54 :             airTerm.ConstantMinAirFracSetByUser = false;
     452           54 :             airTerm.DesignMinAirFrac = 0.0;
     453              :         } else {
     454         2181 :             airTerm.ConstantMinAirFracSetByUser = true;
     455         2181 :             airTerm.DesignMinAirFrac = Numbers(2);
     456         2181 :             if (airTerm.ZoneMinAirFracMethod == MinFlowFraction::Fixed) {
     457            1 :                 ShowWarningError(state, format("Since {} = {}, input for {} will be ignored.", cAlphaFields(5), Alphas(5), cNumericFields(2)));
     458            1 :                 ShowContinueError(state, format("Occurs in {} = {}", airTerm.sysType, airTerm.SysName));
     459            1 :                 airTerm.ZoneMinAirFracDes = 0.0;
     460              :             }
     461              :         }
     462              : 
     463         2235 :         airTerm.ZoneFixedMinAir = Numbers(3);
     464         2235 :         if (lNumericBlanks(3)) {
     465         2177 :             airTerm.FixedMinAirSetByUser = false;
     466         2177 :             airTerm.DesignMinAirFrac = 0.0;
     467              :         } else {
     468           58 :             airTerm.FixedMinAirSetByUser = true;
     469           58 :             airTerm.DesignMinAirFrac = Numbers(3);
     470           58 :             if (airTerm.ZoneMinAirFracMethod == MinFlowFraction::Constant) {
     471           55 :                 ShowWarningError(state, format("Since {} = {}, input for {} will be ignored.", cAlphaFields(5), Alphas(5), cNumericFields(3)));
     472           55 :                 ShowContinueError(state, format("Occurs in {} = {}", airTerm.sysType, airTerm.SysName));
     473           55 :                 airTerm.ZoneFixedMinAir = 0.0;
     474              :             }
     475              :         }
     476              : 
     477         2235 :         if (airTerm.ZoneMinAirFracMethod != MinFlowFraction::Scheduled) {
     478           35 :         } else if (lAlphaBlanks(6)) {
     479            0 :             ShowSevereEmptyField(state, eoh, cAlphaFields(6));
     480            0 :             ErrorsFound = true;
     481           35 :         } else if ((airTerm.zoneMinAirFracSched = Sched::GetSchedule(state, Alphas(6))) == nullptr) {
     482            0 :             ShowSevereItemNotFound(state, eoh, cAlphaFields(6), Alphas(6));
     483            0 :             ErrorsFound = true;
     484           35 :         } else if (!airTerm.zoneMinAirFracSched->checkMinMaxVals(state, Clusive::In, 0.0, Clusive::In, 1.0)) {
     485            0 :             Sched::ShowSevereBadMinMax(state, eoh, cAlphaFields(6), Alphas(6), Clusive::In, 0.0, Clusive::In, 1.0);
     486            0 :             ErrorsFound = true;
     487              :         }
     488              : 
     489              :         // The reheat coil control node is necessary for hot water and steam reheat, but not necessary for
     490              :         // electric or gas reheat.
     491         2235 :         if (airTerm.ReheatComp_Num != HeatingCoilType::Gas && airTerm.ReheatComp_Num != HeatingCoilType::Electric) {
     492         1919 :             if (airTerm.ReheatComp_Num == HeatingCoilType::SteamAirHeating) {
     493           13 :                 IsNotOK = false;
     494           13 :                 airTerm.ReheatControlNode = GetCoilSteamInletNode(state, airTerm.ReheatComp, airTerm.ReheatName, IsNotOK);
     495           13 :                 if (IsNotOK) {
     496            0 :                     ShowContinueError(state, format("..Occurs in {} = {}", airTerm.sysType, airTerm.SysName));
     497            0 :                     ErrorsFound = true;
     498              :                 }
     499              :             } else {
     500         1906 :                 IsNotOK = false;
     501         1906 :                 airTerm.ReheatControlNode = GetCoilWaterInletNode(state, airTerm.ReheatComp, airTerm.ReheatName, IsNotOK);
     502         1906 :                 if (IsNotOK) {
     503            0 :                     ShowContinueError(state, format("..Occurs in {} = {}", airTerm.sysType, airTerm.SysName));
     504            0 :                     ErrorsFound = true;
     505              :                 }
     506              :             }
     507              :         }
     508         6705 :         airTerm.ReheatAirOutletNode = GetOnlySingleNode(state,
     509         2235 :                                                         Alphas(9),
     510              :                                                         ErrorsFound,
     511              :                                                         DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctVAVReheat,
     512         2235 :                                                         Alphas(1),
     513              :                                                         DataLoopNode::NodeFluidType::Air,
     514              :                                                         DataLoopNode::ConnectionType::Outlet,
     515              :                                                         NodeInputManager::CompFluidStream::Primary,
     516              :                                                         ObjectIsParent,
     517         2235 :                                                         cAlphaFields(9));
     518         2235 :         if (airTerm.ReheatComp_Num == HeatingCoilType::SteamAirHeating) {
     519           13 :             airTerm.MaxReheatSteamVolFlow = Numbers(4);
     520           13 :             airTerm.MinReheatSteamVolFlow = Numbers(5);
     521              :         } else {
     522         2222 :             airTerm.MaxReheatWaterVolFlow = Numbers(4);
     523         2222 :             airTerm.MinReheatWaterVolFlow = Numbers(5);
     524              :         }
     525         2235 :         airTerm.ControllerOffset = Numbers(6);
     526              :         // Set default convergence tolerance
     527         2235 :         if (airTerm.ControllerOffset <= 0.0) {
     528            0 :             airTerm.ControllerOffset = 0.001;
     529              :         }
     530         2235 :         if (Util::SameString(Alphas(10), "Reverse")) {
     531           52 :             airTerm.DamperHeatingAction = Action::Reverse;
     532         2183 :         } else if (Util::SameString(Alphas(10), "Normal")) {
     533         1069 :             airTerm.DamperHeatingAction = Action::Normal;
     534         1114 :         } else if (Util::SameString(Alphas(10), "ReverseWithLimits")) {
     535         1114 :             airTerm.DamperHeatingAction = Action::ReverseWithLimits;
     536              :         } else {
     537            0 :             ShowSevereError(state, format("{} = {} not found.", cAlphaFields(10), Alphas(10)));
     538            0 :             ShowContinueError(state, format("Occurs in {} = {}", airTerm.sysType, airTerm.SysName));
     539            0 :             ErrorsFound = true;
     540              :         }
     541              : 
     542              :         // Register component set data
     543         4470 :         TestCompSet(state,
     544              :                     airTerm.sysType,
     545              :                     airTerm.SysName,
     546         2235 :                     state.dataLoopNodes->NodeID(airTerm.InletNodeNum),
     547         2235 :                     state.dataLoopNodes->NodeID(airTerm.ReheatAirOutletNode),
     548              :                     "Air Nodes");
     549              : 
     550        45328 :         for (ADUNum = 1; ADUNum <= (int)state.dataDefineEquipment->AirDistUnit.size(); ++ADUNum) {
     551        45328 :             if (airTerm.ReheatAirOutletNode == state.dataDefineEquipment->AirDistUnit(ADUNum).OutletNodeNum) {
     552         2235 :                 state.dataDefineEquipment->AirDistUnit(ADUNum).InletNodeNum = airTerm.InletNodeNum;
     553         2235 :                 airTerm.ADUNum = ADUNum;
     554         2235 :                 break;
     555              :             }
     556              :         }
     557              :         // one assumes if there isn't one assigned, it's an error?
     558         2235 :         if (airTerm.ADUNum == 0) {
     559            0 :             ShowSevereError(state,
     560            0 :                             format("{}No matching Air Distribution Unit, for System = [{},{}].", RoutineName, airTerm.sysType, airTerm.SysName));
     561            0 :             ShowContinueError(state, format("...should have outlet node = {}", state.dataLoopNodes->NodeID(airTerm.ReheatAirOutletNode)));
     562            0 :             ErrorsFound = true;
     563              :         } else {
     564              : 
     565              :             // Fill the Zone Equipment data with the inlet node number of this unit.
     566        96326 :             for (CtrlZone = 1; CtrlZone <= state.dataGlobal->NumOfZones; ++CtrlZone) {
     567        94091 :                 if (!state.dataZoneEquip->ZoneEquipConfig(CtrlZone).IsControlled) {
     568         5460 :                     continue;
     569              :                 }
     570       177897 :                 for (SupAirIn = 1; SupAirIn <= state.dataZoneEquip->ZoneEquipConfig(CtrlZone).NumInletNodes; ++SupAirIn) {
     571        89266 :                     if (airTerm.ReheatAirOutletNode == state.dataZoneEquip->ZoneEquipConfig(CtrlZone).InletNode(SupAirIn)) {
     572         2235 :                         if (state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).OutNode > 0) {
     573            0 :                             ShowSevereError(state, "Error in connecting a terminal unit to a zone");
     574            0 :                             ShowContinueError(
     575            0 :                                 state, format("{} already connects to another zone", state.dataLoopNodes->NodeID(airTerm.ReheatAirOutletNode)));
     576            0 :                             ShowContinueError(state, format("Occurs for terminal unit {} = {}", airTerm.sysType, airTerm.SysName));
     577            0 :                             ShowContinueError(state, "Check terminal unit node names for errors");
     578            0 :                             ErrorsFound = true;
     579              :                         } else {
     580         2235 :                             state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).InNode = airTerm.InletNodeNum;
     581         2235 :                             state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).OutNode = airTerm.ReheatAirOutletNode;
     582         2235 :                             state.dataDefineEquipment->AirDistUnit(airTerm.ADUNum).TermUnitSizingNum =
     583         2235 :                                 state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).TermUnitSizingIndex;
     584         2235 :                             state.dataDefineEquipment->AirDistUnit(airTerm.ADUNum).ZoneEqNum = CtrlZone;
     585              :                         }
     586              : 
     587         2235 :                         airTerm.CtrlZoneNum = CtrlZone;
     588         2235 :                         airTerm.CtrlZoneInNodeIndex = SupAirIn;
     589         2235 :                         airTerm.ZoneFloorArea = state.dataHeatBal->Zone(CtrlZone).FloorArea * state.dataHeatBal->Zone(CtrlZone).Multiplier *
     590         2235 :                                                 state.dataHeatBal->Zone(CtrlZone).ListMultiplier;
     591              :                     }
     592              :                 }
     593              :             }
     594              :         }
     595         2235 :         if (Numbers(7) == Constant::AutoCalculate) {
     596         2212 :             airTerm.MaxAirVolFlowRateDuringReheat = Numbers(7);
     597              :         } else {
     598           23 :             airTerm.MaxAirVolFlowRateDuringReheat = Numbers(7) * airTerm.ZoneFloorArea;
     599              :         }
     600              : 
     601         2235 :         airTerm.MaxAirVolFractionDuringReheat = Numbers(8);
     602              : 
     603         2235 :         if (airTerm.DamperHeatingAction != Action::ReverseWithLimits) {
     604         1121 :             if (airTerm.MaxAirVolFlowRateDuringReheat > 0.0) {
     605            0 :                 ShowWarningError(state, format("Since {} = {}, input for {} will be ignored.", cAlphaFields(10), Alphas(10), cNumericFields(7)));
     606            0 :                 ShowContinueError(state, format("Occurs in {} = {}", airTerm.sysType, airTerm.SysName));
     607              :             }
     608         1121 :             if (airTerm.MaxAirVolFractionDuringReheat > 0.0) {
     609           15 :                 ShowWarningError(state, format("Since {} = {}, input for {} will be ignored.", cAlphaFields(10), Alphas(10), cNumericFields(8)));
     610           15 :                 ShowContinueError(state, format("Occurs in {} = {}", airTerm.sysType, airTerm.SysName));
     611              :             }
     612              :         }
     613              : 
     614              :         // Maximum reheat air temperature, i.e. the maximum supply air temperature leaving the reheat coil
     615         2235 :         if (!lNumericBlanks(9)) {
     616          422 :             airTerm.MaxReheatTemp = Numbers(9);
     617          422 :             airTerm.MaxReheatTempSetByUser = true;
     618              :         } else {
     619              :             // user does not specify maximum supply air temperature
     620              :             // sd_airterminal(SysNum)%MaxReheatTemp = 35.0D0 !C
     621         1813 :             airTerm.MaxReheatTempSetByUser = false;
     622              :         }
     623              : 
     624         2235 :         if (!lAlphaBlanks(11)) {
     625          292 :             airTerm.OARequirementsPtr = Util::FindItemInList(Alphas(11), state.dataSize->OARequirements);
     626          292 :             if (airTerm.OARequirementsPtr == 0) {
     627            0 :                 ShowSevereError(state, format("{} = {} not found.", cAlphaFields(11), Alphas(11)));
     628            0 :                 ShowContinueError(state, format("Occurs in {} = {}", airTerm.sysType, airTerm.SysName));
     629            0 :                 ErrorsFound = true;
     630              :             } else {
     631          292 :                 airTerm.NoOAFlowInputFromUser = false;
     632              :             }
     633              :         }
     634              : 
     635         2235 :         if (lAlphaBlanks(12)) {
     636         2230 :             airTerm.ZoneTurndownMinAirFrac = 1.0;
     637            5 :         } else if ((airTerm.zoneTurndownMinAirFracSched = Sched::GetSchedule(state, Alphas(12))) == nullptr) {
     638            0 :             ShowSevereItemNotFound(state, eoh, cAlphaFields(12), Alphas(12));
     639            0 :             ErrorsFound = true;
     640              :         }
     641              : 
     642         2235 :         ValidateComponent(state, Alphas(7), Alphas(8), IsNotOK, airTerm.sysType);
     643         2235 :         if (IsNotOK) {
     644            0 :             ShowContinueError(state, format("In {} = {}", airTerm.sysType, airTerm.SysName));
     645            0 :             ErrorsFound = true;
     646              :         }
     647              : 
     648              :         // Add reheat coil to component sets array
     649         2235 :         SetUpCompSets(state, airTerm.sysType, airTerm.SysName, Alphas(7), Alphas(8), Alphas(3), Alphas(9));
     650              : 
     651              :         // Setup the Average damper Position output variable
     652         4470 :         SetupOutputVariable(state,
     653              :                             "Zone Air Terminal VAV Damper Position",
     654              :                             Constant::Units::None,
     655         2235 :                             airTerm.DamperPosition,
     656              :                             OutputProcessor::TimeStepType::System,
     657              :                             OutputProcessor::StoreType::Average,
     658         2235 :                             airTerm.SysName);
     659         4470 :         SetupOutputVariable(state,
     660              :                             "Zone Air Terminal Minimum Air Flow Fraction",
     661              :                             Constant::Units::None,
     662         2235 :                             airTerm.ZoneMinAirFracReport,
     663              :                             OutputProcessor::TimeStepType::System,
     664              :                             OutputProcessor::StoreType::Average,
     665         2235 :                             airTerm.SysName);
     666              : 
     667              :     } // end Number of Sys Loop
     668              : 
     669          534 :     for (state.dataSingleDuct->SysIndexGSI = 1; state.dataSingleDuct->SysIndexGSI <= state.dataSingleDuct->NumCBVAVSysGSI;
     670            9 :          ++state.dataSingleDuct->SysIndexGSI) {
     671              : 
     672            9 :         CurrentModuleObject = "AirTerminal:SingleDuct:VAV:HeatAndCool:Reheat";
     673              : 
     674           18 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     675              :                                                                  CurrentModuleObject,
     676            9 :                                                                  state.dataSingleDuct->SysIndexGSI,
     677              :                                                                  Alphas,
     678            9 :                                                                  state.dataSingleDuct->NumAlphasGSI,
     679              :                                                                  Numbers,
     680            9 :                                                                  state.dataSingleDuct->NumNumsGSI,
     681              :                                                                  IOStat,
     682              :                                                                  lNumericBlanks,
     683              :                                                                  lAlphaBlanks,
     684              :                                                                  cAlphaFields,
     685              :                                                                  cNumericFields);
     686              : 
     687            9 :         ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
     688            9 :         state.dataSingleDuct->SysNumGSI = state.dataSingleDuct->SysIndexGSI + state.dataSingleDuct->NumVAVSysGSI;
     689              : 
     690            9 :         auto &airTerm = state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI);
     691            9 :         airTerm.SysNum = state.dataSingleDuct->SysNumGSI;
     692            9 :         GlobalNames::VerifyUniqueInterObjectName(
     693           18 :             state, state.dataSingleDuct->SysUniqueNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
     694            9 :         airTerm.SysName = Alphas(1);
     695            9 :         airTerm.sysType = CurrentModuleObject;
     696            9 :         airTerm.SysType_Num = SysType::SingleDuctCBVAVReheat;
     697            9 :         airTerm.ReheatComp = Alphas(5);
     698            9 :         if (Util::SameString(airTerm.ReheatComp, "Coil:Heating:Fuel")) {
     699            0 :             airTerm.ReheatComp_Num = HeatingCoilType::Gas;
     700            9 :         } else if (Util::SameString(airTerm.ReheatComp, "Coil:Heating:Electric")) {
     701            9 :             airTerm.ReheatComp_Num = HeatingCoilType::Electric;
     702            0 :         } else if (Util::SameString(airTerm.ReheatComp, "Coil:Heating:Water")) {
     703            0 :             airTerm.ReheatComp_Num = HeatingCoilType::SimpleHeating;
     704            0 :             airTerm.ReheatComp_PlantType = DataPlant::PlantEquipmentType::CoilWaterSimpleHeating;
     705            0 :         } else if (Util::SameString(airTerm.ReheatComp, "Coil:Heating:Steam")) {
     706            0 :             airTerm.ReheatComp_Num = HeatingCoilType::SteamAirHeating;
     707            0 :             airTerm.ReheatComp_PlantType = DataPlant::PlantEquipmentType::CoilSteamAirHeating;
     708            0 :         } else if (!airTerm.ReheatComp.empty()) {
     709            0 :             ShowSevereError(state, format("Illegal {} = {}.", cAlphaFields(5), airTerm.ReheatComp));
     710            0 :             ShowContinueError(state, format("Occurs in {} = {}", airTerm.sysType, airTerm.SysName));
     711            0 :             ErrorsFound = true;
     712              :         }
     713            9 :         airTerm.ReheatName = Alphas(6);
     714            9 :         if (airTerm.ReheatComp_Num == HeatingCoilType::Gas || airTerm.ReheatComp_Num == HeatingCoilType::Electric) {
     715            9 :             HeatingCoils::GetCoilIndex(state, airTerm.ReheatName, airTerm.ReheatComp_Index, ErrorsFound);
     716            9 :             if (airTerm.ReheatComp_Index == 0) {
     717            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(6), Alphas(6));
     718            0 :                 ErrorsFound = true;
     719              :             }
     720            0 :         } else if (airTerm.ReheatComp_Num == HeatingCoilType::SimpleHeating) {
     721            0 :             airTerm.ReheatComp_Index = WaterCoils::GetWaterCoilIndex(state, airTerm.ReheatComp, airTerm.ReheatName, ErrorsFound);
     722            0 :             if (airTerm.ReheatComp_Index == 0) {
     723            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(6), Alphas(6));
     724            0 :                 ErrorsFound = true;
     725              :             }
     726            0 :         } else if (airTerm.ReheatComp_Num == HeatingCoilType::SteamAirHeating) {
     727            0 :             airTerm.ReheatComp_Index = SteamCoils::GetSteamCoilIndex(state, airTerm.ReheatComp, airTerm.ReheatName, ErrorsFound);
     728            0 :             if (airTerm.ReheatComp_Index == 0) {
     729            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(6), Alphas(6));
     730            0 :                 ErrorsFound = true;
     731              :             }
     732              :         }
     733              : 
     734            9 :         if (lAlphaBlanks(2)) {
     735            1 :             airTerm.availSched = Sched::GetScheduleAlwaysOn(state);
     736            8 :         } else if ((airTerm.availSched = Sched::GetSchedule(state, Alphas(2))) == nullptr) {
     737            0 :             ShowSevereItemNotFound(state, eoh, cAlphaFields(2), Alphas(2));
     738            0 :             ErrorsFound = true;
     739              :         }
     740              :         // For node connections, this object is both a parent and a non-parent, because the
     741              :         // VAV damper is not called out as a separate component, its nodes must be connected
     742              :         // as ObjectIsNotParent.  But for the reheat coil, the nodes are connected as ObjectIsParent
     743           27 :         airTerm.OutletNodeNum = GetOnlySingleNode(state,
     744            9 :                                                   Alphas(3),
     745              :                                                   ErrorsFound,
     746              :                                                   DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctVAVHeatAndCoolReheat,
     747            9 :                                                   Alphas(1),
     748              :                                                   DataLoopNode::NodeFluidType::Air,
     749              :                                                   DataLoopNode::ConnectionType::Outlet,
     750              :                                                   NodeInputManager::CompFluidStream::Primary,
     751              :                                                   ObjectIsNotParent,
     752            9 :                                                   cAlphaFields(3));
     753           27 :         airTerm.InletNodeNum = GetOnlySingleNode(state,
     754            9 :                                                  Alphas(4),
     755              :                                                  ErrorsFound,
     756              :                                                  DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctVAVHeatAndCoolReheat,
     757            9 :                                                  Alphas(1),
     758              :                                                  DataLoopNode::NodeFluidType::Air,
     759              :                                                  DataLoopNode::ConnectionType::Inlet,
     760              :                                                  NodeInputManager::CompFluidStream::Primary,
     761              :                                                  ObjectIsNotParent,
     762            9 :                                                  cAlphaFields(4));
     763            9 :         airTerm.MaxAirVolFlowRate = Numbers(1);
     764            9 :         airTerm.ZoneMinAirFracDes = Numbers(2);
     765            9 :         if (airTerm.ZoneMinAirFracDes < 0.0) {
     766            0 :             ShowWarningError(state, format("{} \"{}\"", airTerm.sysType, airTerm.SysName));
     767            0 :             ShowContinueError(state,
     768            0 :                               format("{} must be greater than or equal to 0. Resetting to 0 and the simulation continues.", cNumericFields(2)));
     769            0 :             airTerm.ZoneMinAirFracDes = 0.0;
     770              :         }
     771            9 :         if (airTerm.ZoneMinAirFracDes > 1.0) {
     772            0 :             ShowWarningError(state, format("{} \"{}\"", airTerm.sysType, airTerm.SysName));
     773            0 :             ShowContinueError(state, format("{} must be less than or equal to 1. Resetting to 1 and the simulation continues.", cNumericFields(2)));
     774            0 :             airTerm.ZoneMinAirFracDes = 1.0;
     775              :         }
     776              :         // The reheat coil control node is necessary for hot water and steam reheat, but not necessary for
     777              :         // electric or gas reheat.
     778            9 :         if (airTerm.ReheatComp_Num == HeatingCoilType::Gas || airTerm.ReheatComp_Num == HeatingCoilType::Electric) {
     779              :         } else {
     780            0 :             if (airTerm.ReheatComp_Num == HeatingCoilType::SteamAirHeating) {
     781            0 :                 IsNotOK = false;
     782            0 :                 airTerm.ReheatControlNode = GetCoilSteamInletNode(state, airTerm.ReheatComp, airTerm.ReheatName, IsNotOK);
     783            0 :                 if (IsNotOK) {
     784            0 :                     ShowContinueError(state, format("..Occurs in {} = {}", airTerm.sysType, airTerm.SysName));
     785            0 :                     ErrorsFound = true;
     786              :                 }
     787              :             } else {
     788            0 :                 IsNotOK = false;
     789            0 :                 airTerm.ReheatControlNode = GetCoilWaterInletNode(state, airTerm.ReheatComp, airTerm.ReheatName, IsNotOK);
     790            0 :                 if (IsNotOK) {
     791            0 :                     ShowContinueError(state, format("..Occurs in {} = {}", airTerm.sysType, airTerm.SysName));
     792            0 :                     ErrorsFound = true;
     793              :                 }
     794              :             }
     795              :             //  END IF
     796              :         }
     797           27 :         airTerm.ReheatAirOutletNode = GetOnlySingleNode(state,
     798            9 :                                                         Alphas(7),
     799              :                                                         ErrorsFound,
     800              :                                                         DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctVAVHeatAndCoolReheat,
     801            9 :                                                         Alphas(1),
     802              :                                                         DataLoopNode::NodeFluidType::Air,
     803              :                                                         DataLoopNode::ConnectionType::Outlet,
     804              :                                                         NodeInputManager::CompFluidStream::Primary,
     805              :                                                         ObjectIsParent,
     806            9 :                                                         cAlphaFields(7));
     807            9 :         if (airTerm.ReheatComp_Num == HeatingCoilType::SteamAirHeating) {
     808            0 :             airTerm.MaxReheatSteamVolFlow = Numbers(3);
     809            0 :             airTerm.MinReheatSteamVolFlow = Numbers(4);
     810              :         } else {
     811            9 :             airTerm.MaxReheatWaterVolFlow = Numbers(3);
     812            9 :             airTerm.MinReheatWaterVolFlow = Numbers(4);
     813              :         }
     814            9 :         airTerm.ControllerOffset = Numbers(5);
     815              :         // Set default convergence tolerance
     816            9 :         if (airTerm.ControllerOffset <= 0.0) {
     817            0 :             airTerm.ControllerOffset = 0.001;
     818              :         }
     819              : 
     820            9 :         airTerm.DamperHeatingAction = Action::Reverse;
     821              : 
     822              :         // Register component set data
     823           18 :         TestCompSet(state,
     824              :                     airTerm.sysType,
     825              :                     airTerm.SysName,
     826            9 :                     state.dataLoopNodes->NodeID(airTerm.InletNodeNum),
     827            9 :                     state.dataLoopNodes->NodeID(airTerm.ReheatAirOutletNode),
     828              :                     "Air Nodes");
     829              : 
     830           17 :         for (ADUNum = 1; ADUNum <= (int)state.dataDefineEquipment->AirDistUnit.size(); ++ADUNum) {
     831           17 :             if (airTerm.ReheatAirOutletNode == state.dataDefineEquipment->AirDistUnit(ADUNum).OutletNodeNum) {
     832            9 :                 state.dataDefineEquipment->AirDistUnit(ADUNum).InletNodeNum = airTerm.InletNodeNum;
     833            9 :                 airTerm.ADUNum = ADUNum;
     834            9 :                 break;
     835              :             }
     836              :         }
     837              :         // one assumes if there isn't one assigned, it's an error?
     838            9 :         if (airTerm.ADUNum == 0) {
     839            0 :             ShowSevereError(state,
     840            0 :                             format("{}No matching Air Distribution Unit, for System = [{},{}].", RoutineName, airTerm.sysType, airTerm.SysName));
     841            0 :             ShowContinueError(state, format("...should have outlet node = {}", state.dataLoopNodes->NodeID(airTerm.ReheatAirOutletNode)));
     842            0 :             ErrorsFound = true;
     843              :         } else {
     844              : 
     845              :             // Fill the Zone Equipment data with the inlet node number of this unit
     846           39 :             for (CtrlZone = 1; CtrlZone <= state.dataGlobal->NumOfZones; ++CtrlZone) {
     847           30 :                 if (!state.dataZoneEquip->ZoneEquipConfig(CtrlZone).IsControlled) {
     848            1 :                     continue;
     849              :                 }
     850           58 :                 for (SupAirIn = 1; SupAirIn <= state.dataZoneEquip->ZoneEquipConfig(CtrlZone).NumInletNodes; ++SupAirIn) {
     851           29 :                     if (airTerm.ReheatAirOutletNode == state.dataZoneEquip->ZoneEquipConfig(CtrlZone).InletNode(SupAirIn)) {
     852            9 :                         if (state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).OutNode > 0) {
     853            0 :                             ShowSevereError(state, "Error in connecting a terminal unit to a zone");
     854            0 :                             ShowContinueError(
     855            0 :                                 state, format("{} already connects to another zone", state.dataLoopNodes->NodeID(airTerm.ReheatAirOutletNode)));
     856            0 :                             ShowContinueError(state, format("Occurs for terminal unit {} = {}", airTerm.sysType, airTerm.SysName));
     857            0 :                             ShowContinueError(state, "Check terminal unit node names for errors");
     858            0 :                             ErrorsFound = true;
     859              :                         } else {
     860            9 :                             state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).InNode = airTerm.InletNodeNum;
     861            9 :                             state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).OutNode = airTerm.ReheatAirOutletNode;
     862            9 :                             state.dataDefineEquipment->AirDistUnit(airTerm.ADUNum).TermUnitSizingNum =
     863            9 :                                 state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).TermUnitSizingIndex;
     864            9 :                             state.dataDefineEquipment->AirDistUnit(airTerm.ADUNum).ZoneEqNum = CtrlZone;
     865              :                         }
     866            9 :                         airTerm.CtrlZoneNum = CtrlZone;
     867            9 :                         airTerm.CtrlZoneInNodeIndex = SupAirIn;
     868            9 :                         airTerm.ZoneFloorArea = state.dataHeatBal->Zone(CtrlZone).FloorArea * state.dataHeatBal->Zone(CtrlZone).Multiplier *
     869            9 :                                                 state.dataHeatBal->Zone(CtrlZone).ListMultiplier;
     870              :                     }
     871              :                 }
     872              :             }
     873              :         }
     874            9 :         if (!lNumericBlanks(6)) {
     875            3 :             airTerm.MaxReheatTemp = Numbers(6);
     876            3 :             airTerm.MaxReheatTempSetByUser = true;
     877              :         } else {
     878              :             // user does not specify maximum supply air temperature
     879              :             // sd_airterminal(SysNum)%MaxReheatTemp = 35.0D0 !C
     880            6 :             airTerm.MaxReheatTempSetByUser = false;
     881              :         }
     882              : 
     883            9 :         ValidateComponent(state, Alphas(5), Alphas(6), IsNotOK, airTerm.sysType);
     884            9 :         if (IsNotOK) {
     885            0 :             ShowContinueError(state, format("In {} = {}", airTerm.sysType, airTerm.SysName));
     886            0 :             ErrorsFound = true;
     887              :         }
     888              : 
     889            9 :         if (lAlphaBlanks(8)) {
     890            9 :             airTerm.ZoneTurndownMinAirFrac = 1.0;
     891            0 :         } else if ((airTerm.zoneTurndownMinAirFracSched = Sched::GetSchedule(state, Alphas(8))) == nullptr) {
     892            0 :             ShowSevereItemNotFound(state, eoh, cAlphaFields(8), Alphas(8));
     893            0 :             ErrorsFound = true;
     894              :         }
     895              : 
     896              :         // Add reheat coil to component sets array
     897            9 :         SetUpCompSets(state, airTerm.sysType, airTerm.SysName, Alphas(5), Alphas(6), Alphas(3), Alphas(7));
     898              : 
     899              :         // Setup the Average damper Position output variable
     900           18 :         SetupOutputVariable(state,
     901              :                             "Zone Air Terminal VAV Damper Position",
     902              :                             Constant::Units::None,
     903            9 :                             airTerm.DamperPosition,
     904              :                             OutputProcessor::TimeStepType::System,
     905              :                             OutputProcessor::StoreType::Average,
     906            9 :                             airTerm.SysName);
     907              : 
     908              :     } // end Number of VAVHeatandCool Sys Loop
     909              : 
     910          525 :     CurrentModuleObject = "AirTerminal:SingleDuct:ConstantVolume:Reheat";
     911              : 
     912          794 :     for (state.dataSingleDuct->SysIndexGSI = 1; state.dataSingleDuct->SysIndexGSI <= state.dataSingleDuct->NumConstVolSys;
     913          269 :          ++state.dataSingleDuct->SysIndexGSI) {
     914              : 
     915          538 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     916              :                                                                  CurrentModuleObject,
     917          269 :                                                                  state.dataSingleDuct->SysIndexGSI,
     918              :                                                                  Alphas,
     919          269 :                                                                  state.dataSingleDuct->NumAlphasGSI,
     920              :                                                                  Numbers,
     921          269 :                                                                  state.dataSingleDuct->NumNumsGSI,
     922              :                                                                  IOStat,
     923              :                                                                  lNumericBlanks,
     924              :                                                                  lAlphaBlanks,
     925              :                                                                  cAlphaFields,
     926              :                                                                  cNumericFields);
     927              : 
     928          269 :         ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
     929              : 
     930          538 :         state.dataSingleDuct->SysNumGSI =
     931          269 :             state.dataSingleDuct->SysIndexGSI + state.dataSingleDuct->NumVAVSysGSI + state.dataSingleDuct->NumCBVAVSysGSI;
     932          269 :         auto &airTerm = state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI);
     933              : 
     934          269 :         airTerm.SysNum = state.dataSingleDuct->SysNumGSI;
     935          269 :         GlobalNames::VerifyUniqueInterObjectName(
     936          538 :             state, state.dataSingleDuct->SysUniqueNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
     937          269 :         airTerm.SysName = Alphas(1);
     938          269 :         airTerm.sysType = CurrentModuleObject;
     939          269 :         airTerm.SysType_Num = SysType::SingleDuctConstVolReheat;
     940          269 :         airTerm.ReheatComp = Alphas(5);
     941          269 :         if (Util::SameString(airTerm.ReheatComp, "Coil:Heating:Fuel")) {
     942           38 :             airTerm.ReheatComp_Num = HeatingCoilType::Gas;
     943          231 :         } else if (Util::SameString(airTerm.ReheatComp, "Coil:Heating:Electric")) {
     944            4 :             airTerm.ReheatComp_Num = HeatingCoilType::Electric;
     945          227 :         } else if (Util::SameString(airTerm.ReheatComp, "Coil:Heating:Water")) {
     946          227 :             airTerm.ReheatComp_Num = HeatingCoilType::SimpleHeating;
     947          227 :             airTerm.ReheatComp_PlantType = DataPlant::PlantEquipmentType::CoilWaterSimpleHeating;
     948            0 :         } else if (Util::SameString(airTerm.ReheatComp, "Coil:Heating:Steam")) {
     949            0 :             airTerm.ReheatComp_Num = HeatingCoilType::SteamAirHeating;
     950            0 :             airTerm.ReheatComp_PlantType = DataPlant::PlantEquipmentType::CoilSteamAirHeating;
     951              :         } else {
     952            0 :             ShowSevereError(state, format("Illegal {} = {}.", cAlphaFields(5), airTerm.ReheatComp));
     953            0 :             ShowContinueError(state, format("Occurs in {} = {}", airTerm.sysType, airTerm.SysName));
     954            0 :             ErrorsFound = true;
     955              :         }
     956          269 :         airTerm.ReheatName = Alphas(6);
     957          269 :         if (airTerm.ReheatComp_Num == HeatingCoilType::Gas || airTerm.ReheatComp_Num == HeatingCoilType::Electric) {
     958           42 :             HeatingCoils::GetCoilIndex(state, airTerm.ReheatName, airTerm.ReheatComp_Index, ErrorsFound);
     959           42 :             if (airTerm.ReheatComp_Index == 0) {
     960            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(6), Alphas(6));
     961            0 :                 ErrorsFound = true;
     962              :             }
     963          227 :         } else if (airTerm.ReheatComp_Num == HeatingCoilType::SimpleHeating) {
     964          227 :             airTerm.ReheatComp_Index = WaterCoils::GetWaterCoilIndex(state, airTerm.ReheatComp, airTerm.ReheatName, ErrorsFound);
     965          227 :             if (airTerm.ReheatComp_Index == 0) {
     966            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(6), Alphas(6));
     967            0 :                 ErrorsFound = true;
     968              :             }
     969            0 :         } else if (airTerm.ReheatComp_Num == HeatingCoilType::SteamAirHeating) {
     970            0 :             airTerm.ReheatComp_Index = SteamCoils::GetSteamCoilIndex(state, airTerm.ReheatComp, airTerm.ReheatName, ErrorsFound);
     971            0 :             if (airTerm.ReheatComp_Index == 0) {
     972            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(6), Alphas(6));
     973            0 :                 ErrorsFound = true;
     974              :             }
     975              :         }
     976              : 
     977          269 :         if (lAlphaBlanks(2)) {
     978            4 :             airTerm.availSched = Sched::GetScheduleAlwaysOn(state);
     979          265 :         } else if ((airTerm.availSched = Sched::GetSchedule(state, Alphas(2))) == nullptr) {
     980            0 :             ShowSevereItemNotFound(state, eoh, cAlphaFields(2), Alphas(2));
     981            0 :             ErrorsFound = true;
     982              :         }
     983              : 
     984          807 :         airTerm.OutletNodeNum = GetOnlySingleNode(state,
     985          269 :                                                   Alphas(3),
     986              :                                                   ErrorsFound,
     987              :                                                   DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctConstantVolumeReheat,
     988          269 :                                                   Alphas(1),
     989              :                                                   DataLoopNode::NodeFluidType::Air,
     990              :                                                   DataLoopNode::ConnectionType::Outlet,
     991              :                                                   NodeInputManager::CompFluidStream::Primary,
     992              :                                                   ObjectIsParent,
     993          269 :                                                   cAlphaFields(3));
     994          807 :         airTerm.InletNodeNum = GetOnlySingleNode(state,
     995          269 :                                                  Alphas(4),
     996              :                                                  ErrorsFound,
     997              :                                                  DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctConstantVolumeReheat,
     998          269 :                                                  Alphas(1),
     999              :                                                  DataLoopNode::NodeFluidType::Air,
    1000              :                                                  DataLoopNode::ConnectionType::Inlet,
    1001              :                                                  NodeInputManager::CompFluidStream::Primary,
    1002              :                                                  ObjectIsParent,
    1003          269 :                                                  cAlphaFields(4));
    1004              :         // The reheat coil control node is necessary for hot water reheat, but not necessary for
    1005              :         // electric or gas reheat.
    1006          269 :         if (airTerm.ReheatComp_Num == HeatingCoilType::Gas || airTerm.ReheatComp_Num == HeatingCoilType::Electric) {
    1007              :         } else {
    1008          227 :             if (airTerm.ReheatComp_Num == HeatingCoilType::SteamAirHeating) {
    1009            0 :                 IsNotOK = false;
    1010            0 :                 airTerm.ReheatControlNode = GetCoilSteamInletNode(state, airTerm.ReheatComp, airTerm.ReheatName, IsNotOK);
    1011            0 :                 if (IsNotOK) {
    1012            0 :                     ShowContinueError(state, format("..Occurs in {} = {}", airTerm.sysType, airTerm.SysName));
    1013            0 :                     ErrorsFound = true;
    1014              :                 }
    1015              :             } else {
    1016          227 :                 IsNotOK = false;
    1017          227 :                 airTerm.ReheatControlNode = GetCoilWaterInletNode(state, airTerm.ReheatComp, airTerm.ReheatName, IsNotOK);
    1018          227 :                 if (IsNotOK) {
    1019            0 :                     ShowContinueError(state, format("..Occurs in {} = {}", airTerm.sysType, airTerm.SysName));
    1020            0 :                     ErrorsFound = true;
    1021              :                 }
    1022              :             }
    1023              :         }
    1024          269 :         airTerm.ReheatAirOutletNode = airTerm.OutletNodeNum;
    1025          269 :         airTerm.MaxAirVolFlowRate = Numbers(1);
    1026          269 :         airTerm.ZoneMinAirFracDes = 0.0;
    1027          269 :         airTerm.ZoneMinAirFracMethod = MinFlowFraction::MinFracNotUsed;
    1028          269 :         airTerm.DamperHeatingAction = Action::HeatingNotUsed;
    1029          269 :         if (airTerm.ReheatComp_Num == HeatingCoilType::SteamAirHeating) {
    1030            0 :             airTerm.MaxReheatSteamVolFlow = Numbers(2);
    1031            0 :             airTerm.MinReheatSteamVolFlow = Numbers(3);
    1032              :         } else {
    1033          269 :             airTerm.MaxReheatWaterVolFlow = Numbers(2);
    1034          269 :             airTerm.MinReheatWaterVolFlow = Numbers(3);
    1035              :         }
    1036          269 :         airTerm.ControllerOffset = Numbers(4);
    1037              :         // Set default convergence tolerance
    1038          269 :         if (airTerm.ControllerOffset <= 0.0) {
    1039            0 :             airTerm.ControllerOffset = 0.001;
    1040              :         }
    1041              : 
    1042              :         // Maximum reheat air temperature, i.e. the maximum supply air temperature leaving the reheat coil
    1043          269 :         if (!lNumericBlanks(5)) {
    1044            4 :             airTerm.MaxReheatTemp = Numbers(5);
    1045            4 :             airTerm.MaxReheatTempSetByUser = true;
    1046              :         } else {
    1047              :             // user does not specify maximum supply air temperature
    1048              :             // sd_airterminal(SysNum)%MaxReheatTemp = 35.0D0 !C
    1049          265 :             airTerm.MaxReheatTempSetByUser = false;
    1050              :         }
    1051              :         // Register component set data
    1052          538 :         TestCompSet(state,
    1053              :                     airTerm.sysType,
    1054              :                     airTerm.SysName,
    1055          269 :                     state.dataLoopNodes->NodeID(airTerm.InletNodeNum),
    1056          269 :                     state.dataLoopNodes->NodeID(airTerm.OutletNodeNum),
    1057              :                     "Air Nodes");
    1058              : 
    1059          560 :         for (ADUNum = 1; ADUNum <= (int)state.dataDefineEquipment->AirDistUnit.size(); ++ADUNum) {
    1060          560 :             if (airTerm.ReheatAirOutletNode == state.dataDefineEquipment->AirDistUnit(ADUNum).OutletNodeNum) {
    1061          269 :                 state.dataDefineEquipment->AirDistUnit(ADUNum).InletNodeNum = airTerm.InletNodeNum;
    1062          269 :                 airTerm.ADUNum = ADUNum;
    1063          269 :                 break;
    1064              :             }
    1065              :         }
    1066              :         // one assumes if there isn't one assigned, it's an error?
    1067          269 :         if (airTerm.ADUNum == 0) {
    1068            0 :             ShowSevereError(state,
    1069            0 :                             format("{}No matching Air Distribution Unit, for System = [{},{}].", RoutineName, airTerm.sysType, airTerm.SysName));
    1070            0 :             ShowContinueError(state, format("...should have outlet node = {}", state.dataLoopNodes->NodeID(airTerm.ReheatAirOutletNode)));
    1071            0 :             ErrorsFound = true;
    1072              :         } else {
    1073              : 
    1074              :             // Fill the Zone Equipment data with the inlet node number of this unit.
    1075         1204 :             for (CtrlZone = 1; CtrlZone <= state.dataGlobal->NumOfZones; ++CtrlZone) {
    1076          935 :                 if (!state.dataZoneEquip->ZoneEquipConfig(CtrlZone).IsControlled) {
    1077           66 :                     continue;
    1078              :                 }
    1079         1738 :                 for (SupAirIn = 1; SupAirIn <= state.dataZoneEquip->ZoneEquipConfig(CtrlZone).NumInletNodes; ++SupAirIn) {
    1080          869 :                     if (airTerm.OutletNodeNum == state.dataZoneEquip->ZoneEquipConfig(CtrlZone).InletNode(SupAirIn)) {
    1081          269 :                         if (state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).OutNode > 0) {
    1082            0 :                             ShowSevereError(state, "Error in connecting a terminal unit to a zone");
    1083            0 :                             ShowContinueError(state,
    1084            0 :                                               format("{} already connects to another zone", state.dataLoopNodes->NodeID(airTerm.OutletNodeNum)));
    1085            0 :                             ShowContinueError(state, format("Occurs for terminal unit {} = {}", airTerm.sysType, airTerm.SysName));
    1086            0 :                             ShowContinueError(state, "Check terminal unit node names for errors");
    1087            0 :                             ErrorsFound = true;
    1088              :                         } else {
    1089          269 :                             state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).InNode = airTerm.InletNodeNum;
    1090          269 :                             state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).OutNode = airTerm.OutletNodeNum;
    1091          269 :                             state.dataDefineEquipment->AirDistUnit(airTerm.ADUNum).TermUnitSizingNum =
    1092          269 :                                 state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).TermUnitSizingIndex;
    1093          269 :                             state.dataDefineEquipment->AirDistUnit(airTerm.ADUNum).ZoneEqNum = CtrlZone;
    1094              :                         }
    1095          269 :                         airTerm.CtrlZoneNum = CtrlZone;
    1096          269 :                         airTerm.CtrlZoneInNodeIndex = SupAirIn;
    1097          269 :                         airTerm.ZoneFloorArea = state.dataHeatBal->Zone(CtrlZone).FloorArea * state.dataHeatBal->Zone(CtrlZone).Multiplier *
    1098          269 :                                                 state.dataHeatBal->Zone(CtrlZone).ListMultiplier;
    1099              :                     }
    1100              :                 }
    1101              :             }
    1102              :         }
    1103              : 
    1104          269 :         ValidateComponent(state, Alphas(5), Alphas(6), IsNotOK, airTerm.sysType);
    1105          269 :         if (IsNotOK) {
    1106            0 :             ShowContinueError(state, format("In {} = {}", airTerm.sysType, airTerm.SysName));
    1107            0 :             ErrorsFound = true;
    1108              :         }
    1109              : 
    1110              :         // Add reheat coil to component sets array
    1111          269 :         SetUpCompSets(state, airTerm.sysType, airTerm.SysName, Alphas(5), Alphas(6), Alphas(4), Alphas(3));
    1112              : 
    1113              :         // Setup the Average damper Position output variable
    1114              :         // BG removed 9-10-2009 during work on CR 7770, constant volume has no damper
    1115              :         //  CALL SetupOutputVariable(state, 'Damper Position', Sys(SysNum)%DamperPosition, &
    1116              :         //                        'System','Average',Sys(SysNum)%SysName)
    1117              : 
    1118              :     } // End Number of Sys Loop
    1119              : 
    1120          525 :     CurrentModuleObject = "AirTerminal:SingleDuct:ConstantVolume:NoReheat";
    1121              : 
    1122         1389 :     for (state.dataSingleDuct->SysIndexGSI = 1; state.dataSingleDuct->SysIndexGSI <= state.dataSingleDuct->NumCVNoReheatSysGSI;
    1123          864 :          ++state.dataSingleDuct->SysIndexGSI) {
    1124              : 
    1125         1728 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1126              :                                                                  CurrentModuleObject,
    1127          864 :                                                                  state.dataSingleDuct->SysIndexGSI,
    1128              :                                                                  Alphas,
    1129          864 :                                                                  state.dataSingleDuct->NumAlphasGSI,
    1130              :                                                                  Numbers,
    1131          864 :                                                                  state.dataSingleDuct->NumNumsGSI,
    1132              :                                                                  IOStat,
    1133              :                                                                  lNumericBlanks,
    1134              :                                                                  lAlphaBlanks,
    1135              :                                                                  cAlphaFields,
    1136              :                                                                  cNumericFields);
    1137              : 
    1138          864 :         ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    1139              : 
    1140          864 :         state.dataSingleDuct->SysNumGSI = state.dataSingleDuct->SysIndexGSI + state.dataSingleDuct->NumVAVSysGSI +
    1141          864 :                                           state.dataSingleDuct->NumCBVAVSysGSI + state.dataSingleDuct->NumConstVolSys;
    1142          864 :         auto &airTerm = state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI);
    1143              : 
    1144          864 :         airTerm.SysNum = state.dataSingleDuct->SysNumGSI;
    1145          864 :         GlobalNames::VerifyUniqueInterObjectName(
    1146         1728 :             state, state.dataSingleDuct->SysUniqueNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
    1147          864 :         airTerm.SysName = Alphas(1);
    1148          864 :         airTerm.sysType = CurrentModuleObject;
    1149          864 :         airTerm.SysType_Num = SysType::SingleDuctConstVolNoReheat;
    1150              : 
    1151          864 :         if (lAlphaBlanks(2)) {
    1152          115 :             airTerm.availSched = Sched::GetScheduleAlwaysOn(state);
    1153          749 :         } else if ((airTerm.availSched = Sched::GetSchedule(state, Alphas(2))) == nullptr) {
    1154            0 :             ShowSevereItemNotFound(state, eoh, cAlphaFields(2), Alphas(2));
    1155            0 :             ErrorsFound = true;
    1156              :         }
    1157              : 
    1158         2592 :         airTerm.InletNodeNum = GetOnlySingleNode(state,
    1159          864 :                                                  Alphas(3),
    1160              :                                                  ErrorsFound,
    1161              :                                                  DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctConstantVolumeNoReheat,
    1162          864 :                                                  Alphas(1),
    1163              :                                                  DataLoopNode::NodeFluidType::Air,
    1164              :                                                  DataLoopNode::ConnectionType::Inlet,
    1165              :                                                  NodeInputManager::CompFluidStream::Primary,
    1166              :                                                  ObjectIsNotParent,
    1167          864 :                                                  cAlphaFields(3));
    1168         2592 :         airTerm.OutletNodeNum = GetOnlySingleNode(state,
    1169          864 :                                                   Alphas(4),
    1170              :                                                   ErrorsFound,
    1171              :                                                   DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctConstantVolumeNoReheat,
    1172          864 :                                                   Alphas(1),
    1173              :                                                   DataLoopNode::NodeFluidType::Air,
    1174              :                                                   DataLoopNode::ConnectionType::Outlet,
    1175              :                                                   NodeInputManager::CompFluidStream::Primary,
    1176              :                                                   ObjectIsNotParent,
    1177          864 :                                                   cAlphaFields(4));
    1178              : 
    1179          864 :         airTerm.MaxAirVolFlowRate = Numbers(1);
    1180          864 :         airTerm.ZoneMinAirFracDes = 0.0;
    1181          864 :         airTerm.ZoneMinAirFracMethod = MinFlowFraction::MinFracNotUsed;
    1182          864 :         airTerm.DamperHeatingAction = Action::HeatingNotUsed;
    1183              : 
    1184          864 :         airTerm.ReheatControlNode = 0;
    1185          864 :         airTerm.ReheatAirOutletNode = airTerm.OutletNodeNum;
    1186          864 :         airTerm.MaxReheatWaterVolFlow = 0.0;
    1187          864 :         airTerm.MaxReheatSteamVolFlow = 0.0;
    1188          864 :         airTerm.MinReheatWaterVolFlow = 0.0;
    1189          864 :         airTerm.MinReheatSteamVolFlow = 0.0;
    1190          864 :         airTerm.ControllerOffset = 0.000001;
    1191              : 
    1192              :         // Register component set data
    1193         1728 :         TestCompSet(state,
    1194              :                     airTerm.sysType,
    1195              :                     airTerm.SysName,
    1196          864 :                     state.dataLoopNodes->NodeID(airTerm.InletNodeNum),
    1197          864 :                     state.dataLoopNodes->NodeID(airTerm.OutletNodeNum),
    1198              :                     "Air Nodes");
    1199              : 
    1200         6810 :         for (ADUNum = 1; ADUNum <= (int)state.dataDefineEquipment->AirDistUnit.size(); ++ADUNum) {
    1201         6810 :             if (airTerm.OutletNodeNum == state.dataDefineEquipment->AirDistUnit(ADUNum).OutletNodeNum) {
    1202          864 :                 state.dataDefineEquipment->AirDistUnit(ADUNum).InletNodeNum = airTerm.InletNodeNum;
    1203          864 :                 airTerm.ADUNum = ADUNum;
    1204          864 :                 break;
    1205              :             }
    1206              :         }
    1207              :         // one assumes if there isn't one assigned, it's an error?
    1208          864 :         if (airTerm.ADUNum == 0) {
    1209            0 :             ShowSevereError(state,
    1210            0 :                             format("{}No matching Air Distribution Unit, for System = [{},{}].", RoutineName, airTerm.sysType, airTerm.SysName));
    1211            0 :             ShowContinueError(state, format("...should have outlet node = {}", state.dataLoopNodes->NodeID(airTerm.OutletNodeNum)));
    1212            0 :             ErrorsFound = true;
    1213              :         } else {
    1214              : 
    1215              :             // Fill the Zone Equipment data with the inlet node number of this unit.
    1216        16699 :             for (CtrlZone = 1; CtrlZone <= state.dataGlobal->NumOfZones; ++CtrlZone) {
    1217        15835 :                 if (!state.dataZoneEquip->ZoneEquipConfig(CtrlZone).IsControlled) {
    1218         1680 :                     continue;
    1219              :                 }
    1220        35394 :                 for (SupAirIn = 1; SupAirIn <= state.dataZoneEquip->ZoneEquipConfig(CtrlZone).NumInletNodes; ++SupAirIn) {
    1221        21239 :                     if (airTerm.OutletNodeNum == state.dataZoneEquip->ZoneEquipConfig(CtrlZone).InletNode(SupAirIn)) {
    1222          864 :                         if (state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).OutNode > 0) {
    1223            0 :                             ShowSevereError(state, "Error in connecting a terminal unit to a zone");
    1224            0 :                             ShowContinueError(state,
    1225            0 :                                               format("{} already connects to another zone", state.dataLoopNodes->NodeID(airTerm.OutletNodeNum)));
    1226            0 :                             ShowContinueError(state, format("Occurs for terminal unit {} = {}", airTerm.sysType, airTerm.SysName));
    1227            0 :                             ShowContinueError(state, "Check terminal unit node names for errors");
    1228            0 :                             ErrorsFound = true;
    1229              :                         } else {
    1230          864 :                             state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).InNode = airTerm.InletNodeNum;
    1231          864 :                             state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).OutNode = airTerm.OutletNodeNum;
    1232          864 :                             state.dataDefineEquipment->AirDistUnit(airTerm.ADUNum).TermUnitSizingNum =
    1233          864 :                                 state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).TermUnitSizingIndex;
    1234          864 :                             state.dataDefineEquipment->AirDistUnit(airTerm.ADUNum).ZoneEqNum = CtrlZone;
    1235              :                         }
    1236          864 :                         airTerm.CtrlZoneNum = CtrlZone;
    1237          864 :                         airTerm.CtrlZoneInNodeIndex = SupAirIn;
    1238          864 :                         airTerm.ZoneFloorArea = state.dataHeatBal->Zone(CtrlZone).FloorArea * state.dataHeatBal->Zone(CtrlZone).Multiplier *
    1239          864 :                                                 state.dataHeatBal->Zone(CtrlZone).ListMultiplier;
    1240              :                     }
    1241              :                 }
    1242              :             }
    1243              :         }
    1244              : 
    1245          864 :         if (lAlphaBlanks(5)) {
    1246          862 :             airTerm.NoOAFlowInputFromUser = true;
    1247              :         } else {
    1248            2 :             airTerm.OARequirementsPtr = Util::FindItemInList(Alphas(5), state.dataSize->OARequirements);
    1249            2 :             if (airTerm.OARequirementsPtr == 0) {
    1250            0 :                 ShowSevereError(state, format("{}{}=\"{}\", invalid data.", RoutineName, CurrentModuleObject, Alphas(1)));
    1251            0 :                 ShowContinueError(state, format("..invalid {}=\"{}\".", cAlphaFields(5), Alphas(5)));
    1252            0 :                 ErrorsFound = true;
    1253              :             } else {
    1254            2 :                 airTerm.NoOAFlowInputFromUser = false;
    1255              :             }
    1256              :         }
    1257              : 
    1258          864 :         if (lAlphaBlanks(6)) {
    1259          863 :             airTerm.OAPerPersonMode = DataZoneEquipment::PerPersonVentRateMode::DCVByCurrentLevel;
    1260              :         } else {
    1261            1 :             if (Alphas(6) == "CURRENTOCCUPANCY") {
    1262            1 :                 airTerm.OAPerPersonMode = DataZoneEquipment::PerPersonVentRateMode::DCVByCurrentLevel;
    1263            0 :             } else if (Alphas(6) == "DESIGNOCCUPANCY") {
    1264            0 :                 airTerm.OAPerPersonMode = DataZoneEquipment::PerPersonVentRateMode::ByDesignLevel;
    1265              :             } else {
    1266            0 :                 airTerm.OAPerPersonMode = DataZoneEquipment::PerPersonVentRateMode::DCVByCurrentLevel;
    1267            0 :                 ShowWarningError(state, format("{}{}=\"{}\", invalid data.", RoutineName, CurrentModuleObject, Alphas(1)));
    1268            0 :                 ShowContinueError(state,
    1269            0 :                                   format("..invalid {}=\"{}\". The default input of CurrentOccupancy is assigned", cAlphaFields(6), Alphas(6)));
    1270              :             }
    1271              :         }
    1272              : 
    1273          864 :         if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
    1274              :             // model results related actuators
    1275          266 :             SetupEMSActuator(state,
    1276              :                              "AirTerminal:SingleDuct:ConstantVolume:NoReheat",
    1277              :                              airTerm.SysName,
    1278              :                              "Mass Flow Rate",
    1279              :                              "[kg/s]",
    1280          266 :                              airTerm.EMSOverrideAirFlow,
    1281          266 :                              airTerm.EMSMassFlowRateValue);
    1282              :             // model input related internal variables
    1283          266 :             SetupEMSInternalVariable(state,
    1284              :                                      "AirTerminal:SingleDuct:ConstantVolume:NoReheat Maximum Mass Flow Rate",
    1285              :                                      airTerm.SysName,
    1286              :                                      "[kg/s]",
    1287          266 :                                      airTerm.AirMassFlowRateMax);
    1288              :         }
    1289              : 
    1290              :     } // End Number of Sys Loop
    1291              : 
    1292          743 :     for (state.dataSingleDuct->SysIndexGSI = 1; state.dataSingleDuct->SysIndexGSI <= state.dataSingleDuct->NumNoRHVAVSysGSI;
    1293          218 :          ++state.dataSingleDuct->SysIndexGSI) {
    1294              : 
    1295          218 :         CurrentModuleObject = "AirTerminal:SingleDuct:VAV:NoReheat";
    1296              : 
    1297          436 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1298              :                                                                  CurrentModuleObject,
    1299          218 :                                                                  state.dataSingleDuct->SysIndexGSI,
    1300              :                                                                  Alphas,
    1301          218 :                                                                  state.dataSingleDuct->NumAlphasGSI,
    1302              :                                                                  Numbers,
    1303          218 :                                                                  state.dataSingleDuct->NumNumsGSI,
    1304              :                                                                  IOStat,
    1305              :                                                                  lNumericBlanks,
    1306              :                                                                  lAlphaBlanks,
    1307              :                                                                  cAlphaFields,
    1308              :                                                                  cNumericFields);
    1309              : 
    1310          218 :         ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    1311          218 :         state.dataSingleDuct->SysNumGSI = state.dataSingleDuct->SysIndexGSI + state.dataSingleDuct->NumVAVSysGSI +
    1312          218 :                                           state.dataSingleDuct->NumCBVAVSysGSI + state.dataSingleDuct->NumConstVolSys +
    1313          218 :                                           state.dataSingleDuct->NumCVNoReheatSysGSI;
    1314          218 :         auto &airTerm = state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI);
    1315              : 
    1316          218 :         airTerm.SysNum = state.dataSingleDuct->SysNumGSI;
    1317          218 :         GlobalNames::VerifyUniqueInterObjectName(
    1318          436 :             state, state.dataSingleDuct->SysUniqueNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
    1319          218 :         airTerm.SysName = Alphas(1);
    1320          218 :         airTerm.sysType = CurrentModuleObject;
    1321          218 :         airTerm.SysType_Num = SysType::SingleDuctVAVNoReheat;
    1322          218 :         airTerm.ReheatComp = "";
    1323          218 :         airTerm.ReheatName = "";
    1324              : 
    1325          218 :         if (lAlphaBlanks(2)) {
    1326           30 :             airTerm.availSched = Sched::GetScheduleAlwaysOn(state);
    1327          188 :         } else if ((airTerm.availSched = Sched::GetSchedule(state, Alphas(2))) == nullptr) {
    1328            0 :             ShowSevereItemNotFound(state, eoh, cAlphaFields(2), Alphas(2));
    1329            0 :             ErrorsFound = true;
    1330              :         }
    1331              : 
    1332          654 :         airTerm.OutletNodeNum = GetOnlySingleNode(state,
    1333          218 :                                                   Alphas(3),
    1334              :                                                   ErrorsFound,
    1335              :                                                   DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctVAVNoReheat,
    1336          218 :                                                   Alphas(1),
    1337              :                                                   DataLoopNode::NodeFluidType::Air,
    1338              :                                                   DataLoopNode::ConnectionType::Outlet,
    1339              :                                                   NodeInputManager::CompFluidStream::Primary,
    1340              :                                                   ObjectIsNotParent,
    1341          218 :                                                   cAlphaFields(3));
    1342          654 :         airTerm.InletNodeNum = GetOnlySingleNode(state,
    1343          218 :                                                  Alphas(4),
    1344              :                                                  ErrorsFound,
    1345              :                                                  DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctVAVNoReheat,
    1346          218 :                                                  Alphas(1),
    1347              :                                                  DataLoopNode::NodeFluidType::Air,
    1348              :                                                  DataLoopNode::ConnectionType::Inlet,
    1349              :                                                  NodeInputManager::CompFluidStream::Primary,
    1350              :                                                  ObjectIsNotParent,
    1351          218 :                                                  cAlphaFields(4));
    1352          218 :         airTerm.MaxAirVolFlowRate = Numbers(1);
    1353              : 
    1354          218 :         if (Util::SameString(Alphas(5), "Constant")) {
    1355           90 :             airTerm.ZoneMinAirFracMethod = MinFlowFraction::Constant;
    1356          128 :         } else if (Util::SameString(Alphas(5), "FixedFlowRate")) {
    1357            0 :             airTerm.ZoneMinAirFracMethod = MinFlowFraction::Fixed;
    1358          128 :         } else if (Util::SameString(Alphas(5), "Scheduled")) {
    1359          128 :             airTerm.ZoneMinAirFracMethod = MinFlowFraction::Scheduled;
    1360              :         } else {
    1361            0 :             ShowSevereError(state, format("{} = {} not found.", cAlphaFields(5), Alphas(5)));
    1362            0 :             ShowContinueError(state, format("Occurs in {} = {}", airTerm.sysType, airTerm.SysName));
    1363            0 :             ErrorsFound = true;
    1364              :         }
    1365              : 
    1366          218 :         airTerm.ZoneMinAirFracDes = Numbers(2);
    1367          218 :         if (lNumericBlanks(2)) {
    1368          128 :             airTerm.ConstantMinAirFracSetByUser = false;
    1369          128 :             airTerm.ZoneMinAirFracDes = 0.0;
    1370              :         } else {
    1371           90 :             airTerm.ConstantMinAirFracSetByUser = true;
    1372           90 :             airTerm.ZoneMinAirFracDes = Numbers(2);
    1373           90 :             if (airTerm.ZoneMinAirFracMethod == MinFlowFraction::Fixed) {
    1374            0 :                 ShowWarningError(state, format("Since {} = {}, input for {} will be ignored.", cAlphaFields(5), Alphas(5), cNumericFields(2)));
    1375            0 :                 ShowContinueError(state, format("Occurs in {} = {}", airTerm.sysType, airTerm.SysName));
    1376            0 :                 airTerm.ZoneMinAirFracDes = 0.0;
    1377              :             }
    1378              :         }
    1379              : 
    1380          218 :         airTerm.ZoneFixedMinAir = Numbers(3);
    1381          218 :         if (lNumericBlanks(3)) {
    1382          218 :             airTerm.FixedMinAirSetByUser = false;
    1383          218 :             airTerm.DesignFixedMinAir = 0.0;
    1384              :         } else {
    1385            0 :             airTerm.FixedMinAirSetByUser = true;
    1386            0 :             airTerm.DesignFixedMinAir = Numbers(3);
    1387            0 :             if (airTerm.ZoneMinAirFracMethod == MinFlowFraction::Constant) {
    1388            0 :                 ShowWarningError(state, format("Since {} = {}, input for {} will be ignored.", cAlphaFields(5), Alphas(5), cNumericFields(3)));
    1389            0 :                 ShowContinueError(state, format("Occurs in {} = {}", airTerm.sysType, airTerm.SysName));
    1390            0 :                 airTerm.ZoneFixedMinAir = 0.0;
    1391              :             }
    1392              :         }
    1393              : 
    1394          218 :         if (airTerm.ZoneMinAirFracMethod != MinFlowFraction::Scheduled) {
    1395          128 :         } else if (lAlphaBlanks(6)) {
    1396            0 :             ShowSevereEmptyField(state, eoh, cAlphaFields(6));
    1397            0 :             ErrorsFound = true;
    1398          128 :         } else if ((airTerm.zoneMinAirFracSched = Sched::GetSchedule(state, Alphas(6))) == nullptr) {
    1399            0 :             ShowSevereItemNotFound(state, eoh, cAlphaFields(6), Alphas(6));
    1400            0 :             ErrorsFound = true;
    1401          128 :         } else if (!airTerm.zoneMinAirFracSched->checkMinMaxVals(state, Clusive::In, 0.0, Clusive::In, 1.0)) {
    1402            0 :             Sched::ShowSevereBadMinMax(state, eoh, cAlphaFields(6), Alphas(6), Clusive::In, 0.0, Clusive::In, 1.0);
    1403            0 :             ErrorsFound = true;
    1404              :         }
    1405              : 
    1406          218 :         airTerm.ReheatControlNode = 0;
    1407          218 :         airTerm.ReheatAirOutletNode = airTerm.OutletNodeNum;
    1408          218 :         airTerm.MaxReheatWaterVolFlow = 0.0;
    1409          218 :         airTerm.MaxReheatSteamVolFlow = 0.0;
    1410          218 :         airTerm.MinReheatWaterVolFlow = 0.0;
    1411          218 :         airTerm.MinReheatSteamVolFlow = 0.0;
    1412          218 :         airTerm.ControllerOffset = 0.000001;
    1413          218 :         airTerm.DamperHeatingAction = Action::HeatingNotUsed;
    1414              : 
    1415              :         // Register component set data
    1416          436 :         TestCompSet(state,
    1417              :                     airTerm.sysType,
    1418              :                     airTerm.SysName,
    1419          218 :                     state.dataLoopNodes->NodeID(airTerm.InletNodeNum),
    1420          218 :                     state.dataLoopNodes->NodeID(airTerm.OutletNodeNum),
    1421              :                     "Air Nodes");
    1422              : 
    1423         8705 :         for (ADUNum = 1; ADUNum <= (int)state.dataDefineEquipment->AirDistUnit.size(); ++ADUNum) {
    1424         8705 :             if (airTerm.OutletNodeNum == state.dataDefineEquipment->AirDistUnit(ADUNum).OutletNodeNum) {
    1425          218 :                 state.dataDefineEquipment->AirDistUnit(ADUNum).InletNodeNum = airTerm.InletNodeNum;
    1426          218 :                 airTerm.ADUNum = ADUNum;
    1427          218 :                 break;
    1428              :             }
    1429              :         }
    1430              :         // one assumes if there isn't one assigned, it's an error?
    1431          218 :         if (airTerm.ADUNum == 0) {
    1432            0 :             ShowSevereError(state,
    1433            0 :                             format("{}No matching Air Distribution Unit, for System = [{},{}].", RoutineName, airTerm.sysType, airTerm.SysName));
    1434            0 :             ShowContinueError(state, format("...should have outlet node = {}", state.dataLoopNodes->NodeID(airTerm.ReheatAirOutletNode)));
    1435            0 :             ErrorsFound = true;
    1436              :         } else {
    1437              : 
    1438              :             // Fill the Zone Equipment data with the inlet node number of this unit.
    1439        17369 :             for (CtrlZone = 1; CtrlZone <= state.dataGlobal->NumOfZones; ++CtrlZone) {
    1440        17151 :                 if (!state.dataZoneEquip->ZoneEquipConfig(CtrlZone).IsControlled) {
    1441           89 :                     continue;
    1442              :                 }
    1443        50833 :                 for (SupAirIn = 1; SupAirIn <= state.dataZoneEquip->ZoneEquipConfig(CtrlZone).NumInletNodes; ++SupAirIn) {
    1444        33771 :                     if (airTerm.ReheatAirOutletNode == state.dataZoneEquip->ZoneEquipConfig(CtrlZone).InletNode(SupAirIn)) {
    1445          218 :                         if (state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).OutNode > 0) {
    1446            0 :                             ShowSevereError(state, "Error in connecting a terminal unit to a zone");
    1447            0 :                             ShowContinueError(
    1448            0 :                                 state, format("{} already connects to another zone", state.dataLoopNodes->NodeID(airTerm.ReheatAirOutletNode)));
    1449            0 :                             ShowContinueError(state, format("Occurs for terminal unit {} = {}", airTerm.sysType, airTerm.SysName));
    1450            0 :                             ShowContinueError(state, "Check terminal unit node names for errors");
    1451            0 :                             ErrorsFound = true;
    1452              :                         } else {
    1453          218 :                             state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).InNode = airTerm.InletNodeNum;
    1454          218 :                             state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).OutNode = airTerm.ReheatAirOutletNode;
    1455          218 :                             state.dataDefineEquipment->AirDistUnit(airTerm.ADUNum).TermUnitSizingNum =
    1456          218 :                                 state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).TermUnitSizingIndex;
    1457          218 :                             state.dataDefineEquipment->AirDistUnit(airTerm.ADUNum).ZoneEqNum = CtrlZone;
    1458              :                         }
    1459              : 
    1460          218 :                         airTerm.CtrlZoneNum = CtrlZone;
    1461          218 :                         airTerm.CtrlZoneInNodeIndex = SupAirIn;
    1462          218 :                         airTerm.ZoneFloorArea = state.dataHeatBal->Zone(CtrlZone).FloorArea * state.dataHeatBal->Zone(CtrlZone).Multiplier *
    1463          218 :                                                 state.dataHeatBal->Zone(CtrlZone).ListMultiplier;
    1464              :                     }
    1465              :                 }
    1466              :             }
    1467              :         }
    1468          218 :         if (!lAlphaBlanks(7)) {
    1469          128 :             airTerm.OARequirementsPtr = Util::FindItemInList(Alphas(7), state.dataSize->OARequirements);
    1470          128 :             if (airTerm.OARequirementsPtr == 0) {
    1471            0 :                 ShowSevereError(state, format("{} = {} not found.", cAlphaFields(7), Alphas(7)));
    1472            0 :                 ShowContinueError(state, format("Occurs in {} = {}", airTerm.sysType, airTerm.SysName));
    1473            0 :                 ErrorsFound = true;
    1474              :             } else {
    1475          128 :                 airTerm.NoOAFlowInputFromUser = false;
    1476              :             }
    1477              :         }
    1478              : 
    1479          218 :         if (lAlphaBlanks(8)) {
    1480          218 :             airTerm.ZoneTurndownMinAirFrac = 1.0;
    1481            0 :         } else if ((airTerm.zoneTurndownMinAirFracSched = Sched::GetSchedule(state, Alphas(8))) == nullptr) {
    1482            0 :             ShowSevereItemNotFound(state, eoh, cAlphaFields(8), Alphas(8));
    1483            0 :             ErrorsFound = true;
    1484              :         }
    1485              : 
    1486              :         // Setup the Average damper Position output variable
    1487          436 :         SetupOutputVariable(state,
    1488              :                             "Zone Air Terminal VAV Damper Position",
    1489              :                             Constant::Units::None,
    1490          218 :                             airTerm.DamperPosition,
    1491              :                             OutputProcessor::TimeStepType::System,
    1492              :                             OutputProcessor::StoreType::Average,
    1493          218 :                             airTerm.SysName);
    1494          436 :         SetupOutputVariable(state,
    1495              :                             "Zone Air Terminal Minimum Air Flow Fraction",
    1496              :                             Constant::Units::None,
    1497          218 :                             airTerm.ZoneMinAirFracReport,
    1498              :                             OutputProcessor::TimeStepType::System,
    1499              :                             OutputProcessor::StoreType::Average,
    1500          218 :                             airTerm.SysName);
    1501              : 
    1502              :     } // end Number of Sys Loop
    1503              : 
    1504          529 :     for (state.dataSingleDuct->SysIndexGSI = 1; state.dataSingleDuct->SysIndexGSI <= state.dataSingleDuct->NumNoRHCBVAVSysGSI;
    1505            4 :          ++state.dataSingleDuct->SysIndexGSI) {
    1506              : 
    1507            4 :         CurrentModuleObject = "AirTerminal:SingleDuct:VAV:HeatAndCool:NoReheat";
    1508              : 
    1509            8 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1510              :                                                                  CurrentModuleObject,
    1511            4 :                                                                  state.dataSingleDuct->SysIndexGSI,
    1512              :                                                                  Alphas,
    1513            4 :                                                                  state.dataSingleDuct->NumAlphasGSI,
    1514              :                                                                  Numbers,
    1515            4 :                                                                  state.dataSingleDuct->NumNumsGSI,
    1516              :                                                                  IOStat,
    1517              :                                                                  lNumericBlanks,
    1518              :                                                                  lAlphaBlanks,
    1519              :                                                                  cAlphaFields,
    1520              :                                                                  cNumericFields);
    1521              : 
    1522            4 :         ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    1523            4 :         state.dataSingleDuct->SysNumGSI = state.dataSingleDuct->SysIndexGSI + state.dataSingleDuct->NumVAVSysGSI +
    1524            4 :                                           state.dataSingleDuct->NumCBVAVSysGSI + state.dataSingleDuct->NumConstVolSys +
    1525            4 :                                           state.dataSingleDuct->NumCVNoReheatSysGSI + state.dataSingleDuct->NumNoRHVAVSysGSI;
    1526            4 :         auto &airTerm = state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI);
    1527              : 
    1528            4 :         airTerm.SysNum = state.dataSingleDuct->SysNumGSI;
    1529            4 :         GlobalNames::VerifyUniqueInterObjectName(
    1530            8 :             state, state.dataSingleDuct->SysUniqueNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
    1531            4 :         airTerm.SysName = Alphas(1);
    1532            4 :         airTerm.sysType = CurrentModuleObject;
    1533            4 :         airTerm.SysType_Num = SysType::SingleDuctCBVAVNoReheat;
    1534            4 :         airTerm.ReheatComp = "";
    1535            4 :         airTerm.ReheatName = "";
    1536              : 
    1537            4 :         if (lAlphaBlanks(2)) {
    1538            0 :             airTerm.availSched = Sched::GetScheduleAlwaysOn(state);
    1539            4 :         } else if ((airTerm.availSched = Sched::GetSchedule(state, Alphas(2))) == nullptr) {
    1540            0 :             ShowSevereItemNotFound(state, eoh, cAlphaFields(2), Alphas(2));
    1541            0 :             ErrorsFound = true;
    1542              :         }
    1543              : 
    1544           12 :         airTerm.OutletNodeNum = GetOnlySingleNode(state,
    1545            4 :                                                   Alphas(3),
    1546              :                                                   ErrorsFound,
    1547              :                                                   DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctVAVHeatAndCoolNoReheat,
    1548            4 :                                                   Alphas(1),
    1549              :                                                   DataLoopNode::NodeFluidType::Air,
    1550              :                                                   DataLoopNode::ConnectionType::Outlet,
    1551              :                                                   NodeInputManager::CompFluidStream::Primary,
    1552              :                                                   ObjectIsNotParent,
    1553            4 :                                                   cAlphaFields(3));
    1554           12 :         airTerm.InletNodeNum = GetOnlySingleNode(state,
    1555            4 :                                                  Alphas(4),
    1556              :                                                  ErrorsFound,
    1557              :                                                  DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctVAVHeatAndCoolNoReheat,
    1558            4 :                                                  Alphas(1),
    1559              :                                                  DataLoopNode::NodeFluidType::Air,
    1560              :                                                  DataLoopNode::ConnectionType::Inlet,
    1561              :                                                  NodeInputManager::CompFluidStream::Primary,
    1562              :                                                  ObjectIsNotParent,
    1563            4 :                                                  cAlphaFields(4));
    1564            4 :         airTerm.MaxAirVolFlowRate = Numbers(1);
    1565            4 :         airTerm.ZoneMinAirFracDes = Numbers(2);
    1566            4 :         if (airTerm.ZoneMinAirFracDes < 0.0) {
    1567            0 :             ShowWarningError(state, format("{} = \"{}", airTerm.sysType, airTerm.SysName));
    1568            0 :             ShowContinueError(state,
    1569            0 :                               format("{} must be greater than or equal to 0. Resetting to 0 and the simulation continues.", cNumericFields(2)));
    1570            0 :             airTerm.ZoneMinAirFracDes = 0.0;
    1571              :         }
    1572            4 :         if (airTerm.ZoneMinAirFracDes > 1.0) {
    1573            0 :             ShowWarningError(state, format("{} = \"{}", airTerm.sysType, airTerm.SysName));
    1574            0 :             ShowContinueError(state, format("{} must be less than or equal to 1. Resetting to 1 and the simulation continues.", cNumericFields(2)));
    1575            0 :             airTerm.ZoneMinAirFracDes = 1.0;
    1576              :         }
    1577              : 
    1578            4 :         airTerm.ReheatControlNode = 0;
    1579            4 :         airTerm.ReheatAirOutletNode = airTerm.OutletNodeNum;
    1580            4 :         airTerm.MaxReheatWaterVolFlow = 0.0;
    1581            4 :         airTerm.MaxReheatSteamVolFlow = 0.0;
    1582            4 :         airTerm.MinReheatWaterVolFlow = 0.0;
    1583            4 :         airTerm.MinReheatSteamVolFlow = 0.0;
    1584            4 :         airTerm.ControllerOffset = 0.000001;
    1585            4 :         airTerm.DamperHeatingAction = Action::HeatingNotUsed;
    1586              : 
    1587              :         // Register component set data
    1588            8 :         TestCompSet(state,
    1589              :                     airTerm.sysType,
    1590              :                     airTerm.SysName,
    1591            4 :                     state.dataLoopNodes->NodeID(airTerm.InletNodeNum),
    1592            4 :                     state.dataLoopNodes->NodeID(airTerm.OutletNodeNum),
    1593              :                     "Air Nodes");
    1594              : 
    1595           12 :         for (ADUNum = 1; ADUNum <= (int)state.dataDefineEquipment->AirDistUnit.size(); ++ADUNum) {
    1596           12 :             if (airTerm.OutletNodeNum == state.dataDefineEquipment->AirDistUnit(ADUNum).OutletNodeNum) {
    1597            4 :                 state.dataDefineEquipment->AirDistUnit(ADUNum).InletNodeNum = airTerm.InletNodeNum;
    1598            4 :                 airTerm.ADUNum = ADUNum;
    1599            4 :                 break;
    1600              :             }
    1601              :         }
    1602              :         // one assumes if there isn't one assigned, it's an error?
    1603            4 :         if (airTerm.ADUNum == 0) {
    1604            0 :             ShowSevereError(state,
    1605            0 :                             format("{}No matching Air Distribution Unit, for System = [{},{}].", RoutineName, airTerm.sysType, airTerm.SysName));
    1606            0 :             ShowContinueError(state, format("...should have outlet node = {}", state.dataLoopNodes->NodeID(airTerm.ReheatAirOutletNode)));
    1607            0 :             ErrorsFound = true;
    1608              :         } else {
    1609              : 
    1610              :             // Fill the Zone Equipment data with the inlet node number of this unit.
    1611           16 :             for (CtrlZone = 1; CtrlZone <= state.dataGlobal->NumOfZones; ++CtrlZone) {
    1612           12 :                 if (!state.dataZoneEquip->ZoneEquipConfig(CtrlZone).IsControlled) {
    1613            0 :                     continue;
    1614              :                 }
    1615           24 :                 for (SupAirIn = 1; SupAirIn <= state.dataZoneEquip->ZoneEquipConfig(CtrlZone).NumInletNodes; ++SupAirIn) {
    1616           12 :                     if (airTerm.ReheatAirOutletNode == state.dataZoneEquip->ZoneEquipConfig(CtrlZone).InletNode(SupAirIn)) {
    1617            4 :                         if (state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).OutNode > 0) {
    1618            0 :                             ShowSevereError(state, "Error in connecting a terminal unit to a zone");
    1619            0 :                             ShowContinueError(
    1620            0 :                                 state, format("{} already connects to another zone", state.dataLoopNodes->NodeID(airTerm.ReheatAirOutletNode)));
    1621            0 :                             ShowContinueError(state, format("Occurs for terminal unit {} = {}", airTerm.sysType, airTerm.SysName));
    1622            0 :                             ShowContinueError(state, "Check terminal unit node names for errors");
    1623            0 :                             ErrorsFound = true;
    1624              :                         } else {
    1625            4 :                             state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).InNode = airTerm.InletNodeNum;
    1626            4 :                             state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).OutNode = airTerm.ReheatAirOutletNode;
    1627            4 :                             state.dataDefineEquipment->AirDistUnit(airTerm.ADUNum).TermUnitSizingNum =
    1628            4 :                                 state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).TermUnitSizingIndex;
    1629            4 :                             state.dataDefineEquipment->AirDistUnit(airTerm.ADUNum).ZoneEqNum = CtrlZone;
    1630              :                         }
    1631            4 :                         airTerm.CtrlZoneNum = CtrlZone;
    1632            4 :                         airTerm.CtrlZoneInNodeIndex = SupAirIn;
    1633            4 :                         airTerm.ZoneFloorArea = state.dataHeatBal->Zone(CtrlZone).FloorArea * state.dataHeatBal->Zone(CtrlZone).Multiplier *
    1634            4 :                                                 state.dataHeatBal->Zone(CtrlZone).ListMultiplier;
    1635              :                     }
    1636              :                 }
    1637              :             }
    1638              :         }
    1639              : 
    1640            4 :         if (lAlphaBlanks(5)) {
    1641            4 :             airTerm.ZoneTurndownMinAirFrac = 1.0;
    1642            0 :         } else if ((airTerm.zoneTurndownMinAirFracSched = Sched::GetSchedule(state, Alphas(5))) == nullptr) {
    1643            0 :             ShowSevereItemNotFound(state, eoh, cAlphaFields(5), Alphas(5));
    1644            0 :             ErrorsFound = true;
    1645              :         }
    1646              : 
    1647              :         // Setup the Average damper Position output variable
    1648            8 :         SetupOutputVariable(state,
    1649              :                             "Zone Air Terminal VAV Damper Position",
    1650              :                             Constant::Units::None,
    1651            4 :                             airTerm.DamperPosition,
    1652              :                             OutputProcessor::TimeStepType::System,
    1653              :                             OutputProcessor::StoreType::Average,
    1654            4 :                             airTerm.SysName);
    1655              : 
    1656              :     } // end Number of VAVHeatandCool:NoReheat Sys Loop
    1657              : 
    1658              :     // read in the SINGLE DUCT:VAV:REHEAT:VS FAN data
    1659          533 :     for (state.dataSingleDuct->SysIndexGSI = 1; state.dataSingleDuct->SysIndexGSI <= state.dataSingleDuct->NumVAVVSGSI;
    1660            8 :          ++state.dataSingleDuct->SysIndexGSI) {
    1661              : 
    1662            8 :         CurrentModuleObject = "AirTerminal:SingleDuct:VAV:Reheat:VariableSpeedFan";
    1663              : 
    1664           16 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1665              :                                                                  CurrentModuleObject,
    1666            8 :                                                                  state.dataSingleDuct->SysIndexGSI,
    1667              :                                                                  Alphas,
    1668            8 :                                                                  state.dataSingleDuct->NumAlphasGSI,
    1669              :                                                                  Numbers,
    1670            8 :                                                                  state.dataSingleDuct->NumNumsGSI,
    1671              :                                                                  IOStat,
    1672              :                                                                  lNumericBlanks,
    1673              :                                                                  lAlphaBlanks,
    1674              :                                                                  cAlphaFields,
    1675              :                                                                  cNumericFields);
    1676              : 
    1677            8 :         ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    1678              : 
    1679            8 :         state.dataSingleDuct->SysNumGSI = state.dataSingleDuct->SysIndexGSI + state.dataSingleDuct->NumVAVSysGSI +
    1680            8 :                                           state.dataSingleDuct->NumCBVAVSysGSI + state.dataSingleDuct->NumConstVolSys +
    1681            8 :                                           state.dataSingleDuct->NumCVNoReheatSysGSI + state.dataSingleDuct->NumNoRHVAVSysGSI +
    1682            8 :                                           state.dataSingleDuct->NumNoRHCBVAVSysGSI;
    1683            8 :         auto &airTerm = state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI);
    1684            8 :         airTerm.SysNum = state.dataSingleDuct->SysNumGSI;
    1685            8 :         GlobalNames::VerifyUniqueInterObjectName(
    1686           16 :             state, state.dataSingleDuct->SysUniqueNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
    1687            8 :         airTerm.SysName = Alphas(1);
    1688            8 :         airTerm.sysType = CurrentModuleObject;
    1689            8 :         airTerm.SysType_Num = SysType::SingleDuctVAVReheatVSFan;
    1690            8 :         airTerm.ReheatComp = Alphas(7);
    1691            8 :         airTerm.ReheatName = Alphas(8);
    1692            8 :         IsNotOK = false;
    1693            8 :         if (Util::SameString(airTerm.ReheatComp, "Coil:Heating:Fuel")) {
    1694            0 :             airTerm.ReheatComp_Num = HeatingCoilType::Gas;
    1695            0 :             airTerm.ReheatAirOutletNode = GetHeatingCoilOutletNode(state, airTerm.ReheatComp, airTerm.ReheatName, IsNotOK);
    1696            0 :             airTerm.ReheatCoilMaxCapacity = GetHeatingCoilCapacity(state, airTerm.ReheatComp, airTerm.ReheatName, IsNotOK);
    1697            0 :             if (IsNotOK) {
    1698            0 :                 ShowContinueError(state, format("Occurs for terminal unit {} = {}", airTerm.sysType, airTerm.SysName));
    1699              :             }
    1700            8 :         } else if (Util::SameString(airTerm.ReheatComp, "Coil:Heating:Electric")) {
    1701            0 :             airTerm.ReheatComp_Num = HeatingCoilType::Electric;
    1702            0 :             airTerm.ReheatAirOutletNode = GetHeatingCoilOutletNode(state, airTerm.ReheatComp, airTerm.ReheatName, IsNotOK);
    1703            0 :             airTerm.ReheatCoilMaxCapacity = GetHeatingCoilCapacity(state, airTerm.ReheatComp, airTerm.ReheatName, IsNotOK);
    1704            0 :             if (IsNotOK) {
    1705            0 :                 ShowContinueError(state, format("Occurs for terminal unit {} = {}", airTerm.sysType, airTerm.SysName));
    1706              :             }
    1707            8 :         } else if (Util::SameString(airTerm.ReheatComp, "Coil:Heating:Water")) {
    1708            8 :             airTerm.ReheatComp_Num = HeatingCoilType::SimpleHeating;
    1709            8 :             airTerm.ReheatComp_PlantType = DataPlant::PlantEquipmentType::CoilWaterSimpleHeating;
    1710            0 :         } else if (Util::SameString(airTerm.ReheatComp, "Coil:Heating:Steam")) {
    1711            0 :             airTerm.ReheatComp_Num = HeatingCoilType::SteamAirHeating;
    1712            0 :             airTerm.ReheatComp_PlantType = DataPlant::PlantEquipmentType::CoilSteamAirHeating;
    1713            0 :         } else if (!airTerm.ReheatComp.empty()) {
    1714            0 :             ShowSevereError(state, format("Illegal {} = {}.", cAlphaFields(7), airTerm.ReheatComp));
    1715            0 :             ShowContinueError(state, format("Occurs in {} = {}", airTerm.sysType, airTerm.SysName));
    1716            0 :             ErrorsFound = true;
    1717              :         }
    1718              : 
    1719            8 :         if (airTerm.ReheatComp_Num == HeatingCoilType::Gas || airTerm.ReheatComp_Num == HeatingCoilType::Electric) {
    1720            0 :             HeatingCoils::GetCoilIndex(state, airTerm.ReheatName, airTerm.ReheatComp_Index, ErrorsFound);
    1721            0 :             if (airTerm.ReheatComp_Index == 0) {
    1722            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(8), Alphas(8));
    1723            0 :                 ErrorsFound = true;
    1724              :             }
    1725            8 :         } else if (airTerm.ReheatComp_Num == HeatingCoilType::SimpleHeating) {
    1726            8 :             airTerm.ReheatComp_Index = WaterCoils::GetWaterCoilIndex(state, airTerm.ReheatComp, airTerm.ReheatName, ErrorsFound);
    1727            8 :             if (airTerm.ReheatComp_Index == 0) {
    1728            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(8), Alphas(8));
    1729            0 :                 ErrorsFound = true;
    1730              :             }
    1731            0 :         } else if (airTerm.ReheatComp_Num == HeatingCoilType::SteamAirHeating) {
    1732            0 :             airTerm.ReheatComp_Index = SteamCoils::GetSteamCoilIndex(state, airTerm.ReheatComp, airTerm.ReheatName, ErrorsFound);
    1733            0 :             if (airTerm.ReheatComp_Index == 0) {
    1734            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(8), Alphas(8));
    1735            0 :                 ErrorsFound = true;
    1736              :             }
    1737              :         }
    1738              : 
    1739            8 :         airTerm.fanType = static_cast<HVAC::FanType>(getEnumValue(HVAC::fanTypeNamesUC, Alphas(5)));
    1740              : 
    1741            8 :         if (airTerm.fanType != HVAC::FanType::VAV && airTerm.fanType != HVAC::FanType::SystemModel) {
    1742            0 :             ShowSevereInvalidKey(state, eoh, cAlphaFields(5), Alphas(5), "Support fan types are Fan:VAV and Fan:SystemModel");
    1743              : 
    1744            0 :             ErrorsFound = true;
    1745              :         }
    1746              : 
    1747            8 :         airTerm.FanName = Alphas(6);
    1748              : 
    1749            8 :         airTerm.Fan_Index = Fans::GetFanIndex(state, airTerm.FanName);
    1750            8 :         if (airTerm.Fan_Index == 0) {
    1751            0 :             ShowSevereItemNotFound(state, eoh, cAlphaFields(6), airTerm.FanName);
    1752            0 :             ErrorsFound = true;
    1753              :         }
    1754            8 :         airTerm.OutletNodeNum = state.dataFans->fans(airTerm.Fan_Index)->outletNodeNum;
    1755            8 :         airTerm.InletNodeNum = state.dataFans->fans(airTerm.Fan_Index)->inletNodeNum;
    1756              : 
    1757            8 :         if (airTerm.fanType == HVAC::FanType::SystemModel) {
    1758            4 :             dynamic_cast<Fans::FanSystem *>(state.dataFans->fans(airTerm.Fan_Index))->isSecondaryDriver = true;
    1759              :         }
    1760              : 
    1761            8 :         if (lAlphaBlanks(2)) {
    1762            0 :             airTerm.availSched = Sched::GetScheduleAlwaysOn(state);
    1763            8 :         } else if ((airTerm.availSched = Sched::GetSchedule(state, Alphas(2))) == nullptr) {
    1764            0 :             ShowSevereItemNotFound(state, eoh, cAlphaFields(2), Alphas(2));
    1765            0 :             ErrorsFound = true;
    1766              :         }
    1767              : 
    1768            8 :         AirTermSysInletNodeName = state.dataLoopNodes->NodeID(airTerm.InletNodeNum);
    1769            8 :         if (!Util::SameString(Alphas(3), AirTermSysInletNodeName)) {
    1770            0 :             ShowWarningError(state,
    1771            0 :                              format("{}Invalid air terminal object air inlet node name in {} = {}", RoutineName, airTerm.sysType, airTerm.SysName));
    1772            0 :             ShowContinueError(state, format(" Specified air inlet node name is = {}.", Alphas(3)));
    1773            0 :             ShowContinueError(state, format(" Expected air inlet node name is = {}.", AirTermSysInletNodeName));
    1774              :             // ErrorsFound = true;
    1775              :         }
    1776              : 
    1777            8 :         airTerm.MaxAirVolFlowRate = Numbers(1);
    1778            8 :         airTerm.MaxHeatAirVolFlowRate = Numbers(2);
    1779            8 :         airTerm.ZoneMinAirFracDes = Numbers(3);
    1780              :         // The reheat coil control node is necessary for hot water reheat, but not necessary for
    1781              :         // electric or gas reheat.
    1782            8 :         if (airTerm.ReheatComp_Num == HeatingCoilType::Gas || airTerm.ReheatComp_Num == HeatingCoilType::Electric) {
    1783              :             //          IF(.NOT. lAlphaBlanks(6)) THEN
    1784              :             //            CALL ShowWarningError(state, 'In '//TRIM(sd_airterminal(SysNum)%SysType)//' = ' // TRIM(sd_airterminal(SysNum)%SysName) &
    1785              :             //                                 // ' the '//TRIM(cAlphaFields(6))//' is not needed and will be ignored.')
    1786              :             //            CALL ShowContinueError(state, '  It is used for hot water reheat coils only.')
    1787              :             //          END IF
    1788              :         } else {
    1789              :             //          IF(lAlphaBlanks(6)) THEN
    1790              :             //            CALL ShowSevereError(state, 'In '//TRIM(sd_airterminal(SysNum)%SysType)//' = ' // TRIM(sd_airterminal(SysNum)%SysName) &
    1791              :             //                                 // ' the '//TRIM(cAlphaFields(6))//' is undefined')
    1792              :             //            ErrorsFound=.TRUE.
    1793              :             //          END IF
    1794            8 :             if (airTerm.ReheatComp_Num == HeatingCoilType::SteamAirHeating) {
    1795            0 :                 IsNotOK = false;
    1796            0 :                 airTerm.ReheatControlNode = GetCoilSteamInletNode(state, airTerm.ReheatComp, airTerm.ReheatName, IsNotOK);
    1797            0 :                 if (IsNotOK) {
    1798            0 :                     ShowContinueError(state, format("..Occurs in {} = {}", airTerm.sysType, airTerm.SysName));
    1799            0 :                     ErrorsFound = true;
    1800              :                 } else {
    1801              :                     //  A4,     \field Unit supply air outlet node
    1802              :                     //          \note same as heating coil air outlet node
    1803              :                     //          \note same as zone inlet node
    1804              :                     //          \type alpha
    1805            0 :                     IsNotOK = false;
    1806            0 :                     airTerm.ReheatAirOutletNode = GetCoilAirOutletNode(state, airTerm.ReheatComp, airTerm.ReheatName, IsNotOK);
    1807            0 :                     if (IsNotOK) {
    1808            0 :                         ShowContinueError(state, format("..Occurs in {} = {}", airTerm.sysType, airTerm.SysName));
    1809            0 :                         ErrorsFound = true;
    1810              :                     }
    1811              :                 }
    1812              :                 //               GetOnlySingleNode(state, Alphas(6),ErrorsFound,sd_airterminal(SysNum)%SysType,Alphas(1), &
    1813              :                 //                                DataLoopNode::NodeFluidType::Steam,DataLoopNode::NodeConnectionType::Actuator,1,ObjectIsParent)
    1814              :             } else {
    1815            8 :                 IsNotOK = false;
    1816            8 :                 airTerm.ReheatControlNode = GetCoilWaterInletNode(state, airTerm.ReheatComp, airTerm.ReheatName, IsNotOK);
    1817            8 :                 if (IsNotOK) {
    1818            0 :                     ShowContinueError(state, format("..Occurs in {} = {}", airTerm.sysType, airTerm.SysName));
    1819            0 :                     ErrorsFound = true;
    1820              :                 } else {
    1821              :                     //  A4,     \field Unit supply air outlet node
    1822              :                     //          \note same as heating coil air outlet node
    1823              :                     //          \note same as zone inlet node
    1824              :                     //          \type alpha
    1825            8 :                     IsNotOK = false;
    1826            8 :                     airTerm.ReheatAirOutletNode = GetCoilOutletNode(state, airTerm.ReheatComp, airTerm.ReheatName, IsNotOK);
    1827            8 :                     if (IsNotOK) {
    1828            0 :                         ShowContinueError(state, format("..Occurs in {} = {}", airTerm.sysType, airTerm.SysName));
    1829            0 :                         ErrorsFound = true;
    1830              :                     }
    1831              :                 }
    1832              :                 //               GetOnlySingleNode(state, Alphas(6),ErrorsFound,sd_airterminal(SysNum)%SysType,Alphas(1), &
    1833              :                 //                                DataLoopNode::NodeFluidType::Water,DataLoopNode::NodeConnectionType::Actuator,1,ObjectIsParent)
    1834              :             }
    1835              :         }
    1836              :         //  A4,     \field Unit supply air outlet node
    1837              :         //          \note same as heating coil air outlet node
    1838              :         //          \note same as zone inlet node
    1839              :         //          \type alpha
    1840              :         //        sd_airterminal(SysNum)%ReheatAirOutletNode  = &
    1841              :         //               GetOnlySingleNode(state, Alphas(4),ErrorsFound,sd_airterminal(SysNum)%SysType,Alphas(1), &
    1842              :         //                            DataLoopNode::NodeFluidType::Air,DataLoopNode::NodeConnectionType::Outlet,1,ObjectIsParent)
    1843            8 :         AirTermSysOutletNodeName = state.dataLoopNodes->NodeID(airTerm.ReheatAirOutletNode);
    1844            8 :         if (!Util::SameString(Alphas(4), AirTermSysOutletNodeName)) {
    1845            0 :             ShowWarningError(state,
    1846            0 :                              format("{}Invalid air terminal object air outlet node name in {} = {}", RoutineName, airTerm.sysType, airTerm.SysName));
    1847            0 :             ShowContinueError(state, format(" Specified air outlet node name is = {}.", Alphas(4)));
    1848            0 :             ShowContinueError(state, format(" Expected air outlet node name is = {}.", AirTermSysOutletNodeName));
    1849              :             // ErrorsFound = true;
    1850              :         }
    1851              : 
    1852            8 :         if (airTerm.ReheatComp_Num == HeatingCoilType::SteamAirHeating) {
    1853            0 :             airTerm.MaxReheatSteamVolFlow = Numbers(4);
    1854            0 :             airTerm.MinReheatSteamVolFlow = Numbers(5);
    1855              :         } else {
    1856            8 :             airTerm.MaxReheatWaterVolFlow = Numbers(4);
    1857            8 :             airTerm.MinReheatWaterVolFlow = Numbers(5);
    1858              :         }
    1859            8 :         airTerm.ControllerOffset = Numbers(6);
    1860              :         // Set default convergence tolerance
    1861            8 :         if (airTerm.ControllerOffset <= 0.0) {
    1862            0 :             airTerm.ControllerOffset = 0.001;
    1863              :         }
    1864            8 :         airTerm.DamperHeatingAction = Action::HeatingNotUsed;
    1865              : 
    1866              :         // Register component set data
    1867           16 :         TestCompSet(state,
    1868              :                     airTerm.sysType,
    1869              :                     airTerm.SysName,
    1870            8 :                     state.dataLoopNodes->NodeID(airTerm.InletNodeNum),
    1871            8 :                     state.dataLoopNodes->NodeID(airTerm.ReheatAirOutletNode),
    1872              :                     "Air Nodes");
    1873              : 
    1874           20 :         for (ADUNum = 1; ADUNum <= (int)state.dataDefineEquipment->AirDistUnit.size(); ++ADUNum) {
    1875           20 :             if (airTerm.ReheatAirOutletNode == state.dataDefineEquipment->AirDistUnit(ADUNum).OutletNodeNum) {
    1876            8 :                 state.dataDefineEquipment->AirDistUnit(ADUNum).InletNodeNum = airTerm.InletNodeNum;
    1877            8 :                 airTerm.ADUNum = ADUNum;
    1878            8 :                 break;
    1879              :             }
    1880              :         }
    1881              :         // one assumes if there isn't one assigned, it's an error?
    1882            8 :         if (airTerm.ADUNum == 0) {
    1883            0 :             ShowSevereError(state,
    1884            0 :                             format("{}No matching Air Distribution Unit, for System = [{},{}].", RoutineName, airTerm.sysType, airTerm.SysName));
    1885            0 :             ShowContinueError(state, format("...should have outlet node = {}", state.dataLoopNodes->NodeID(airTerm.ReheatAirOutletNode)));
    1886            0 :             ErrorsFound = true;
    1887              :         } else {
    1888              : 
    1889              :             // Fill the Zone Equipment data with the inlet node number of this unit.
    1890              :             // what if not found?  error?
    1891            8 :             IsNotOK = true;
    1892           64 :             for (CtrlZone = 1; CtrlZone <= state.dataGlobal->NumOfZones; ++CtrlZone) {
    1893           56 :                 if (!state.dataZoneEquip->ZoneEquipConfig(CtrlZone).IsControlled) {
    1894           16 :                     continue;
    1895              :                 }
    1896           80 :                 for (SupAirIn = 1; SupAirIn <= state.dataZoneEquip->ZoneEquipConfig(CtrlZone).NumInletNodes; ++SupAirIn) {
    1897           40 :                     if (airTerm.ReheatAirOutletNode == state.dataZoneEquip->ZoneEquipConfig(CtrlZone).InletNode(SupAirIn)) {
    1898            8 :                         IsNotOK = false;
    1899            8 :                         if (state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).OutNode > 0) {
    1900            0 :                             ShowSevereError(state, "Error in connecting a terminal unit to a zone");
    1901            0 :                             ShowContinueError(
    1902            0 :                                 state, format("{} already connects to another zone", state.dataLoopNodes->NodeID(airTerm.ReheatAirOutletNode)));
    1903            0 :                             ShowContinueError(state, format("Occurs for terminal unit {} = {}", airTerm.sysType, airTerm.SysName));
    1904            0 :                             ShowContinueError(state, "Check terminal unit node names for errors");
    1905            0 :                             ErrorsFound = true;
    1906              :                         } else {
    1907            8 :                             state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).InNode = airTerm.InletNodeNum;
    1908            8 :                             state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).OutNode = airTerm.ReheatAirOutletNode;
    1909            8 :                             state.dataDefineEquipment->AirDistUnit(airTerm.ADUNum).TermUnitSizingNum =
    1910            8 :                                 state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).TermUnitSizingIndex;
    1911            8 :                             state.dataDefineEquipment->AirDistUnit(airTerm.ADUNum).ZoneEqNum = CtrlZone;
    1912              :                         }
    1913            8 :                         airTerm.CtrlZoneNum = CtrlZone;
    1914            8 :                         airTerm.CtrlZoneInNodeIndex = SupAirIn;
    1915            8 :                         airTerm.ZoneFloorArea = state.dataHeatBal->Zone(CtrlZone).FloorArea * state.dataHeatBal->Zone(CtrlZone).Multiplier *
    1916            8 :                                                 state.dataHeatBal->Zone(CtrlZone).ListMultiplier;
    1917              :                     }
    1918              :                 }
    1919              :             }
    1920              :         }
    1921            8 :         if (IsNotOK) {
    1922            0 :             ShowWarningError(state, "Did not Match Supply Air Outlet Node to any Zone Node");
    1923            0 :             ShowContinueError(state, format("..Occurs in {} = {}", airTerm.sysType, airTerm.SysName));
    1924              :         }
    1925              : 
    1926            8 :         if (lAlphaBlanks(9)) {
    1927            8 :             airTerm.ZoneTurndownMinAirFrac = 1.0;
    1928            0 :         } else if ((airTerm.zoneTurndownMinAirFracSched = Sched::GetSchedule(state, Alphas(9))) == nullptr) {
    1929            0 :             ShowSevereItemNotFound(state, eoh, cAlphaFields(9), Alphas(9));
    1930            0 :             ErrorsFound = true;
    1931              :         }
    1932              : 
    1933              :         // Add reheat coil to component sets array
    1934           16 :         SetUpCompSets(state,
    1935              :                       airTerm.sysType,
    1936              :                       airTerm.SysName,
    1937            8 :                       Alphas(7),
    1938            8 :                       Alphas(8),
    1939            8 :                       state.dataLoopNodes->NodeID(airTerm.OutletNodeNum),
    1940            8 :                       state.dataLoopNodes->NodeID(airTerm.ReheatAirOutletNode));
    1941              :         // Add fan to component sets array
    1942           16 :         SetUpCompSets(state,
    1943              :                       airTerm.sysType,
    1944              :                       airTerm.SysName,
    1945            8 :                       Alphas(5),
    1946            8 :                       Alphas(6),
    1947            8 :                       state.dataLoopNodes->NodeID(airTerm.InletNodeNum),
    1948            8 :                       state.dataLoopNodes->NodeID(airTerm.OutletNodeNum));
    1949              : 
    1950              :         // Setup the Average damper Position output variable
    1951           16 :         SetupOutputVariable(state,
    1952              :                             "Zone Air Terminal VAV Damper Position",
    1953              :                             Constant::Units::None,
    1954            8 :                             airTerm.DamperPosition,
    1955              :                             OutputProcessor::TimeStepType::System,
    1956              :                             OutputProcessor::StoreType::Average,
    1957            8 :                             airTerm.SysName);
    1958              :     }
    1959              : 
    1960              :     // common report variable for all single duct air terminals
    1961         4132 :     for (int sdIndex = 1; sdIndex <= state.dataSingleDuct->NumSDAirTerminal; ++sdIndex) {
    1962         7214 :         SetupOutputVariable(state,
    1963              :                             "Zone Air Terminal Outdoor Air Volume Flow Rate",
    1964              :                             Constant::Units::m3_s,
    1965         3607 :                             state.dataSingleDuct->sd_airterminal(sdIndex).OutdoorAirFlowRate,
    1966              :                             OutputProcessor::TimeStepType::System,
    1967              :                             OutputProcessor::StoreType::Average,
    1968         3607 :                             state.dataSingleDuct->sd_airterminal(sdIndex).SysName);
    1969              :     }
    1970              : 
    1971              :     // Error check to see if a single duct air terminal is assigned to zone that has zone secondary recirculation
    1972              :     // specified in the Sizing:Zone object
    1973              : 
    1974          525 :     NumZoneSiz = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Sizing:Zone");
    1975          525 :     if (NumZoneSiz > 0) {
    1976         3506 :         for (state.dataSingleDuct->SysIndexGSI = 1; state.dataSingleDuct->SysIndexGSI <= state.dataSingleDuct->NumSDAirTerminal;
    1977         3151 :              ++state.dataSingleDuct->SysIndexGSI) {
    1978       122207 :             for (ZoneSizIndex = 1; ZoneSizIndex <= NumZoneSiz; ++ZoneSizIndex) {
    1979       119060 :                 if (state.dataGlobal->DoZoneSizing) {
    1980       118783 :                     if (state.dataSize->FinalZoneSizing(ZoneSizIndex).ZoneNum ==
    1981       118783 :                         state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysIndexGSI).CtrlZoneNum) {
    1982         2791 :                         if (state.dataSize->FinalZoneSizing(ZoneSizIndex).ZoneSecondaryRecirculation > 0.0) {
    1983            8 :                             ShowWarningError(state,
    1984            8 :                                              format("{}A zone secondary recirculation fraction is specified for zone served by ", RoutineName));
    1985            8 :                             ShowContinueError(state,
    1986            8 :                                               format("...terminal unit \"{}\" , that indicates a single path system",
    1987            4 :                                                      state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysIndexGSI).SysName));
    1988            8 :                             ShowContinueError(state, "...The zone secondary recirculation for that zone was set to 0.0");
    1989            4 :                             state.dataSize->FinalZoneSizing(ZoneSizIndex).ZoneSecondaryRecirculation = 0.0;
    1990            4 :                             goto SizLoop_exit;
    1991              :                         }
    1992              :                     }
    1993              :                 }
    1994              :             }
    1995         3151 :         SizLoop_exit:;
    1996              :         }
    1997              :     }
    1998              : 
    1999          525 :     Alphas.deallocate();
    2000          525 :     cAlphaFields.deallocate();
    2001          525 :     cNumericFields.deallocate();
    2002          525 :     Numbers.deallocate();
    2003          525 :     lAlphaBlanks.deallocate();
    2004          525 :     lNumericBlanks.deallocate();
    2005              : 
    2006          525 :     if (ErrorsFound) {
    2007            0 :         ShowFatalError(state, format("{}Errors found in input.  Preceding condition(s) cause termination.", RoutineName));
    2008              :     }
    2009          525 : }
    2010              : 
    2011              : // End of Get Input subroutines for the Module
    2012              : //******************************************************************************
    2013              : 
    2014              : // Beginning Initialization Section of the Module
    2015              : //******************************************************************************
    2016              : 
    2017     37322114 : void SingleDuctAirTerminal::InitSys(EnergyPlusData &state, bool const FirstHVACIteration)
    2018              : {
    2019              : 
    2020              :     // SUBROUTINE INFORMATION:
    2021              :     //       AUTHOR         Richard J. Liesen
    2022              :     //       DATE WRITTEN   January 2000
    2023              : 
    2024              :     // PURPOSE OF THIS SUBROUTINE:
    2025              :     // This subroutine is for  initializations of the Sys Components.
    2026              : 
    2027              :     // METHODOLOGY EMPLOYED:
    2028              :     // Uses the status flags to trigger events.
    2029              : 
    2030              :     // Using/Aliasing
    2031              : 
    2032              :     using DataZoneEquipment::CheckZoneEquipmentList;
    2033              :     using PlantUtilities::InitComponentNodes;
    2034              :     using PlantUtilities::ScanPlantLoopsForObject;
    2035     37322114 :     auto &GetHeatingCoilCapacity(HeatingCoils::GetCoilCapacity);
    2036              : 
    2037              :     // SUBROUTINE PARAMETER DEFINITIONS:
    2038              :     static constexpr std::string_view RoutineName("InitSys");
    2039              :     static constexpr std::string_view RoutineNameFull("InitHVACSingleDuct");
    2040              : 
    2041              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2042              :     int InletNode;
    2043              :     int OutletNode;
    2044              :     Real64 SteamTemp;
    2045              :     Real64 SteamDensity;
    2046              :     Real64 rho;
    2047              :     bool errFlag;
    2048              : 
    2049              :     // static Array1D_bool PlantLoopScanFlag;
    2050              : 
    2051              :     // Do the Begin Simulation initializations
    2052     37322114 :     if (this->PlantLoopScanFlag && allocated(state.dataPlnt->PlantLoop)) {
    2053         3607 :         if ((this->ReheatComp_PlantType == DataPlant::PlantEquipmentType::CoilWaterSimpleHeating) ||
    2054         1466 :             (this->ReheatComp_PlantType == DataPlant::PlantEquipmentType::CoilSteamAirHeating)) {
    2055              :             // setup plant topology indices for plant fed heating coils
    2056         2154 :             errFlag = false;
    2057         2154 :             ScanPlantLoopsForObject(state, this->ReheatName, this->ReheatComp_PlantType, this->HWplantLoc, errFlag, _, _, _, _, _);
    2058              : 
    2059         2154 :             if (errFlag) {
    2060            0 :                 ShowContinueError(state, format("Reference Unit=\"{}\", type={}", this->SysName, this->sysType));
    2061            0 :                 ShowFatalError(state, "InitSys: Program terminated for previous conditions.");
    2062              :             }
    2063              : 
    2064         2154 :             this->ReheatCoilOutletNode = DataPlant::CompData::getPlantComponent(state, this->HWplantLoc).NodeNumOut;
    2065              : 
    2066         2154 :             this->PlantLoopScanFlag = false;
    2067              :         } else {
    2068         1453 :             this->PlantLoopScanFlag = false;
    2069              :         }
    2070     37318507 :     } else if (this->PlantLoopScanFlag && !state.dataGlobal->AnyPlantInModel) {
    2071            0 :         this->PlantLoopScanFlag = false;
    2072              :     }
    2073              : 
    2074     37322114 :     if (!state.dataSingleDuct->ZoneEquipmentListChecked && state.dataZoneEquip->ZoneEquipInputsFilled) {
    2075          525 :         state.dataSingleDuct->ZoneEquipmentListChecked = true;
    2076              :         // Check to see if there is a Air Distribution Unit on the Zone Equipment List
    2077         4132 :         for (int SysIndex = 1; SysIndex <= state.dataSingleDuct->NumSDAirTerminal; ++SysIndex) {
    2078         3607 :             if (state.dataSingleDuct->sd_airterminal(SysIndex).ADUNum == 0) {
    2079            0 :                 continue;
    2080              :             }
    2081         7214 :             if (CheckZoneEquipmentList(state,
    2082              :                                        "ZoneHVAC:AirDistributionUnit",
    2083         3607 :                                        state.dataDefineEquipment->AirDistUnit(state.dataSingleDuct->sd_airterminal(SysIndex).ADUNum).Name)) {
    2084         3607 :                 continue;
    2085              :             }
    2086            0 :             ShowSevereError(state,
    2087            0 :                             format("InitSingleDuctSystems: ADU=[Air Distribution Unit,{}] is not on any ZoneHVAC:EquipmentList.",
    2088            0 :                                    state.dataDefineEquipment->AirDistUnit(state.dataSingleDuct->sd_airterminal(SysIndex).ADUNum).Name));
    2089            0 :             ShowContinueError(state,
    2090            0 :                               format("...System=[{},{}] will not be simulated.",
    2091            0 :                                      state.dataSingleDuct->sd_airterminal(SysIndex).sysType,
    2092            0 :                                      state.dataSingleDuct->sd_airterminal(SysIndex).SysName));
    2093              :         }
    2094              :     }
    2095              : 
    2096              :     // get current time step air terminal box turndown minimum flow fraction
    2097     37322114 :     if (this->zoneTurndownMinAirFracSched != nullptr) {
    2098        18510 :         this->ZoneTurndownMinAirFrac = this->zoneTurndownMinAirFracSched->getCurrentVal();
    2099              :     } else {
    2100     37303604 :         this->ZoneTurndownMinAirFrac = 1.0;
    2101              :     }
    2102              : 
    2103     37322114 :     if (!state.dataGlobal->SysSizingCalc && this->MySizeFlag) {
    2104              : 
    2105         3602 :         this->SizeSys(state);
    2106              : 
    2107         3602 :         this->MySizeFlag = false;
    2108              :     }
    2109              : 
    2110     37322114 :     if (this->GetGasElecHeatCoilCap) {
    2111         3607 :         if (this->ReheatComp_Num == HeatingCoilType::Electric || this->ReheatComp_Num == HeatingCoilType::Gas) {
    2112          367 :             if (this->ReheatCoilMaxCapacity == AutoSize) {
    2113            0 :                 errFlag = false;
    2114            0 :                 this->ReheatCoilMaxCapacity = GetHeatingCoilCapacity(state, this->ReheatComp, this->ReheatName, errFlag);
    2115            0 :                 if (errFlag) {
    2116            0 :                     ShowContinueError(state, format("Occurs for terminal unit {} = {}", this->sysType, this->SysName));
    2117              :                 }
    2118              :             }
    2119          367 :             if (this->ReheatCoilMaxCapacity != AutoSize) {
    2120          367 :                 this->GetGasElecHeatCoilCap = false;
    2121              :             }
    2122              :         } else {
    2123         3240 :             this->GetGasElecHeatCoilCap = false;
    2124              :         }
    2125              :     }
    2126              : 
    2127              :     // Do the Begin Environment initializations
    2128     37322114 :     if (state.dataGlobal->BeginEnvrnFlag && this->MyEnvrnFlag) {
    2129              : 
    2130              :         // Set the outlet node max mass flow rate to the Max Air Flow specified for the Sys
    2131        23015 :         OutletNode = this->OutletNodeNum;
    2132        23015 :         InletNode = this->InletNodeNum;
    2133        23015 :         state.dataLoopNodes->Node(OutletNode).MassFlowRateMax = this->MaxAirVolFlowRate * state.dataEnvrn->StdRhoAir;
    2134        23015 :         this->AirMassFlowRateMax = this->MaxAirVolFlowRate * state.dataEnvrn->StdRhoAir;
    2135        23015 :         this->HeatAirMassFlowRateMax = this->MaxHeatAirVolFlowRate * state.dataEnvrn->StdRhoAir;
    2136        23015 :         state.dataLoopNodes->Node(InletNode).MassFlowRateMax = this->MaxAirVolFlowRate * state.dataEnvrn->StdRhoAir;
    2137        23015 :         this->MassFlowDiff = 1.0e-10 * this->AirMassFlowRateMax;
    2138              : 
    2139        23015 :         if (this->HWplantLoc.loopNum > 0 && this->ReheatComp_Num != HeatingCoilType::SteamAirHeating) { // protect early calls before plant is setup
    2140        14269 :             rho = state.dataPlnt->PlantLoop(this->HWplantLoc.loopNum).glycol->getDensity(state, Constant::HWInitConvTemp, RoutineName);
    2141              :         } else {
    2142         8746 :             rho = 1000.0;
    2143              :         }
    2144              : 
    2145        23015 :         this->MaxReheatWaterFlow = rho * this->MaxReheatWaterVolFlow;
    2146        23015 :         this->MinReheatWaterFlow = rho * this->MinReheatWaterVolFlow;
    2147              : 
    2148        23015 :         this->AirMassFlowDuringReheatMax = this->MaxAirVolFlowRateDuringReheat * state.dataEnvrn->StdRhoAir;
    2149              : 
    2150              :         // set the upstream leakage flowrate - remove from here - done in ZoneAirLoopEquipmentManager::SimZoneAirLoopEquipment
    2151              : 
    2152        23015 :         if (this->ReheatComp_Num == HeatingCoilType::SteamAirHeating) {
    2153           78 :             SteamTemp = 100.0;
    2154           78 :             SteamDensity = Fluid::GetSteam(state)->getSatDensity(state, SteamTemp, 1.0, RoutineNameFull);
    2155           78 :             this->MaxReheatSteamFlow = SteamDensity * this->MaxReheatSteamVolFlow;
    2156           78 :             this->MinReheatSteamFlow = SteamDensity * this->MinReheatSteamVolFlow;
    2157              :         }
    2158              : 
    2159              :         // get current environment air terminal box turndown minimum flow fraction
    2160        23015 :         Real64 CurrentEnvZoneTurndownMinAirFrac = 1.0;
    2161        23015 :         if (this->zoneTurndownMinAirFracSched != nullptr) {
    2162           80 :             CurrentEnvZoneTurndownMinAirFrac = this->zoneTurndownMinAirFracSched->getCurrentVal();
    2163              :         }
    2164        23015 :         if ((this->SysType_Num == SysType::SingleDuctVAVReheat || this->SysType_Num == SysType::SingleDuctCBVAVReheat) ||
    2165         8232 :             (this->SysType_Num == SysType::SingleDuctCBVAVNoReheat)) {
    2166              :             // need the lowest schedule value
    2167        14803 :             if (this->ZoneMinAirFracMethod == MinFlowFraction::Scheduled) {
    2168          232 :                 this->ZoneMinAirFracDes = this->zoneMinAirFracSched->getCurrentVal();
    2169              :             }
    2170        14803 :             state.dataLoopNodes->Node(OutletNode).MassFlowRateMin =
    2171        14803 :                 state.dataLoopNodes->Node(OutletNode).MassFlowRateMax * this->ZoneMinAirFracDes * CurrentEnvZoneTurndownMinAirFrac;
    2172        14803 :             state.dataLoopNodes->Node(InletNode).MassFlowRateMin =
    2173        14803 :                 state.dataLoopNodes->Node(InletNode).MassFlowRateMax * this->ZoneMinAirFracDes * CurrentEnvZoneTurndownMinAirFrac;
    2174              :         } else {
    2175         8212 :             state.dataLoopNodes->Node(OutletNode).MassFlowRateMin = 0.0;
    2176         8212 :             state.dataLoopNodes->Node(InletNode).MassFlowRateMin = 0.0;
    2177              :         }
    2178        23015 :         if ((this->ReheatControlNode > 0) && !this->PlantLoopScanFlag) {
    2179        14347 :             if (this->ReheatComp_Num == HeatingCoilType::SteamAirHeating) {
    2180           78 :                 InitComponentNodes(state, this->MinReheatSteamFlow, this->MaxReheatSteamFlow, this->ReheatControlNode, this->ReheatCoilOutletNode);
    2181              :             } else {
    2182        14269 :                 InitComponentNodes(state, this->MinReheatWaterFlow, this->MaxReheatWaterFlow, this->ReheatControlNode, this->ReheatCoilOutletNode);
    2183              :             }
    2184              :         }
    2185              :         // Find air loop associated with terminal unit
    2186        23015 :         if ((this->CtrlZoneNum > 0) && (this->CtrlZoneInNodeIndex > 0)) {
    2187        23015 :             this->AirLoopNum = state.dataZoneEquip->ZoneEquipConfig(this->CtrlZoneNum).InletNodeAirLoopNum(this->CtrlZoneInNodeIndex);
    2188        23015 :             state.dataDefineEquipment->AirDistUnit(this->ADUNum).AirLoopNum = this->AirLoopNum;
    2189              :         }
    2190              : 
    2191        23015 :         this->MyEnvrnFlag = false;
    2192              :     }
    2193              : 
    2194     37322114 :     if (!state.dataGlobal->BeginEnvrnFlag) {
    2195     37157682 :         this->MyEnvrnFlag = true;
    2196              :     }
    2197              : 
    2198              :     // Initialize the Inlet Nodes of the air side of air terminal
    2199     37322114 :     InletNode = this->InletNodeNum;
    2200     37322114 :     OutletNode = this->OutletNodeNum;
    2201              : 
    2202     37322114 :     Real64 mDotFromOARequirement(0.0);
    2203              : 
    2204     37322114 :     if (this->SysType_Num == SysType::SingleDuctConstVolNoReheat) {
    2205      8544703 :         if (!this->NoOAFlowInputFromUser) {
    2206         6414 :             mDotFromOARequirement = this->AirMassFlowRateMax;
    2207         6414 :             int airLoopNum(0);
    2208         6414 :             Real64 airLoopOAFrac(0.0);
    2209         6414 :             airLoopNum = this->AirLoopNum;
    2210         6414 :             if (airLoopNum > 0) {
    2211         6405 :                 airLoopOAFrac = state.dataAirLoop->AirLoopFlow(airLoopNum).OAFrac;
    2212         6405 :                 bool UseOccSchFlag = false;
    2213         6405 :                 if (this->OAPerPersonMode == DataZoneEquipment::PerPersonVentRateMode::DCVByCurrentLevel) {
    2214         6405 :                     UseOccSchFlag = true;
    2215              :                 }
    2216         6405 :                 if (airLoopOAFrac > 0.0) {
    2217              :                     Real64 vDotOAReq =
    2218         6389 :                         DataSizing::calcDesignSpecificationOutdoorAir(state, this->OARequirementsPtr, this->CtrlZoneNum, UseOccSchFlag, true);
    2219         6389 :                     mDotFromOARequirement = vDotOAReq * state.dataEnvrn->StdRhoAir / airLoopOAFrac;
    2220         6389 :                     mDotFromOARequirement = min(mDotFromOARequirement, this->AirMassFlowRateMax);
    2221              :                 } else {
    2222           16 :                     mDotFromOARequirement = this->AirMassFlowRateMax;
    2223              :                 }
    2224              :             }
    2225              :         }
    2226              :     }
    2227              : 
    2228     37322114 :     if (this->ZoneMinAirFracMethod == MinFlowFraction::Scheduled) {
    2229      2288391 :         this->ZoneMinAirFracDes = this->zoneMinAirFracSched->getCurrentVal();
    2230              :         // now reset inlet node min avail
    2231      2288391 :         state.dataLoopNodes->Node(InletNode).MassFlowRateMinAvail = this->AirMassFlowRateMax * this->ZoneMinAirFracDes * this->ZoneTurndownMinAirFrac;
    2232              :     }
    2233              : 
    2234     37322114 :     if (FirstHVACIteration) {
    2235              :         // The first time through set the mass flow rate to the Max
    2236     14340948 :         if ((state.dataLoopNodes->Node(InletNode).MassFlowRate > 0.0) && (this->availSched->getCurrentVal() > 0.0)) {
    2237     11590966 :             if (!(state.afn->distribution_simulated && state.afn->AirflowNetworkFanActivated)) {
    2238     11590950 :                 state.dataLoopNodes->Node(InletNode).MassFlowRate = this->AirMassFlowRateMax;
    2239              :             }
    2240              :         } else {
    2241      2749982 :             state.dataLoopNodes->Node(InletNode).MassFlowRate = 0.0;
    2242              :         }
    2243     14340948 :         if ((state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail > 0.0) && (this->availSched->getCurrentVal() > 0.0)) {
    2244     11591228 :             if (!(state.afn->distribution_simulated && state.afn->AirflowNetworkFanActivated)) {
    2245     11591212 :                 if (this->SysType_Num == SysType::SingleDuctConstVolNoReheat) {
    2246      2350930 :                     if (this->NoOAFlowInputFromUser) {
    2247      2347731 :                         state.dataLoopNodes->Node(InletNode).MassFlowRate = this->AirMassFlowRateMax;
    2248      2347731 :                         state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail = this->AirMassFlowRateMax;
    2249              :                     } else {
    2250         3199 :                         state.dataLoopNodes->Node(InletNode).MassFlowRate = mDotFromOARequirement;
    2251         3199 :                         state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail = mDotFromOARequirement;
    2252              :                     }
    2253      2350930 :                     if (this->EMSOverrideAirFlow) {
    2254            0 :                         state.dataLoopNodes->Node(InletNode).MassFlowRate = this->EMSMassFlowRateValue;
    2255            0 :                         state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail = this->EMSMassFlowRateValue;
    2256              :                     }
    2257              :                 } else {
    2258      9240282 :                     state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail = this->AirMassFlowRateMax;
    2259              :                 }
    2260              :             }
    2261              :         } else {
    2262      2749720 :             state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail = 0.0;
    2263              :         }
    2264              : 
    2265     14340948 :         if ((state.dataLoopNodes->Node(InletNode).MassFlowRate > 0.0) && (this->availSched->getCurrentVal() > 0.0)) {
    2266     11590967 :             if (!(state.afn->distribution_simulated && state.afn->AirflowNetworkFanActivated)) {
    2267     11590951 :                 state.dataLoopNodes->Node(InletNode).MassFlowRateMinAvail =
    2268     11590951 :                     this->AirMassFlowRateMax * this->ZoneMinAirFracDes * this->ZoneTurndownMinAirFrac;
    2269              :             }
    2270              :         } else {
    2271      2749981 :             state.dataLoopNodes->Node(InletNode).MassFlowRateMinAvail = 0.0;
    2272              :         }
    2273              :         // reset the mass flow rate histories
    2274     14340948 :         this->MassFlow1 = 0.0;
    2275     14340948 :         this->MassFlow2 = 0.0;
    2276     14340948 :         this->MassFlow3 = 0.0;
    2277     14340948 :         this->MassFlow3 = 0.0;
    2278              : 
    2279              :     } else {
    2280     22981166 :         if (this->SysType_Num == SysType::SingleDuctConstVolNoReheat) {
    2281      5468931 :             if (!this->EMSOverrideAirFlow) {
    2282      5468931 :                 if ((state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail > 0.0) && (this->availSched->getCurrentVal() > 0.0)) {
    2283      4676379 :                     if (this->NoOAFlowInputFromUser) {
    2284      4673185 :                         if (state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail < state.dataLoopNodes->Node(InletNode).MassFlowRateMax) {
    2285      1871145 :                             state.dataLoopNodes->Node(InletNode).MassFlowRate = state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail;
    2286      2802040 :                         } else if (state.dataLoopNodes->Node(InletNode).MassFlowRateMinAvail > state.dataLoopNodes->Node(InletNode).MassFlowRateMin) {
    2287        92214 :                             state.dataLoopNodes->Node(InletNode).MassFlowRate = state.dataLoopNodes->Node(InletNode).MassFlowRateMinAvail;
    2288              :                         } else {
    2289      2709826 :                             state.dataLoopNodes->Node(InletNode).MassFlowRate = state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail;
    2290              :                         }
    2291              :                     } else {
    2292         3194 :                         state.dataLoopNodes->Node(InletNode).MassFlowRate = mDotFromOARequirement;
    2293              :                         // but also apply constraints
    2294         3194 :                         state.dataLoopNodes->Node(InletNode).MassFlowRate =
    2295         3194 :                             min(state.dataLoopNodes->Node(InletNode).MassFlowRate, state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail);
    2296         3194 :                         state.dataLoopNodes->Node(InletNode).MassFlowRate =
    2297         3194 :                             min(state.dataLoopNodes->Node(InletNode).MassFlowRate, state.dataLoopNodes->Node(InletNode).MassFlowRateMax);
    2298         3194 :                         state.dataLoopNodes->Node(InletNode).MassFlowRate =
    2299         3194 :                             max(state.dataLoopNodes->Node(InletNode).MassFlowRate, state.dataLoopNodes->Node(InletNode).MassFlowRateMinAvail);
    2300         3194 :                         state.dataLoopNodes->Node(InletNode).MassFlowRate =
    2301         3194 :                             max(state.dataLoopNodes->Node(InletNode).MassFlowRate, state.dataLoopNodes->Node(InletNode).MassFlowRateMin);
    2302              :                     }
    2303              :                 } else {
    2304       792552 :                     state.dataLoopNodes->Node(InletNode).MassFlowRate = 0.0;
    2305       792552 :                     state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail = 0.0;
    2306       792552 :                     state.dataLoopNodes->Node(InletNode).MassFlowRateMinAvail = 0.0;
    2307              :                 }
    2308              :             } else { // EMS override on
    2309            0 :                 state.dataLoopNodes->Node(InletNode).MassFlowRate = this->EMSMassFlowRateValue;
    2310              :                 // but also apply constraints
    2311            0 :                 state.dataLoopNodes->Node(InletNode).MassFlowRate =
    2312            0 :                     min(state.dataLoopNodes->Node(InletNode).MassFlowRate, state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail);
    2313            0 :                 state.dataLoopNodes->Node(InletNode).MassFlowRate =
    2314            0 :                     min(state.dataLoopNodes->Node(InletNode).MassFlowRate, state.dataLoopNodes->Node(InletNode).MassFlowRateMax);
    2315            0 :                 state.dataLoopNodes->Node(InletNode).MassFlowRate =
    2316            0 :                     max(state.dataLoopNodes->Node(InletNode).MassFlowRate, state.dataLoopNodes->Node(InletNode).MassFlowRateMinAvail);
    2317            0 :                 state.dataLoopNodes->Node(InletNode).MassFlowRate =
    2318            0 :                     max(state.dataLoopNodes->Node(InletNode).MassFlowRate, state.dataLoopNodes->Node(InletNode).MassFlowRateMin);
    2319              :             }
    2320              :         }
    2321              :     }
    2322              : 
    2323              :     // Do a check and make sure that the max and min available(control) flow is
    2324              :     //  between the physical max and min while operating.
    2325     37322114 :     this->sd_airterminalInlet.AirMassFlowRateMaxAvail = min(this->AirMassFlowRateMax, state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail);
    2326     37322114 :     this->sd_airterminalInlet.AirMassFlowRateMinAvail =
    2327     37322114 :         min(max(state.dataLoopNodes->Node(OutletNode).MassFlowRateMin, state.dataLoopNodes->Node(InletNode).MassFlowRateMinAvail),
    2328              :             this->sd_airterminalInlet.AirMassFlowRateMaxAvail);
    2329              : 
    2330              :     // Do the following initializations (every time step): This should be the info from
    2331              :     // the previous components outlets or the node data in this section.
    2332              :     // Load the node data in this section for the component simulation
    2333     37322114 :     this->sd_airterminalInlet.AirMassFlowRate = state.dataLoopNodes->Node(InletNode).MassFlowRate;
    2334     37322114 :     this->sd_airterminalInlet.AirTemp = state.dataLoopNodes->Node(InletNode).Temp;
    2335     37322114 :     this->sd_airterminalInlet.AirHumRat = state.dataLoopNodes->Node(InletNode).HumRat;
    2336     37322114 :     this->sd_airterminalInlet.AirEnthalpy = state.dataLoopNodes->Node(InletNode).Enthalpy;
    2337              : 
    2338              :     // update to the current minimum air flow fraction
    2339     37322114 :     this->ZoneMinAirFrac = this->ZoneMinAirFracDes * this->ZoneTurndownMinAirFrac;
    2340     37322114 : }
    2341              : 
    2342         3602 : void SingleDuctAirTerminal::SizeSys(EnergyPlusData &state)
    2343              : {
    2344              : 
    2345              :     // SUBROUTINE INFORMATION:
    2346              :     //       AUTHOR         Fred Buhl
    2347              :     //       DATE WRITTEN   September 2001
    2348              :     //       MODIFIED       August 2013 Daeho Kang, add component sizing table entries
    2349              : 
    2350              :     // PURPOSE OF THIS SUBROUTINE:
    2351              :     // This subroutine is for sizing Sys Components for which flow rates have not been
    2352              :     // specified in the input.
    2353              : 
    2354              :     // METHODOLOGY EMPLOYED:
    2355              :     // Obtains flow rates from the zone or system sizing arrays.
    2356              : 
    2357              :     // Using/Aliasing
    2358              :     using General::SafeDivide;
    2359              :     using PlantUtilities::MyPlantSizingIndex;
    2360              :     using SteamCoils::GetCoilSteamInletNode;
    2361              :     using SteamCoils::GetCoilSteamOutletNode;
    2362              :     using WaterCoils::GetCoilWaterInletNode;
    2363              :     using WaterCoils::GetCoilWaterOutletNode;
    2364              :     using WaterCoils::SetCoilDesFlow;
    2365              : 
    2366              :     // SUBROUTINE PARAMETER DEFINITIONS:
    2367              :     static constexpr std::string_view RoutineName("SizeSys");
    2368              :     static constexpr std::string_view RoutineNameFull("SizeHVACSingleDuct");
    2369              : 
    2370              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2371              :     int PltSizHeatNum; // index of plant sizing object for 1st heating loop
    2372              :     Real64 TempSteamIn;
    2373              :     Real64 EnthSteamOutWet;
    2374              :     Real64 EnthSteamInDry;
    2375              :     Real64 LatentHeatSteam;
    2376              :     Real64 SteamDensity;
    2377              : 
    2378              :     bool PlantSizingErrorsFound;
    2379              :     Real64 rho; // local fluid density
    2380              :     Real64 Cp;  // local fluid specific heat
    2381              : 
    2382         3602 :     Real64 DesMassFlow = 0.0;
    2383         3602 :     bool ErrorsFound = false;
    2384         3602 :     bool IsAutoSize = false;
    2385         3602 :     bool IsMaxFlowAutoSize = false;
    2386         3602 :     Real64 MaxAirVolFlowRateDes = 0.0;              // Autosized maximum air flow rate for reporting
    2387         3602 :     Real64 MaxAirVolFlowRateUser = 0.0;             // Hardsized maximum air flow rate for reporting
    2388         3602 :     Real64 MaxHeatAirVolFlowRateDes = 0.0;          // Autosized maximum heating air flow rate for reporting
    2389         3602 :     Real64 MaxHeatAirVolFlowRateUser = 0.0;         // Hardsized maximum heating air flow rate for reporting
    2390         3602 :     Real64 MinAirFlowFracDes = 0.0;                 // Autosized minimum cooling air flow fraction for reporting
    2391         3602 :     Real64 MinAirFlowFracUser = 0.0;                // User input minimum cooling air flow fraction for reporting
    2392         3602 :     Real64 FixedMinAirDes = 0.0;                    // Autosized minimum cooling air flow rate for reporting [m3/s]
    2393         3602 :     Real64 FixedMinAirUser = 0.0;                   // User input minimum cooling air flow rate for reporting [m3/s]
    2394         3602 :     Real64 MaxAirVolFlowRateDuringReheatDes = 0.0;  // Autosized maximum air flow durign reheat for reporting
    2395         3602 :     Real64 MaxAirVolFlowRateDuringReheatUser = 0.0; // Hardsized maximum air flow durign reheat for reporting
    2396         3602 :     Real64 MaxAirVolFractionDuringReheatDes = 0.0;  // Autosized maximum air fraction durign reheat for reporting
    2397         3602 :     Real64 MaxAirVolFractionDuringReheatUser = 0.0; // Hardsized maximum air flow durign reheat for reporting
    2398         3602 :     Real64 MaxReheatWaterVolFlowDes = 0.0;          // Autosized reheat water flow or reporting
    2399         3602 :     Real64 MaxReheatWaterVolFlowUser = 0.0;         // Hardsized reheat water flow for reporting
    2400         3602 :     Real64 MaxReheatSteamVolFlowDes = 0.0;          // Autosized reheat steam flow for reporting
    2401         3602 :     Real64 MaxReheatSteamVolFlowUser = 0.0;         // Hardsized reheat steam flow for reporting
    2402         3602 :     Real64 MinMinFlowRatio = 0.0;                   // the minimum minimum flow ratio
    2403         3602 :     int SysSizNum = 0;                              // System sizing number
    2404              : 
    2405         3602 :     int ZoneNum = this->CtrlZoneNum;
    2406              : 
    2407         3602 :     auto &TermUnitSizing(state.dataSize->TermUnitSizing);
    2408              : 
    2409         3602 :     if (this->MaxAirVolFlowRate == AutoSize) {
    2410         3025 :         IsAutoSize = true;
    2411              :     }
    2412              : 
    2413         3602 :     if (state.dataSize->CurTermUnitSizingNum > 0) {
    2414         3602 :         if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // simulation continue
    2415          515 :             if (this->MaxAirVolFlowRate > 0.0) {
    2416          515 :                 BaseSizer::reportSizerOutput(
    2417              :                     state, this->sysType, this->SysName, "User-Specified Maximum Air Flow Rate [m3/s]", this->MaxAirVolFlowRate);
    2418              :             }
    2419              :         } else { // Autosize or hard-size with sizing run
    2420              : 
    2421         3087 :             CheckZoneSizing(state, this->sysType, this->SysName);
    2422              : 
    2423              :             Real64 heatingMaxFlow;
    2424         4179 :             if (this->DamperHeatingAction == Action::ReverseWithLimits &&
    2425         1092 :                 state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatVolFlow >
    2426         1092 :                     state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatVolFlowMax) {
    2427          199 :                 heatingMaxFlow = state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatVolFlowMax;
    2428              :             } else {
    2429         2888 :                 heatingMaxFlow = state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatVolFlow;
    2430              :             }
    2431         3087 :             MaxAirVolFlowRateDes = max(state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesCoolVolFlow, heatingMaxFlow);
    2432              : 
    2433         3087 :             if (MaxAirVolFlowRateDes < SmallAirVolFlow) {
    2434            0 :                 MaxAirVolFlowRateDes = 0.0;
    2435              :             }
    2436         3087 :             if (IsAutoSize) {
    2437         3025 :                 this->MaxAirVolFlowRate = MaxAirVolFlowRateDes;
    2438         3025 :                 IsMaxFlowAutoSize = true;
    2439         3025 :                 BaseSizer::reportSizerOutput(state, this->sysType, this->SysName, "Design Size Maximum Air Flow Rate [m3/s]", MaxAirVolFlowRateDes);
    2440              :             } else { // Hard-size with sizing data
    2441           62 :                 if (this->MaxAirVolFlowRate > 0.0 && MaxAirVolFlowRateDes > 0.0) {
    2442           62 :                     MaxAirVolFlowRateUser = this->MaxAirVolFlowRate;
    2443           62 :                     BaseSizer::reportSizerOutput(state,
    2444              :                                                  this->sysType,
    2445              :                                                  this->SysName,
    2446              :                                                  "Design Size Maximum Air Flow Rate [m3/s]",
    2447              :                                                  MaxAirVolFlowRateDes,
    2448              :                                                  "User-Specified Maximum Air Flow Rate [m3/s]",
    2449              :                                                  MaxAirVolFlowRateUser);
    2450           62 :                     if (state.dataGlobal->DisplayExtraWarnings) {
    2451            0 :                         if ((std::abs(MaxAirVolFlowRateDes - MaxAirVolFlowRateUser) / MaxAirVolFlowRateUser) >
    2452            0 :                             state.dataSize->AutoVsHardSizingThreshold) {
    2453            0 :                             ShowMessage(
    2454              :                                 state,
    2455            0 :                                 format("SizeHVACSingleDuct: Potential issue with equipment sizing for {} = \"{}\".", this->sysType, this->SysName));
    2456            0 :                             ShowContinueError(state, format("User-Specified Maximum Air Flow Rate of {:.5R} [m3/s]", MaxAirVolFlowRateUser));
    2457            0 :                             ShowContinueError(state, format("differs from Design Size Maximum Air Flow Rate of {:.5R} [m3/s]", MaxAirVolFlowRateDes));
    2458            0 :                             ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
    2459            0 :                             ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
    2460              :                         }
    2461              :                     }
    2462              :                 }
    2463              :             }
    2464              :         }
    2465              :     }
    2466              : 
    2467         3602 :     IsAutoSize = false;
    2468         3602 :     if (this->MaxHeatAirVolFlowRate == AutoSize) {
    2469            8 :         IsAutoSize = true;
    2470              :     }
    2471         3602 :     if (state.dataSize->CurTermUnitSizingNum > 0) {
    2472         3602 :         if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // simulation should continue
    2473          515 :             state.dataSingleDuct->UserInputMaxHeatAirVolFlowRateSS = this->MaxHeatAirVolFlowRate;
    2474          515 :             if (this->MaxHeatAirVolFlowRate > 0.0) {
    2475            0 :                 BaseSizer::reportSizerOutput(
    2476              :                     state, this->sysType, this->SysName, "User-Specified Maximum Heating Air Flow Rate [m3/s]", this->MaxHeatAirVolFlowRate);
    2477              :             }
    2478              :         } else {
    2479         3087 :             CheckZoneSizing(state, this->sysType, this->SysName);
    2480         4179 :             if (this->DamperHeatingAction == Action::ReverseWithLimits &&
    2481         1092 :                 state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatVolFlow >
    2482         1092 :                     state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatVolFlowMax) {
    2483          199 :                 MaxHeatAirVolFlowRateDes = state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatVolFlowMax;
    2484              :             } else {
    2485         2888 :                 MaxHeatAirVolFlowRateDes = state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatVolFlow;
    2486              :             }
    2487         3087 :             if (MaxHeatAirVolFlowRateDes < SmallAirVolFlow) {
    2488           14 :                 MaxHeatAirVolFlowRateDes = 0.0;
    2489              :             }
    2490         3087 :             if (IsAutoSize) {
    2491            8 :                 this->MaxHeatAirVolFlowRate = MaxHeatAirVolFlowRateDes;
    2492            8 :                 state.dataSingleDuct->UserInputMaxHeatAirVolFlowRateSS = 0.0;
    2493            8 :                 BaseSizer::reportSizerOutput(
    2494              :                     state, this->sysType, this->SysName, "Design Size Maximum Heating Air Flow Rate [m3/s]", MaxHeatAirVolFlowRateDes);
    2495              :             } else { // Hard-size with sizing data
    2496         3079 :                 if (this->MaxHeatAirVolFlowRate > 0.0 && MaxHeatAirVolFlowRateDes > 0.0) {
    2497            0 :                     MaxHeatAirVolFlowRateUser = this->MaxHeatAirVolFlowRate;
    2498            0 :                     state.dataSingleDuct->UserInputMaxHeatAirVolFlowRateSS = this->MaxHeatAirVolFlowRate;
    2499            0 :                     BaseSizer::reportSizerOutput(state,
    2500              :                                                  this->sysType,
    2501              :                                                  this->SysName,
    2502              :                                                  "Design Size Maximum Heating Air Flow Rate [m3/s]",
    2503              :                                                  MaxHeatAirVolFlowRateDes,
    2504              :                                                  "User-Specified Maximum Heating Air Flow Rate [m3/s]",
    2505              :                                                  MaxHeatAirVolFlowRateUser);
    2506            0 :                     if (state.dataGlobal->DisplayExtraWarnings) {
    2507            0 :                         if ((std::abs(MaxHeatAirVolFlowRateDes - MaxHeatAirVolFlowRateUser) / MaxHeatAirVolFlowRateUser) >
    2508            0 :                             state.dataSize->AutoVsHardSizingThreshold) {
    2509            0 :                             ShowMessage(
    2510              :                                 state,
    2511            0 :                                 format("SizeHVACSingleDuct: Potential issue with equipment sizing for {} = \"{}\".", this->sysType, this->SysName));
    2512            0 :                             ShowContinueError(state,
    2513            0 :                                               format("User-Specified Maximum Heating Air Flow Rate of {:.5R} [m3/s]", MaxHeatAirVolFlowRateUser));
    2514            0 :                             ShowContinueError(
    2515            0 :                                 state, format("differs from Design Size Maximum Heating Air Flow Rate of {:.5R} [m3/s]", MaxHeatAirVolFlowRateDes));
    2516            0 :                             ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
    2517            0 :                             ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
    2518              :                         }
    2519              :                     }
    2520              :                 }
    2521              :             }
    2522              :         }
    2523              :     }
    2524              : 
    2525              :     // get design day terminal unit turndown minimum flow fraction
    2526         3602 :     if (this->zoneTurndownMinAirFracSched != nullptr) {
    2527            5 :         this->ZoneTurndownMinAirFrac = this->zoneTurndownMinAirFracSched->getCurrentVal();
    2528              :     } else {
    2529         3597 :         this->ZoneTurndownMinAirFrac = 1.0;
    2530              :     }
    2531              : 
    2532              :     // if a sizing run has been done, check if system sizing has been done for this system
    2533         3602 :     bool SizingDesRunThisAirSys = false;
    2534         3602 :     if (state.dataSize->SysSizingRunDone) {
    2535         3059 :         int AirLoopNum = state.dataZoneEquip->ZoneEquipConfig(this->CtrlZoneNum).InletNodeAirLoopNum(this->CtrlZoneInNodeIndex);
    2536         3059 :         if (AirLoopNum > 0) {
    2537         3059 :             CheckThisAirSystemForSizing(state, AirLoopNum, SizingDesRunThisAirSys);
    2538              :         }
    2539              : 
    2540              :         // get system sizing id if a sizing run has been done for this system
    2541         3059 :         if (SizingDesRunThisAirSys) {
    2542         3055 :             SysSizNum = Util::FindItemInList(
    2543         3055 :                 state.dataSize->FinalSysSizing(AirLoopNum).AirPriLoopName, state.dataSize->SysSizInput, &SystemSizingInputData::AirPriLoopName);
    2544         3055 :             if (SysSizNum == 0) {
    2545            0 :                 SysSizNum = 1; // use first when none applicable
    2546              :             }
    2547              :         }
    2548              :     }
    2549              : 
    2550         3602 :     IsAutoSize = false;
    2551         3602 :     if (this->ZoneMinAirFracDes == AutoSize) {
    2552           45 :         IsAutoSize = true;
    2553              :     }
    2554         3602 :     if (this->ZoneMinAirFracMethod == MinFlowFraction::Constant) {
    2555         2308 :         if (state.dataSize->ZoneSizingRunDone) {
    2556         2264 :             if (state.dataSize->CurTermUnitSizingNum > 0) {
    2557              :                 // use the combined defaults or other user inputs stored in DesCoolVolFlowMin
    2558         2264 :                 if (this->MaxAirVolFlowRate > 0.0) {
    2559         2264 :                     MinAirFlowFracDes = min(1.0,
    2560         2264 :                                             state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesCoolVolFlowMin /
    2561         2264 :                                                 this->MaxAirVolFlowRate);
    2562              :                 } else {
    2563            0 :                     MinAirFlowFracDes = 0.0;
    2564              :                 }
    2565              :             }
    2566              :         } else {
    2567              :             // if no zone sizing values available; use max of min frac = 0.2 and 0.000762 [m3/s-m2]
    2568           44 :             if (this->MaxAirVolFlowRate > 0.0) {
    2569           44 :                 MinMinFlowRatio = (0.000762 * state.dataHeatBal->Zone(ZoneNum).FloorArea * state.dataHeatBal->Zone(ZoneNum).Multiplier *
    2570           44 :                                    state.dataHeatBal->Zone(ZoneNum).ListMultiplier) /
    2571           44 :                                   this->MaxAirVolFlowRate;
    2572           44 :                 MinAirFlowFracDes = max(0.2, MinMinFlowRatio);
    2573              :             } else {
    2574            0 :                 MinAirFlowFracDes = 0.0;
    2575              :             }
    2576              :         }
    2577         2308 :         if (SizingDesRunThisAirSys) {
    2578         2261 :             if (state.dataSize->SysSizInput(SysSizNum).SystemOAMethod == SysOAMethod::SP) { // 62.1 simplified procedure
    2579            4 :                 if (this->MaxAirVolFlowRate > 0.0) {
    2580            4 :                     MinAirFlowFracDes = 1.5 *
    2581            4 :                                         max(state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).VozClgByZone,
    2582            4 :                                             state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).VozHtgByZone) /
    2583            4 :                                         this->MaxAirVolFlowRate;
    2584              : 
    2585              :                     // adjust maximum flow rate
    2586            4 :                     if (MinAirFlowFracDes > 1.0 && IsMaxFlowAutoSize) {
    2587            0 :                         this->MaxAirVolFlowRate *= MinAirFlowFracDes;
    2588            0 :                         MinAirFlowFracDes = 1.0;
    2589            0 :                         ShowWarningError(state,
    2590            0 :                                          format("SingleDuctSystem:SizeSys: Autosized maximum air flow rate for {} was increased to meet the zone "
    2591              :                                                 "primary air flow determined according to the ASHRAE Standard 62.1 Simplified Procedure.",
    2592            0 :                                                 this->SysName));
    2593            4 :                     } else if (MinAirFlowFracDes > 1.0) {
    2594            0 :                         ShowWarningError(state,
    2595            0 :                                          format("SingleDuctSystem:SizeSys: Maximum air flow rate for {} is potentially too low.", this->SysName));
    2596            0 :                         ShowContinueError(
    2597              :                             state,
    2598              :                             "The flow is lower than the minimum flow rate calculated following the ASHRAE Standard 62.1 Simplified Procedure:");
    2599            0 :                         ShowContinueError(state, format(" User-specified maximum air flow rate: {:.3R} m3/s.", this->MaxAirVolFlowRate));
    2600            0 :                         ShowContinueError(state,
    2601            0 :                                           format(" Calculated minimum air flow rate: {:.3R} m3/s.", this->MaxAirVolFlowRate * MinAirFlowFracDes));
    2602            0 :                         MinAirFlowFracDes = 1.0;
    2603              :                     }
    2604              :                 }
    2605              :             }
    2606              :         }
    2607         2308 :         if (IsAutoSize) {
    2608              :             // report out autosized result and save value in Sys array
    2609           86 :             BaseSizer::reportSizerOutput(state,
    2610              :                                          this->sysType,
    2611              :                                          this->SysName,
    2612              :                                          "Design Size Constant Minimum Air Flow Fraction",
    2613           43 :                                          MinAirFlowFracDes * this->ZoneTurndownMinAirFrac);
    2614           43 :             if (SizingDesRunThisAirSys) {
    2615           43 :                 if (state.dataSize->SysSizInput(SysSizNum).SystemOAMethod == SysOAMethod::SP) {
    2616            4 :                     state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).VpzMinByZoneSPSized = true;
    2617              :                 }
    2618              :             }
    2619           43 :             this->ZoneMinAirFracDes = MinAirFlowFracDes;
    2620              :         } else {
    2621              :             // report out hard (user set) value and issue warning if appropriate
    2622         2265 :             MinAirFlowFracUser = this->ZoneMinAirFracDes;
    2623         4530 :             BaseSizer::reportSizerOutput(state,
    2624              :                                          this->sysType,
    2625              :                                          this->SysName,
    2626              :                                          "Design Size Constant Minimum Air Flow Fraction",
    2627         2265 :                                          MinAirFlowFracDes * this->ZoneTurndownMinAirFrac,
    2628              :                                          "User-Specified Constant Minimum Air Flow Fraction",
    2629         2265 :                                          MinAirFlowFracUser * this->ZoneTurndownMinAirFrac);
    2630         2265 :             if (state.dataGlobal->DisplayExtraWarnings) {
    2631          220 :                 if ((MinAirFlowFracUser > 0.0) &&
    2632          110 :                     ((std::abs(MinAirFlowFracDes - MinAirFlowFracUser) / MinAirFlowFracUser) > state.dataSize->AutoVsHardSizingThreshold)) {
    2633          194 :                     ShowMessage(state,
    2634          194 :                                 format("SizeHVACSingleDuct: Potential issue with equipment sizing for {} = \"{}\".", this->sysType, this->SysName));
    2635           97 :                     ShowContinueError(state, format("User-Specified Minimum Cooling Air Flow Fraction of {:.5R}", MinAirFlowFracUser));
    2636           97 :                     ShowContinueError(state, format("differs from Design Size Minimum Cooling Air Flow Fraction of {:.5R}", MinAirFlowFracDes));
    2637          194 :                     ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
    2638          291 :                     ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
    2639              :                 }
    2640              :             }
    2641              :         }
    2642              :         // report out the min air flow rate set by min air flow frac
    2643         4616 :         BaseSizer::reportSizerOutput(state,
    2644              :                                      this->sysType,
    2645              :                                      this->SysName,
    2646              :                                      "Design Size Minimum Air Flow Rate [m3/s]",
    2647         2308 :                                      this->MaxAirVolFlowRate * this->ZoneMinAirFracDes * this->ZoneTurndownMinAirFrac);
    2648              :     } else {
    2649         1294 :         if (IsAutoSize) {
    2650            2 :             this->ZoneMinAirFracDes = 0.0;
    2651              :         }
    2652              :     }
    2653              : 
    2654         3602 :     IsAutoSize = false;
    2655         3602 :     if (this->ZoneFixedMinAir == AutoSize) {
    2656         2397 :         IsAutoSize = true;
    2657              :     }
    2658         3602 :     if (this->ZoneMinAirFracMethod == MinFlowFraction::Fixed) {
    2659            3 :         if (state.dataSize->ZoneSizingRunDone) {
    2660            2 :             if (state.dataSize->CurTermUnitSizingNum > 0) {
    2661              :                 // use the combined defaults or other user inputs stored in DesCoolVolFlowMin
    2662            2 :                 if (this->MaxAirVolFlowRate > 0.0) {
    2663            2 :                     FixedMinAirDes = state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesCoolVolFlowMin;
    2664              :                 } else {
    2665            0 :                     MinAirFlowFracDes = 0.0;
    2666              :                 }
    2667              :             }
    2668              :         } else {
    2669              :             // if no zone sizing values available; use max of min frac = 0.2 and 0.000762 [m3/s-m2]
    2670            1 :             if (this->MaxAirVolFlowRate > 0.0) {
    2671            1 :                 FixedMinAirDes = max(0.2 * this->MaxAirVolFlowRate,
    2672            1 :                                      0.000762 * state.dataHeatBal->Zone(ZoneNum).FloorArea * state.dataHeatBal->Zone(ZoneNum).Multiplier *
    2673            1 :                                          state.dataHeatBal->Zone(ZoneNum).ListMultiplier);
    2674              :             } else {
    2675            0 :                 MinAirFlowFracDes = 0.0;
    2676              :             }
    2677              :         }
    2678            3 :         if (SizingDesRunThisAirSys) {
    2679            2 :             if (state.dataSize->SysSizInput(SysSizNum).SystemOAMethod == SysOAMethod::SP) { // 62.1 simplified procedure
    2680            2 :                 if (this->MaxAirVolFlowRate > 0.0) {
    2681            2 :                     FixedMinAirDes = 1.5 * max(state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).VozClgByZone,
    2682            2 :                                                state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).VozHtgByZone);
    2683              : 
    2684              :                     // adjust maximum flow rate
    2685            2 :                     if (FixedMinAirDes > this->MaxAirVolFlowRate && IsMaxFlowAutoSize) {
    2686            0 :                         this->MaxAirVolFlowRate = FixedMinAirDes;
    2687            0 :                         ShowWarningError(state,
    2688            0 :                                          format("SingleDuctSystem:SizeSys: Autosized maximum air flow rate for {} was increased to meet the zone "
    2689              :                                                 "primary air flow determined according to the ASHRAE Standard 62.1 Simplified Procedure.",
    2690            0 :                                                 this->SysName));
    2691            2 :                     } else if (FixedMinAirDes > this->MaxAirVolFlowRate) {
    2692            0 :                         ShowWarningError(state,
    2693            0 :                                          format("SingleDuctSystem:SizeSys: Maximum air flow rate for {} is potentially too low.", this->SysName));
    2694            0 :                         ShowContinueError(
    2695              :                             state,
    2696              :                             "The flow is lower than the minimum flow rate calculated following the ASHRAE Standard 62.1 Simplified Procedure:");
    2697            0 :                         ShowContinueError(state, format(" User-specified maximum air flow rate: {:.3R} m3/s.", this->MaxAirVolFlowRate));
    2698            0 :                         ShowContinueError(state, format(" Calculated minimum air flow rate: {:.3R} m3/s.", FixedMinAirDes));
    2699            0 :                         FixedMinAirDes = this->MaxAirVolFlowRate;
    2700              :                     }
    2701              :                 }
    2702              :             }
    2703              :         }
    2704            3 :         if (IsAutoSize) {
    2705              :             // report out autosized result and save value in Sys array
    2706            4 :             BaseSizer::reportSizerOutput(
    2707            2 :                 state, this->sysType, this->SysName, "Design Size Fixed Minimum Air Flow Rate [m3/s]", FixedMinAirDes * this->ZoneTurndownMinAirFrac);
    2708            2 :             if (SizingDesRunThisAirSys) {
    2709            2 :                 if (state.dataSize->SysSizInput(SysSizNum).SystemOAMethod == SysOAMethod::SP) {
    2710            2 :                     state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).VpzMinByZoneSPSized = true;
    2711              :                 }
    2712              :             }
    2713            2 :             this->ZoneFixedMinAir = FixedMinAirDes;
    2714              :         } else {
    2715              :             // report out hard (user set) value and issue warning if appropriate
    2716            1 :             FixedMinAirUser = this->ZoneFixedMinAir;
    2717            2 :             BaseSizer::reportSizerOutput(state,
    2718              :                                          this->sysType,
    2719              :                                          this->SysName,
    2720              :                                          "Design Size Fixed Minimum Air Flow Rate [m3/s]",
    2721            1 :                                          FixedMinAirDes * this->ZoneTurndownMinAirFrac,
    2722              :                                          "User-Specified Fixed Minimum Air Flow Rate [m3/s]",
    2723            1 :                                          FixedMinAirUser * this->ZoneTurndownMinAirFrac);
    2724            1 :             if (state.dataGlobal->DisplayExtraWarnings) {
    2725            0 :                 if ((std::abs(FixedMinAirDes - FixedMinAirUser) / FixedMinAirUser) > state.dataSize->AutoVsHardSizingThreshold) {
    2726            0 :                     ShowMessage(state,
    2727            0 :                                 format("SizeHVACSingleDuct: Potential issue with equipment sizing for {} = \"{}\".", this->sysType, this->SysName));
    2728            0 :                     ShowContinueError(state, format("User-Specified Minimum Cooling Air Flow Rate of {:.5R} [m3/s]", FixedMinAirUser));
    2729            0 :                     ShowContinueError(state, format("differs from Design Size Minimum Cooling Air Flow Rate of {:.5R} [m3/s]", FixedMinAirDes));
    2730            0 :                     ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
    2731            0 :                     ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
    2732              :                 }
    2733              :             }
    2734              :         }
    2735              :         // report out the min air flow frac set by the min air flow rate
    2736            3 :         if (this->MaxAirVolFlowRate > 0.0) {
    2737            6 :             BaseSizer::reportSizerOutput(state,
    2738              :                                          this->sysType,
    2739              :                                          this->SysName,
    2740              :                                          "Design Size Minimum Air Flow Fraction [m3/s]",
    2741            3 :                                          this->ZoneFixedMinAir * this->ZoneTurndownMinAirFrac / this->MaxAirVolFlowRate);
    2742              :         }
    2743              :     } else {
    2744         3599 :         if (IsAutoSize) {
    2745         2395 :             this->ZoneFixedMinAir = 0.0;
    2746              :         }
    2747              :     }
    2748              : 
    2749         3602 :     if (this->ZoneMinAirFracMethod == MinFlowFraction::Scheduled) {
    2750              :         // need a value for sizing.
    2751          163 :         if (this->ConstantMinAirFracSetByUser) {
    2752            3 :             this->ZoneMinAirFracDes = this->DesignMinAirFrac;
    2753              :             // if both inputs are defined, use the max
    2754            3 :             if (this->FixedMinAirSetByUser) {
    2755            0 :                 this->ZoneMinAirFracDes = min(1.0, max(this->ZoneMinAirFracDes, SafeDivide(this->DesignFixedMinAir, this->MaxAirVolFlowRate)));
    2756              :             }
    2757              :             // if only fixed is defined, use the value
    2758          160 :         } else if (this->FixedMinAirSetByUser) {
    2759            0 :             this->ZoneMinAirFracDes = min(1.0, SafeDivide(this->DesignFixedMinAir, this->MaxAirVolFlowRate));
    2760              :         } else {
    2761              :             // use an average of min and max in schedule
    2762          160 :             this->ZoneMinAirFracDes = (this->zoneMinAirFracSched->getMinVal(state) + this->zoneMinAirFracSched->getMaxVal(state)) / 2.0;
    2763              :         }
    2764              :     }
    2765              : 
    2766         3602 :     if (this->ZoneMinAirFracMethod == MinFlowFraction::Fixed) {
    2767              :         // need a value for sizing.
    2768            3 :         this->ZoneMinAirFracDes = min(1.0, SafeDivide(this->ZoneFixedMinAir, this->MaxAirVolFlowRate));
    2769              :     }
    2770              : 
    2771         3602 :     if (this->DamperHeatingAction == Action::ReverseWithLimits) {
    2772         1114 :         if (state.dataSize->ZoneSizingRunDone) {
    2773         1092 :             if (state.dataSize->CurTermUnitSizingNum > 0) {
    2774              :                 // if zone sizing run done, set the design max reheat air flow to the value from the design calcs
    2775         1092 :                 if (state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatVolFlow >
    2776         1092 :                     state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatVolFlowMax) {
    2777          199 :                     MaxAirVolFlowRateDuringReheatDes =
    2778          199 :                         state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatVolFlowMax;
    2779              :                 } else {
    2780          893 :                     MaxAirVolFlowRateDuringReheatDes = state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatVolFlow;
    2781              :                 }
    2782              :             }
    2783              :         } else {
    2784              :             // if no design calc use 0.002032 [m3/s-m2] times floor area. That's .40 cfm/ft2
    2785           22 :             MaxAirVolFlowRateDuringReheatDes = min(0.002032 * this->ZoneFloorArea, this->MaxAirVolFlowRate);
    2786              :         }
    2787              :         // check that result is not greater than the max flow or less than the min flow.
    2788         1114 :         MaxAirVolFlowRateDuringReheatDes = min(MaxAirVolFlowRateDuringReheatDes, this->MaxAirVolFlowRate);
    2789         1114 :         MaxAirVolFlowRateDuringReheatDes = max(MaxAirVolFlowRateDuringReheatDes, (this->MaxAirVolFlowRate * this->ZoneMinAirFracDes));
    2790         1114 :         if (this->MaxAirVolFlowRate > 0.0) {
    2791         1114 :             MaxAirVolFractionDuringReheatDes = MaxAirVolFlowRateDuringReheatDes / this->MaxAirVolFlowRate;
    2792              :         } else {
    2793            0 :             MaxAirVolFractionDuringReheatDes = 0.0;
    2794              :         }
    2795         1114 :         if (this->MaxAirVolFlowRateDuringReheat == Constant::AutoCalculate && this->MaxAirVolFractionDuringReheat == Constant::AutoCalculate) {
    2796              :             // if both inputs are autosize (the default) report both out and save in the Sys array.
    2797          740 :             BaseSizer::reportSizerOutput(
    2798              :                 state, this->sysType, this->SysName, "Design Size Maximum Flow Fraction during Reheat []", MaxAirVolFractionDuringReheatDes);
    2799          740 :             if (this->ZoneFloorArea > 0.0) {
    2800         1480 :                 BaseSizer::reportSizerOutput(state,
    2801              :                                              this->sysType,
    2802              :                                              this->SysName,
    2803              :                                              "Design Size Maximum Flow per Zone Floor Area during Reheat [m3/s-m2]",
    2804          740 :                                              MaxAirVolFlowRateDuringReheatDes / this->ZoneFloorArea);
    2805              :             }
    2806          740 :             this->MaxAirVolFlowRateDuringReheat = MaxAirVolFlowRateDuringReheatDes;
    2807          740 :             this->MaxAirVolFractionDuringReheat = MaxAirVolFractionDuringReheatDes;
    2808          374 :         } else if (this->MaxAirVolFlowRateDuringReheat == Constant::AutoCalculate && this->MaxAirVolFractionDuringReheat != Constant::AutoCalculate) {
    2809              :             // if max reheat flow fraction was input, set the max reheat flow design value correspondingly, report both out.
    2810              :             // Check for optional caution message that user input value is not within 10% of the design value.
    2811          351 :             MaxAirVolFlowRateDuringReheatDes = this->MaxAirVolFractionDuringReheat * this->MaxAirVolFlowRate;
    2812          351 :             MaxAirVolFractionDuringReheatUser = this->MaxAirVolFractionDuringReheat;
    2813          351 :             BaseSizer::reportSizerOutput(state,
    2814              :                                          this->sysType,
    2815              :                                          this->SysName,
    2816              :                                          "Design Size Maximum Flow Fraction during Reheat []",
    2817              :                                          MaxAirVolFractionDuringReheatDes,
    2818              :                                          "User-Specified Maximum Flow Fraction during Reheat []",
    2819              :                                          MaxAirVolFractionDuringReheatUser);
    2820          351 :             if (this->ZoneFloorArea > 0.0) {
    2821          702 :                 BaseSizer::reportSizerOutput(state,
    2822              :                                              this->sysType,
    2823              :                                              this->SysName,
    2824              :                                              "Design Size Maximum Flow per Zone Floor Area during Reheat [m3/s-m2]",
    2825          351 :                                              MaxAirVolFlowRateDuringReheatDes / this->ZoneFloorArea);
    2826              :             }
    2827          351 :             this->MaxAirVolFlowRateDuringReheat = MaxAirVolFlowRateDuringReheatDes;
    2828          351 :             if (state.dataGlobal->DisplayExtraWarnings) {
    2829            0 :                 if ((std::abs(MaxAirVolFractionDuringReheatDes - MaxAirVolFractionDuringReheatUser) / MaxAirVolFractionDuringReheatUser) >
    2830            0 :                     state.dataSize->AutoVsHardSizingThreshold) {
    2831            0 :                     ShowMessage(state,
    2832            0 :                                 format("SizeHVACSingleDuct: Potential issue with equipment sizing for {} = \"{}\".", this->sysType, this->SysName));
    2833            0 :                     ShowContinueError(state,
    2834            0 :                                       format("User-Specified Maximum Flow Fraction during Reheat of {:.5R} []", MaxAirVolFractionDuringReheatUser));
    2835            0 :                     ShowContinueError(
    2836            0 :                         state, format("differs from Design Size Maximum Flow Fraction during Reheat of {:.5R} []", MaxAirVolFractionDuringReheatDes));
    2837            0 :                     ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
    2838            0 :                     ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
    2839              :                 }
    2840              :             }
    2841           23 :         } else if (this->MaxAirVolFlowRateDuringReheat != Constant::AutoCalculate && this->MaxAirVolFractionDuringReheat == Constant::AutoCalculate) {
    2842              :             // if max reheat flow was input set the design max reheat flow frac to the corresponding value, report both out, save the design value
    2843              :             // of the flow frac in Sys. Check for optional caution message that user input value is not within 10% of the design value.
    2844           23 :             if (this->MaxAirVolFlowRate > 0.0) {
    2845           23 :                 MaxAirVolFractionDuringReheatDes = MaxAirVolFlowRateDuringReheatDes / this->MaxAirVolFlowRate;
    2846              :             } else {
    2847            0 :                 MaxAirVolFractionDuringReheatDes = 0.0;
    2848              :             }
    2849           23 :             MaxAirVolFlowRateDuringReheatUser = this->MaxAirVolFlowRateDuringReheat;
    2850           23 :             BaseSizer::reportSizerOutput(
    2851              :                 state, this->sysType, this->SysName, "Design Size Maximum Flow Fraction during Reheat []", MaxAirVolFractionDuringReheatDes);
    2852           23 :             if (this->ZoneFloorArea > 0.0) {
    2853           46 :                 BaseSizer::reportSizerOutput(state,
    2854              :                                              this->sysType,
    2855              :                                              this->SysName,
    2856              :                                              "Design Size Maximum Flow per Zone Floor Area during Reheat [ m3/s-m2 ]",
    2857           23 :                                              MaxAirVolFlowRateDuringReheatDes / this->ZoneFloorArea,
    2858              :                                              "User-Specified Maximum Flow per Zone Floor Area during Reheat [m3/s-m2]",
    2859           46 :                                              MaxAirVolFlowRateDuringReheatUser / this->ZoneFloorArea);
    2860              :             }
    2861           23 :             this->MaxAirVolFractionDuringReheat = MaxAirVolFractionDuringReheatDes;
    2862           23 :             if (state.dataGlobal->DisplayExtraWarnings) {
    2863            0 :                 if ((std::abs(MaxAirVolFlowRateDuringReheatDes - MaxAirVolFlowRateDuringReheatUser) / MaxAirVolFlowRateDuringReheatUser) >
    2864            0 :                     state.dataSize->AutoVsHardSizingThreshold) {
    2865            0 :                     ShowMessage(state,
    2866            0 :                                 format("SizeHVACSingleDuct: Potential issue with equipment sizing for {} = \"{}\".", this->sysType, this->SysName));
    2867            0 :                     ShowContinueError(state,
    2868            0 :                                       format("User-Specified Maximum Flow per Zone Floor Area during Reheat of {:.5R} [m3/s-m2]",
    2869              :                                              MaxAirVolFlowRateDuringReheatUser));
    2870            0 :                     ShowContinueError(state,
    2871            0 :                                       format("differs from Design Size Maximum Flow per Zone Floor Area during Reheat of {:.5R} [m3/s-m2]",
    2872              :                                              MaxAirVolFlowRateDuringReheatDes));
    2873            0 :                     ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
    2874            0 :                     ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
    2875              :                 }
    2876              :             }
    2877              :         } else {
    2878              :             // both fields have user input. Report both out, use the larger of the 2 values. Note that only sd_airterminal( SysNum
    2879              :             // ).MaxAirVolFlowRateDuringReheat is used subsequently. Check both inputs for optional caution message that user input value is not
    2880              :             // within 10% of the design value.
    2881            0 :             MaxAirVolFlowRateDuringReheatUser = this->MaxAirVolFlowRateDuringReheat;
    2882            0 :             MaxAirVolFractionDuringReheatUser = this->MaxAirVolFractionDuringReheat;
    2883            0 :             BaseSizer::reportSizerOutput(state,
    2884              :                                          this->sysType,
    2885              :                                          this->SysName,
    2886              :                                          "Design Size Maximum Flow Fraction during Reheat []",
    2887              :                                          MaxAirVolFractionDuringReheatDes,
    2888              :                                          "User-Specified Maximum Flow Fraction during Reheat []",
    2889              :                                          MaxAirVolFractionDuringReheatUser);
    2890            0 :             if (this->ZoneFloorArea > 0.0) {
    2891            0 :                 BaseSizer::reportSizerOutput(state,
    2892              :                                              this->sysType,
    2893              :                                              this->SysName,
    2894              :                                              "Design Size Maximum Flow per Zone Floor Area during Reheat [m3/s-m2]",
    2895            0 :                                              MaxAirVolFlowRateDuringReheatDes / this->ZoneFloorArea,
    2896              :                                              "User-Specified Maximum Flow per Zone Floor Area during Reheat [m3/s-m2]",
    2897            0 :                                              MaxAirVolFlowRateDuringReheatUser / this->ZoneFloorArea);
    2898              :             }
    2899            0 :             this->MaxAirVolFlowRateDuringReheat =
    2900            0 :                 max(this->MaxAirVolFlowRateDuringReheat, this->MaxAirVolFractionDuringReheat * this->MaxAirVolFlowRate);
    2901            0 :             if (state.dataGlobal->DisplayExtraWarnings) {
    2902            0 :                 if ((std::abs(MaxAirVolFractionDuringReheatDes - MaxAirVolFractionDuringReheatUser) / MaxAirVolFractionDuringReheatUser) >
    2903            0 :                     state.dataSize->AutoVsHardSizingThreshold) {
    2904            0 :                     ShowMessage(state,
    2905            0 :                                 format("SizeHVACSingleDuct: Potential issue with equipment sizing for {} = \"{}\".", this->sysType, this->SysName));
    2906            0 :                     ShowContinueError(state,
    2907            0 :                                       format("User-Specified Maximum Flow Fraction during Reheat of {:.5R} []", MaxAirVolFractionDuringReheatUser));
    2908            0 :                     ShowContinueError(
    2909            0 :                         state, format("differs from Design Size Maximum Flow Fraction during Reheat of {:.5R} []", MaxAirVolFractionDuringReheatDes));
    2910            0 :                     ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
    2911            0 :                     ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
    2912              :                 }
    2913              :             }
    2914            0 :             if (state.dataGlobal->DisplayExtraWarnings) {
    2915            0 :                 if ((std::abs(MaxAirVolFlowRateDuringReheatDes - MaxAirVolFlowRateDuringReheatUser) / MaxAirVolFlowRateDuringReheatUser) >
    2916            0 :                     state.dataSize->AutoVsHardSizingThreshold) {
    2917            0 :                     ShowMessage(state,
    2918            0 :                                 format("SizeHVACSingleDuct: Potential issue with equipment sizing for {} = \"{}\".", this->sysType, this->SysName));
    2919            0 :                     ShowContinueError(state,
    2920            0 :                                       format("User-Specified Maximum Flow per Zone Floor Area during Reheat of {:.5R} [m3/s-m2]",
    2921              :                                              MaxAirVolFlowRateDuringReheatUser));
    2922            0 :                     ShowContinueError(state,
    2923            0 :                                       format("differs from Design Size Maximum Flow per Zone Floor Area during Reheat of {:.5R} [m3/s-m2]",
    2924              :                                              MaxAirVolFlowRateDuringReheatDes));
    2925            0 :                     ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
    2926            0 :                     ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
    2927              :                 }
    2928              :             }
    2929              :         }
    2930              :         // check that MaxAirVolFlowRateDuringReheat is greater than the min and less than the max
    2931         1114 :         this->MaxAirVolFlowRateDuringReheat = min(MaxAirVolFlowRateDuringReheatDes, this->MaxAirVolFlowRate);
    2932         1114 :         this->MaxAirVolFlowRateDuringReheat = max(MaxAirVolFlowRateDuringReheatDes, (this->MaxAirVolFlowRate * this->ZoneMinAirFracDes));
    2933         2488 :     } else if (this->DamperHeatingAction == Action::Normal) {
    2934              :         // for Normal action, max reheat flow is equal to the minimum. Report it.
    2935         1069 :         if (this->ZoneFloorArea > 0.0) {
    2936         2138 :             BaseSizer::reportSizerOutput(state,
    2937              :                                          this->sysType,
    2938              :                                          this->SysName,
    2939              :                                          "Design Size Maximum Flow per Zone Floor Area during Reheat [m3/s-m2]",
    2940         1069 :                                          (this->MaxAirVolFlowRate * this->ZoneMinAirFracDes) / this->ZoneFloorArea);
    2941              :         }
    2942         1069 :         BaseSizer::reportSizerOutput(
    2943              :             state, this->sysType, this->SysName, "Design Size Maximum Flow Fraction during Reheat []", this->ZoneMinAirFracDes);
    2944              :         // zero the ReverseActioWithLimits inputs
    2945         1069 :         this->MaxAirVolFlowRateDuringReheat = max(this->MaxAirVolFlowRateDuringReheat, 0.0);
    2946         1069 :         this->MaxAirVolFractionDuringReheat = max(this->MaxAirVolFractionDuringReheat, 0.0);
    2947         1419 :     } else if (this->DamperHeatingAction == Action::Reverse) {
    2948              :         // for ReverseAction, max reheat flow is equal to the maximum. Report it.
    2949           61 :         if (this->ZoneFloorArea > 0.0) {
    2950          122 :             BaseSizer::reportSizerOutput(state,
    2951              :                                          this->sysType,
    2952              :                                          this->SysName,
    2953              :                                          "Design Size Maximum Flow per Zone Floor Area during Reheat [m3/s-m2]",
    2954           61 :                                          this->MaxAirVolFlowRate / this->ZoneFloorArea);
    2955              :         }
    2956           61 :         BaseSizer::reportSizerOutput(state, this->sysType, this->SysName, "Design Size Maximum Flow Fraction during Reheat []", 1.0);
    2957              :         // zero the ReverseActioWithLimits inputs
    2958           61 :         this->MaxAirVolFlowRateDuringReheat = max(this->MaxAirVolFlowRateDuringReheat, 0.0);
    2959           61 :         this->MaxAirVolFractionDuringReheat = max(this->MaxAirVolFractionDuringReheat, 0.0);
    2960              :     }
    2961              : 
    2962         3602 :     if (state.dataSize->CurTermUnitSizingNum > 0) {
    2963         3602 :         TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatAirFlowMult = 1.0;
    2964         3602 :         TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatLoadMult = 1.0;
    2965         3602 :         if (state.dataSize->ZoneSizingRunDone) {
    2966              :             // set air flow rate used to size heating coils, ZoneTurndownMinAirFrac defaults to 1 for those TU types that do not use it
    2967         3087 :             if (this->SysType_Num == SysType::SingleDuctVAVReheatVSFan) {
    2968            8 :                 TermUnitSizing(state.dataSize->CurTermUnitSizingNum).AirVolFlow =
    2969            8 :                     max(state.dataSingleDuct->UserInputMaxHeatAirVolFlowRateSS,
    2970            8 :                         state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).NonAirSysDesHeatVolFlow,
    2971            8 :                         this->MaxAirVolFlowRate * this->ZoneMinAirFracDes * this->ZoneTurndownMinAirFrac);
    2972         3079 :             } else if (this->SysType_Num == SysType::SingleDuctConstVolReheat || this->SysType_Num == SysType::SingleDuctConstVolNoReheat) {
    2973          658 :                 TermUnitSizing(state.dataSize->CurTermUnitSizingNum).AirVolFlow =
    2974          658 :                     max(state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).NonAirSysDesHeatVolFlow,
    2975          658 :                         this->MaxAirVolFlowRate * this->ZoneTurndownMinAirFrac);
    2976              :             } else {
    2977         2421 :                 if (this->SysType_Num == SysType::SingleDuctVAVReheat && this->DamperHeatingAction == Action::ReverseWithLimits) {
    2978         1092 :                     TermUnitSizing(state.dataSize->CurTermUnitSizingNum).AirVolFlow = this->MaxAirVolFlowRateDuringReheat;
    2979              :                 } else {
    2980         1329 :                     TermUnitSizing(state.dataSize->CurTermUnitSizingNum).AirVolFlow =
    2981         1329 :                         max(state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).NonAirSysDesHeatVolFlow,
    2982         1329 :                             this->MaxAirVolFlowRate * this->ZoneMinAirFracDes * this->ZoneTurndownMinAirFrac);
    2983              :                 }
    2984              :             }
    2985              :         } else {
    2986          515 :             if (this->SysType_Num == SysType::SingleDuctVAVReheatVSFan) {
    2987            0 :                 TermUnitSizing(state.dataSize->CurTermUnitSizingNum).AirVolFlow =
    2988            0 :                     max(this->MaxHeatAirVolFlowRate, this->MaxAirVolFlowRate * this->ZoneMinAirFracDes * this->ZoneTurndownMinAirFrac);
    2989          515 :             } else if (this->SysType_Num == SysType::SingleDuctConstVolReheat || this->SysType_Num == SysType::SingleDuctConstVolNoReheat) {
    2990          470 :                 TermUnitSizing(state.dataSize->CurTermUnitSizingNum).AirVolFlow = this->MaxAirVolFlowRate;
    2991              :             } else {
    2992           45 :                 if (this->DamperHeatingAction == Action::Reverse) {
    2993            0 :                     TermUnitSizing(state.dataSize->CurTermUnitSizingNum).AirVolFlow = this->MaxAirVolFlowRate;
    2994           45 :                 } else if (this->DamperHeatingAction == Action::ReverseWithLimits) {
    2995           22 :                     TermUnitSizing(state.dataSize->CurTermUnitSizingNum).AirVolFlow =
    2996           22 :                         max(this->MaxAirVolFlowRateDuringReheat, (this->MaxAirVolFlowRate * this->ZoneMinAirFracDes * this->ZoneTurndownMinAirFrac));
    2997              :                 } else {
    2998           23 :                     TermUnitSizing(state.dataSize->CurTermUnitSizingNum).AirVolFlow =
    2999           23 :                         this->MaxAirVolFlowRate * this->ZoneMinAirFracDes * this->ZoneTurndownMinAirFrac;
    3000              :                 }
    3001              :             }
    3002              :         }
    3003              : 
    3004         3602 :         if (TermUnitSizing(state.dataSize->CurTermUnitSizingNum).AirVolFlow > SmallAirVolFlow) {
    3005         3602 :             if (this->DamperHeatingAction == Action::ReverseWithLimits) {
    3006         1114 :                 TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatAirFlowMult =
    3007         1114 :                     min(this->MaxAirVolFlowRateDuringReheat, this->MaxAirVolFlowRate) /
    3008         1114 :                     TermUnitSizing(state.dataSize->CurTermUnitSizingNum).AirVolFlow;
    3009         1114 :                 TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatLoadMult =
    3010         1114 :                     TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatAirFlowMult;
    3011         2488 :             } else if (this->DamperHeatingAction == Action::Reverse) {
    3012           61 :                 TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatAirFlowMult =
    3013           61 :                     this->MaxAirVolFlowRate / TermUnitSizing(state.dataSize->CurTermUnitSizingNum).AirVolFlow;
    3014           61 :                 TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatLoadMult =
    3015           61 :                     TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatAirFlowMult;
    3016         2427 :             } else if (this->DamperHeatingAction == Action::Normal && this->MaxAirVolFlowRateDuringReheat > 0.0) {
    3017            0 :                 TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatAirFlowMult =
    3018            0 :                     min(this->MaxAirVolFlowRateDuringReheat, (this->MaxAirVolFlowRate * this->ZoneMinAirFracDes * this->ZoneTurndownMinAirFrac)) /
    3019            0 :                     TermUnitSizing(state.dataSize->CurTermUnitSizingNum).AirVolFlow;
    3020            0 :                 TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatLoadMult = 1.0;
    3021         2427 :             } else if (this->DamperHeatingAction == Action::Normal && this->MaxAirVolFlowRateDuringReheat == 0.0) {
    3022         1069 :                 TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatAirFlowMult =
    3023         2138 :                     (this->MaxAirVolFlowRate * this->ZoneMinAirFracDes * this->ZoneTurndownMinAirFrac) /
    3024         1069 :                     TermUnitSizing(state.dataSize->CurTermUnitSizingNum).AirVolFlow;
    3025         1069 :                 TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatLoadMult = 1.0;
    3026              :             } else {
    3027         1358 :                 TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatAirFlowMult =
    3028         1358 :                     this->MaxAirVolFlowRate / TermUnitSizing(state.dataSize->CurTermUnitSizingNum).AirVolFlow;
    3029         1358 :                 TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatLoadMult =
    3030         1358 :                     TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatAirFlowMult;
    3031              :             }
    3032         3602 :             TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatAirFlowMult =
    3033         3602 :                 max(1.0, TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatAirFlowMult);
    3034         3602 :             TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatLoadMult =
    3035         3602 :                 max(1.0, TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatLoadMult);
    3036              :         } else {
    3037            0 :             TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatAirFlowMult = 1.0;
    3038            0 :             TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatLoadMult = 1.0;
    3039              :         }
    3040         3602 :         if (this->ReheatComp_Index > 0) {
    3041         2521 :             state.dataRptCoilSelection->coilSelectionReportObj->setCoilReheatMultiplier(
    3042         2521 :                 state, this->ReheatName, this->ReheatComp, TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatLoadMult);
    3043              :         }
    3044              :     }
    3045              : 
    3046         3602 :     IsAutoSize = false;
    3047         3602 :     if (this->MaxReheatWaterVolFlow == AutoSize) {
    3048         2125 :         IsAutoSize = true;
    3049              :     }
    3050         3602 :     if (state.dataSize->CurTermUnitSizingNum > 0) {
    3051         3602 :         if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) {
    3052          515 :             if (this->MaxReheatWaterVolFlow > 0.0) {
    3053          214 :                 BaseSizer::reportSizerOutput(
    3054              :                     state, this->sysType, this->SysName, "User-Specified Maximum Reheat Water Flow Rate [m3/s]", this->MaxReheatWaterVolFlow);
    3055              :             }
    3056              :         } else {
    3057         3087 :             CheckZoneSizing(state, this->sysType, this->SysName);
    3058         3087 :             if (Util::SameString(this->ReheatComp, "Coil:Heating:Water")) {
    3059         1927 :                 state.dataSingleDuct->CoilWaterInletNodeSS = GetCoilWaterInletNode(state, "Coil:Heating:Water", this->ReheatName, ErrorsFound);
    3060         1927 :                 state.dataSingleDuct->CoilWaterOutletNodeSS = GetCoilWaterOutletNode(state, "Coil:Heating:Water", this->ReheatName, ErrorsFound);
    3061         1927 :                 if (IsAutoSize) {
    3062         1871 :                     PlantSizingErrorsFound = false;
    3063         1871 :                     PltSizHeatNum = MyPlantSizingIndex(state,
    3064              :                                                        "Coil:Heating:Water",
    3065              :                                                        this->ReheatName,
    3066         1871 :                                                        state.dataSingleDuct->CoilWaterInletNodeSS,
    3067         1871 :                                                        state.dataSingleDuct->CoilWaterOutletNodeSS,
    3068              :                                                        PlantSizingErrorsFound);
    3069         1871 :                     if (PlantSizingErrorsFound) {
    3070            0 :                         ShowContinueError(state, format("...Occurs in {}:{}", this->sysType, this->SysName));
    3071            0 :                         ErrorsFound = true;
    3072              :                     }
    3073         1871 :                     if (PltSizHeatNum > 0) {
    3074         3742 :                         state.dataSingleDuct->CoilInTempSS =
    3075         1871 :                             state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatCoilInTempTU;
    3076         1871 :                         DesMassFlow = state.dataEnvrn->StdRhoAir * TermUnitSizing(state.dataSize->CurTermUnitSizingNum).AirVolFlow;
    3077         3742 :                         state.dataSingleDuct->DesZoneHeatLoadSS =
    3078         1871 :                             state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).NonAirSysDesHeatLoad;
    3079         3742 :                         state.dataSingleDuct->ZoneDesTempSS =
    3080         1871 :                             state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).ZoneTempAtHeatPeak;
    3081         3742 :                         state.dataSingleDuct->ZoneDesHumRatSS =
    3082         1871 :                             state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).ZoneHumRatAtHeatPeak;
    3083              :                         // the coil load is the zone design heating load plus (or minus!) the reheat load
    3084         3742 :                         state.dataSingleDuct->DesCoilLoadSS =
    3085         1871 :                             state.dataSingleDuct->DesZoneHeatLoadSS + PsyCpAirFnW(state.dataSingleDuct->ZoneDesHumRatSS) * DesMassFlow *
    3086         1871 :                                                                           (state.dataSingleDuct->ZoneDesTempSS - state.dataSingleDuct->CoilInTempSS);
    3087         1871 :                         if (state.dataSingleDuct->DesCoilLoadSS >= SmallLoad) {
    3088              : 
    3089              :                             rho =
    3090         1871 :                                 state.dataPlnt->PlantLoop(this->HWplantLoc.loopNum).glycol->getDensity(state, Constant::HWInitConvTemp, RoutineName);
    3091              : 
    3092         1871 :                             Cp = state.dataPlnt->PlantLoop(this->HWplantLoc.loopNum)
    3093         1871 :                                      .glycol->getSpecificHeat(state, Constant::HWInitConvTemp, RoutineName);
    3094              : 
    3095         1871 :                             MaxReheatWaterVolFlowDes =
    3096         1871 :                                 state.dataSingleDuct->DesCoilLoadSS / (state.dataSize->PlantSizData(PltSizHeatNum).DeltaT * Cp * rho);
    3097              :                         } else {
    3098            0 :                             MaxReheatWaterVolFlowDes = 0.0;
    3099              :                         }
    3100              :                     } else {
    3101            0 :                         ShowSevereError(state, "Autosizing of water flow requires a heating loop Sizing:Plant object");
    3102            0 :                         ShowContinueError(state, format("Occurs in AirTerminal Object={}", this->SysName));
    3103            0 :                         ErrorsFound = true;
    3104              :                     }
    3105         1871 :                     this->MaxReheatWaterVolFlow = MaxReheatWaterVolFlowDes;
    3106         1871 :                     BaseSizer::reportSizerOutput(
    3107              :                         state, this->sysType, this->SysName, "Design Size Maximum Reheat Water Flow Rate [m3/s]", MaxReheatWaterVolFlowDes);
    3108         3742 :                     BaseSizer::reportSizerOutput(state,
    3109              :                                                  this->sysType,
    3110              :                                                  this->SysName,
    3111              :                                                  "Design Size Reheat Coil Sizing Air Volume Flow Rate [m3/s]",
    3112         1871 :                                                  TermUnitSizing(state.dataSize->CurTermUnitSizingNum).AirVolFlow);
    3113         3742 :                     BaseSizer::reportSizerOutput(state,
    3114              :                                                  this->sysType,
    3115              :                                                  this->SysName,
    3116              :                                                  "Design Size Reheat Coil Sizing Inlet Air Temperature [C]",
    3117         1871 :                                                  state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatCoilInTempTU);
    3118         3742 :                     BaseSizer::reportSizerOutput(state,
    3119              :                                                  this->sysType,
    3120              :                                                  this->SysName,
    3121              :                                                  "Design Size Reheat Coil Sizing Inlet Air Humidity Ratio [kgWater/kgDryAir]",
    3122         1871 :                                                  state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatCoilInHumRatTU);
    3123              :                 } else { // Hard-size with sizing data
    3124           56 :                     if (this->MaxReheatWaterVolFlow > 0.0 && MaxReheatWaterVolFlowDes > 0.0) {
    3125            0 :                         MaxReheatWaterVolFlowUser = this->MaxReheatWaterVolFlow;
    3126            0 :                         BaseSizer::reportSizerOutput(state,
    3127              :                                                      this->sysType,
    3128              :                                                      this->SysName,
    3129              :                                                      "Design Size Maximum Reheat Water Flow Rate [m3/s]",
    3130              :                                                      MaxReheatWaterVolFlowDes,
    3131              :                                                      "User-Specified Maximum Reheat Water Flow Rate [m3/s]",
    3132              :                                                      MaxReheatWaterVolFlowUser);
    3133            0 :                         if (state.dataGlobal->DisplayExtraWarnings) {
    3134            0 :                             if ((std::abs(MaxReheatWaterVolFlowDes - MaxReheatWaterVolFlowUser) / MaxReheatWaterVolFlowUser) >
    3135            0 :                                 state.dataSize->AutoVsHardSizingThreshold) {
    3136            0 :                                 ShowMessage(state,
    3137            0 :                                             format("SizeHVACSingleDuct: Potential issue with equipment sizing for {} = \"{}\".",
    3138            0 :                                                    this->sysType,
    3139            0 :                                                    this->SysName));
    3140            0 :                                 ShowContinueError(
    3141            0 :                                     state, format("User-Specified Maximum Reheat Water Flow Rate of {:.5R} [m3/s]", MaxReheatWaterVolFlowUser));
    3142            0 :                                 ShowContinueError(
    3143              :                                     state,
    3144            0 :                                     format("differs from Design Size Maximum Reheat Water Flow Rate of {:.5R} [m3/s]", MaxReheatWaterVolFlowDes));
    3145            0 :                                 ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
    3146            0 :                                 ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
    3147              :                             }
    3148              :                         }
    3149              :                     }
    3150              :                 }
    3151              :             }
    3152              :         }
    3153              :     } else {
    3154            0 :         this->MaxReheatWaterVolFlow = 0.0;
    3155              :     }
    3156              : 
    3157         3602 :     IsAutoSize = false;
    3158         3602 :     if (this->MaxReheatSteamVolFlow == AutoSize) {
    3159           13 :         IsAutoSize = true;
    3160              :     }
    3161         3602 :     if (state.dataSize->CurTermUnitSizingNum > 0) {
    3162         3602 :         if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) {
    3163          515 :             if (this->MaxReheatSteamVolFlow > 0.0) {
    3164            0 :                 BaseSizer::reportSizerOutput(
    3165              :                     state, this->sysType, this->SysName, "User-Specified Maximum Reheat Steam Flow Rate [m3/s]", this->MaxReheatSteamVolFlow);
    3166              :             }
    3167              :         } else {
    3168         3087 :             CheckZoneSizing(state, this->sysType, this->SysName);
    3169         3087 :             if (Util::SameString(this->ReheatComp, "Coil:Heating:Steam")) {
    3170           26 :                 state.dataSingleDuct->CoilSteamInletNodeSS = GetCoilSteamInletNode(state, "Coil:Heating:Steam", this->ReheatName, ErrorsFound);
    3171           13 :                 state.dataSingleDuct->CoilSteamOutletNodeSS = GetCoilSteamOutletNode(state, "Coil:Heating:Steam", this->ReheatName, ErrorsFound);
    3172           13 :                 if (IsAutoSize) {
    3173           13 :                     PlantSizingErrorsFound = false;
    3174           13 :                     PltSizHeatNum = MyPlantSizingIndex(state,
    3175              :                                                        "Coil:Heating:Steam",
    3176              :                                                        this->ReheatName,
    3177           13 :                                                        state.dataSingleDuct->CoilSteamInletNodeSS,
    3178           13 :                                                        state.dataSingleDuct->CoilSteamOutletNodeSS,
    3179              :                                                        PlantSizingErrorsFound);
    3180           13 :                     if (PlantSizingErrorsFound) {
    3181            0 :                         ShowContinueError(state, format("...Occurs in {}:{}", this->sysType, this->SysName));
    3182            0 :                         ErrorsFound = true;
    3183              :                     }
    3184           13 :                     if (PltSizHeatNum > 0) {
    3185           26 :                         state.dataSingleDuct->CoilInTempSS =
    3186           13 :                             state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatCoilInTempTU;
    3187           13 :                         DesMassFlow = state.dataEnvrn->StdRhoAir * TermUnitSizing(state.dataSize->CurTermUnitSizingNum).AirVolFlow;
    3188           26 :                         state.dataSingleDuct->DesZoneHeatLoadSS =
    3189           13 :                             state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).NonAirSysDesHeatLoad;
    3190           26 :                         state.dataSingleDuct->ZoneDesTempSS =
    3191           13 :                             state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).ZoneTempAtHeatPeak;
    3192           26 :                         state.dataSingleDuct->ZoneDesHumRatSS =
    3193           13 :                             state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).ZoneHumRatAtHeatPeak;
    3194              :                         // the coil load is the zone design heating load plus (or minus!) the reheat load
    3195           26 :                         state.dataSingleDuct->DesCoilLoadSS =
    3196           13 :                             state.dataSingleDuct->DesZoneHeatLoadSS + PsyCpAirFnW(state.dataSingleDuct->ZoneDesHumRatSS) * DesMassFlow *
    3197           13 :                                                                           (state.dataSingleDuct->ZoneDesTempSS - state.dataSingleDuct->CoilInTempSS);
    3198           13 :                         if (state.dataSingleDuct->DesCoilLoadSS >= SmallLoad) {
    3199           13 :                             TempSteamIn = 100.00;
    3200           13 :                             auto *steam = Fluid::GetSteam(state);
    3201           13 :                             EnthSteamInDry = steam->getSatEnthalpy(state, TempSteamIn, 1.0, RoutineNameFull);
    3202           13 :                             EnthSteamOutWet = steam->getSatEnthalpy(state, TempSteamIn, 0.0, RoutineNameFull);
    3203           13 :                             LatentHeatSteam = EnthSteamInDry - EnthSteamOutWet;
    3204           13 :                             SteamDensity = steam->getSatDensity(state, TempSteamIn, 1.0, RoutineNameFull);
    3205              : 
    3206           13 :                             Cp = Fluid::GetWater(state)->getSpecificHeat(state, state.dataSize->PlantSizData(PltSizHeatNum).ExitTemp, RoutineName);
    3207           13 :                             MaxReheatSteamVolFlowDes = state.dataSingleDuct->DesCoilLoadSS /
    3208           13 :                                                        (SteamDensity * (LatentHeatSteam + state.dataSize->PlantSizData(PltSizHeatNum).DeltaT * Cp));
    3209              :                         } else {
    3210            0 :                             MaxReheatSteamVolFlowDes = 0.0;
    3211              :                         }
    3212              :                     } else {
    3213            0 :                         ShowSevereError(state, "Autosizing of Steam flow requires a heating loop Sizing:Plant object");
    3214            0 :                         ShowContinueError(state, format("Occurs in AirTerminal:SingleDuct:ConstantVolume:Reheat Object={}", this->SysName));
    3215            0 :                         ErrorsFound = true;
    3216              :                     }
    3217           13 :                     this->MaxReheatSteamVolFlow = MaxReheatSteamVolFlowDes;
    3218           13 :                     BaseSizer::reportSizerOutput(
    3219              :                         state, this->sysType, this->SysName, "Design Size Maximum Reheat Steam Flow Rate [m3/s]", MaxReheatSteamVolFlowDes);
    3220              :                 } else {
    3221            0 :                     if (this->MaxReheatSteamVolFlow > 0.0 && MaxReheatSteamVolFlowDes > 0.0) {
    3222            0 :                         MaxReheatSteamVolFlowUser = this->MaxReheatSteamVolFlow;
    3223            0 :                         BaseSizer::reportSizerOutput(state,
    3224              :                                                      this->sysType,
    3225              :                                                      this->SysName,
    3226              :                                                      "Design Size Maximum Reheat Steam Flow Rate [m3/s]",
    3227              :                                                      MaxReheatSteamVolFlowDes,
    3228              :                                                      "User-Specified Maximum Reheat Steam Flow Rate [m3/s]",
    3229              :                                                      MaxReheatSteamVolFlowUser);
    3230            0 :                         if (state.dataGlobal->DisplayExtraWarnings) {
    3231            0 :                             if ((std::abs(MaxReheatSteamVolFlowDes - MaxReheatSteamVolFlowUser) / MaxReheatSteamVolFlowUser) >
    3232            0 :                                 state.dataSize->AutoVsHardSizingThreshold) {
    3233            0 :                                 ShowMessage(state,
    3234            0 :                                             format("SizeHVACSingleDuct: Potential issue with equipment sizing for {} = \"{}\".",
    3235            0 :                                                    this->sysType,
    3236            0 :                                                    this->SysName));
    3237            0 :                                 ShowContinueError(
    3238            0 :                                     state, format("User-Specified Maximum Reheat Steam Flow Rate of {:.5R} [m3/s]", MaxReheatSteamVolFlowUser));
    3239            0 :                                 ShowContinueError(
    3240              :                                     state,
    3241            0 :                                     format("differs from Design Size Maximum Reheat Steam Flow Rate of {:.5R} [m3/s]", MaxReheatSteamVolFlowDes));
    3242            0 :                                 ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
    3243            0 :                                 ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
    3244              :                             }
    3245              :                         }
    3246              :                     }
    3247              :                 }
    3248              :             }
    3249              :         }
    3250              :     } else {
    3251            0 :         this->MaxReheatSteamVolFlow = 0.0;
    3252              :     }
    3253              : 
    3254         3602 :     if (state.dataSize->CurTermUnitSizingNum > 0) {
    3255         3602 :         TermUnitSizing(state.dataSize->CurTermUnitSizingNum).MinPriFlowFrac = this->ZoneMinAirFracDes * this->ZoneTurndownMinAirFrac;
    3256         3602 :         TermUnitSizing(state.dataSize->CurTermUnitSizingNum).MaxHWVolFlow = this->MaxReheatWaterVolFlow;
    3257         3602 :         TermUnitSizing(state.dataSize->CurTermUnitSizingNum).MaxSTVolFlow = this->MaxReheatSteamVolFlow;
    3258         3602 :         TermUnitSizing(state.dataSize->CurTermUnitSizingNum).DesHeatingLoad = state.dataSingleDuct->DesCoilLoadSS; // Coil Summary report
    3259         3602 :         if (this->ReheatComp_Num == HeatingCoilType::SimpleHeating) {
    3260         2141 :             if (this->DamperHeatingAction == Action::Normal) {
    3261          880 :                 SetCoilDesFlow(state, this->ReheatComp, this->ReheatName, this->ZoneMinAirFracDes * this->MaxAirVolFlowRate, ErrorsFound);
    3262              :             } else {
    3263         1261 :                 SetCoilDesFlow(
    3264         1261 :                     state, this->ReheatComp, this->ReheatName, TermUnitSizing(state.dataSize->CurTermUnitSizingNum).AirVolFlow, ErrorsFound);
    3265              :             }
    3266              :         }
    3267              :     }
    3268              : 
    3269         3602 :     if (this->MaxAirVolFlowRateDuringReheat > 0.0) {
    3270              :         // check for inconsistent dual max input
    3271         1114 :         if (this->MaxAirVolFlowRateDuringReheat < (this->ZoneMinAirFracDes * this->MaxAirVolFlowRate)) {
    3272              :             // Only warn when really out of bounds
    3273            0 :             if ((this->ZoneMinAirFracDes * this->MaxAirVolFlowRate) - this->MaxAirVolFlowRateDuringReheat > 1.e-8) {
    3274            0 :                 ShowWarningError(state,
    3275              :                                  "SingleDuctSystem:SizeSys: Air Terminal Unit flow limits are not consistent, minimum flow limit is larger than "
    3276              :                                  "reheat maximum");
    3277            0 :                 ShowContinueError(state, format("Air Terminal Unit name = {}", this->SysName));
    3278            0 :                 ShowContinueError(state,
    3279            0 :                                   format("Maximum terminal flow during reheat = {:.6R} [m3/s] or flow fraction = {:.4R}",
    3280            0 :                                          this->MaxAirVolFlowRateDuringReheat,
    3281            0 :                                          (this->MaxAirVolFlowRateDuringReheat / this->MaxAirVolFlowRate)));
    3282            0 :                 ShowContinueError(state,
    3283            0 :                                   format("Minimum terminal flow = {:.6R} [m3/s] or flow fraction = {:.4R}",
    3284            0 :                                          (this->ZoneMinAirFracDes * this->MaxAirVolFlowRate),
    3285            0 :                                          this->ZoneMinAirFracDes));
    3286            0 :                 ShowContinueError(state, "The reheat maximum flow limit will be replaced by the minimum limit, and the simulation continues");
    3287              :             }
    3288            0 :             this->MaxAirVolFlowRateDuringReheat = (this->ZoneMinAirFracDes * this->MaxAirVolFlowRate);
    3289              :         }
    3290              :     }
    3291              : 
    3292         3602 :     if (ErrorsFound) {
    3293            0 :         ShowFatalError(state, "Preceding sizing errors cause program termination");
    3294              :     }
    3295         3602 : }
    3296              : 
    3297              : // End Initialization Section of the Module
    3298              : //******************************************************************************
    3299              : 
    3300              : // Begin Algorithm Section of the Module
    3301              : //******************************************************************************
    3302              : 
    3303     27022691 : void SingleDuctAirTerminal::SimVAV(EnergyPlusData &state, bool const FirstHVACIteration, int const ZoneNum, int const ZoneNodeNum)
    3304              : {
    3305              : 
    3306              :     // SUBROUTINE INFORMATION:
    3307              :     //       AUTHOR         Richard J. Liesen
    3308              :     //       DATE WRITTEN   January 2000
    3309              :     //       MODIFIED       Fred Buhl: added reverse action damper heating action: August 2001
    3310              :     //                      KHL/TH 7/2010: revise to support dual max
    3311              :     //                      FB/KHL/TH 9/2010: added maximum supply air temperature leaving reheat coil
    3312              :     //                      TH 3/2012: added supply air flow adjustment based on zone maximum outdoor
    3313              :     //                                 air fraction - a TRACE feature
    3314              :     //                      Brent Griffith, 5/2012, general cleanup, fix negatives CR 8767, fix phantom coil flows CR 8854
    3315              : 
    3316              :     // PURPOSE OF THIS SUBROUTINE:
    3317              :     // This subroutine simulates the simple single duct volume VAV.
    3318              : 
    3319              :     // METHODOLOGY EMPLOYED:
    3320              :     // There is method to this madness.
    3321              : 
    3322              :     // Using/Aliasing
    3323              :     using namespace DataZoneEnergyDemands;
    3324              :     // unused   USE DataHeatBalFanSys, ONLY: Mat
    3325              :     using HeatingCoils::SimulateHeatingCoilComponents;
    3326              :     using HVAC::SmallLoad;
    3327              :     using PlantUtilities::SetActuatedBranchFlowRate;
    3328              :     using SteamCoils::SimulateSteamCoilComponents;
    3329              :     using WaterCoils::SimulateWaterCoilComponents;
    3330              : 
    3331              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    3332              :     Real64 MassFlow;     // [kg/sec]   Total Mass Flow Rate from Hot & Cold Inlets
    3333              :     Real64 QTotLoad;     // [Watts] Remaining load required for this zone
    3334              :     Real64 QZnReq;       // [Watts] Load calculated for heating coil
    3335              :     Real64 QToHeatSetPt; // [W]  remaining load to heating setpoint
    3336              :     Real64 CpAirAvg;
    3337              :     Real64 DeltaTemp;
    3338              :     int SysOutletNode;        // The node number of the terminal unit outlet node
    3339              :     int SysInletNode;         // the node number of the terminal unit inlet node
    3340              :     Real64 MaxFlowWater;      // This is the value passed to the Controller depending if FirstHVACIteration or not
    3341              :     Real64 MinFlowWater;      // This is the value passed to the Controller depending if FirstHVACIteration or not
    3342              :     Real64 QActualHeating;    // the heating load seen by the reheat coil
    3343              :     Real64 QHeatingDelivered; // the actual output from heating coil
    3344              :     Real64 LeakLoadMult;      // load multiplier to adjust for downstream leaks
    3345              :     Real64 MinFlowFrac;       // minimum flow fraction (and minimum damper position)
    3346              :     Real64 MassFlowBasedOnOA; // supply air mass flow rate based on zone OA requirements
    3347              :     Real64 AirLoopOAFrac;     // fraction of outside air entering air loop
    3348              :     Real64 DummyMdot;         // temporary mass flow rate argument
    3349              : 
    3350              :     // Note to the perplexed
    3351              :     // The SINGLE DUCT:VAV:REHEAT terminal unit originally contained 2 components: a damper
    3352              :     // and a reheat coil. The damper has become a virtual component - it consists only of
    3353              :     // an air inlet node and an air outlet node. The damper is upstream of the heating coil.
    3354              :     // sd_airterminal(SysNum)%InletNodeNum is the inlet node to the terminal unit and the damper
    3355              :     // sd_airterminal(SysNum)%OutletNodeNum is the outlet node of the damper and the inlet node of the heating coil
    3356              :     // sd_airterminal(SysNum)%ReheatAirOutletNode is the outlet node of the terminal unit and the heating coil
    3357              : 
    3358              :     // The calculated load from the Heat Balance
    3359     27022691 :     LeakLoadMult = state.dataDefineEquipment->AirDistUnit(this->ADUNum).LeakLoadMult;
    3360     27022691 :     QTotLoad = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).RemainingOutputRequired * LeakLoadMult;
    3361     27022691 :     QToHeatSetPt = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).RemainingOutputReqToHeatSP * LeakLoadMult;
    3362     27022691 :     SysOutletNode = this->ReheatAirOutletNode;
    3363     27022691 :     SysInletNode = this->InletNodeNum;
    3364     27022691 :     CpAirAvg = PsyCpAirFnW(0.5 * (state.dataLoopNodes->Node(ZoneNodeNum).HumRat + this->sd_airterminalInlet.AirHumRat));
    3365     27022691 :     MinFlowFrac = this->ZoneMinAirFrac;
    3366     27022691 :     MassFlowBasedOnOA = 0.0;
    3367     27022691 :     state.dataSingleDuct->ZoneTempSDAT = state.dataLoopNodes->Node(ZoneNodeNum).Temp;
    3368     27022691 :     state.dataSingleDuct->MinMassAirFlowSDAT = MinFlowFrac * state.dataEnvrn->StdRhoAir * this->MaxAirVolFlowRate;
    3369              : 
    3370              :     // Then depending on if the Load is for heating or cooling it is handled differently.  First
    3371              :     // the massflow rate for cooling is determined to meet the entire load.  Then
    3372              :     // if the massflow is below the minimum or greater than the Max it is set to either the Min
    3373              :     // or the Max as specified for the VAV model.
    3374      9472132 :     if ((QTotLoad < 0.0) && (this->sd_airterminalInlet.AirMassFlowRateMaxAvail > 0.0) &&
    3375     36494823 :         (state.dataHeatBalFanSys->TempControlType(ZoneNum) != HVAC::SetptType::SingleHeat) && (this->availSched->getCurrentVal() > 0.0)) {
    3376              :         // Calculate the flow required for cooling
    3377              : 
    3378      9061063 :         DeltaTemp = CpAirAvg * (this->sd_airterminalInlet.AirTemp - state.dataSingleDuct->ZoneTempSDAT);
    3379              : 
    3380              :         // Need to check DeltaTemp and ensure that it is not zero
    3381      9061063 :         if (DeltaTemp != 0.0) {
    3382      9060648 :             MassFlow = QTotLoad / DeltaTemp;
    3383              :         } else {
    3384          415 :             MassFlow = this->sd_airterminalInlet.AirMassFlowRateMaxAvail;
    3385              :         }
    3386              : 
    3387              :         // Apply the zone maximum outdoor air fraction FOR VAV boxes - a TRACE feature
    3388      9061063 :         if (state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).SupplyAirAdjustFactor > 1.0) {
    3389            0 :             MassFlow *= state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).SupplyAirAdjustFactor;
    3390              :         }
    3391              : 
    3392              :         // calculate supply air flow rate based on user specified OA requirement
    3393      9061063 :         this->CalcOAMassFlow(state, MassFlowBasedOnOA, AirLoopOAFrac);
    3394      9061063 :         MassFlow = max(MassFlow, MassFlowBasedOnOA);
    3395              : 
    3396              :         // used for normal acting damper
    3397      9061063 :         state.dataSingleDuct->MinMassAirFlowSDAT = max(state.dataSingleDuct->MinMassAirFlowSDAT, MassFlowBasedOnOA);
    3398      9061063 :         state.dataSingleDuct->MinMassAirFlowSDAT = max(state.dataSingleDuct->MinMassAirFlowSDAT, this->sd_airterminalInlet.AirMassFlowRateMinAvail);
    3399      9061063 :         state.dataSingleDuct->MinMassAirFlowSDAT = min(state.dataSingleDuct->MinMassAirFlowSDAT, this->sd_airterminalInlet.AirMassFlowRateMaxAvail);
    3400              : 
    3401              :         // limit the OA based supply air flow rate based on optional user input
    3402              :         // Check to see if the flow is < the Min or > the Max air Fraction to the zone; then set to min or max
    3403      9061063 :         MassFlow = max(MassFlow, this->sd_airterminalInlet.AirMassFlowRateMinAvail);
    3404      9061063 :         MassFlow = min(MassFlow, this->sd_airterminalInlet.AirMassFlowRateMaxAvail);
    3405              : 
    3406      9061063 :         if (state.afn->distribution_simulated && state.afn->AirflowNetworkFanActivated && state.afn->VAVTerminalRatio > 0.0) {
    3407            0 :             MassFlow *= state.afn->VAVTerminalRatio;
    3408            0 :             if (MassFlow > state.dataLoopNodes->Node(this->InletNodeNum).MassFlowRate) {
    3409            0 :                 MassFlow = state.dataLoopNodes->Node(this->InletNodeNum).MassFlowRate;
    3410              :             }
    3411              :         }
    3412              : 
    3413     14430118 :     } else if ((this->sd_airterminalInlet.AirMassFlowRateMaxAvail > 0.0) &&
    3414     32408747 :                (QTotLoad >= 0.0 || state.dataHeatBalFanSys->TempControlType(ZoneNum) == HVAC::SetptType::SingleHeat) &&
    3415     14430118 :                (this->availSched->getCurrentVal() > 0.0)) {
    3416              :         //     IF (sd_airterminal(SysNum)%DamperHeatingAction .EQ. ReverseAction .AND. this->sd_airterminalInlet%AirMassFlowRateMinAvail <=
    3417              :         //     SmallMassFlow) THEN
    3418              :         // special case for heating: reverse action and damper allowed to close - set the minimum flow rate to a small but nonzero value
    3419              :         //       MassFlow = 0.01d0*this->sd_airterminalInlet%AirMassFlowRateMaxAvail
    3420              :         //     ELSE
    3421              :         // usual case for heating: set the air mass flow rate to the minimum
    3422     14430118 :         MassFlow = this->sd_airterminalInlet.AirMassFlowRateMinAvail;
    3423              :         //     END IF
    3424              : 
    3425              :         // Apply the zone maximum outdoor air fraction for VAV boxes - a TRACE feature
    3426     14430118 :         if (state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).SupplyAirAdjustFactor > 1.0) {
    3427            0 :             MassFlow *= state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).SupplyAirAdjustFactor;
    3428              :         }
    3429              : 
    3430              :         // calculate supply air flow rate based on user specified OA requirement
    3431     14430118 :         this->CalcOAMassFlow(state, MassFlowBasedOnOA, AirLoopOAFrac);
    3432     14430118 :         MassFlow = max(MassFlow, MassFlowBasedOnOA);
    3433              : 
    3434              :         // Check to see if the flow is < the Min or > the Max air Fraction to the zone; then set to min or max
    3435     14430118 :         if (MassFlow <= this->sd_airterminalInlet.AirMassFlowRateMinAvail) {
    3436     13820544 :             MassFlow = this->sd_airterminalInlet.AirMassFlowRateMinAvail;
    3437       609574 :         } else if (MassFlow >= this->sd_airterminalInlet.AirMassFlowRateMaxAvail) {
    3438       497041 :             MassFlow = this->sd_airterminalInlet.AirMassFlowRateMaxAvail;
    3439              :         }
    3440              : 
    3441              :         // the AirflowNetwork model overrids the mass flow rate value
    3442     14430118 :         if (state.afn->distribution_simulated && state.afn->AirflowNetworkFanActivated && state.afn->VAVTerminalRatio > 0.0) {
    3443            0 :             MassFlow *= state.afn->VAVTerminalRatio;
    3444            0 :             if (MassFlow > state.dataLoopNodes->Node(this->InletNodeNum).MassFlowRate) {
    3445            0 :                 MassFlow = state.dataLoopNodes->Node(this->InletNodeNum).MassFlowRate;
    3446              :             }
    3447              :         }
    3448              : 
    3449              :     } else {
    3450              :         // System is Off set massflow to 0.0
    3451      3531510 :         MassFlow = 0.0;
    3452      3531510 :         AirLoopOAFrac = 0.0;
    3453              :     }
    3454              : 
    3455              :     // look for bang-bang condition: flow rate oscillating between 2 values during the air loop / zone
    3456              :     // equipment iteration. If detected, set flow rate to previous value.
    3457     33747468 :     if (((std::abs(MassFlow - this->MassFlow2) < this->MassFlowDiff) || (std::abs(MassFlow - this->MassFlow3) < this->MassFlowDiff)) &&
    3458      6724777 :         (std::abs(MassFlow - this->MassFlow1) >= this->MassFlowDiff)) {
    3459        18771 :         if (MassFlow > 0.0) {
    3460        18766 :             MassFlow = this->MassFlow1;
    3461              :         }
    3462              :     }
    3463              : 
    3464              :     // Move data to the damper outlet node
    3465     27022691 :     this->sd_airterminalOutlet.AirTemp = this->sd_airterminalInlet.AirTemp;
    3466     27022691 :     this->sd_airterminalOutlet.AirHumRat = this->sd_airterminalInlet.AirHumRat;
    3467     27022691 :     this->sd_airterminalOutlet.AirMassFlowRate = MassFlow;
    3468     27022691 :     this->sd_airterminalOutlet.AirMassFlowRateMaxAvail = this->sd_airterminalInlet.AirMassFlowRateMaxAvail;
    3469     27022691 :     this->sd_airterminalOutlet.AirMassFlowRateMinAvail = this->sd_airterminalInlet.AirMassFlowRateMinAvail;
    3470     27022691 :     this->sd_airterminalOutlet.AirEnthalpy = this->sd_airterminalInlet.AirEnthalpy;
    3471              : 
    3472              :     //   ! Calculate the Damper Position when there is a Max air flow specified.
    3473              :     //  If (MassFlow == 0.0D0) THEN
    3474              :     //    sd_airterminal(SysNum)%DamperPosition = 0.0D0
    3475              :     //  ELSE IF (this->sd_airterminalInlet%AirMassFlowRateMaxAvail > this->sd_airterminalInlet%AirMassFlowRateMinAvail) THEN
    3476              :     //    sd_airterminal(SysNum)%DamperPosition = ((MassFlow-this->sd_airterminalInlet%AirMassFlowRateMinAvail) / &
    3477              :     //                                   (this->sd_airterminalInlet%AirMassFlowRateMaxAvail-this->sd_airterminalInlet%AirMassFlowRateMinAvail)) *
    3478              :     //                                   &
    3479              :     //                                  (1.0d0-MinFlowFrac) + MinFlowFrac
    3480              :     //  ELSE
    3481              :     //    sd_airterminal(SysNum)%DamperPosition = 1.0D0
    3482              :     //  END IF
    3483              : 
    3484     27022691 :     if (MassFlow == 0.0) {
    3485      3532227 :         this->DamperPosition = 0.0;
    3486      3532227 :         this->ZoneMinAirFracReport = 0.0;
    3487     23490464 :     } else if ((MassFlow > 0.0) && (MassFlow < this->AirMassFlowRateMax)) {
    3488     16694565 :         this->DamperPosition = MassFlow / this->AirMassFlowRateMax;
    3489     16694565 :         this->ZoneMinAirFracReport = this->ZoneMinAirFrac;
    3490      6795899 :     } else if (MassFlow == this->AirMassFlowRateMax) {
    3491      6795899 :         this->DamperPosition = 1.0;
    3492      6795899 :         this->ZoneMinAirFracReport = this->ZoneMinAirFrac;
    3493              :     }
    3494              : 
    3495              :     // Need to make sure that the damper outlets are passed to the coil inlet
    3496     27022691 :     this->UpdateSys(state);
    3497              : 
    3498              :     // At the current air mass flow rate, calculate heating coil load
    3499     27022691 :     QActualHeating = QToHeatSetPt - MassFlow * CpAirAvg * (this->sd_airterminalInlet.AirTemp - state.dataSingleDuct->ZoneTempSDAT); // reheat needed
    3500              : 
    3501              :     // do the reheat calculation if there's some air nass flow (or the damper action is "reverse action"), the flow is <= minimum ,
    3502              :     // there's a heating requirement, and there's a thermostat with a heating setpoint
    3503              :     // Reverse damper option is working only for water coils for now.
    3504     27022691 :     if ((MassFlow > SmallMassFlow) && (QActualHeating > 0.0) && (state.dataHeatBalFanSys->TempControlType(ZoneNum) != HVAC::SetptType::SingleCool)) {
    3505              :         // At this point we know that there is a heating requirement: i.e., the heating coil needs to
    3506              :         // be activated (there's a zone heating load or there's a reheat requirement). There are 3 possible
    3507              :         // situations: 1) the coil load can be met by variable temperature air (below the max heat temp) at
    3508              :         // the minimum air mass flow rate; 2) the coil load can be met by variable air flow rate with the air
    3509              :         // temperature fixed at the max heat temp; 3) the load cannot be met (we will run at max air temp and
    3510              :         // max air flow rate). We check for condition 2 by assuming the air temperatute is at the max heat temp
    3511              :         // and solving for the air mass flow rate that will meet the load. If the flow rate is between the min and
    3512              :         // max we are in condition 2.
    3513              : 
    3514     12072410 :         state.dataSingleDuct->QZoneMax2SDAT = QToHeatSetPt;
    3515              : 
    3516              :         // fill dual-max reheat flow limit, if any
    3517     12072410 :         if (this->DamperHeatingAction == Action::Reverse) {
    3518        85724 :             state.dataSingleDuct->MaxDeviceAirMassFlowReheatSDAT = this->AirMassFlowRateMax;
    3519     11986686 :         } else if (this->DamperHeatingAction == Action::ReverseWithLimits) {
    3520      5643659 :             state.dataSingleDuct->MaxDeviceAirMassFlowReheatSDAT = this->AirMassFlowDuringReheatMax;
    3521      6343027 :         } else if (this->DamperHeatingAction == Action::Normal) {
    3522      5468141 :             state.dataSingleDuct->MaxDeviceAirMassFlowReheatSDAT = this->ZoneMinAirFrac * this->AirMassFlowRateMax;
    3523              :         } else {
    3524              :             // used for AIRTERMINAL_SINGLEDUCT_VAV_NOREHEAT or SingleDuctVAVNoReheat
    3525       874886 :             state.dataSingleDuct->MaxDeviceAirMassFlowReheatSDAT = this->AirMassFlowRateMax;
    3526              :         }
    3527              : 
    3528              :         // determine flow based on leaving reheat temperature limit
    3529     12072410 :         if (this->MaxReheatTempSetByUser) {
    3530              : 
    3531      2593700 :             state.dataSingleDuct->MaxHeatTempSDAT = this->MaxReheatTemp;
    3532      2593700 :             if (QToHeatSetPt > SmallLoad) { // zone has a positive load to heating setpoint
    3533      2165628 :                 state.dataSingleDuct->MassFlowReqToLimitLeavingTempSDAT =
    3534      2165628 :                     QToHeatSetPt / (CpAirAvg * (state.dataSingleDuct->MaxHeatTempSDAT - state.dataSingleDuct->ZoneTempSDAT));
    3535              :             } else {
    3536       428072 :                 state.dataSingleDuct->MassFlowReqToLimitLeavingTempSDAT = 0.0;
    3537              :             }
    3538              :         }
    3539              : 
    3540              :         // (re)apply limits to find air mass flow
    3541     12072410 :         MassFlow = max(MassFlow, state.dataSingleDuct->MassFlowReqToLimitLeavingTempSDAT);
    3542     12072410 :         MassFlow = min(MassFlow, state.dataSingleDuct->MaxDeviceAirMassFlowReheatSDAT);
    3543     12072410 :         MassFlow = max(MassFlow, MassFlowBasedOnOA);
    3544     12072410 :         MassFlow = min(MassFlow, this->sd_airterminalInlet.AirMassFlowRateMaxAvail);
    3545     12072410 :         MassFlow = max(MassFlow, this->sd_airterminalInlet.AirMassFlowRateMinAvail);
    3546              : 
    3547     12072410 :         if (state.afn->distribution_simulated && state.afn->AirflowNetworkFanActivated && state.afn->VAVTerminalRatio > 0.0) {
    3548            0 :             MassFlow *= state.afn->VAVTerminalRatio;
    3549            0 :             if (MassFlow > state.dataLoopNodes->Node(this->InletNodeNum).MassFlowRate) {
    3550            0 :                 MassFlow = state.dataLoopNodes->Node(this->InletNodeNum).MassFlowRate;
    3551              :             }
    3552              :         }
    3553              : 
    3554              :         // now make any corrections to heating coil loads
    3555     12072410 :         if (this->MaxReheatTempSetByUser) {
    3556      5187400 :             state.dataSingleDuct->QZoneMaxRHTempLimitSDAT =
    3557      2593700 :                 MassFlow * CpAirAvg * (state.dataSingleDuct->MaxHeatTempSDAT - state.dataSingleDuct->ZoneTempSDAT);
    3558      2593700 :             state.dataSingleDuct->QZoneMax2SDAT = min(state.dataSingleDuct->QZoneMaxRHTempLimitSDAT, QToHeatSetPt);
    3559              :         }
    3560              : 
    3561     12072410 :         this->sd_airterminalOutlet.AirMassFlowRate = MassFlow;
    3562              : 
    3563     12072410 :         this->UpdateSys(state);
    3564              : 
    3565              :         // Now do the heating coil calculation for each heating coil type
    3566     12072410 :         switch (this->ReheatComp_Num) { // Reverse damper option is working only for water coils for now.
    3567              :             // hot water heating coil
    3568      9673211 :         case HeatingCoilType::SimpleHeating: { // COIL:WATER:SIMPLEHEATING
    3569              :             // Determine the load required to pass to the Component controller
    3570              :             // Although this equation looks strange (using temp instead of deltaT), it is corrected later in ControlCompOutput
    3571              :             // and is working as-is, temperature setpoints are maintained as expected.
    3572      9673211 :             QZnReq = state.dataSingleDuct->QZoneMax2SDAT + MassFlow * CpAirAvg * state.dataSingleDuct->ZoneTempSDAT;
    3573              : 
    3574              :             // Initialize hot water flow rate to zero.
    3575      9673211 :             DummyMdot = 0.0;
    3576      9673211 :             SetActuatedBranchFlowRate(state, DummyMdot, this->ReheatControlNode, this->HWplantLoc, true);
    3577              :             // On the first HVAC iteration the system values are given to the controller, but after that
    3578              :             // the demand limits are in place and there needs to be feedback to the Zone Equipment
    3579      9673211 :             if (FirstHVACIteration) {
    3580      3883970 :                 MaxFlowWater = this->MaxReheatWaterFlow;
    3581      3883970 :                 MinFlowWater = this->MinReheatWaterFlow;
    3582              :             } else {
    3583      5789241 :                 int WaterControlNode = this->ReheatControlNode;
    3584      5789241 :                 MaxFlowWater = state.dataLoopNodes->Node(WaterControlNode).MassFlowRateMaxAvail;
    3585      5789241 :                 MinFlowWater = state.dataLoopNodes->Node(WaterControlNode).MassFlowRateMinAvail;
    3586              :             }
    3587              : 
    3588              :             // Simulate the reheat coil at constant air flow. Control by varying the
    3589              :             // hot water flow rate.
    3590              :             // FB use QActualHeating, change ControlCompOutput to use new
    3591     29019633 :             ControlCompOutput(state,
    3592      9673211 :                               this->ReheatName,
    3593      9673211 :                               this->ReheatComp,
    3594      9673211 :                               this->ReheatComp_Index,
    3595              :                               FirstHVACIteration,
    3596              :                               QZnReq,
    3597              :                               this->ReheatControlNode,
    3598              :                               MaxFlowWater,
    3599              :                               MinFlowWater,
    3600              :                               this->ControllerOffset,
    3601      9673211 :                               this->ControlCompTypeNum,
    3602      9673211 :                               this->CompErrIndex,
    3603              :                               _,
    3604              :                               SysOutletNode,
    3605              :                               MassFlow,
    3606              :                               _,
    3607              :                               _,
    3608      9673211 :                               this->HWplantLoc);
    3609              : 
    3610              :             // If reverse action damper and the hot water flow is at maximum, simulate the
    3611              :             // hot water coil with fixed (maximum) hot water flow but allow the air flow to
    3612              :             // vary up to the maximum (air damper opens to try to meet zone load)
    3613      9673211 :             if (this->DamperHeatingAction == Action::Reverse || this->DamperHeatingAction == Action::ReverseWithLimits) {
    3614      4826685 :                 if (state.dataLoopNodes->Node(this->ReheatControlNode).MassFlowRate == MaxFlowWater) {
    3615              :                     // fill limits for air flow for controller
    3616      1581245 :                     state.dataSingleDuct->MinAirMassFlowRevActSVAV = this->AirMassFlowRateMax * this->ZoneMinAirFrac;
    3617      1581245 :                     state.dataSingleDuct->MinAirMassFlowRevActSVAV =
    3618      1581245 :                         min(state.dataSingleDuct->MinAirMassFlowRevActSVAV, this->sd_airterminalInlet.AirMassFlowRateMaxAvail);
    3619      1581245 :                     state.dataSingleDuct->MinAirMassFlowRevActSVAV =
    3620      1581245 :                         max(state.dataSingleDuct->MinAirMassFlowRevActSVAV, this->sd_airterminalInlet.AirMassFlowRateMinAvail);
    3621              : 
    3622      1581245 :                     state.dataSingleDuct->MaxAirMassFlowRevActSVAV = this->AirMassFlowRateMax;
    3623      1581245 :                     state.dataSingleDuct->MaxAirMassFlowRevActSVAV =
    3624      1581245 :                         min(state.dataSingleDuct->MaxAirMassFlowRevActSVAV, state.dataSingleDuct->MaxDeviceAirMassFlowReheatSDAT);
    3625      1581245 :                     state.dataSingleDuct->MaxAirMassFlowRevActSVAV =
    3626      1581245 :                         max(state.dataSingleDuct->MaxAirMassFlowRevActSVAV, state.dataSingleDuct->MinAirMassFlowRevActSVAV);
    3627      1581245 :                     state.dataSingleDuct->MaxAirMassFlowRevActSVAV =
    3628      1581245 :                         min(state.dataSingleDuct->MaxAirMassFlowRevActSVAV, this->sd_airterminalInlet.AirMassFlowRateMaxAvail);
    3629              : 
    3630      1581245 :                     state.dataLoopNodes->Node(this->OutletNodeNum).MassFlowRateMaxAvail =
    3631      1581245 :                         state.dataSingleDuct->MaxAirMassFlowRevActSVAV; // suspect, check how/if used in ControlCompOutput
    3632      3162490 :                     ControlCompOutput(state,
    3633      1581245 :                                       this->ReheatName,
    3634      1581245 :                                       this->ReheatComp,
    3635      1581245 :                                       this->ReheatComp_Index,
    3636              :                                       FirstHVACIteration,
    3637      1581245 :                                       state.dataSingleDuct->QZoneMax2SDAT,
    3638              :                                       this->OutletNodeNum,
    3639      1581245 :                                       state.dataSingleDuct->MaxAirMassFlowRevActSVAV,
    3640      1581245 :                                       state.dataSingleDuct->MinAirMassFlowRevActSVAV,
    3641              :                                       this->ControllerOffset,
    3642      1581245 :                                       this->ControlCompTypeNum,
    3643      1581245 :                                       this->CompErrIndex,
    3644              :                                       ZoneNodeNum,
    3645              :                                       SysOutletNode);
    3646              :                     // air flow controller, not on plant, don't pass plant topology info
    3647              :                     // reset terminal unit inlet air mass flow to new value.
    3648      1581245 :                     state.dataLoopNodes->Node(this->OutletNodeNum).MassFlowRateMaxAvail = this->sd_airterminalInlet.AirMassFlowRateMaxAvail;
    3649      1581245 :                     MassFlow = state.dataLoopNodes->Node(SysOutletNode).MassFlowRate;
    3650              : 
    3651              :                     //         ! look for bang-bang condition: flow rate oscillating between 2 values during the air loop / zone
    3652              :                     //         ! equipment iteration. If detected, set flow rate to previous value and recalc HW flow.
    3653      1581245 :                     if (((std::abs(MassFlow - this->MassFlow2) < this->MassFlowDiff) ||
    3654      2004045 :                          (std::abs(MassFlow - this->MassFlow3) < this->MassFlowDiff)) &&
    3655       422800 :                         (std::abs(MassFlow - this->MassFlow1) >= this->MassFlowDiff)) {
    3656         2211 :                         if (MassFlow > 0.0) {
    3657         2211 :                             MassFlow = this->MassFlow1;
    3658              :                         }
    3659         2211 :                         this->sd_airterminalOutlet.AirMassFlowRate = MassFlow;
    3660         2211 :                         this->UpdateSys(state);
    3661              : 
    3662              :                         // Although this equation looks strange (using temp instead of deltaT), it is corrected later in ControlCompOutput
    3663              :                         // and is working as-is, temperature setpoints are maintained as expected.
    3664         2211 :                         QZnReq = state.dataSingleDuct->QZoneMax2SDAT + MassFlow * CpAirAvg * state.dataSingleDuct->ZoneTempSDAT;
    3665         6633 :                         ControlCompOutput(state,
    3666         2211 :                                           this->ReheatName,
    3667         2211 :                                           this->ReheatComp,
    3668         2211 :                                           this->ReheatComp_Index,
    3669              :                                           FirstHVACIteration,
    3670              :                                           QZnReq,
    3671              :                                           this->ReheatControlNode,
    3672              :                                           MaxFlowWater,
    3673              :                                           MinFlowWater,
    3674              :                                           this->ControllerOffset,
    3675         2211 :                                           this->ControlCompTypeNum,
    3676         2211 :                                           this->CompErrIndex,
    3677              :                                           _,
    3678              :                                           SysOutletNode,
    3679              :                                           MassFlow,
    3680              :                                           _,
    3681              :                                           _,
    3682         2211 :                                           this->HWplantLoc);
    3683              :                     }
    3684              : 
    3685      1581245 :                     this->sd_airterminalOutlet.AirMassFlowRate = MassFlow;
    3686              :                     // reset OA report variable
    3687      1581245 :                     this->UpdateSys(state);
    3688              :                 } // IF (Node(sd_airterminal(SysNum)%ReheatControlNode)%MassFlowRate .EQ. MaxFlowWater) THEN
    3689              :             } // IF (sd_airterminal(SysNum)%DamperHeatingAction .EQ. ReverseAction) THEN
    3690              : 
    3691              :             // Recalculate the Damper Position.
    3692      9673211 :             if (MassFlow == 0.0) {
    3693            0 :                 this->DamperPosition = 0.0;
    3694            0 :                 this->ZoneMinAirFracReport = 0.0;
    3695      9673211 :             } else if ((MassFlow > 0.0) && (MassFlow < this->AirMassFlowRateMax)) {
    3696      5869847 :                 this->DamperPosition = MassFlow / this->AirMassFlowRateMax;
    3697      5869847 :                 this->ZoneMinAirFracReport = this->ZoneMinAirFrac;
    3698      3803364 :             } else if (MassFlow == this->AirMassFlowRateMax) {
    3699      3803364 :                 this->DamperPosition = 1.0;
    3700      3803364 :                 this->ZoneMinAirFracReport = this->ZoneMinAirFrac;
    3701              :             }
    3702      9673211 :         } break;
    3703        17699 :         case HeatingCoilType::SteamAirHeating: { // ! COIL:STEAM:AIRHEATING
    3704              :             // Determine the load required to pass to the Component controller
    3705        17699 :             QZnReq =
    3706        17699 :                 state.dataSingleDuct->QZoneMax2SDAT - MassFlow * CpAirAvg * (this->sd_airterminalInlet.AirTemp - state.dataSingleDuct->ZoneTempSDAT);
    3707              : 
    3708              :             // Simulate reheat coil for the VAV system
    3709        17699 :             SimulateSteamCoilComponents(state, this->ReheatName, FirstHVACIteration, this->ReheatComp_Index, QZnReq);
    3710        17699 :         } break;
    3711      1412559 :         case HeatingCoilType::Electric: { // COIL:ELECTRIC:HEATING
    3712              :             // Determine the load required to pass to the Component controller
    3713      1412559 :             QZnReq =
    3714      1412559 :                 state.dataSingleDuct->QZoneMax2SDAT - MassFlow * CpAirAvg * (this->sd_airterminalInlet.AirTemp - state.dataSingleDuct->ZoneTempSDAT);
    3715              : 
    3716              :             // Simulate reheat coil for the VAV system
    3717      1412559 :             SimulateHeatingCoilComponents(state, this->ReheatName, FirstHVACIteration, QZnReq, this->ReheatComp_Index);
    3718      1412559 :         } break;
    3719        94055 :         case HeatingCoilType::Gas: { // COIL:GAS:HEATING
    3720              :             // Determine the load required to pass to the Component controller
    3721        94055 :             QZnReq =
    3722        94055 :                 state.dataSingleDuct->QZoneMax2SDAT - MassFlow * CpAirAvg * (this->sd_airterminalInlet.AirTemp - state.dataSingleDuct->ZoneTempSDAT);
    3723              : 
    3724              :             // Simulate reheat coil for the VAV system
    3725        94055 :             SimulateHeatingCoilComponents(state, this->ReheatName, FirstHVACIteration, QZnReq, this->ReheatComp_Index, QHeatingDelivered);
    3726        94055 :         } break;
    3727       874886 :         case HeatingCoilType::None: { // blank
    3728              :                                       // I no reheat is defined then assume that the damper is the only component.
    3729              :             // If something else is there that is not a reheat coil or a blank then give the error message
    3730       874886 :         } break;
    3731            0 :         default: {
    3732            0 :             ShowFatalError(state, format("Invalid Reheat Component={}", this->ReheatComp));
    3733            0 :         } break;
    3734              :         }
    3735              : 
    3736              :         // the COIL is OFF the properties are calculated for this special case.
    3737              :     } else {
    3738     14950281 :         switch (this->ReheatComp_Num) {
    3739     10808025 :         case HeatingCoilType::SimpleHeating: { // COIL:WATER:SIMPLEHEATING
    3740              :             // Simulate reheat coil for the Const Volume system
    3741     10808025 :             DummyMdot = 0.0;
    3742     10808025 :             SetActuatedBranchFlowRate(state, DummyMdot, this->ReheatControlNode, this->HWplantLoc, true);
    3743              :             // call the reheat coil with the NO FLOW condition to make sure that the Node values
    3744              :             // are passed through to the coil outlet correctly
    3745     10808025 :             SimulateWaterCoilComponents(state, this->ReheatName, FirstHVACIteration, this->ReheatComp_Index);
    3746     10808025 :         } break;
    3747        29755 :         case HeatingCoilType::SteamAirHeating: { // COIL:STEAM:AIRHEATING
    3748              :             // Simulate reheat coil for the VAV system
    3749        29755 :             SimulateSteamCoilComponents(state, this->ReheatName, FirstHVACIteration, this->ReheatComp_Index, 0.0);
    3750        29755 :         } break;
    3751      2210610 :         case HeatingCoilType::Electric: { // COIL:ELECTRIC:HEATING
    3752              :             // Simulate reheat coil for the VAV system
    3753      2210610 :             SimulateHeatingCoilComponents(state, this->ReheatName, FirstHVACIteration, 0.0, this->ReheatComp_Index);
    3754      2210610 :         } break;
    3755       470554 :         case HeatingCoilType::Gas: { // COIL:GAS:HEATING
    3756              :             // Simulate reheat coil for the VAV system
    3757       470554 :             SimulateHeatingCoilComponents(state, this->ReheatName, FirstHVACIteration, 0.0, this->ReheatComp_Index);
    3758       470554 :         } break;
    3759      1431337 :         case HeatingCoilType::None: { // blank
    3760              :                                       // If no reheat is defined then assume that the damper is the only component.
    3761              :                                       // If something else is that is not a reheat coil or a blank then give the error message
    3762      1431337 :         } break;
    3763            0 :         default: {
    3764            0 :             ShowFatalError(state, format("Invalid Reheat Component={}", this->ReheatComp));
    3765            0 :         } break;
    3766              :         }
    3767              :     }
    3768              : 
    3769              :     // push the flow rate history
    3770     27022691 :     this->MassFlow3 = this->MassFlow2;
    3771     27022691 :     this->MassFlow2 = this->MassFlow1;
    3772     27022691 :     this->MassFlow1 = MassFlow;
    3773     27022691 : }
    3774              : 
    3775     23491181 : void SingleDuctAirTerminal::CalcOAMassFlow(EnergyPlusData &state,
    3776              :                                            Real64 &SAMassFlow,   // outside air based on optional user input
    3777              :                                            Real64 &AirLoopOAFrac // outside air based on optional user input
    3778              : ) const
    3779              : {
    3780              : 
    3781              :     // FUNCTION INFORMATION:
    3782              :     //       AUTHOR         R. Raustad (FSEC)
    3783              :     //       DATE WRITTEN   Jan 2010
    3784              :     //       MODIFIED       Mangesh Basarkar, 06/2011: Modifying outside air based on airloop DCV flag
    3785              : 
    3786              :     // PURPOSE OF THIS FUNCTION:
    3787              :     // Calculates the amount of outside air required based on optional user input.
    3788              :     // Zone multipliers are included and are applied in GetInput.
    3789              : 
    3790              :     // METHODOLOGY EMPLOYED:
    3791              :     // User input defines method used to calculate OA.
    3792              : 
    3793              :     // Using/Aliasing
    3794              :     using Psychrometrics::PsyRhoAirFnPbTdbW;
    3795              : 
    3796              :     // FUNCTION PARAMETER DEFINITIONS:
    3797     23491181 :     bool constexpr UseMinOASchFlag(true); // Always use min OA schedule in calculations.
    3798              : 
    3799              :     // FUNCTION LOCAL VARIABLE DECLARATIONS:
    3800              :     Real64 OAVolumeFlowRate; // outside air volume flow rate (m3/s)
    3801              :     Real64 OAMassFlow;       // outside air mass flow rate (kg/s)
    3802              : 
    3803              :     // initialize OA flow rate and OA report variable
    3804     23491181 :     SAMassFlow = 0.0;
    3805     23491181 :     AirLoopOAFrac = 0.0;
    3806     23491181 :     int AirLoopNum = this->AirLoopNum;
    3807              : 
    3808              :     // Calculate the amount of OA based on optional user inputs
    3809     23491181 :     if (AirLoopNum > 0) {
    3810     23490893 :         AirLoopOAFrac = state.dataAirLoop->AirLoopFlow(AirLoopNum).OAFrac;
    3811              :         // If no additional input from user, RETURN from subroutine
    3812     23490893 :         if (this->NoOAFlowInputFromUser) {
    3813     19011378 :             return;
    3814              :         }
    3815              :         // Calculate outdoor air flow rate, zone multipliers are applied in GetInput
    3816      4479515 :         if (AirLoopOAFrac > 0.0) {
    3817      8959030 :             OAVolumeFlowRate = DataSizing::calcDesignSpecificationOutdoorAir(
    3818      4479515 :                 state, this->OARequirementsPtr, this->CtrlZoneNum, state.dataAirLoop->AirLoopControlInfo(AirLoopNum).AirLoopDCVFlag, UseMinOASchFlag);
    3819      4479515 :             OAMassFlow = OAVolumeFlowRate * state.dataEnvrn->StdRhoAir;
    3820              : 
    3821              :             // convert OA mass flow rate to supply air flow rate based on air loop OA fraction
    3822      4479515 :             SAMassFlow = OAMassFlow / AirLoopOAFrac;
    3823              :         }
    3824              :     }
    3825              : }
    3826              : 
    3827        67274 : void SingleDuctAirTerminal::SimCBVAV(EnergyPlusData &state, bool const FirstHVACIteration, int const ZoneNum, int const ZoneNodeNum)
    3828              : {
    3829              : 
    3830              :     // SUBROUTINE INFORMATION:
    3831              :     //       AUTHOR         Richard Raustad
    3832              :     //       DATE WRITTEN   August 2006
    3833              :     //       MODIFIED       KHL/TH 10/2010: added maximum supply air temperature leaving reheat coil
    3834              : 
    3835              :     // PURPOSE OF THIS SUBROUTINE:
    3836              :     // This subroutine simulates the VAV box with varying airflow in heating and cooling.
    3837              :     // Modified version of SimVAV.
    3838              : 
    3839              :     // Using/Aliasing
    3840              :     using namespace DataZoneEnergyDemands;
    3841              :     using HVAC::SmallLoad;
    3842              :     // unused   USE DataHeatBalFanSys,    ONLY: Mat
    3843              :     using HeatingCoils::SimulateHeatingCoilComponents;
    3844              :     using SteamCoils::SimulateSteamCoilComponents;
    3845              :     using WaterCoils::SimulateWaterCoilComponents;
    3846              :     // unused   USE DataHeatBalFanSys,    ONLY: ZoneThermostatSetPointHi, ZoneThermostatSetPointLo
    3847              :     using PlantUtilities::SetActuatedBranchFlowRate;
    3848              : 
    3849              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    3850              :     Real64 MassFlow;     // Total Mass Flow Rate from Hot & Cold Inlets [kg/sec]
    3851              :     Real64 QTotLoad;     // Total load based on thermostat setpoint temperature [Watts]
    3852              :     Real64 QZnReq;       // Total load to be met by terminal heater [Watts]
    3853              :     Real64 QToHeatSetPt; // Remaining load to heating setpoint [W]
    3854              :     Real64 QSupplyAir;   // Zone load met by VAVHeatandCool system
    3855              :     Real64 CpAirZn;      // Specific heat of zone air [J/kg-C]
    3856              :     Real64 CpAirSysIn;   // Specific heat of VAVHeatandCool box entering air [J/kg-C]
    3857              :     Real64 DeltaTemp;    // Temperature difference multiplied by specific heat [J/kg]
    3858              :     Real64 MaxFlowWater; // This is the value passed to the Controller depending if FirstHVACIteration or not
    3859              :     Real64 MinFlowWater; // This is the value passed to the Controller depending if FirstHVACIteration or not
    3860              :     Real64 LeakLoadMult; // Load multiplier to adjust for downstream leaks
    3861              :     int SysOutletNode;   // The node number of the terminal unit outlet node
    3862              :     int SysInletNode;    // The node number of the terminal unit inlet node
    3863              :     Real64 DummyMdot;
    3864              :     Real64 QActualHeating;
    3865              :     Real64 MinFlowFrac; // minimum flow fraction (and minimum damper position)
    3866              : 
    3867              :     // sd_airterminal(SysNum)%InletNodeNum is the inlet node to the terminal unit and the damper
    3868              :     // sd_airterminal(SysNum)%OutletNodeNum is the outlet node of the damper and the inlet node of the heating coil
    3869              :     // sd_airterminal(SysNum)%ReheatAirOutletNode is the outlet node of the terminal unit and the heating coil
    3870              : 
    3871              :     // The calculated load from the Heat Balance
    3872        67274 :     LeakLoadMult = state.dataDefineEquipment->AirDistUnit(this->ADUNum).LeakLoadMult;
    3873        67274 :     QTotLoad = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).RemainingOutputRequired * LeakLoadMult;
    3874        67274 :     QToHeatSetPt = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).RemainingOutputReqToHeatSP * LeakLoadMult;
    3875        67274 :     SysOutletNode = this->ReheatAirOutletNode;
    3876        67274 :     SysInletNode = this->InletNodeNum;
    3877        67274 :     CpAirZn = PsyCpAirFnW(state.dataLoopNodes->Node(ZoneNodeNum).HumRat);
    3878        67274 :     MinFlowFrac = this->ZoneMinAirFrac;
    3879        67274 :     state.dataSingleDuct->MinMassAirFlowSCBVAV = MinFlowFrac * state.dataEnvrn->StdRhoAir * this->MaxAirVolFlowRate;
    3880        67274 :     state.dataSingleDuct->ZoneTempSCBVAV = state.dataLoopNodes->Node(ZoneNodeNum).Temp;
    3881              : 
    3882              :     // Then depending on if the Load is for heating or cooling it is handled differently.  First
    3883              :     // the massflow rate for cooling is determined to meet the entire load.  Then
    3884              :     // if the massflow is below the minimum or greater than the Max it is set to either the Min
    3885              :     // or the Max as specified for the VAV model.
    3886        67274 :     if (this->sd_airterminalInlet.AirMassFlowRateMaxAvail > 0.0) {
    3887              :         // Calculate the flow required for cooling
    3888        43670 :         CpAirSysIn = PsyCpAirFnW(this->sd_airterminalInlet.AirHumRat);
    3889        43670 :         DeltaTemp = CpAirSysIn * this->sd_airterminalInlet.AirTemp - CpAirZn * state.dataSingleDuct->ZoneTempSCBVAV;
    3890              : 
    3891              :         // Need to check DeltaTemp and ensure that it is not zero
    3892        43670 :         if (DeltaTemp != 0.0) {
    3893        43662 :             MassFlow = QTotLoad / DeltaTemp;
    3894              :         } else {
    3895            8 :             MassFlow = this->sd_airterminalInlet.AirMassFlowRateMaxAvail;
    3896              :         }
    3897              : 
    3898              :         // Check to see if the flow is < the Min or > the Max air Fraction to the zone; then set to min or max
    3899        43670 :         MassFlow = max(MassFlow, this->sd_airterminalInlet.AirMassFlowRateMinAvail);
    3900        43670 :         MassFlow = min(MassFlow, this->sd_airterminalInlet.AirMassFlowRateMaxAvail);
    3901              :     } else {
    3902              :         // System is Off set massflow to 0.0
    3903        23604 :         MassFlow = 0.0;
    3904              :     }
    3905              :     // look for bang-bang condition: flow rate oscillating between 2 values during the air loop / zone
    3906              :     // equipment iteration. If detected, set flow rate to previous value.
    3907        91631 :     if (((std::abs(MassFlow - this->MassFlow2) < this->MassFlowDiff) || (std::abs(MassFlow - this->MassFlow3) < this->MassFlowDiff)) &&
    3908        24357 :         (std::abs(MassFlow - this->MassFlow1) >= this->MassFlowDiff)) {
    3909            0 :         MassFlow = this->MassFlow1;
    3910              :     }
    3911              : 
    3912              :     // Move data to the damper outlet node
    3913        67274 :     this->sd_airterminalOutlet.AirTemp = this->sd_airterminalInlet.AirTemp;
    3914        67274 :     this->sd_airterminalOutlet.AirHumRat = this->sd_airterminalInlet.AirHumRat;
    3915        67274 :     this->sd_airterminalOutlet.AirMassFlowRate = MassFlow;
    3916        67274 :     this->sd_airterminalOutlet.AirMassFlowRateMaxAvail = this->sd_airterminalInlet.AirMassFlowRateMaxAvail;
    3917        67274 :     this->sd_airterminalOutlet.AirMassFlowRateMinAvail = this->sd_airterminalInlet.AirMassFlowRateMinAvail;
    3918        67274 :     this->sd_airterminalOutlet.AirEnthalpy = this->sd_airterminalInlet.AirEnthalpy;
    3919              : 
    3920              :     // Calculate the Damper Position when there is a Max air flow specified.
    3921        67274 :     if (this->AirMassFlowRateMax == 0.0) {
    3922           13 :         this->DamperPosition = 0.0;
    3923              :     } else {
    3924        67261 :         this->DamperPosition = MassFlow / this->AirMassFlowRateMax;
    3925              :     }
    3926              : 
    3927              :     // Need to make sure that the damper outlets are passed to the coil inlet
    3928        67274 :     this->UpdateSys(state);
    3929              : 
    3930        67274 :     QActualHeating = QToHeatSetPt - MassFlow * CpAirZn * (this->sd_airterminalInlet.AirTemp - state.dataSingleDuct->ZoneTempSCBVAV);
    3931              : 
    3932        67274 :     if ((MassFlow > SmallMassFlow) && (QActualHeating > 0.0) && (state.dataHeatBalFanSys->TempControlType(ZoneNum) != HVAC::SetptType::SingleCool)) {
    3933              :         //   VAVHeatandCool boxes operate at varying mass flow rates when reheating, VAV boxes operate at min flow
    3934              :         //      (MassFlow <= this->sd_airterminalInlet%AirMassFlowRateMinAvail) .AND. &
    3935              :         //   Per Fred Buhl, don't use DeadBandOrSetback to determine if heaters operate
    3936              :         //      (.NOT. DeadBandOrSetback(ZoneNum))) Then
    3937              : 
    3938              :         // At this point we know that there is a heating requirement: i.e., the heating coil needs to
    3939              :         // be activated (there's a zone heating load or there's a reheat requirement). There are 3 possible
    3940              :         // situations: 1) the coil load can be met by variable temperature air (below the max heat temp) at
    3941              :         // the minimum air mass flow rate; 2) the coil load can be met by variable air flow rate with the air
    3942              :         // temperature fixed at the max heat temp; 3) the load cannot be met (we will run at max air temp and
    3943              :         // max air flow rate). We check for condition 2 by assuming the air temperatute is at the max heat temp
    3944              :         // and solving for the air mass flow rate that will meet the load. If the flow rate is between the min and
    3945              :         // max we are in condition 2.
    3946              : 
    3947        20307 :         state.dataSingleDuct->QZoneMax2SCBVAV = QToHeatSetPt;
    3948              : 
    3949        20307 :         if (this->MaxReheatTempSetByUser) {
    3950              : 
    3951         5082 :             state.dataSingleDuct->MaxHeatTempSCBVAV = this->MaxReheatTemp;
    3952         5082 :             if (QToHeatSetPt > SmallLoad) { // zone has a positive load to heating setpoint
    3953         5082 :                 state.dataSingleDuct->MassFlowReqSCBVAV =
    3954         5082 :                     QToHeatSetPt / (CpAirZn * (state.dataSingleDuct->MaxHeatTempSCBVAV - state.dataSingleDuct->ZoneTempSCBVAV));
    3955              :             } else {
    3956            0 :                 state.dataSingleDuct->MassFlowReqSCBVAV = MassFlow;
    3957              :             }
    3958              : 
    3959        10164 :             state.dataSingleDuct->QZoneMax3SCBVAV =
    3960         5082 :                 CpAirZn * (state.dataSingleDuct->MaxHeatTempSCBVAV - state.dataSingleDuct->ZoneTempSCBVAV) * MassFlow;
    3961              : 
    3962         5082 :             state.dataSingleDuct->MassFlowActualSCBVAV = MassFlow;
    3963              : 
    3964         5082 :             if (state.dataSingleDuct->QZoneMax3SCBVAV < QToHeatSetPt) {
    3965         2395 :                 state.dataSingleDuct->MassFlowActualSCBVAV = state.dataSingleDuct->MassFlowReqSCBVAV;
    3966              :                 // QZoneMax3 = CpAirZn * (MaxHeatTemp - ZoneTemp) * MassFlowActual
    3967              :             }
    3968              : 
    3969         5082 :             if (state.dataSingleDuct->MassFlowActualSCBVAV <= state.dataSingleDuct->MinMassAirFlowSCBVAV) {
    3970            0 :                 state.dataSingleDuct->MassFlowActualSCBVAV = state.dataSingleDuct->MinMassAirFlowSCBVAV;
    3971         5082 :             } else if (state.dataSingleDuct->MassFlowActualSCBVAV >= this->AirMassFlowRateMax) {
    3972         3802 :                 state.dataSingleDuct->MassFlowActualSCBVAV = this->AirMassFlowRateMax;
    3973              :             }
    3974              : 
    3975         5082 :             state.dataSingleDuct->QZoneMaxSCBVAV = CpAirZn * state.dataSingleDuct->MassFlowActualSCBVAV *
    3976         5082 :                                                    (state.dataSingleDuct->MaxHeatTempSCBVAV - state.dataSingleDuct->ZoneTempSCBVAV);
    3977              : 
    3978              :             // temporary variable
    3979         5082 :             state.dataSingleDuct->QZoneMax2SCBVAV = min(state.dataSingleDuct->QZoneMaxSCBVAV, QToHeatSetPt);
    3980              : 
    3981         5082 :             MassFlow = state.dataSingleDuct->MassFlowActualSCBVAV;
    3982              : 
    3983              :         } // IF (sd_airterminal(SysNum)%MaxReheatTempSetByUser) THEN
    3984              : 
    3985        20307 :         this->sd_airterminalOutlet.AirMassFlowRate = MassFlow;
    3986              : 
    3987        20307 :         this->UpdateSys(state);
    3988              : 
    3989        20307 :         switch (this->ReheatComp_Num) {        // hot water heating coil
    3990            0 :         case HeatingCoilType::SimpleHeating: { // COIL:WATER:SIMPLEHEATING
    3991              :             // Determine the load required to pass to the Component controller
    3992              :             // Although this equation looks strange (using temp instead of deltaT), it is corrected later in ControlCompOutput
    3993              :             // and is working as-is, temperature setpoints are maintained as expected.
    3994            0 :             QZnReq = state.dataSingleDuct->QZoneMax2SCBVAV + MassFlow * CpAirZn * state.dataLoopNodes->Node(ZoneNodeNum).Temp;
    3995            0 :             if (QZnReq < SmallLoad) {
    3996            0 :                 QZnReq = 0.0;
    3997              :             }
    3998              : 
    3999              :             // Initialize hot water flow rate to zero.
    4000              :             // Node(sd_airterminal(SysNum)%ReheatControlNode)%MassFlowRate = 0.0D0
    4001            0 :             DummyMdot = 0.0;
    4002            0 :             SetActuatedBranchFlowRate(state, DummyMdot, this->ReheatControlNode, this->HWplantLoc, true);
    4003              :             // On the first HVAC iteration the system values are given to the controller, but after that
    4004              :             // the demand limits are in place and there needs to be feedback to the Zone Equipment
    4005            0 :             if (FirstHVACIteration) {
    4006            0 :                 MaxFlowWater = this->MaxReheatWaterFlow;
    4007            0 :                 MinFlowWater = this->MinReheatWaterFlow;
    4008              :             } else {
    4009            0 :                 int WaterControlNode = this->ReheatControlNode;
    4010            0 :                 MaxFlowWater = state.dataLoopNodes->Node(WaterControlNode).MassFlowRateMaxAvail;
    4011            0 :                 MinFlowWater = state.dataLoopNodes->Node(WaterControlNode).MassFlowRateMinAvail;
    4012              :             }
    4013              : 
    4014              :             // Simulate the reheat coil at constant air flow. Control by varying the
    4015              :             // hot water flow rate.
    4016            0 :             ControlCompOutput(state,
    4017            0 :                               this->ReheatName,
    4018            0 :                               this->ReheatComp,
    4019            0 :                               this->ReheatComp_Index,
    4020              :                               FirstHVACIteration,
    4021              :                               QZnReq,
    4022              :                               this->ReheatControlNode,
    4023              :                               MaxFlowWater,
    4024              :                               MinFlowWater,
    4025              :                               this->ControllerOffset,
    4026            0 :                               this->ControlCompTypeNum,
    4027            0 :                               this->CompErrIndex,
    4028              :                               _,
    4029              :                               SysOutletNode,
    4030              :                               MassFlow,
    4031              :                               _,
    4032              :                               _,
    4033            0 :                               this->HWplantLoc);
    4034              : 
    4035              :             // If reverse action damper and the hot water flow is at maximum, simulate the
    4036              :             // hot water coil with fixed (maximum) hot water flow but allow the air flow to
    4037              :             // vary up to the maximum (air damper opens to try to meet zone load).
    4038            0 :             if (this->DamperHeatingAction == Action::Reverse) {
    4039            0 :                 if (state.dataLoopNodes->Node(this->ReheatControlNode).MassFlowRate == this->MaxReheatWaterFlow) {
    4040            0 :                     ControlCompOutput(state,
    4041            0 :                                       this->ReheatName,
    4042            0 :                                       this->ReheatComp,
    4043            0 :                                       this->ReheatComp_Index,
    4044              :                                       FirstHVACIteration,
    4045            0 :                                       state.dataSingleDuct->QZoneMax2SCBVAV,
    4046              :                                       this->OutletNodeNum,
    4047              :                                       this->sd_airterminalInlet.AirMassFlowRateMaxAvail,
    4048              :                                       this->sd_airterminalInlet.AirMassFlowRateMinAvail,
    4049              :                                       this->ControllerOffset,
    4050            0 :                                       this->ControlCompTypeNum,
    4051            0 :                                       this->CompErrIndex,
    4052              :                                       ZoneNodeNum,
    4053              :                                       SysOutletNode);
    4054              :                     //                                   ! air flow controller, not on plant, don't pass plant topology info
    4055              : 
    4056              :                     // reset terminal unit inlet air mass flow to new value.
    4057            0 :                     MassFlow = state.dataLoopNodes->Node(SysOutletNode).MassFlowRate;
    4058            0 :                     this->sd_airterminalOutlet.AirMassFlowRate = MassFlow;
    4059            0 :                     this->UpdateSys(state);
    4060              :                 }
    4061              :                 // look for bang-bang condition: flow rate oscillating between 2 values during the air loop / zone
    4062              :                 // equipment iteration. If detected, set flow rate to previous value and recalc HW flow.
    4063            0 :                 if (((std::abs(MassFlow - this->MassFlow2) < this->MassFlowDiff) || (std::abs(MassFlow - this->MassFlow3) < this->MassFlowDiff)) &&
    4064            0 :                     (std::abs(MassFlow - this->MassFlow1) >= this->MassFlowDiff)) {
    4065            0 :                     MassFlow = this->MassFlow1;
    4066            0 :                     this->sd_airterminalOutlet.AirMassFlowRate = MassFlow;
    4067            0 :                     this->UpdateSys(state);
    4068            0 :                     ControlCompOutput(state,
    4069            0 :                                       this->ReheatName,
    4070            0 :                                       this->ReheatComp,
    4071            0 :                                       this->ReheatComp_Index,
    4072              :                                       FirstHVACIteration,
    4073              :                                       QZnReq,
    4074              :                                       this->ReheatControlNode,
    4075              :                                       MaxFlowWater,
    4076              :                                       MinFlowWater,
    4077              :                                       this->ControllerOffset,
    4078            0 :                                       this->ControlCompTypeNum,
    4079            0 :                                       this->CompErrIndex,
    4080              :                                       _,
    4081              :                                       SysOutletNode,
    4082              :                                       MassFlow,
    4083              :                                       _,
    4084              :                                       _,
    4085            0 :                                       this->HWplantLoc);
    4086              :                 }
    4087              :                 // recalculate damper position
    4088            0 :                 if (this->AirMassFlowRateMax == 0.0) {
    4089            0 :                     this->DamperPosition = 0.0;
    4090              :                 } else {
    4091            0 :                     this->DamperPosition = MassFlow / this->AirMassFlowRateMax;
    4092              :                 }
    4093              :             }
    4094            0 :         } break;
    4095            0 :         case HeatingCoilType::SteamAirHeating: { // ! COIL:STEAM:AIRHEATING
    4096              :             // Determine the load required to pass to the Component controller
    4097            0 :             QZnReq = state.dataSingleDuct->QZoneMax2SCBVAV -
    4098            0 :                      MassFlow * CpAirZn * (this->sd_airterminalInlet.AirTemp - state.dataSingleDuct->ZoneTempSCBVAV);
    4099            0 :             if (QZnReq < SmallLoad) {
    4100            0 :                 QZnReq = 0.0;
    4101              :             }
    4102              : 
    4103              :             // Simulate reheat coil for the VAV system
    4104            0 :             SimulateSteamCoilComponents(state, this->ReheatName, FirstHVACIteration, this->ReheatComp_Index, QZnReq);
    4105            0 :         } break;
    4106        13145 :         case HeatingCoilType::Electric: { // COIL:ELECTRIC:HEATING
    4107              :             // Determine the load required to pass to the Component controller
    4108        13145 :             QSupplyAir = MassFlow * CpAirZn * (this->sd_airterminalInlet.AirTemp - state.dataSingleDuct->ZoneTempSCBVAV);
    4109        13145 :             QZnReq = state.dataSingleDuct->QZoneMax2SCBVAV - QSupplyAir;
    4110        13145 :             if (QZnReq < SmallLoad) {
    4111         4105 :                 QZnReq = 0.0;
    4112              :             }
    4113              : 
    4114              :             // Simulate reheat coil for the VAV system
    4115        13145 :             SimulateHeatingCoilComponents(state, this->ReheatName, FirstHVACIteration, QZnReq, this->ReheatComp_Index);
    4116        13145 :         } break;
    4117            0 :         case HeatingCoilType::Gas: { // COIL:GAS:HEATING
    4118              :             // Determine the load required to pass to the Component controller
    4119            0 :             QZnReq = state.dataSingleDuct->QZoneMax2SCBVAV -
    4120            0 :                      MassFlow * CpAirZn * (this->sd_airterminalInlet.AirTemp - state.dataSingleDuct->ZoneTempSCBVAV);
    4121            0 :             if (QZnReq < SmallLoad) {
    4122            0 :                 QZnReq = 0.0;
    4123              :             }
    4124              : 
    4125              :             // Simulate reheat coil for the VAV system
    4126            0 :             SimulateHeatingCoilComponents(state, this->ReheatName, FirstHVACIteration, QZnReq, this->ReheatComp_Index);
    4127            0 :         } break;
    4128         7162 :         case HeatingCoilType::None: { // blank
    4129              :                                       // If no reheat is defined then assume that the damper is the only component.
    4130              :             // If something else is there that is not a reheat coil then give the error message below.
    4131         7162 :         } break;
    4132            0 :         default: {
    4133            0 :             ShowFatalError(state, format("Invalid Reheat Component={}", this->ReheatComp));
    4134            0 :         } break;
    4135              :         }
    4136              : 
    4137              :         // the COIL is OFF the properties are calculated for this special case.
    4138              :     } else {
    4139        46967 :         switch (this->ReheatComp_Num) {
    4140            0 :         case HeatingCoilType::SimpleHeating: { // COIL:WATER:SIMPLEHEATING
    4141              :             // Simulate reheat coil for the Const Volume system
    4142              :             // Node(sd_airterminal(SysNum)%ReheatControlNode)%MassFlowRate = 0.0D0
    4143              :             // Initialize hot water flow rate to zero.
    4144            0 :             DummyMdot = 0.0;
    4145            0 :             SetActuatedBranchFlowRate(state, DummyMdot, this->ReheatControlNode, this->HWplantLoc, true);
    4146              : 
    4147              :             // call the reheat coil with the NO FLOW condition to make sure that the Node values
    4148              :             // are passed through to the coil outlet correctly
    4149            0 :             SimulateWaterCoilComponents(state, this->ReheatName, FirstHVACIteration, this->ReheatComp_Index);
    4150            0 :         } break;
    4151            0 :         case HeatingCoilType::SteamAirHeating: { // COIL:STEAM:AIRHEATING
    4152              :             // Simulate reheat coil for the VAV system
    4153            0 :             SimulateSteamCoilComponents(state, this->ReheatName, FirstHVACIteration, this->ReheatComp_Index, 0.0);
    4154            0 :         } break;
    4155        32905 :         case HeatingCoilType::Electric: { // COIL:ELECTRIC:HEATING
    4156              :             // Simulate reheat coil for the VAV system
    4157        32905 :             SimulateHeatingCoilComponents(state, this->ReheatName, FirstHVACIteration, 0.0, this->ReheatComp_Index);
    4158        32905 :         } break;
    4159            0 :         case HeatingCoilType::Gas: { // COIL:GAS:HEATING
    4160              :             // Simulate reheat coil for the VAV system
    4161            0 :             SimulateHeatingCoilComponents(state, this->ReheatName, FirstHVACIteration, 0.0, this->ReheatComp_Index);
    4162            0 :         } break;
    4163        14062 :         case HeatingCoilType::None: { // blank
    4164              :                                       // If no reheat is defined then assume that the damper is the only component.
    4165              :                                       // If something else is there that is not a reheat coil then give the error message
    4166        14062 :         } break;
    4167            0 :         default: {
    4168            0 :             ShowFatalError(state, format("Invalid Reheat Component={}", this->ReheatComp));
    4169            0 :         } break;
    4170              :         }
    4171              :     }
    4172              :     // push the flow rate history
    4173        67274 :     this->MassFlow3 = this->MassFlow2;
    4174        67274 :     this->MassFlow2 = this->MassFlow1;
    4175        67274 :     this->MassFlow1 = MassFlow;
    4176        67274 : }
    4177              : 
    4178        30864 : void SingleDuctAirTerminal::SimVAVVS(EnergyPlusData &state, bool const FirstHVACIteration, int const ZoneNum, int const ZoneNodeNum)
    4179              : {
    4180              : 
    4181              :     // SUBROUTINE INFORMATION:
    4182              :     //       AUTHOR         Fred Buhl
    4183              :     //       DATE WRITTEN   July 2004
    4184              : 
    4185              :     // PURPOSE OF THIS SUBROUTINE:
    4186              :     // This subroutine simulates a single duct VAV terminal unit with a variable-speed fan upstream
    4187              :     // and a reheat coil on the downstream side.
    4188              : 
    4189              :     // METHODOLOGY EMPLOYED:
    4190              :     // Define a compound component in CalcVAVVS. Break the heating/cooling load into 4 regions based
    4191              :     // on equip on/off combinations. Assign the heating load to the appropriate region and iteratively
    4192              :     // solve for the appropriate control variable value using Regula-Falsi solver.
    4193              : 
    4194              :     // Using/Aliasing
    4195              :     using namespace DataZoneEnergyDemands;
    4196              :     using General::SolveRoot;
    4197              :     using SteamCoils::GetCoilCapacity;
    4198              : 
    4199              :     // SUBROUTINE PARAMETER DEFINITIONS:
    4200        30864 :     Real64 constexpr BigLoad(1.0e+20);
    4201              : 
    4202              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    4203        30864 :     Real64 MassFlow = 0; // [kg/sec]   Total Mass Flow Rate from Hot & Cold Inlets
    4204              :     Real64 QTotLoad;     // [Watts]
    4205              :     // unused  REAL(r64) :: QZnReq      ! [Watts]
    4206              :     Real64 CpAirZn;
    4207              :     // unused  REAL(r64) :: CpAirSysIn
    4208              :     // unused  REAL(r64) :: DeltaTemp
    4209              :     int SysOutletNode;    // The node number of the terminal unit outlet node
    4210              :     int SysInletNode;     // the node number of the terminal unit inlet node
    4211              :     int WaterControlNode; // This is the Actuated Reheat Control Node
    4212              :     int SteamControlNode;
    4213              :     Real64 MaxFlowWater;    // This is the value passed to the Controller depending if FirstHVACIteration or not
    4214              :     Real64 MinFlowWater;    // This is the value passed to the Controller depending if FirstHVACIteration or not
    4215              :     Real64 MaxFlowSteam;    // This is the value passed to the Controller depending if FirstHVACIteration or not
    4216              :     Real64 MinFlowSteam;    // This is the value passed to the Controller depending if FirstHVACIteration or not
    4217              :     Real64 HWFlow;          // the hot water flow rate [kg/s]
    4218              :     Real64 QCoolFanOnMax;   // max cooling - fan at max flow; note that cooling is always < 0. [W]
    4219              :     Real64 QCoolFanOnMin;   // min active cooling with fan on - fan at lowest speed. [W]
    4220              :     Real64 QHeatFanOnMax;   // max heating - fan at heat flow max, hot water flow at max [W]
    4221              :     Real64 QHeatFanOnMin;   // min heating - fan at min flow, hot water at max flow [W]
    4222              :     Real64 QHeatFanOffMax;  // max heating - fan off, hot water flow at max [W]
    4223              :     Real64 QNoHeatFanOff;   // min heating - fan off, hot water at min flow [W]
    4224              :     HeatingCoilType HCType; // heating coil type
    4225              :     HVAC::FanType fanType;  // fan type (as a number)
    4226              :     int FanOp;              // 1 if fan is on; 0 if off.
    4227              :     Real64 MaxCoolMassFlow; // air flow at max cooling [kg/s]
    4228              :     Real64 MaxHeatMassFlow; // air flow at max heating [kg/s]
    4229              :     Real64 MinMassFlow;     // minimum air flow rate [kg/s]
    4230              :     Real64 UnitFlowToler;   // flow rate tolerance
    4231              :     Real64 QDelivered;
    4232              :     Real64 FracDelivered;
    4233              :     int SolFlag;
    4234              :     Real64 ErrTolerance;
    4235              :     Real64 MaxSteamCap; // steam coil capacity at full load
    4236              : 
    4237              :     // The calculated load from the Heat Balance
    4238        30864 :     QTotLoad = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).RemainingOutputRequired;
    4239        30864 :     SysOutletNode = this->ReheatAirOutletNode;
    4240        30864 :     SysInletNode = this->InletNodeNum;
    4241        30864 :     CpAirZn = PsyCpAirFnW(state.dataLoopNodes->Node(ZoneNodeNum).HumRat);
    4242        30864 :     HCType = this->ReheatComp_Num;
    4243        30864 :     fanType = this->fanType;
    4244        30864 :     MaxCoolMassFlow = this->sd_airterminalInlet.AirMassFlowRateMaxAvail;
    4245        30864 :     MaxHeatMassFlow = min(this->HeatAirMassFlowRateMax, this->sd_airterminalInlet.AirMassFlowRateMaxAvail);
    4246        30864 :     MinMassFlow = MaxCoolMassFlow * this->ZoneMinAirFrac;
    4247        30864 :     UnitFlowToler = 0.001 * DataConvergParams::HVACFlowRateToler;
    4248        30864 :     QDelivered = 0.0;
    4249        30864 :     HWFlow = 0.0;
    4250        30864 :     if (this->sd_airterminalInlet.AirMassFlowRateMaxAvail <= 0.0 || state.dataZoneEnergyDemand->CurDeadBandOrSetback(ZoneNum)) {
    4251         7828 :         MassFlow = 0.0;
    4252         7828 :         FanOp = 0;
    4253         7828 :         this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, 0.0, 0.0, fanType, MassFlow, FanOp, QDelivered);
    4254         7828 :         return;
    4255              :     }
    4256              : 
    4257        23036 :     if (HCType == HeatingCoilType::SimpleHeating) {
    4258        23036 :         WaterControlNode = this->ReheatControlNode;
    4259        23036 :         if (FirstHVACIteration) {
    4260        11518 :             MaxFlowWater = this->MaxReheatWaterFlow;
    4261        11518 :             MinFlowWater = this->MinReheatWaterFlow;
    4262              :         } else {
    4263        11518 :             WaterControlNode = this->ReheatControlNode;
    4264        11518 :             MaxFlowWater = state.dataLoopNodes->Node(WaterControlNode).MassFlowRateMaxAvail;
    4265        11518 :             MinFlowWater = state.dataLoopNodes->Node(WaterControlNode).MassFlowRateMinAvail;
    4266              :         }
    4267              :     } else {
    4268            0 :         WaterControlNode = 0;
    4269            0 :         MaxFlowWater = 0.0;
    4270            0 :         MinFlowWater = 0.0;
    4271              :     }
    4272              : 
    4273        23036 :     if (HCType == HeatingCoilType::SteamAirHeating) {
    4274            0 :         SteamControlNode = this->ReheatControlNode;
    4275            0 :         if (FirstHVACIteration) {
    4276            0 :             MaxFlowSteam = this->MaxReheatSteamFlow;
    4277            0 :             MinFlowSteam = this->MinReheatSteamFlow;
    4278              :         } else {
    4279            0 :             MaxFlowSteam = state.dataLoopNodes->Node(SteamControlNode).MassFlowRateMaxAvail;
    4280            0 :             MinFlowSteam = state.dataLoopNodes->Node(SteamControlNode).MassFlowRateMinAvail;
    4281              :         }
    4282              :     } else {
    4283        23036 :         SteamControlNode = 0;
    4284        23036 :         MaxFlowSteam = 0.0;
    4285        23036 :         MinFlowSteam = 0.0;
    4286              :     }
    4287              : 
    4288              :     // define 3 load regions and assign the current load to the correct region.
    4289              :     // region 1: active cooling with fan on
    4290        23036 :     FanOp = 1;
    4291        23036 :     if (HCType == HeatingCoilType::SteamAirHeating) {
    4292              :         bool ErrorsFound; // returned from mining function call
    4293            0 :         this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, MinFlowSteam, 0.0, fanType, MaxCoolMassFlow, FanOp, QCoolFanOnMax);
    4294            0 :         this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, MinFlowSteam, 0.0, fanType, MinMassFlow, FanOp, QCoolFanOnMin);
    4295              :         // region 2: active heating with fan on
    4296            0 :         this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, MaxFlowSteam, BigLoad, fanType, MaxHeatMassFlow, FanOp, QHeatFanOnMax);
    4297            0 :         MaxSteamCap = GetCoilCapacity(state, this->ReheatComp, this->ReheatName, ErrorsFound);
    4298            0 :         this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, MaxFlowSteam, 0.0, fanType, MinMassFlow, FanOp, QHeatFanOnMin);
    4299              :         // region 3: active heating with fan off
    4300            0 :         FanOp = 0;
    4301            0 :         this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, MaxFlowSteam, BigLoad, fanType, MinMassFlow, FanOp, QHeatFanOffMax);
    4302            0 :         this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, MinFlowSteam, 0.0, fanType, MinMassFlow, FanOp, QNoHeatFanOff);
    4303              :     } else {
    4304        23036 :         this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, MinFlowWater, 0.0, fanType, MaxCoolMassFlow, FanOp, QCoolFanOnMax);
    4305        23036 :         this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, MinFlowWater, 0.0, fanType, MinMassFlow, FanOp, QCoolFanOnMin);
    4306              :         // region 2: active heating with fan on
    4307        23036 :         this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, MaxFlowWater, BigLoad, fanType, MaxHeatMassFlow, FanOp, QHeatFanOnMax);
    4308        23036 :         this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, MaxFlowWater, 0.0, fanType, MinMassFlow, FanOp, QHeatFanOnMin);
    4309              :         // region 3: active heating with fan off
    4310        23036 :         FanOp = 0;
    4311        23036 :         this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, MaxFlowWater, BigLoad, fanType, MinMassFlow, FanOp, QHeatFanOffMax);
    4312        23036 :         this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, MinFlowWater, 0.0, fanType, MinMassFlow, FanOp, QNoHeatFanOff);
    4313              :     }
    4314              : 
    4315              :     // Active cooling with fix for issue #5592
    4316        32132 :     if (QTotLoad < (-1.0 * SmallLoad) && QTotLoad < (QCoolFanOnMin - SmallLoad) && this->sd_airterminalInlet.AirMassFlowRateMaxAvail > 0.0 &&
    4317         9096 :         !state.dataZoneEnergyDemand->CurDeadBandOrSetback(ZoneNum)) {
    4318              :         // check that it can meet the load
    4319         9096 :         FanOp = 1;
    4320         9096 :         if (QCoolFanOnMax < QTotLoad - SmallLoad) {
    4321         9096 :             Real64 MinHWFlow = (HCType == HeatingCoilType::SteamAirHeating) ? MinFlowSteam : MinFlowWater;
    4322              : 
    4323        45066 :             auto f = [&state, this, FirstHVACIteration, ZoneNodeNum, MinHWFlow, fanType, FanOp, QTotLoad](Real64 const SupplyAirMassFlow) {
    4324        45066 :                 Real64 UnitOutput = 0.0; // cooling output [W] (cooling is negative)
    4325              : 
    4326        45066 :                 state.dataSingleDuct->sd_airterminal(this->SysNum)
    4327        45066 :                     .CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, MinHWFlow, 0.0, fanType, SupplyAirMassFlow, FanOp, UnitOutput);
    4328        45066 :                 return (QTotLoad - UnitOutput) / QTotLoad;
    4329         9096 :             };
    4330              : 
    4331         9096 :             SolveRoot(state, UnitFlowToler, 50, SolFlag, MassFlow, f, MinMassFlow, MaxCoolMassFlow);
    4332         9096 :             if (SolFlag == -1) {
    4333            0 :                 if (this->IterationLimit == 0) {
    4334            0 :                     ShowWarningError(state, format("Supply air flow control failed in VS VAV terminal unit {}", this->SysName));
    4335            0 :                     ShowContinueError(state, "  Iteration limit exceeded in calculating air flow rate");
    4336              :                 }
    4337            0 :                 ShowRecurringWarningErrorAtEnd(
    4338            0 :                     state, "Supply air flow Iteration limit exceeded in VS VAV terminal unit " + this->SysName, this->IterationLimit);
    4339         9096 :             } else if (SolFlag == -2) {
    4340            0 :                 if (this->IterationFailed == 0) {
    4341            0 :                     ShowWarningError(state, format("Supply air flow control failed in VS VAV terminal unit {}", this->SysName));
    4342            0 :                     ShowContinueError(state, "  Bad air flow limits");
    4343              :                 }
    4344            0 :                 ShowRecurringWarningErrorAtEnd(
    4345            0 :                     state, "Supply air flow control failed in VS VAV terminal unit " + this->SysName, this->IterationFailed);
    4346              :             }
    4347              : 
    4348              :         } else {
    4349              : 
    4350            0 :             MassFlow = MaxCoolMassFlow;
    4351              : 
    4352            0 :             if (HCType == HeatingCoilType::SteamAirHeating) {
    4353            0 :                 this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, MinFlowSteam, 0.0, fanType, MassFlow, FanOp, QDelivered);
    4354              :             } else {
    4355            0 :                 this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, MinFlowWater, 0.0, fanType, MassFlow, FanOp, QDelivered);
    4356              :             }
    4357              :         }
    4358              : 
    4359              :         // no active heating or cooling
    4360        13940 :     } else if ((QTotLoad >= QCoolFanOnMin - SmallLoad && QTotLoad <= QNoHeatFanOff + SmallLoad &&
    4361        27880 :                 this->sd_airterminalInlet.AirMassFlowRateMaxAvail > 0.0) ||
    4362        13940 :                (this->sd_airterminalInlet.AirMassFlowRateMaxAvail > 0.0 && state.dataZoneEnergyDemand->CurDeadBandOrSetback(ZoneNum))) {
    4363            0 :         MassFlow = MinMassFlow;
    4364            0 :         FanOp = 0;
    4365            0 :         if (HCType == HeatingCoilType::SteamAirHeating) {
    4366            0 :             this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, MinFlowSteam, QTotLoad, fanType, MassFlow, FanOp, QNoHeatFanOff);
    4367              :         } else {
    4368            0 :             this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, MinFlowWater, 0.0, fanType, MassFlow, FanOp, QNoHeatFanOff);
    4369              :         }
    4370              : 
    4371              :         // active heating
    4372        27880 :     } else if (QTotLoad > QNoHeatFanOff + SmallLoad && this->sd_airterminalInlet.AirMassFlowRateMaxAvail > 0.0 &&
    4373        13940 :                !state.dataZoneEnergyDemand->CurDeadBandOrSetback(ZoneNum)) {
    4374              :         // hot water coil
    4375        13940 :         if (HCType == HeatingCoilType::SimpleHeating) {
    4376        13940 :             if (QTotLoad < QHeatFanOffMax - SmallLoad) {
    4377              :                 // vary HW flow, leave air flow at minimum
    4378         7575 :                 ErrTolerance = this->ControllerOffset;
    4379         7575 :                 MassFlow = MinMassFlow;
    4380         7575 :                 FanOp = 0;
    4381              : 
    4382       120869 :                 auto f = [&state, this, FirstHVACIteration, ZoneNodeNum, MassFlow, fanType, FanOp, QTotLoad](Real64 const HWMassFlow) {
    4383       120869 :                     Real64 UnitOutput = 0.0; // heating output [W]
    4384       120869 :                     Real64 QSteamLoad = 0.0; // proportional load to calculate steam flow [W]
    4385              : 
    4386       120869 :                     state.dataSingleDuct->sd_airterminal(this->SysNum)
    4387       120869 :                         .CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, HWMassFlow, QSteamLoad, fanType, MassFlow, FanOp, UnitOutput);
    4388              : 
    4389       120869 :                     return (QTotLoad - UnitOutput) / QTotLoad;
    4390         7575 :                 };
    4391              : 
    4392         7575 :                 SolveRoot(state, ErrTolerance, 500, SolFlag, HWFlow, f, MinFlowWater, MaxFlowWater);
    4393         7575 :                 if (SolFlag == -1) {
    4394            0 :                     ShowRecurringWarningErrorAtEnd(state, "Hot Water flow control failed in VS VAV terminal unit " + this->SysName, this->ErrCount1);
    4395            0 :                     ShowRecurringContinueErrorAtEnd(
    4396            0 :                         state, "...Iteration limit (500) exceeded in calculating the hot water flow rate", this->ErrCount1c);
    4397            0 :                     this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, HWFlow, 0.0, fanType, MassFlow, FanOp, QDelivered);
    4398         7575 :                 } else if (SolFlag == -2) {
    4399            0 :                     ShowRecurringWarningErrorAtEnd(
    4400            0 :                         state, "Hot Water flow control failed (bad air flow limits) in VS VAV terminal unit " + this->SysName, this->ErrCount2);
    4401              :                 }
    4402         6365 :             } else if (QTotLoad >= QHeatFanOffMax - SmallLoad && QTotLoad <= QHeatFanOnMin + SmallLoad) {
    4403           14 :                 MassFlow = MinMassFlow;
    4404           14 :                 FanOp = 0;
    4405           14 :                 this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, MaxFlowWater, 0.0, fanType, MassFlow, FanOp, QDelivered);
    4406         6351 :             } else if (QTotLoad > QHeatFanOnMin + SmallLoad && QTotLoad < QHeatFanOnMax - SmallLoad) {
    4407              :                 // set hot water flow to max and vary the supply air flow rate
    4408         6351 :                 FanOp = 1;
    4409        47467 :                 auto f = [&state, this, FirstHVACIteration, ZoneNodeNum, MaxFlowWater, fanType, FanOp, QTotLoad](Real64 const SupplyAirMassFlow) {
    4410        47467 :                     Real64 UnitOutput = 0.0; // heating output [W]
    4411        47467 :                     state.dataSingleDuct->sd_airterminal(this->SysNum)
    4412        47467 :                         .CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, MaxFlowWater, QTotLoad, fanType, SupplyAirMassFlow, FanOp, UnitOutput);
    4413              : 
    4414        47467 :                     return (QTotLoad - UnitOutput) / QTotLoad;
    4415         6351 :                 };
    4416         6351 :                 SolveRoot(state, UnitFlowToler, 50, SolFlag, MassFlow, f, MinMassFlow, MaxHeatMassFlow);
    4417         6351 :                 if (SolFlag == -1) {
    4418            0 :                     if (this->IterationLimit == 0) {
    4419            0 :                         ShowWarningError(state, format("Supply air flow control failed in VS VAV terminal unit {}", this->SysName));
    4420            0 :                         ShowContinueError(state, "  Iteration limit exceeded in calculating air flow rate");
    4421              :                     }
    4422            0 :                     ShowRecurringWarningErrorAtEnd(
    4423            0 :                         state, "Supply air flow Iteration limit exceeded in VS VAV terminal unit " + this->SysName, this->IterationLimit);
    4424         6351 :                 } else if (SolFlag == -2) {
    4425            0 :                     if (this->IterationFailed == 0) {
    4426            0 :                         ShowWarningError(state, format("Supply air flow control failed in VS VAV terminal unit {}", this->SysName));
    4427            0 :                         ShowContinueError(state, "  Bad air flow limits");
    4428              :                     }
    4429            0 :                     ShowRecurringWarningErrorAtEnd(
    4430            0 :                         state, "Supply air flow control failed in VS VAV terminal unit " + this->SysName, this->IterationFailed);
    4431              :                 }
    4432         6351 :             } else {
    4433            0 :                 MassFlow = MaxHeatMassFlow;
    4434            0 :                 FanOp = 1;
    4435            0 :                 this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, MaxFlowWater, 0.0, fanType, MassFlow, FanOp, QDelivered);
    4436              :             }
    4437            0 :         } else if (HCType == HeatingCoilType::SteamAirHeating) {
    4438              :             //      IF (QTotLoad > QNoHeatFanOff + SmallLoad .AND. QTotLoad < QHeatFanOffMax - SmallLoad) THEN
    4439            0 :             if (QTotLoad < QHeatFanOffMax - SmallLoad) {
    4440            0 :                 ErrTolerance = this->ControllerOffset;
    4441            0 :                 MassFlow = MinMassFlow;
    4442            0 :                 FanOp = 0;
    4443            0 :                 auto f = [&state, this, FirstHVACIteration, ZoneNodeNum, MassFlow, fanType, FanOp, QTotLoad, MinFlowSteam, MaxFlowSteam, MaxSteamCap](
    4444              :                              Real64 const HWMassFlow) {
    4445            0 :                     Real64 UnitOutput = 0.0; // heating output [W]
    4446            0 :                     Real64 QSteamLoad = 0.0; // proportional load to calculate steam flow [W]
    4447              : 
    4448              :                     // vary the load to be met by the steam coil to converge on a steam flow rate to meet the load
    4449              :                     //   backwards way of varying steam flow rate. Steam coil calculates a flow rate to meet a load.
    4450            0 :                     if ((MaxFlowSteam - MinFlowSteam) == 0.0) {
    4451            0 :                         QSteamLoad = QTotLoad; // Use QTotLoad, bad starting value error for RegulaFalsi will occur
    4452              :                     } else {
    4453            0 :                         QSteamLoad = MaxSteamCap * HWMassFlow / (MaxFlowSteam - MinFlowSteam);
    4454              :                     }
    4455            0 :                     state.dataSingleDuct->sd_airterminal(this->SysNum)
    4456            0 :                         .CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, HWMassFlow, QSteamLoad, fanType, MassFlow, FanOp, UnitOutput);
    4457              : 
    4458            0 :                     return (QTotLoad - UnitOutput) / QTotLoad;
    4459            0 :                 };
    4460            0 :                 SolveRoot(state, ErrTolerance, 500, SolFlag, HWFlow, f, MinFlowSteam, MaxFlowSteam);
    4461            0 :                 if (SolFlag == -1) {
    4462            0 :                     ShowRecurringWarningErrorAtEnd(state, "Steam flow control failed in VS VAV terminal unit " + this->SysName, this->ErrCount1);
    4463            0 :                     ShowRecurringContinueErrorAtEnd(
    4464            0 :                         state, "...Iteration limit (500) exceeded in calculating the hot water flow rate", this->ErrCount1c);
    4465            0 :                     this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, HWFlow, 0.0, fanType, MassFlow, FanOp, QDelivered);
    4466            0 :                 } else if (SolFlag == -2) {
    4467            0 :                     ShowRecurringWarningErrorAtEnd(
    4468            0 :                         state, "Steam flow control failed (bad air flow limits) in VS VAV terminal unit " + this->SysName, this->ErrCount2);
    4469              :                 }
    4470            0 :             } else if (QTotLoad >= QHeatFanOffMax - SmallLoad && QTotLoad <= QHeatFanOnMin + SmallLoad) {
    4471            0 :                 MassFlow = MinMassFlow;
    4472            0 :                 FanOp = 0;
    4473            0 :                 this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, MaxFlowWater, 0.0, fanType, MassFlow, FanOp, QDelivered);
    4474            0 :             } else if (QTotLoad > QHeatFanOnMin + SmallLoad && QTotLoad < QHeatFanOnMax - SmallLoad) {
    4475            0 :                 FanOp = 1;
    4476              : 
    4477            0 :                 auto f = [&state, this, FirstHVACIteration, ZoneNodeNum, MaxFlowSteam, fanType, FanOp, QTotLoad](Real64 const SupplyAirMassFlow) {
    4478            0 :                     Real64 UnitOutput = 0.0; // heating output [W]
    4479              : 
    4480            0 :                     state.dataSingleDuct->sd_airterminal(this->SysNum)
    4481            0 :                         .CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, MaxFlowSteam, QTotLoad, fanType, SupplyAirMassFlow, FanOp, UnitOutput);
    4482              : 
    4483            0 :                     return (QTotLoad - UnitOutput) / QTotLoad;
    4484            0 :                 };
    4485              : 
    4486            0 :                 SolveRoot(state, UnitFlowToler, 50, SolFlag, MassFlow, f, MinMassFlow, MaxHeatMassFlow);
    4487            0 :                 if (SolFlag == -1) {
    4488            0 :                     if (this->IterationLimit == 0) {
    4489            0 :                         ShowWarningError(state, format("Steam heating coil control failed in VS VAV terminal unit {}", this->SysName));
    4490            0 :                         ShowContinueError(state, "  Iteration limit exceeded in calculating air flow rate");
    4491              :                     }
    4492            0 :                     ShowRecurringWarningErrorAtEnd(
    4493            0 :                         state, "Steam heating coil iteration limit exceeded in VS VAV terminal unit " + this->SysName, this->IterationLimit);
    4494            0 :                 } else if (SolFlag == -2) {
    4495            0 :                     if (this->IterationFailed == 0) {
    4496            0 :                         ShowWarningError(state, format("Steam heating coil control failed in VS VAV terminal unit {}", this->SysName));
    4497            0 :                         ShowContinueError(state, "  Bad air flow limits");
    4498              :                     }
    4499            0 :                     ShowRecurringWarningErrorAtEnd(
    4500            0 :                         state, "Steam heating coil control failed in VS VAV terminal unit " + this->SysName, this->IterationFailed);
    4501              :                 }
    4502            0 :             } else {
    4503            0 :                 MassFlow = MaxHeatMassFlow;
    4504            0 :                 FanOp = 1;
    4505            0 :                 this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, QTotLoad, QTotLoad, fanType, MassFlow, FanOp, QDelivered);
    4506              :             }
    4507            0 :         } else if (HCType == HeatingCoilType::Gas || HCType == HeatingCoilType::Electric) {
    4508            0 :             if (QTotLoad <= QHeatFanOnMin + SmallLoad) {
    4509              :                 // vary heating coil power, leave mass flow at minimum
    4510            0 :                 MassFlow = MinMassFlow;
    4511            0 :                 FanOp = 0;
    4512            0 :                 this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, 0.0, QTotLoad, fanType, MassFlow, FanOp, QDelivered);
    4513            0 :             } else if (QTotLoad > QHeatFanOnMin + SmallLoad && QTotLoad < QHeatFanOnMax - SmallLoad) {
    4514            0 :                 FanOp = 1;
    4515              : 
    4516            0 :                 auto f = [&state, this, FirstHVACIteration, ZoneNodeNum, fanType, FanOp, QTotLoad](Real64 const HeatingFrac) {
    4517            0 :                     Real64 MaxHeatOut{this->ReheatCoilMaxCapacity}; // maximum heating output [W]
    4518              :                     Real64 UnitOutput;                              // heating output [W]
    4519              :                     Real64 AirMassFlowRate;                         // [kg/s]
    4520              :                     Real64 HeatOut;                                 // heating coil output [W]
    4521              : 
    4522            0 :                     HeatOut = HeatingFrac * MaxHeatOut;
    4523            0 :                     AirMassFlowRate = max(HeatingFrac * state.dataSingleDuct->sd_airterminal(this->SysNum).HeatAirMassFlowRateMax,
    4524            0 :                                           state.dataSingleDuct->sd_airterminal(this->SysNum).sd_airterminalInlet.AirMassFlowRateMaxAvail *
    4525            0 :                                               state.dataSingleDuct->sd_airterminal(this->SysNum).ZoneMinAirFrac);
    4526              : 
    4527            0 :                     state.dataSingleDuct->sd_airterminal(this->SysNum)
    4528            0 :                         .CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, 0.0, HeatOut, fanType, AirMassFlowRate, FanOp, UnitOutput);
    4529              : 
    4530            0 :                     return (QTotLoad - UnitOutput) / QTotLoad;
    4531            0 :                 };
    4532              : 
    4533            0 :                 SolveRoot(state, UnitFlowToler, 50, SolFlag, FracDelivered, f, 0.0, 1.0);
    4534            0 :                 MassFlow = state.dataLoopNodes->Node(SysInletNode).MassFlowRate;
    4535            0 :                 if (SolFlag == -1) {
    4536            0 :                     if (this->IterationLimit == 0) {
    4537            0 :                         ShowWarningError(state, format("Heating coil control failed in VS VAV terminal unit {}", this->SysName));
    4538            0 :                         ShowContinueError(state, "  Iteration limit exceeded in calculating air flow rate");
    4539              :                     }
    4540            0 :                     ShowRecurringWarningErrorAtEnd(
    4541            0 :                         state, "Heating coil control iteration limit exceeded in VS VAV terminal unit " + this->SysName, this->IterationLimit);
    4542            0 :                 } else if (SolFlag == -2) {
    4543            0 :                     if (this->IterationFailed == 0) {
    4544            0 :                         ShowWarningError(state, format("Heating coil control failed in VS VAV terminal unit {}", this->SysName));
    4545            0 :                         ShowContinueError(state, "  Bad air flow limits");
    4546              :                     }
    4547            0 :                     ShowRecurringWarningErrorAtEnd(
    4548            0 :                         state, "Heating coil control failed in VS VAV terminal unit " + this->SysName, this->IterationFailed);
    4549              :                 }
    4550            0 :             } else {
    4551            0 :                 MassFlow = MaxHeatMassFlow;
    4552            0 :                 FanOp = 1;
    4553            0 :                 this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, 0.0, QTotLoad, fanType, MassFlow, FanOp, QDelivered);
    4554              :             }
    4555            0 :         } else {
    4556            0 :             ShowFatalError(state, format("Invalid Reheat Component={}", this->ReheatComp));
    4557              :         }
    4558              : 
    4559              :     } else {
    4560              : 
    4561            0 :         MassFlow = 0.0;
    4562            0 :         FanOp = 0;
    4563            0 :         this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, 0.0, 0.0, fanType, MassFlow, FanOp, QDelivered);
    4564              :     }
    4565              : 
    4566              :     // Move mass flow rates to the damper outlet node
    4567        23036 :     this->sd_airterminalOutlet.AirMassFlowRate = MassFlow;
    4568        23036 :     this->sd_airterminalOutlet.AirMassFlowRateMaxAvail = this->sd_airterminalInlet.AirMassFlowRateMaxAvail;
    4569        23036 :     this->sd_airterminalOutlet.AirMassFlowRateMinAvail = this->sd_airterminalInlet.AirMassFlowRateMinAvail;
    4570              : 
    4571              :     // calculate VAV damper Position.
    4572        23036 :     if (this->AirMassFlowRateMax == 0.0) {
    4573            0 :         this->DamperPosition = 0.0;
    4574              :     } else {
    4575        23036 :         this->DamperPosition = MassFlow / this->AirMassFlowRateMax;
    4576              :     }
    4577              :     // update the air terminal outlet node data
    4578        23036 :     this->UpdateSys(state);
    4579              : }
    4580              : 
    4581      1656582 : void SingleDuctAirTerminal::SimConstVol(EnergyPlusData &state, bool const FirstHVACIteration, int const ZoneNum, int const ZoneNodeNum)
    4582              : {
    4583              : 
    4584              :     // SUBROUTINE INFORMATION:
    4585              :     //       AUTHOR         Richard J. Liesen
    4586              :     //       DATE WRITTEN   February 2000
    4587              :     //       MODIFIED       FB/KHL/TH 2/2011: added maximum supply air temperature leaving reheat coil
    4588              : 
    4589              :     // PURPOSE OF THIS SUBROUTINE:
    4590              :     // This subroutine simulates the simple single duct constant volume systems.
    4591              : 
    4592              :     // Using/Aliasing
    4593              :     using namespace DataZoneEnergyDemands;
    4594              :     // unused   USE DataHeatBalFanSys, ONLY: Mat
    4595              :     using HeatingCoils::SimulateHeatingCoilComponents;
    4596              :     using PlantUtilities::SetActuatedBranchFlowRate;
    4597              :     using SteamCoils::SimulateSteamCoilComponents;
    4598              :     using WaterCoils::SimulateWaterCoilComponents;
    4599              : 
    4600              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    4601              :     Real64 MaxFlowWater; // This is the value passed to the Controller depending if FirstHVACIteration or not
    4602              :     Real64 MinFlowWater; // This is the value passed to the Controller depending if FirstHVACIteration or not
    4603              :     Real64 DummyMdot;    // local fluid mass flow rate
    4604              : 
    4605              :     Real64 QToHeatSetPt =
    4606      1656582 :         state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).RemainingOutputReqToHeatSP; // The calculated load from the Heat Balance
    4607      1656582 :     Real64 MassFlow = this->sd_airterminalInlet.AirMassFlowRateMaxAvail;                     // System massflow is set to the Available
    4608      1656582 :     state.dataSingleDuct->QMax2SCV = QToHeatSetPt;
    4609      1656582 :     state.dataSingleDuct->ZoneTempSCV = state.dataLoopNodes->Node(ZoneNodeNum).Temp;
    4610      1656582 :     Real64 CpAir = PsyCpAirFnW(state.dataLoopNodes->Node(ZoneNodeNum).HumRat); // zone air specific heat
    4611      1656582 :     if (this->MaxReheatTempSetByUser) {
    4612        13970 :         state.dataSingleDuct->TAirMaxSCV = this->MaxReheatTemp;
    4613        13970 :         state.dataSingleDuct->QMaxSCV = CpAir * MassFlow * (state.dataSingleDuct->TAirMaxSCV - state.dataSingleDuct->ZoneTempSCV);
    4614        13970 :         state.dataSingleDuct->QMax2SCV = min(QToHeatSetPt, state.dataSingleDuct->QMaxSCV);
    4615              :     } // if (this->MaxReheatTempSetByUser) {
    4616              : 
    4617      1656582 :     if (((this->sd_airterminalInlet.AirMassFlowRateMaxAvail == 0.0) && (this->sd_airterminalInlet.AirMassFlowRateMinAvail == 0.0)) ||
    4618      1023023 :         (this->sd_airterminalInlet.AirMassFlowRate == 0.0)) {
    4619              :         // System is Off set massflow to 0.0
    4620       633559 :         MassFlow = 0.0;
    4621              :     }
    4622              : 
    4623              :     // Calculate the Damper Position when there is a Max air flow specified.
    4624      1656582 :     if (this->AirMassFlowRateMax == 0.0) {
    4625           47 :         this->DamperPosition = 0.0;
    4626              :     } else {
    4627      1656535 :         this->DamperPosition = MassFlow / this->AirMassFlowRateMax;
    4628              :     }
    4629              : 
    4630              :     // make sure the inlet node flow rate is updated if the mass flow has been limited
    4631      1656582 :     this->sd_airterminalOutlet.AirMassFlowRate = MassFlow;
    4632      1656582 :     this->sd_airterminalOutlet.AirMassFlowRateMaxAvail = this->sd_airterminalInlet.AirMassFlowRateMaxAvail;
    4633      1656582 :     this->sd_airterminalOutlet.AirMassFlowRateMinAvail = this->sd_airterminalInlet.AirMassFlowRateMinAvail;
    4634      1656582 :     this->UpdateSys(state);
    4635              : 
    4636              :     Real64 QActualHeating =
    4637      1656582 :         QToHeatSetPt - MassFlow * CpAir * (this->sd_airterminalInlet.AirTemp - state.dataSingleDuct->ZoneTempSCV); // reheat needed
    4638              :     // Now the massflow for reheating has been determined. If it is zero, or in SetBack, or the
    4639              :     // system scheduled OFF then not operational and shut the system down.
    4640      1656582 :     if ((MassFlow > SmallMassFlow) && (QActualHeating > 0.0) && (state.dataHeatBalFanSys->TempControlType(ZoneNum) != HVAC::SetptType::SingleCool)) {
    4641              : 
    4642              :         Real64 QZnReq;
    4643              : 
    4644       487632 :         switch (this->ReheatComp_Num) {
    4645       436108 :         case HeatingCoilType::SimpleHeating: { // COIL:WATER:SIMPLEHEATING
    4646              :             // Determine the load required to pass to the Component controller
    4647       436108 :             QZnReq = state.dataSingleDuct->QMax2SCV + MassFlow * CpAir * state.dataSingleDuct->ZoneTempSCV;
    4648              : 
    4649              :             // Before Iterating through the Reheat Coil and Controller set the flags for the
    4650              :             // Do Loop to initialized conditions.
    4651              :             // Node(sd_airterminal(SysNum)%ReheatControlNode)%MassFlowRate = 0.0D0
    4652              :             // Initialize hot water flow rate to zero.
    4653       436108 :             DummyMdot = 0.0;
    4654       436108 :             SetActuatedBranchFlowRate(state, DummyMdot, this->ReheatControlNode, this->HWplantLoc, true);
    4655              : 
    4656              :             // On the first HVAC iteration the system values are given to the controller, but after that
    4657              :             // the demand limits are in place and there needs to be feedback to the Zone Equipment
    4658       436108 :             if (FirstHVACIteration) {
    4659       218354 :                 MaxFlowWater = this->MaxReheatWaterFlow;
    4660       218354 :                 MinFlowWater = this->MinReheatWaterFlow;
    4661              :             } else {
    4662       217754 :                 int WaterControlNode = this->ReheatControlNode;
    4663       217754 :                 MaxFlowWater = state.dataLoopNodes->Node(WaterControlNode).MassFlowRateMaxAvail;
    4664       217754 :                 MinFlowWater = state.dataLoopNodes->Node(WaterControlNode).MassFlowRateMinAvail;
    4665              :             }
    4666              : 
    4667              :             // Simulate reheat coil for the Const Volume system
    4668              :             // Set Converged to True & when controller is not converged it will set to False.
    4669      1744432 :             ControlCompOutput(state,
    4670       436108 :                               this->ReheatName,
    4671       436108 :                               this->ReheatComp,
    4672       436108 :                               this->ReheatComp_Index,
    4673              :                               FirstHVACIteration,
    4674              :                               QZnReq,
    4675              :                               this->ReheatControlNode,
    4676              :                               MaxFlowWater,
    4677              :                               MinFlowWater,
    4678              :                               this->ControllerOffset,
    4679       436108 :                               this->ControlCompTypeNum,
    4680       436108 :                               this->CompErrIndex,
    4681              :                               _,
    4682       436108 :                               this->ReheatAirOutletNode,
    4683              :                               MassFlow,
    4684              :                               _,
    4685              :                               _,
    4686       436108 :                               this->HWplantLoc);
    4687              : 
    4688       436108 :         } break;
    4689            0 :         case HeatingCoilType::SteamAirHeating: { // COIL:STEAM:STEAMAIRHEATING
    4690              :             // Determine the load required to pass to the Component controller
    4691            0 :             QZnReq = state.dataSingleDuct->QMax2SCV - MassFlow * CpAir * (this->sd_airterminalInlet.AirTemp - state.dataSingleDuct->ZoneTempSCV);
    4692              : 
    4693              :             // Simulate reheat coil for the VAV system
    4694            0 :             SimulateSteamCoilComponents(state, this->ReheatName, FirstHVACIteration, this->ReheatComp_Index, QZnReq);
    4695            0 :         } break;
    4696         4576 :         case HeatingCoilType::Electric: { // COIL:ELECTRIC:HEATING
    4697              :             // Determine the load required to pass to the Component controller
    4698         4576 :             QZnReq = state.dataSingleDuct->QMax2SCV - MassFlow * CpAir * (this->sd_airterminalInlet.AirTemp - state.dataSingleDuct->ZoneTempSCV);
    4699              : 
    4700              :             // Simulate reheat coil for the VAV system
    4701         4576 :             SimulateHeatingCoilComponents(state, this->ReheatName, FirstHVACIteration, QZnReq, this->ReheatComp_Index);
    4702              : 
    4703         4576 :         } break;
    4704        46948 :         case HeatingCoilType::Gas: { // COIL:GAS:HEATING
    4705              :             // Determine the load required to pass to the Component controller
    4706        46948 :             QZnReq = state.dataSingleDuct->QMax2SCV - MassFlow * CpAir * (this->sd_airterminalInlet.AirTemp - state.dataSingleDuct->ZoneTempSCV);
    4707              : 
    4708              :             // Simulate reheat coil for the VAV system
    4709        46948 :             SimulateHeatingCoilComponents(state, this->ReheatName, FirstHVACIteration, QZnReq, this->ReheatComp_Index);
    4710        46948 :         } break;
    4711            0 :         default: {
    4712            0 :             ShowFatalError(state, format("Invalid Reheat Component={}", this->ReheatComp));
    4713            0 :         } break;
    4714              :         }
    4715              : 
    4716              :         // the COIL is OFF the properties are calculated for this special case.
    4717              :     } else {
    4718      1168950 :         switch (this->ReheatComp_Num) {
    4719       945001 :         case HeatingCoilType::SimpleHeating: { // COIL:WATER:SIMPLEHEATING
    4720              :             // Simulate reheat coil for the Const Volume system
    4721              :             // Node(sd_airterminal(SysNum)%ReheatControlNode)%MassFlowRate = 0.0D0
    4722              :             // Initialize hot water flow rate to zero.
    4723       945001 :             DummyMdot = 0.0;
    4724       945001 :             SetActuatedBranchFlowRate(state, DummyMdot, this->ReheatControlNode, this->HWplantLoc, true);
    4725              : 
    4726              :             // call the reheat coil with the NO FLOW condition to make sure that the Node values
    4727              :             // are passed through to the coil outlet correctly
    4728       945001 :             SimulateWaterCoilComponents(state, this->ReheatName, FirstHVACIteration, this->ReheatComp_Index);
    4729       945001 :         } break;
    4730            0 :         case HeatingCoilType::SteamAirHeating: { // COIL:STEAM:AIRHEATING
    4731              :             // Simulate reheat coil for the Const Volume system
    4732            0 :             SimulateSteamCoilComponents(state, this->ReheatName, FirstHVACIteration, this->ReheatComp_Index, 0.0);
    4733            0 :         } break;
    4734        19886 :         case HeatingCoilType::Electric: { // COIL:ELECTRIC:HEATING
    4735              :             // Simulate reheat coil for the Const Volume system
    4736        19886 :             SimulateHeatingCoilComponents(state, this->ReheatName, FirstHVACIteration, 0.0, this->ReheatComp_Index);
    4737        19886 :         } break;
    4738       204063 :         case HeatingCoilType::Gas: { // COIL:GAS:HEATING
    4739              :             // Simulate reheat coil for the Const Volume system
    4740       204063 :             SimulateHeatingCoilComponents(state, this->ReheatName, FirstHVACIteration, 0.0, this->ReheatComp_Index);
    4741       204063 :         } break;
    4742            0 :         default: {
    4743            0 :             ShowFatalError(state, format("Invalid Reheat Component={}", this->ReheatComp));
    4744            0 :         } break;
    4745              :         }
    4746              :     }
    4747      1656582 : }
    4748              : 
    4749      8544703 : void SingleDuctAirTerminal::SimConstVolNoReheat(EnergyPlusData &state)
    4750              : {
    4751              : 
    4752              :     // PURPOSE OF THIS SUBROUTINE:
    4753              :     // Sets outlet flow rate and conditions for singleduct constantvolume with no reheat air terminal.
    4754              : 
    4755      8544703 :     this->sd_airterminalOutlet = this->sd_airterminalInlet;
    4756              : 
    4757              :     // update the air terminal outlet node data
    4758      8544703 :     this->UpdateSys(state);
    4759      8544703 : }
    4760              : 
    4761       359460 : void SingleDuctAirTerminal::CalcVAVVS(EnergyPlusData &state,
    4762              :                                       bool const FirstHVACIteration,          // flag for 1st HVAV iteration in the time step
    4763              :                                       int const ZoneNode,                     // zone node number
    4764              :                                       Real64 const HWFlow,                    // hot water flow (kg/s)
    4765              :                                       Real64 const HCoilReq,                  // gas or elec coil demand requested
    4766              :                                       [[maybe_unused]] HVAC::FanType fanType, // type of fan
    4767              :                                       Real64 const AirFlow,                   // air flow rate (kg/s)
    4768              :                                       int const FanOn,                        // 1 means fan is on
    4769              :                                       Real64 &LoadMet                         // load met by unit (watts)
    4770              : )
    4771              : {
    4772              : 
    4773              :     // SUBROUTINE INFORMATION:
    4774              :     //       AUTHOR         Fred Buhl
    4775              :     //       DATE WRITTEN   July 2004
    4776              : 
    4777              :     // PURPOSE OF THIS SUBROUTINE:
    4778              :     // Simulate the components making up the VAV terminal unit with variable speed fan.
    4779              : 
    4780              :     // METHODOLOGY EMPLOYED:
    4781              :     // Simulates the unit components sequentially in the air flow direction.
    4782              : 
    4783              :     // Using/Aliasing
    4784              :     using HeatingCoils::SimulateHeatingCoilComponents;
    4785              :     using PlantUtilities::SetComponentFlowRate;
    4786              :     using SteamCoils::SimulateSteamCoilComponents;
    4787              :     using WaterCoils::SimulateWaterCoilComponents;
    4788              : 
    4789              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    4790              :     int FanInNode;       // unit air inlet node (fan inlet)
    4791              :     int FanOutNode;      // fan outlet node (heating coil inlet node)
    4792              :     int HCOutNode;       // unit air outlet node (heating coil air outlet node)
    4793              :     int HotControlNode;  // the hot water inlet node
    4794              :     Real64 AirMassFlow;  // total air mass flow rate [kg/s]
    4795              :     Real64 CpAirZn;      // zone air specific heat [J/kg-C]
    4796              :     bool TurnFansOffSav; // save the fan off flag
    4797              :     Real64 mdot;
    4798              : 
    4799       359460 :     TurnFansOffSav = state.dataHVACGlobal->TurnFansOff;
    4800       359460 :     FanInNode = this->InletNodeNum;
    4801       359460 :     FanOutNode = this->OutletNodeNum;
    4802       359460 :     HCOutNode = this->ReheatAirOutletNode;
    4803       359460 :     HotControlNode = this->ReheatControlNode;
    4804       359460 :     AirMassFlow = AirFlow;
    4805       359460 :     state.dataLoopNodes->Node(FanInNode).MassFlowRate = AirMassFlow;
    4806       359460 :     CpAirZn = PsyCpAirFnW(state.dataLoopNodes->Node(ZoneNode).HumRat);
    4807       359460 :     if (FanOn == 1) {
    4808       184677 :         state.dataFans->fans(this->Fan_Index)->simulate(state, FirstHVACIteration, _, _);
    4809              : 
    4810              :     } else { // pass through conditions
    4811       174783 :         state.dataHVACGlobal->TurnFansOff = true;
    4812       174783 :         state.dataFans->fans(this->Fan_Index)->simulate(state, FirstHVACIteration, _, _);
    4813       174783 :         state.dataHVACGlobal->TurnFansOff = TurnFansOffSav;
    4814       174783 :         state.dataLoopNodes->Node(FanOutNode).MassFlowRate = state.dataLoopNodes->Node(FanInNode).MassFlowRate;
    4815       174783 :         state.dataLoopNodes->Node(FanOutNode).MassFlowRateMaxAvail = state.dataLoopNodes->Node(FanInNode).MassFlowRateMaxAvail;
    4816       174783 :         state.dataLoopNodes->Node(FanOutNode).MassFlowRateMinAvail = state.dataLoopNodes->Node(FanInNode).MassFlowRateMinAvail;
    4817              :     }
    4818       359460 :     switch (this->ReheatComp_Num) {
    4819       359460 :     case HeatingCoilType::SimpleHeating: { // COIL:WATER:SIMPLEHEATING
    4820       359460 :         mdot = HWFlow;
    4821       359460 :         if (this->HWplantLoc.loopNum > 0) {
    4822       359460 :             SetComponentFlowRate(state, mdot, this->ReheatControlNode, this->ReheatCoilOutletNode, this->HWplantLoc);
    4823              :         }
    4824              : 
    4825       359460 :         SimulateWaterCoilComponents(state, this->ReheatName, FirstHVACIteration, this->ReheatComp_Index);
    4826       359460 :     } break;
    4827            0 :     case HeatingCoilType::SteamAirHeating: { // HW Flow is steam mass flow here
    4828            0 :         mdot = HWFlow;
    4829            0 :         if (this->HWplantLoc.loopNum > 0) {
    4830            0 :             SetComponentFlowRate(state, mdot, this->ReheatControlNode, this->ReheatCoilOutletNode, this->HWplantLoc);
    4831              :         }
    4832            0 :         SimulateSteamCoilComponents(state, this->ReheatName, FirstHVACIteration, this->ReheatComp_Index, HCoilReq);
    4833            0 :     } break;
    4834            0 :     case HeatingCoilType::Electric: { // COIL:ELECTRIC:HEATING
    4835            0 :         SimulateHeatingCoilComponents(state, this->ReheatName, FirstHVACIteration, HCoilReq, this->ReheatComp_Index);
    4836            0 :     } break;
    4837            0 :     case HeatingCoilType::Gas: { // COIL:GAS:HEATING
    4838            0 :         SimulateHeatingCoilComponents(state, this->ReheatName, FirstHVACIteration, HCoilReq, this->ReheatComp_Index);
    4839            0 :     } break;
    4840            0 :     default: {
    4841            0 :         ShowFatalError(state, format("Invalid Reheat Component={}", this->ReheatComp));
    4842            0 :     } break;
    4843              :     }
    4844              : 
    4845       359460 :     LoadMet = AirMassFlow * CpAirZn * (state.dataLoopNodes->Node(HCOutNode).Temp - state.dataLoopNodes->Node(ZoneNode).Temp);
    4846       359460 : }
    4847              : 
    4848              : // End Algorithm Section of the Module
    4849              : // *****************************************************************************
    4850              : 
    4851              : // Beginning of Update subroutines for the Sys Module
    4852              : // *****************************************************************************
    4853              : 
    4854     50990459 : void SingleDuctAirTerminal::UpdateSys(EnergyPlusData &state) const
    4855              : {
    4856              : 
    4857              :     // SUBROUTINE INFORMATION:
    4858              :     //       AUTHOR         Richard J. Liesen
    4859              :     //       DATE WRITTEN   january 2000
    4860              : 
    4861              :     // PURPOSE OF THIS SUBROUTINE:
    4862              :     // This subroutine updates the Syss.
    4863              : 
    4864     50990459 :     int OutletNode = this->OutletNodeNum;
    4865     50990459 :     int InletNode = this->InletNodeNum;
    4866              : 
    4867     50990459 :     if (this->SysType_Num == SysType::SingleDuctVAVReheat || this->SysType_Num == SysType::SingleDuctCBVAVReheat ||
    4868     13433816 :         this->SysType_Num == SysType::SingleDuctCBVAVNoReheat || this->SysType_Num == SysType::SingleDuctVAVNoReheat ||
    4869     10224321 :         this->SysType_Num == SysType::SingleDuctConstVolNoReheat) {
    4870              :         // Set the outlet air nodes of the Sys
    4871     49310841 :         state.dataLoopNodes->Node(OutletNode).MassFlowRate = this->sd_airterminalOutlet.AirMassFlowRate;
    4872     49310841 :         state.dataLoopNodes->Node(OutletNode).Temp = this->sd_airterminalOutlet.AirTemp;
    4873     49310841 :         state.dataLoopNodes->Node(OutletNode).HumRat = this->sd_airterminalOutlet.AirHumRat;
    4874     49310841 :         state.dataLoopNodes->Node(OutletNode).Enthalpy = this->sd_airterminalOutlet.AirEnthalpy;
    4875              :         // Set the outlet nodes for properties that just pass through & not used
    4876     49310841 :         state.dataLoopNodes->Node(OutletNode).Quality = state.dataLoopNodes->Node(InletNode).Quality;
    4877     49310841 :         state.dataLoopNodes->Node(OutletNode).Press = state.dataLoopNodes->Node(InletNode).Press;
    4878              :     }
    4879              : 
    4880              :     // After all of the Outlets are updated the mass flow information needs to be
    4881              :     // passed back to the system inlet.
    4882     50990459 :     state.dataLoopNodes->Node(InletNode).MassFlowRate = this->sd_airterminalOutlet.AirMassFlowRate;
    4883     50990459 :     state.dataLoopNodes->Node(OutletNode).MassFlowRateMaxAvail =
    4884     50990459 :         min(this->sd_airterminalOutlet.AirMassFlowRateMaxAvail, state.dataLoopNodes->Node(OutletNode).MassFlowRateMax);
    4885     50990459 :     state.dataLoopNodes->Node(OutletNode).MassFlowRateMinAvail = this->sd_airterminalOutlet.AirMassFlowRateMinAvail;
    4886              : 
    4887     50990459 :     if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    4888        98625 :         state.dataLoopNodes->Node(OutletNode).CO2 = state.dataLoopNodes->Node(InletNode).CO2;
    4889              :     }
    4890              : 
    4891     50990459 :     if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    4892        34833 :         state.dataLoopNodes->Node(OutletNode).GenContam = state.dataLoopNodes->Node(InletNode).GenContam;
    4893              :     }
    4894     50990459 : }
    4895              : 
    4896              : //        End of Update subroutines for the Sys Module
    4897              : // *****************************************************************************
    4898              : 
    4899              : // Beginning of Reporting subroutines for the Sys Module
    4900              : // *****************************************************************************
    4901              : 
    4902     37322114 : void SingleDuctAirTerminal::ReportSys(EnergyPlusData &state) // unused1208
    4903              : {
    4904              : 
    4905              :     // set zone OA volume flow rate
    4906     37322114 :     this->CalcOutdoorAirVolumeFlowRate(state);
    4907     37322114 : }
    4908              : 
    4909          111 : void GetHVACSingleDuctSysIndex(EnergyPlusData &state,
    4910              :                                std::string const &SDSName,
    4911              :                                int &SDSIndex,
    4912              :                                bool &ErrorsFound,
    4913              :                                std::string_view const ThisObjectType,
    4914              :                                ObjexxFCL::Optional_int DamperInletNode, // Damper inlet node number
    4915              :                                ObjexxFCL::Optional_int DamperOutletNode // Damper outlet node number
    4916              : )
    4917              : {
    4918              : 
    4919              :     // SUBROUTINE INFORMATION:
    4920              :     //       AUTHOR         Lixing Gu
    4921              :     //       DATE WRITTEN   February 2006
    4922              : 
    4923              :     // PURPOSE OF THIS SUBROUTINE:
    4924              :     // This subroutine sets an index for a given single duct system -- issues error message if that system
    4925              :     // is not a legal system.
    4926              : 
    4927          111 :     if (state.dataSingleDuct->GetInputFlag) { // First time subroutine has been entered
    4928            0 :         GetSysInput(state);
    4929            0 :         state.dataSingleDuct->GetInputFlag = false;
    4930              :     }
    4931              : 
    4932          111 :     SDSIndex = Util::FindItemInList(SDSName, state.dataSingleDuct->sd_airterminal, &SingleDuctAirTerminal::SysName);
    4933          111 :     if (SDSIndex == 0) {
    4934            0 :         if (!ThisObjectType.empty()) {
    4935            0 :             ShowSevereError(state, fmt::format("{}, GetHVACSingleDuctSysIndex: Single duct system not found={}", ThisObjectType, SDSName));
    4936              :         } else {
    4937            0 :             ShowSevereError(state, format("GetHVACSingleDuctSysIndex: Single duct system not found={}", SDSName));
    4938              :         }
    4939            0 :         ErrorsFound = true;
    4940              :     } else {
    4941          201 :         if ((state.dataSingleDuct->sd_airterminal(SDSIndex).SysType_Num != SysType::SingleDuctConstVolReheat) &&
    4942           90 :             (state.dataSingleDuct->sd_airterminal(SDSIndex).SysType_Num != SysType::SingleDuctVAVReheat)) {
    4943            0 :             if (!ThisObjectType.empty()) {
    4944            0 :                 ShowSevereError(state, fmt::format("{}, GetHVACSingleDuctSysIndex: Could not find allowed types={}", ThisObjectType, SDSName));
    4945              :             } else {
    4946            0 :                 ShowSevereError(state, format("GetHVACSingleDuctSysIndex: Could not find allowed types={}", SDSName));
    4947              :             }
    4948            0 :             ShowContinueError(state, "The allowed types are: AirTerminal:SingleDuct:ConstantVolume:Reheat and AirTerminal:SingleDuct:VAV:Reheat");
    4949            0 :             ErrorsFound = true;
    4950              :         }
    4951          111 :         if (state.dataSingleDuct->sd_airterminal(SDSIndex).SysType_Num == SysType::SingleDuctVAVReheat) {
    4952           90 :             if (present(DamperInletNode)) {
    4953           90 :                 DamperInletNode = state.dataSingleDuct->sd_airterminal(SDSIndex).InletNodeNum;
    4954              :             }
    4955           90 :             if (present(DamperOutletNode)) {
    4956           90 :                 DamperOutletNode = state.dataSingleDuct->sd_airterminal(SDSIndex).OutletNodeNum;
    4957              :             }
    4958              :         }
    4959              :     }
    4960          111 : }
    4961              : 
    4962      1862128 : void SimATMixer(EnergyPlusData &state, std::string const &SysName, bool const FirstHVACIteration, int &SysIndex)
    4963              : {
    4964              : 
    4965              :     // SUBROUTINE INFORMATION:
    4966              :     //       DATE WRITTEN   March 2012
    4967              : 
    4968              :     // PURPOSE OF THIS SUBROUTINE
    4969              :     // Simulate an Air Terminal Mixer component
    4970              : 
    4971      1862128 :     if (state.dataSingleDuct->GetATMixerFlag) {
    4972            0 :         state.dataSingleDuct->GetATMixerFlag = false;
    4973              :     }
    4974              : 
    4975      1862128 :     if (SysIndex == 0) {
    4976            0 :         state.dataSingleDuct->SysNumSATM = Util::FindItemInList(SysName, state.dataSingleDuct->SysATMixer);
    4977            0 :         SysIndex = state.dataSingleDuct->SysNumSATM;
    4978            0 :         if (state.dataSingleDuct->SysNumSATM == 0) {
    4979            0 :             ShowFatalError(state, format("Object {} not found", SysName));
    4980              :         }
    4981              :     } else {
    4982      1862128 :         state.dataSingleDuct->SysNumSATM = SysIndex;
    4983              :     }
    4984              : 
    4985      1862128 :     state.dataSingleDuct->SysATMixer(state.dataSingleDuct->SysNumSATM).InitATMixer(state, FirstHVACIteration);
    4986              : 
    4987      1862128 :     CalcATMixer(state, state.dataSingleDuct->SysNumSATM);
    4988              : 
    4989      1862128 :     UpdateATMixer(state, state.dataSingleDuct->SysNumSATM);
    4990      1862128 : }
    4991              : 
    4992       235659 : void GetATMixers(EnergyPlusData &state)
    4993              : {
    4994              : 
    4995              :     // SUBROUTINE INFORMATION:
    4996              :     //       DATE WRITTEN   March 2012
    4997              : 
    4998              :     // PURPOSE OF THIS SUBROUTINE
    4999              :     // Get input for inlet side air terminal mixers and store it in the inlet side air terminal mixer array
    5000              : 
    5001              :     // METHODOLOGY EMPLOYED:
    5002              :     // Use the Get routines from the InputProcessor module.
    5003              : 
    5004              :     // Using/Aliasing
    5005              :     using DataZoneEquipment::EquipmentData;
    5006              :     using DataZoneEquipment::SubEquipmentData;
    5007              :     using NodeInputManager::GetOnlySingleNode;
    5008              :     using namespace DataLoopNode;
    5009              :     using BranchNodeConnections::TestCompSet;
    5010              : 
    5011              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    5012              :     int NumNums;    // Number of REAL(r64) numbers returned by GetObjectItem
    5013              :     int NumAlphas;  // Number of alphanumerics returned by GetObjectItem
    5014              :     int ATMixerNum; // Index of inlet side mixer air terminal unit
    5015              :     int IOStat;
    5016              :     static constexpr std::string_view RoutineName("GetATMixers: "); // include trailing blank space
    5017       235659 :     bool ErrorsFound(false);                                        // Error flag
    5018              :     int NodeNum;                                                    // Index to node number
    5019              :     int CtrlZone;                                                   // Index to control zone
    5020              :     bool ZoneNodeNotFound;                                          // Flag for error checking
    5021              :     bool errFlag;                                                   // error flag from component validation
    5022              : 
    5023       235659 :     if (!state.dataSingleDuct->GetATMixerFlag) {
    5024       235456 :         return;
    5025              :     }
    5026          203 :     state.dataSingleDuct->GetATMixerFlag = false;
    5027              : 
    5028          203 :     auto &ipsc = state.dataIPShortCut;
    5029              : 
    5030          203 :     auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    5031          203 :     cCurrentModuleObject = "AirTerminal:SingleDuct:Mixer";
    5032          203 :     state.dataSingleDuct->NumATMixers = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    5033          203 :     state.dataSingleDuct->SysATMixer.allocate(state.dataSingleDuct->NumATMixers);
    5034              : 
    5035              :     // make sure the input data is read in only once
    5036          203 :     if (state.dataZoneAirLoopEquipmentManager->GetAirDistUnitsFlag) {
    5037              :         // Need air distribution units first
    5038           43 :         ZoneAirLoopEquipmentManager::GetZoneAirLoopEquipment(state);
    5039           43 :         state.dataZoneAirLoopEquipmentManager->GetAirDistUnitsFlag = false;
    5040              :     }
    5041              : 
    5042          262 :     for (ATMixerNum = 1; ATMixerNum <= state.dataSingleDuct->NumATMixers; ++ATMixerNum) {
    5043          118 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
    5044              :                                                                  cCurrentModuleObject,
    5045              :                                                                  ATMixerNum,
    5046           59 :                                                                  state.dataIPShortCut->cAlphaArgs,
    5047              :                                                                  NumAlphas,
    5048           59 :                                                                  state.dataIPShortCut->rNumericArgs,
    5049              :                                                                  NumNums,
    5050              :                                                                  IOStat,
    5051           59 :                                                                  state.dataIPShortCut->lNumericFieldBlanks,
    5052           59 :                                                                  state.dataIPShortCut->lAlphaFieldBlanks,
    5053           59 :                                                                  state.dataIPShortCut->cAlphaFieldNames,
    5054           59 :                                                                  state.dataIPShortCut->cNumericFieldNames);
    5055              : 
    5056           59 :         auto &atMixer = state.dataSingleDuct->SysATMixer(ATMixerNum);
    5057           59 :         Util::IsNameEmpty(state, state.dataIPShortCut->cAlphaArgs(1), cCurrentModuleObject, ErrorsFound);
    5058           59 :         state.dataSingleDuct->SysATMixer(ATMixerNum).Name = state.dataIPShortCut->cAlphaArgs(1);
    5059              : 
    5060           59 :         atMixer.type = static_cast<HVAC::MixerType>(getEnumValue(HVAC::mixerTypeLocNamesUC, ipsc->cAlphaArgs(7)));
    5061              : 
    5062           59 :         if (state.dataIPShortCut->cAlphaArgs(2) == "ZONEHVAC:WATERTOAIRHEATPUMP") {
    5063           15 :             state.dataSingleDuct->SysATMixer(ATMixerNum).ZoneHVACUnitType = 1;
    5064           44 :         } else if (state.dataIPShortCut->cAlphaArgs(2) == "ZONEHVAC:FOURPIPEFANCOIL") {
    5065           10 :             state.dataSingleDuct->SysATMixer(ATMixerNum).ZoneHVACUnitType = 2;
    5066           34 :         } else if (state.dataIPShortCut->cAlphaArgs(2) == "ZONEHVAC:PACKAGEDTERMINALAIRCONDITIONER") {
    5067            9 :             state.dataSingleDuct->SysATMixer(ATMixerNum).ZoneHVACUnitType = 3;
    5068           25 :         } else if (state.dataIPShortCut->cAlphaArgs(2) == "ZONEHVAC:PACKAGEDTERMINALHEATPUMP") {
    5069            5 :             state.dataSingleDuct->SysATMixer(ATMixerNum).ZoneHVACUnitType = 4;
    5070           20 :         } else if (state.dataIPShortCut->cAlphaArgs(2) == "ZONEHVAC:VARIABLEREFRIGERANTFLOW") {
    5071            0 :             state.dataSingleDuct->SysATMixer(ATMixerNum).ZoneHVACUnitType = 5;
    5072           20 :         } else if (state.dataIPShortCut->cAlphaArgs(2) == "AIRLOOPHVAC:UNITARYSYSTEM") {
    5073            5 :             state.dataSingleDuct->SysATMixer(ATMixerNum).ZoneHVACUnitType = 6;
    5074           15 :         } else if (state.dataIPShortCut->cAlphaArgs(2) == "ZONEHVAC:UNITVENTILATOR") {
    5075            5 :             state.dataSingleDuct->SysATMixer(ATMixerNum).ZoneHVACUnitType = 7;
    5076              :         }
    5077              : 
    5078           59 :         state.dataSingleDuct->SysATMixer(ATMixerNum).ZoneHVACUnitName = state.dataIPShortCut->cAlphaArgs(3);
    5079              : 
    5080          118 :         ValidateComponent(
    5081           59 :             state, state.dataIPShortCut->cAlphaArgs(2), state.dataSingleDuct->SysATMixer(ATMixerNum).ZoneHVACUnitName, errFlag, cCurrentModuleObject);
    5082              : 
    5083           59 :         state.dataSingleDuct->SysATMixer(ATMixerNum).MixedAirOutNode =
    5084           59 :             GetOnlySingleNode(state,
    5085           59 :                               state.dataIPShortCut->cAlphaArgs(4),
    5086              :                               ErrorsFound,
    5087              :                               DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctMixer,
    5088           59 :                               state.dataIPShortCut->cAlphaArgs(1),
    5089              :                               DataLoopNode::NodeFluidType::Air,
    5090              :                               DataLoopNode::ConnectionType::Outlet,
    5091              :                               NodeInputManager::CompFluidStream::Primary,
    5092              :                               ObjectIsNotParent,
    5093           59 :                               state.dataIPShortCut->cAlphaFieldNames(4));
    5094              : 
    5095           59 :         state.dataSingleDuct->SysATMixer(ATMixerNum).PriInNode = GetOnlySingleNode(state,
    5096           59 :                                                                                    state.dataIPShortCut->cAlphaArgs(5),
    5097              :                                                                                    ErrorsFound,
    5098              :                                                                                    DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctMixer,
    5099           59 :                                                                                    state.dataIPShortCut->cAlphaArgs(1),
    5100              :                                                                                    DataLoopNode::NodeFluidType::Air,
    5101              :                                                                                    DataLoopNode::ConnectionType::Inlet,
    5102              :                                                                                    NodeInputManager::CompFluidStream::Primary,
    5103              :                                                                                    ObjectIsNotParent,
    5104           59 :                                                                                    state.dataIPShortCut->cAlphaFieldNames(5));
    5105           59 :         state.dataSingleDuct->SysATMixer(ATMixerNum).SecInNode = GetOnlySingleNode(state,
    5106           59 :                                                                                    state.dataIPShortCut->cAlphaArgs(6),
    5107              :                                                                                    ErrorsFound,
    5108              :                                                                                    DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctMixer,
    5109           59 :                                                                                    state.dataIPShortCut->cAlphaArgs(1),
    5110              :                                                                                    DataLoopNode::NodeFluidType::Air,
    5111              :                                                                                    DataLoopNode::ConnectionType::Inlet,
    5112              :                                                                                    NodeInputManager::CompFluidStream::Primary,
    5113              :                                                                                    ObjectIsNotParent,
    5114           59 :                                                                                    state.dataIPShortCut->cAlphaFieldNames(6));
    5115              : 
    5116           59 :         if (state.dataIPShortCut->lAlphaFieldBlanks(8)) {
    5117           40 :             state.dataSingleDuct->SysATMixer(ATMixerNum).NoOAFlowInputFromUser = true;
    5118              :         } else {
    5119           19 :             state.dataSingleDuct->SysATMixer(ATMixerNum).OARequirementsPtr =
    5120           19 :                 Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(8), state.dataSize->OARequirements);
    5121           19 :             if (state.dataSingleDuct->SysATMixer(ATMixerNum).OARequirementsPtr == 0) {
    5122            0 :                 ShowSevereError(state, format("{}{}=\"{}\", invalid data.", RoutineName, cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
    5123            0 :                 ShowContinueError(state,
    5124            0 :                                   format("..invalid {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(8), state.dataIPShortCut->cAlphaArgs(8)));
    5125            0 :                 ErrorsFound = true;
    5126              :             } else {
    5127           19 :                 state.dataSingleDuct->SysATMixer(ATMixerNum).NoOAFlowInputFromUser = false;
    5128              :             }
    5129              :         }
    5130              : 
    5131           59 :         if (state.dataIPShortCut->lAlphaFieldBlanks(9)) {
    5132           50 :             state.dataSingleDuct->SysATMixer(ATMixerNum).OAPerPersonMode = DataZoneEquipment::PerPersonVentRateMode::DCVByCurrentLevel;
    5133              :         } else {
    5134            9 :             if (state.dataIPShortCut->cAlphaArgs(9) == "CURRENTOCCUPANCY") {
    5135            9 :                 state.dataSingleDuct->SysATMixer(ATMixerNum).OAPerPersonMode = DataZoneEquipment::PerPersonVentRateMode::DCVByCurrentLevel;
    5136            0 :             } else if (state.dataIPShortCut->cAlphaArgs(9) == "DESIGNOCCUPANCY") {
    5137            0 :                 state.dataSingleDuct->SysATMixer(ATMixerNum).OAPerPersonMode = DataZoneEquipment::PerPersonVentRateMode::ByDesignLevel;
    5138              :             } else {
    5139            0 :                 state.dataSingleDuct->SysATMixer(ATMixerNum).OAPerPersonMode = DataZoneEquipment::PerPersonVentRateMode::DCVByCurrentLevel;
    5140            0 :                 ShowWarningError(state, format("{}{}=\"{}\", invalid data.", RoutineName, cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
    5141            0 :                 ShowContinueError(state,
    5142            0 :                                   format("..invalid {}=\"{}\". The default input of CurrentOccupancy is assigned",
    5143            0 :                                          state.dataIPShortCut->cAlphaFieldNames(9),
    5144            0 :                                          state.dataIPShortCut->cAlphaArgs(9)));
    5145              :             }
    5146              :         }
    5147              : 
    5148              :         // Check for dupes in the three nodes.
    5149           59 :         if (state.dataSingleDuct->SysATMixer(ATMixerNum).SecInNode == state.dataSingleDuct->SysATMixer(ATMixerNum).PriInNode) {
    5150            0 :             ShowSevereError(state,
    5151            0 :                             format("{} = {} {} = {} duplicates the {}.",
    5152              :                                    cCurrentModuleObject,
    5153            0 :                                    state.dataSingleDuct->SysATMixer(ATMixerNum).Name,
    5154            0 :                                    state.dataIPShortCut->cAlphaArgs(5),
    5155            0 :                                    state.dataLoopNodes->NodeID(state.dataSingleDuct->SysATMixer(ATMixerNum).PriInNode),
    5156            0 :                                    state.dataIPShortCut->cAlphaArgs(4)));
    5157            0 :             ErrorsFound = true;
    5158           59 :         } else if (state.dataSingleDuct->SysATMixer(ATMixerNum).SecInNode == state.dataSingleDuct->SysATMixer(ATMixerNum).MixedAirOutNode) {
    5159            0 :             ShowSevereError(state,
    5160            0 :                             format("{} = {} {} = {} duplicates the {}.",
    5161              :                                    cCurrentModuleObject,
    5162            0 :                                    state.dataSingleDuct->SysATMixer(ATMixerNum).Name,
    5163            0 :                                    state.dataIPShortCut->cAlphaArgs(6),
    5164            0 :                                    state.dataLoopNodes->NodeID(state.dataSingleDuct->SysATMixer(ATMixerNum).MixedAirOutNode),
    5165            0 :                                    state.dataIPShortCut->cAlphaArgs(4)));
    5166            0 :             ErrorsFound = true;
    5167              :         }
    5168              : 
    5169           59 :         if (state.dataSingleDuct->SysATMixer(ATMixerNum).PriInNode == state.dataSingleDuct->SysATMixer(ATMixerNum).MixedAirOutNode) {
    5170            0 :             ShowSevereError(state,
    5171            0 :                             format("{} = {} {} = {} duplicates the {}.",
    5172              :                                    cCurrentModuleObject,
    5173            0 :                                    state.dataSingleDuct->SysATMixer(ATMixerNum).Name,
    5174            0 :                                    state.dataIPShortCut->cAlphaArgs(6),
    5175            0 :                                    state.dataLoopNodes->NodeID(state.dataSingleDuct->SysATMixer(ATMixerNum).MixedAirOutNode),
    5176            0 :                                    state.dataIPShortCut->cAlphaArgs(5)));
    5177            0 :             ErrorsFound = true;
    5178              :         }
    5179              : 
    5180          178 :         for (int ADUNum = 1; ADUNum <= (int)state.dataDefineEquipment->AirDistUnit.size(); ++ADUNum) {
    5181          178 :             if (state.dataSingleDuct->SysATMixer(ATMixerNum).MixedAirOutNode == state.dataDefineEquipment->AirDistUnit(ADUNum).OutletNodeNum) {
    5182           59 :                 state.dataDefineEquipment->AirDistUnit(ADUNum).InletNodeNum = state.dataSingleDuct->SysATMixer(ATMixerNum).PriInNode;
    5183           59 :                 state.dataSingleDuct->SysATMixer(ATMixerNum).ADUNum = ADUNum;
    5184           59 :                 break;
    5185              :             }
    5186              :         }
    5187              :         // one assumes if there isn't one assigned, it's an error?
    5188           59 :         if (state.dataSingleDuct->SysATMixer(ATMixerNum).ADUNum == 0) {
    5189            0 :             ShowSevereError(state,
    5190            0 :                             format("{}No matching Air Distribution Unit, for System = [{},{}].",
    5191              :                                    RoutineName,
    5192              :                                    cCurrentModuleObject,
    5193            0 :                                    state.dataSingleDuct->SysATMixer(ATMixerNum).Name));
    5194            0 :             ShowContinueError(
    5195              :                 state,
    5196            0 :                 format("...should have outlet node = {}", state.dataLoopNodes->NodeID(state.dataSingleDuct->SysATMixer(ATMixerNum).MixedAirOutNode)));
    5197            0 :             ErrorsFound = true;
    5198              :         } else {
    5199              : 
    5200           59 :             if (state.dataSingleDuct->SysATMixer(ATMixerNum).type == HVAC::MixerType::InletSide) {
    5201              :                 // Air Terminal inlet node must be the same as a zone exhaust node
    5202           35 :                 ZoneNodeNotFound = true;
    5203          123 :                 for (CtrlZone = 1; CtrlZone <= state.dataGlobal->NumOfZones; ++CtrlZone) {
    5204          122 :                     if (!state.dataZoneEquip->ZoneEquipConfig(CtrlZone).IsControlled) {
    5205           35 :                         continue;
    5206              :                     }
    5207          137 :                     for (NodeNum = 1; NodeNum <= state.dataZoneEquip->ZoneEquipConfig(CtrlZone).NumExhaustNodes; ++NodeNum) {
    5208           84 :                         if (state.dataSingleDuct->SysATMixer(ATMixerNum).SecInNode ==
    5209           84 :                             state.dataZoneEquip->ZoneEquipConfig(CtrlZone).ExhaustNode(NodeNum)) {
    5210           34 :                             ZoneNodeNotFound = false;
    5211           34 :                             state.dataDefineEquipment->AirDistUnit(state.dataSingleDuct->SysATMixer(ATMixerNum).ADUNum).ZoneEqNum = CtrlZone;
    5212           34 :                             state.dataSingleDuct->SysATMixer(ATMixerNum).ZoneNum = CtrlZone;
    5213              :                             // Must wait until InitATMixer to fill other zone equip config data because ultimate zone inlet node is not known yet
    5214              :                             // for inlet side mixers
    5215           34 :                             if (!state.dataSingleDuct->SysATMixer(ATMixerNum).NoOAFlowInputFromUser) {
    5216           10 :                                 bool UseOccSchFlag = false;
    5217           10 :                                 bool UseMinOASchFlag = false;
    5218           10 :                                 state.dataSingleDuct->SysATMixer(ATMixerNum).DesignPrimaryAirVolRate =
    5219           10 :                                     DataSizing::calcDesignSpecificationOutdoorAir(state,
    5220           10 :                                                                                   state.dataSingleDuct->SysATMixer(ATMixerNum).OARequirementsPtr,
    5221           10 :                                                                                   state.dataSingleDuct->SysATMixer(ATMixerNum).ZoneNum,
    5222              :                                                                                   UseOccSchFlag,
    5223              :                                                                                   UseMinOASchFlag);
    5224              :                             }
    5225           34 :                             goto ControlledZoneLoop_exit;
    5226              :                         }
    5227              :                     }
    5228              :                 }
    5229            1 :             ControlledZoneLoop_exit:;
    5230           35 :                 if (ZoneNodeNotFound) {
    5231            1 :                     bool ZoneNodeFoundAgain = false;
    5232            4 :                     for (CtrlZone = 1; CtrlZone <= state.dataGlobal->NumOfZones; ++CtrlZone) {
    5233            9 :                         for (int Num = 1; Num <= state.dataZoneEquip->ZoneEquipList(CtrlZone).NumOfEquipTypes; ++Num) {
    5234            7 :                             if (Util::SameString(state.dataIPShortCut->cAlphaArgs(3), state.dataZoneEquip->ZoneEquipList(CtrlZone).EquipName(Num)) &&
    5235            1 :                                 Util::SameString(state.dataIPShortCut->cAlphaArgs(2),
    5236            1 :                                                  state.dataZoneEquip->ZoneEquipList(CtrlZone).EquipTypeName(Num))) {
    5237            1 :                                 state.dataDefineEquipment->AirDistUnit(state.dataSingleDuct->SysATMixer(ATMixerNum).ADUNum).ZoneEqNum = CtrlZone;
    5238            1 :                                 state.dataSingleDuct->SysATMixer(ATMixerNum).ZoneNum = CtrlZone;
    5239              :                                 // Must wait until InitATMixer to fill other zone equip config data because ultimate zone inlet node is not known yet
    5240              :                                 // for inlet side mixers
    5241            1 :                                 if (!state.dataSingleDuct->SysATMixer(ATMixerNum).NoOAFlowInputFromUser) {
    5242            1 :                                     bool UseOccSchFlag = false;
    5243            1 :                                     bool UseMinOASchFlag = false;
    5244            1 :                                     state.dataSingleDuct->SysATMixer(ATMixerNum).DesignPrimaryAirVolRate =
    5245            1 :                                         DataSizing::calcDesignSpecificationOutdoorAir(state,
    5246            1 :                                                                                       state.dataSingleDuct->SysATMixer(ATMixerNum).OARequirementsPtr,
    5247            1 :                                                                                       state.dataSingleDuct->SysATMixer(ATMixerNum).ZoneNum,
    5248              :                                                                                       UseOccSchFlag,
    5249              :                                                                                       UseMinOASchFlag);
    5250              :                                 }
    5251            1 :                                 ZoneNodeFoundAgain = true;
    5252            1 :                                 break;
    5253              :                             }
    5254              :                         }
    5255            4 :                         if (ZoneNodeFoundAgain) {
    5256            1 :                             break;
    5257              :                         }
    5258              :                     }
    5259            1 :                     if (!ZoneNodeFoundAgain) {
    5260            0 :                         ShowSevereError(state,
    5261            0 :                                         format("{} = \"{}\". Inlet Side Air Terminal Mixer air inlet node name must be the same as either a zone "
    5262              :                                                "exhaust node name or an induced air node in ZonePlenum.",
    5263              :                                                cCurrentModuleObject,
    5264            0 :                                                state.dataSingleDuct->SysATMixer(ATMixerNum).Name));
    5265            0 :                         ShowContinueError(state, "..Zone exhaust node name is specified in ZoneHVAC:EquipmentConnections object.");
    5266            0 :                         ShowContinueError(state, "..Induced Air Outlet Node name is specified in AirLoopHVAC:ReturnPlenum object.");
    5267            0 :                         ShowContinueError(state,
    5268            0 :                                           format("..Inlet Side CONNECTED Air Terminal Mixer inlet node name = {}",
    5269            0 :                                                  state.dataLoopNodes->NodeID(state.dataSingleDuct->SysATMixer(ATMixerNum).SecInNode)));
    5270            0 :                         ErrorsFound = true;
    5271              :                     }
    5272              :                 }
    5273              :             }
    5274              : 
    5275           59 :             if (state.dataSingleDuct->SysATMixer(ATMixerNum).type == HVAC::MixerType::SupplySide) {
    5276           24 :                 ZoneNodeNotFound = true;
    5277          117 :                 for (CtrlZone = 1; CtrlZone <= state.dataGlobal->NumOfZones; ++CtrlZone) {
    5278          117 :                     if (!state.dataZoneEquip->ZoneEquipConfig(CtrlZone).IsControlled) {
    5279           24 :                         continue;
    5280              :                     }
    5281          164 :                     for (NodeNum = 1; NodeNum <= state.dataZoneEquip->ZoneEquipConfig(CtrlZone).NumInletNodes; ++NodeNum) {
    5282           95 :                         if (state.dataSingleDuct->SysATMixer(ATMixerNum).MixedAirOutNode ==
    5283           95 :                             state.dataZoneEquip->ZoneEquipConfig(CtrlZone).InletNode(NodeNum)) {
    5284           24 :                             ZoneNodeNotFound = false;
    5285           24 :                             state.dataDefineEquipment->AirDistUnit(state.dataSingleDuct->SysATMixer(ATMixerNum).ADUNum).ZoneEqNum = CtrlZone;
    5286           24 :                             state.dataSingleDuct->SysATMixer(ATMixerNum).ZoneNum = CtrlZone;
    5287              :                             // Wait until InitATMixer to fill other zone equip config data
    5288              : 
    5289           24 :                             if (!state.dataSingleDuct->SysATMixer(ATMixerNum).NoOAFlowInputFromUser) {
    5290            8 :                                 bool UseOccSchFlag = false;
    5291            8 :                                 bool UseMinOASchFlag = false;
    5292            8 :                                 state.dataSingleDuct->SysATMixer(ATMixerNum).DesignPrimaryAirVolRate =
    5293            8 :                                     DataSizing::calcDesignSpecificationOutdoorAir(state,
    5294            8 :                                                                                   state.dataSingleDuct->SysATMixer(ATMixerNum).OARequirementsPtr,
    5295            8 :                                                                                   state.dataSingleDuct->SysATMixer(ATMixerNum).ZoneNum,
    5296              :                                                                                   UseOccSchFlag,
    5297              :                                                                                   UseMinOASchFlag);
    5298              :                             }
    5299           24 :                             goto ControlZoneLoop_exit;
    5300              :                         }
    5301              :                     }
    5302              :                 }
    5303            0 :             ControlZoneLoop_exit:;
    5304           24 :                 if (ZoneNodeNotFound) {
    5305            0 :                     ShowSevereError(
    5306              :                         state,
    5307            0 :                         format("{} = \"{}\". Supply Side Air Terminal Mixer air outlet node name must be the same as a zone inlet node name.",
    5308              :                                cCurrentModuleObject,
    5309            0 :                                state.dataSingleDuct->SysATMixer(ATMixerNum).Name));
    5310            0 :                     ShowContinueError(state, "..Zone inlet node name is specified in ZoneHVAC:EquipmentConnections object.");
    5311            0 :                     ShowContinueError(state,
    5312            0 :                                       format("..Supply Side connected Air Terminal Mixer outlet node name = {}",
    5313            0 :                                              state.dataLoopNodes->NodeID(state.dataSingleDuct->SysATMixer(ATMixerNum).MixedAirOutNode)));
    5314            0 :                     ErrorsFound = true;
    5315              :                 }
    5316              :             }
    5317              :         }
    5318          118 :         TestCompSet(state,
    5319              :                     cCurrentModuleObject,
    5320           59 :                     state.dataSingleDuct->SysATMixer(ATMixerNum).Name,
    5321           59 :                     state.dataIPShortCut->cAlphaArgs(5),
    5322           59 :                     state.dataIPShortCut->cAlphaArgs(4),
    5323              :                     "Air Nodes");
    5324              : 
    5325           59 :         if (state.dataSingleDuct->SysATMixer(ATMixerNum).OARequirementsPtr == 0) {
    5326           40 :             if (state.dataSize->ZoneSizingInput.allocated()) {
    5327          240 :                 for (int SizingInputNum = 1; SizingInputNum <= state.dataSize->NumZoneSizingInput; ++SizingInputNum) {
    5328          200 :                     if (state.dataSize->ZoneSizingInput(SizingInputNum).ZoneNum == state.dataSingleDuct->SysATMixer(ATMixerNum).ZoneNum) {
    5329           40 :                         if (state.dataSize->ZoneSizingInput(SizingInputNum).ZoneDesignSpecOAIndex == 0) {
    5330            0 :                             ShowWarningError(
    5331            0 :                                 state, format("{}{}=\"{}\", invalid data.", RoutineName, cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
    5332            0 :                             ShowContinueError(state,
    5333            0 :                                               format("{} is blank in both the mixer and the Sizing:Zone object for the same zone.",
    5334            0 :                                                      state.dataIPShortCut->cAlphaFieldNames(8)));
    5335            0 :                             ShowContinueError(state, "The mixer outdoor airflow rate is set to zero.");
    5336            0 :                             state.dataSingleDuct->SysATMixer(ATMixerNum).DesignPrimaryAirVolRate = 0.0;
    5337              :                         } else {
    5338           40 :                             state.dataSingleDuct->SysATMixer(ATMixerNum).OARequirementsPtr =
    5339           40 :                                 state.dataSize->ZoneSizingInput(SizingInputNum).ZoneDesignSpecOAIndex;
    5340           40 :                             state.dataSingleDuct->SysATMixer(ATMixerNum).DesignPrimaryAirVolRate =
    5341           40 :                                 DataSizing::calcDesignSpecificationOutdoorAir(state,
    5342           40 :                                                                               state.dataSingleDuct->SysATMixer(ATMixerNum).OARequirementsPtr,
    5343           40 :                                                                               state.dataSingleDuct->SysATMixer(ATMixerNum).ZoneNum,
    5344              :                                                                               false,
    5345              :                                                                               false);
    5346           40 :                             state.dataSingleDuct->SysATMixer(ATMixerNum).NoOAFlowInputFromUser = false;
    5347              :                         }
    5348              :                     }
    5349              :                 }
    5350              :             } else {
    5351            0 :                 ShowWarningError(state,
    5352            0 :                                  format("{}is blank and there is no Sizing:Zone for the same zone. The mixer outdoor airflow rate is set to zero.",
    5353            0 :                                         state.dataIPShortCut->cAlphaFieldNames(8)));
    5354            0 :                 state.dataSingleDuct->SysATMixer(ATMixerNum).DesignPrimaryAirVolRate = 0.0;
    5355              :             }
    5356              :         }
    5357           59 :         state.dataSingleDuct->SysATMixer(ATMixerNum).MassFlowRateMaxAvail =
    5358           59 :             state.dataSingleDuct->SysATMixer(ATMixerNum).DesignPrimaryAirVolRate * state.dataEnvrn->StdRhoAir;
    5359              :     }
    5360              : 
    5361          203 :     if (ErrorsFound) {
    5362            0 :         ShowFatalError(state, format("{}Errors found in input.  Program terminates.", RoutineName));
    5363              :     }
    5364              : }
    5365              : 
    5366      1862187 : void AirTerminalMixerData::InitATMixer(EnergyPlusData &state, bool const FirstHVACIteration)
    5367              : {
    5368              :     // Purpose: Initialize the AirTerminalMixers data structure with node data
    5369      1862187 :     if (this->OneTimeInitFlag) {
    5370              :         {
    5371           59 :             auto &thisADU(state.dataDefineEquipment->AirDistUnit(this->ADUNum));
    5372              :             {
    5373           59 :                 auto &thisZoneEqConfig(state.dataZoneEquip->ZoneEquipConfig(thisADU.ZoneEqNum));
    5374          118 :                 for (int SupAirIn = 1; SupAirIn <= thisZoneEqConfig.NumInletNodes; ++SupAirIn) {
    5375           59 :                     if (this->ZoneInletNode == thisZoneEqConfig.InletNode(SupAirIn)) {
    5376           59 :                         thisZoneEqConfig.AirDistUnitCool(SupAirIn).InNode = this->PriInNode;
    5377           59 :                         thisZoneEqConfig.AirDistUnitCool(SupAirIn).OutNode = this->MixedAirOutNode;
    5378           59 :                         thisZoneEqConfig.AirDistUnitHeat(SupAirIn).InNode = this->PriInNode;
    5379           59 :                         thisZoneEqConfig.AirDistUnitHeat(SupAirIn).OutNode = this->MixedAirOutNode;
    5380           59 :                         thisADU.TermUnitSizingNum = thisZoneEqConfig.AirDistUnitCool(SupAirIn).TermUnitSizingIndex;
    5381           59 :                         this->CtrlZoneInNodeIndex = SupAirIn;
    5382              :                         {
    5383           59 :                             auto &thisTermUnitSizingData(state.dataSize->TermUnitSizing(thisADU.TermUnitSizingNum));
    5384           59 :                             thisTermUnitSizingData.ADUName = thisADU.Name;
    5385              :                             // Fill TermUnitSizing with specs from DesignSpecification:AirTerminal:Sizing if there is one attached to this
    5386              :                             // terminal unit
    5387           59 :                             if (thisADU.AirTerminalSizingSpecIndex > 0) {
    5388              :                                 {
    5389            0 :                                     auto const &thisAirTermSizingSpec(state.dataSize->AirTerminalSizingSpec(thisADU.AirTerminalSizingSpecIndex));
    5390            0 :                                     thisTermUnitSizingData.SpecDesCoolSATRatio = thisAirTermSizingSpec.DesCoolSATRatio;
    5391            0 :                                     thisTermUnitSizingData.SpecDesHeatSATRatio = thisAirTermSizingSpec.DesHeatSATRatio;
    5392            0 :                                     thisTermUnitSizingData.SpecDesSensCoolingFrac = thisAirTermSizingSpec.DesSensCoolingFrac;
    5393            0 :                                     thisTermUnitSizingData.SpecDesSensHeatingFrac = thisAirTermSizingSpec.DesSensHeatingFrac;
    5394            0 :                                     thisTermUnitSizingData.SpecMinOAFrac = thisAirTermSizingSpec.MinOAFrac;
    5395              :                                 }
    5396              :                             }
    5397              :                         }
    5398              :                     }
    5399              :                 }
    5400              :             }
    5401              :         }
    5402           59 :         this->OneTimeInitFlag = false;
    5403              :     }
    5404              : 
    5405              :     // Keep trying until we find it, the airloopnum, that is
    5406      1862187 :     if (this->OneTimeInitFlag2) {
    5407          270 :         this->AirLoopNum = state.dataZoneEquip->ZoneEquipConfig(state.dataDefineEquipment->AirDistUnit(this->ADUNum).ZoneEqNum)
    5408          270 :                                .InletNodeAirLoopNum(this->CtrlZoneInNodeIndex);
    5409          270 :         state.dataDefineEquipment->AirDistUnit(this->ADUNum).AirLoopNum = this->AirLoopNum;
    5410          270 :         if (this->AirLoopNum > 0) {
    5411           59 :             this->OneTimeInitFlag2 = false;
    5412              :         }
    5413              :     }
    5414              : 
    5415              :     // Every iteration
    5416      1862187 :     Real64 mDotFromOARequirement(0.0);
    5417      1862187 :     Real64 vDotOAReq(0.0);
    5418      1862187 :     if (!this->NoOAFlowInputFromUser) {
    5419      1862187 :         Real64 airLoopOAFrac(0.0);
    5420      1862187 :         bool UseOccSchFlag = false;
    5421      1862187 :         if (this->OAPerPersonMode == DataZoneEquipment::PerPersonVentRateMode::DCVByCurrentLevel) {
    5422      1862187 :             UseOccSchFlag = true;
    5423              :         }
    5424      1862187 :         if (this->AirLoopNum > 0) {
    5425      1861976 :             airLoopOAFrac = state.dataAirLoop->AirLoopFlow(this->AirLoopNum).OAFrac;
    5426      1861976 :             if (airLoopOAFrac > 0.0) {
    5427      1590720 :                 vDotOAReq = DataSizing::calcDesignSpecificationOutdoorAir(state, this->OARequirementsPtr, this->ZoneNum, UseOccSchFlag, true);
    5428      1590720 :                 mDotFromOARequirement = vDotOAReq * state.dataEnvrn->StdRhoAir / airLoopOAFrac;
    5429              :             } else {
    5430       271256 :                 mDotFromOARequirement = state.dataLoopNodes->Node(this->PriInNode).MassFlowRate;
    5431              :             }
    5432              :         }
    5433      1862187 :         if (FirstHVACIteration) {
    5434       903307 :             state.dataLoopNodes->Node(this->PriInNode).MassFlowRate = mDotFromOARequirement;
    5435       903307 :             state.dataLoopNodes->Node(this->PriInNode).MassFlowRateMaxAvail = this->MassFlowRateMaxAvail;
    5436       903307 :             state.dataLoopNodes->Node(this->PriInNode).MassFlowRateMinAvail = 0.0;
    5437              :         } else {
    5438       958880 :             state.dataLoopNodes->Node(this->PriInNode).MassFlowRate = mDotFromOARequirement;
    5439              : 
    5440       958880 :             state.dataLoopNodes->Node(this->PriInNode).MassFlowRate =
    5441       958880 :                 min(state.dataLoopNodes->Node(this->PriInNode).MassFlowRate, state.dataLoopNodes->Node(this->PriInNode).MassFlowRateMaxAvail);
    5442       958880 :             state.dataLoopNodes->Node(this->PriInNode).MassFlowRate =
    5443       958880 :                 max(state.dataLoopNodes->Node(this->PriInNode).MassFlowRate, state.dataLoopNodes->Node(this->PriInNode).MassFlowRateMinAvail);
    5444       958880 :             state.dataLoopNodes->Node(this->PriInNode).MassFlowRate =
    5445       958880 :                 max(state.dataLoopNodes->Node(this->PriInNode).MassFlowRate, state.dataLoopNodes->Node(this->PriInNode).MassFlowRateMin);
    5446              :         }
    5447              :     }
    5448      1862187 :     if (this->type == HVAC::MixerType::InletSide) {
    5449      1193352 :         state.dataLoopNodes->Node(this->PriInNode).MassFlowRate =
    5450      1193352 :             min(state.dataLoopNodes->Node(this->PriInNode).MassFlowRate, state.dataLoopNodes->Node(this->MixedAirOutNode).MassFlowRate);
    5451              :     }
    5452      1862187 : }
    5453              : 
    5454      1862128 : void CalcATMixer(EnergyPlusData &state, int const SysNum)
    5455              : {
    5456              : 
    5457              :     // SUBROUTINE INFORMATION:
    5458              :     //       DATE WRITTEN   March 2012
    5459              : 
    5460              :     // PURPOSE OF THIS SUBROUTINE
    5461              :     // Calculate the mixed air flow and conditions in the air terminal mixer
    5462              : 
    5463      1862128 :     auto &atMixer = state.dataSingleDuct->SysATMixer(SysNum);
    5464      1862128 :     auto &priInNode = state.dataLoopNodes->Node(atMixer.PriInNode);
    5465      1862128 :     auto &secInNode = state.dataLoopNodes->Node(atMixer.SecInNode);
    5466      1862128 :     auto &mixedAirOutNode = state.dataLoopNodes->Node(atMixer.MixedAirOutNode);
    5467              : 
    5468      1862128 :     Real64 MixedAirMassFlowRate =
    5469      1862128 :         (atMixer.type == HVAC::MixerType::SupplySide) ? secInNode.MassFlowRate + priInNode.MassFlowRate : mixedAirOutNode.MassFlowRate;
    5470              : 
    5471      1862128 :     if (atMixer.type == HVAC::MixerType::InletSide) {
    5472              :         // for inlet side mixer, the mixed air flow has been set, but we don't know the secondary flow
    5473      1193317 :         secInNode.MassFlowRate = max(MixedAirMassFlowRate - priInNode.MassFlowRate, 0.0);
    5474      1193317 :         if (std::abs(priInNode.MassFlowRate + secInNode.MassFlowRate - MixedAirMassFlowRate) > SmallMassFlow) {
    5475            0 :             ShowSevereError(state, format("CalcATMixer: Invalid mass flow rates in AirTerminal:SingleDuct:Mixer={}", atMixer.Name));
    5476            0 :             ShowContinueErrorTimeStamp(state,
    5477            0 :                                        format("Primary mass flow rate={:.6R}Secondary mass flow rate={:.6R}Mixed mass flow rate={:.6R}",
    5478            0 :                                               priInNode.MassFlowRate,
    5479            0 :                                               secInNode.MassFlowRate,
    5480              :                                               MixedAirMassFlowRate));
    5481            0 :             ShowFatalError(state, "Simulation terminates.");
    5482              :         }
    5483              :     }
    5484              :     // now calculate the mixed (outlet) conditions
    5485      1862128 :     if ((atMixer.MixedAirMassFlowRate = MixedAirMassFlowRate) > 0.0) {
    5486      1730111 :         Real64 MixedAirEnthalpy = (secInNode.MassFlowRate * secInNode.Enthalpy + priInNode.MassFlowRate * priInNode.Enthalpy) / MixedAirMassFlowRate;
    5487      1730111 :         Real64 MixedAirHumRat = (secInNode.MassFlowRate * secInNode.HumRat + priInNode.MassFlowRate * priInNode.HumRat) / MixedAirMassFlowRate;
    5488              :         // Mixed air temperature is calculated from the mixed air enthalpy and humidity ratio.
    5489      1730111 :         atMixer.MixedAirTemp = Psychrometrics::PsyTdbFnHW(MixedAirEnthalpy, MixedAirHumRat);
    5490      1730111 :         atMixer.MixedAirEnthalpy = MixedAirEnthalpy;
    5491      1730111 :         atMixer.MixedAirHumRat = MixedAirHumRat;
    5492              :     } else {
    5493       132017 :         atMixer.MixedAirEnthalpy = priInNode.Enthalpy;
    5494       132017 :         atMixer.MixedAirHumRat = priInNode.HumRat;
    5495       132017 :         atMixer.MixedAirTemp = priInNode.Temp;
    5496              :     }
    5497      1862128 : }
    5498              : 
    5499      1862128 : void UpdateATMixer(EnergyPlusData &state, int const SysNum)
    5500              : {
    5501              : 
    5502              :     // SUBROUTINE INFORMATION:
    5503              :     //       DATE WRITTEN   March 2012
    5504              : 
    5505              :     // PURPOSE OF THIS SUBROUTINE
    5506              :     // Move the results of CalcATMixer to the affected nodes
    5507              : 
    5508              :     // Using/Aliasing
    5509              :     using namespace DataLoopNode;
    5510              : 
    5511              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    5512      1862128 :     int PriInNode = state.dataSingleDuct->SysATMixer(SysNum).PriInNode;
    5513      1862128 :     int SecInNode = state.dataSingleDuct->SysATMixer(SysNum).SecInNode;
    5514      1862128 :     int MixedAirOutNode = state.dataSingleDuct->SysATMixer(SysNum).MixedAirOutNode;
    5515              : 
    5516              :     // mixed air data
    5517      1862128 :     state.dataLoopNodes->Node(MixedAirOutNode).Temp = state.dataSingleDuct->SysATMixer(SysNum).MixedAirTemp;
    5518      1862128 :     state.dataLoopNodes->Node(MixedAirOutNode).HumRat = state.dataSingleDuct->SysATMixer(SysNum).MixedAirHumRat;
    5519      1862128 :     state.dataLoopNodes->Node(MixedAirOutNode).Enthalpy = state.dataSingleDuct->SysATMixer(SysNum).MixedAirEnthalpy;
    5520      1862128 :     state.dataLoopNodes->Node(MixedAirOutNode).Press = state.dataSingleDuct->SysATMixer(SysNum).MixedAirPressure;
    5521      1862128 :     state.dataLoopNodes->Node(MixedAirOutNode).MassFlowRate = state.dataSingleDuct->SysATMixer(SysNum).MixedAirMassFlowRate;
    5522              : 
    5523      1862128 :     if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    5524       326026 :         if (state.dataSingleDuct->SysATMixer(SysNum).MixedAirMassFlowRate <= HVAC::VerySmallMassFlow) {
    5525         9396 :             state.dataLoopNodes->Node(MixedAirOutNode).CO2 = state.dataLoopNodes->Node(PriInNode).CO2;
    5526              :         } else {
    5527       316630 :             state.dataLoopNodes->Node(MixedAirOutNode).CO2 =
    5528       316630 :                 (state.dataLoopNodes->Node(SecInNode).MassFlowRate * state.dataLoopNodes->Node(SecInNode).CO2 +
    5529       316630 :                  state.dataLoopNodes->Node(PriInNode).MassFlowRate * state.dataLoopNodes->Node(PriInNode).CO2) /
    5530       316630 :                 state.dataLoopNodes->Node(MixedAirOutNode).MassFlowRate;
    5531              :         }
    5532              :     }
    5533              : 
    5534      1862128 :     if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    5535            0 :         if (state.dataSingleDuct->SysATMixer(SysNum).MixedAirMassFlowRate <= HVAC::VerySmallMassFlow) {
    5536            0 :             state.dataLoopNodes->Node(MixedAirOutNode).GenContam = state.dataLoopNodes->Node(PriInNode).GenContam;
    5537              :         } else {
    5538            0 :             state.dataLoopNodes->Node(MixedAirOutNode).GenContam =
    5539            0 :                 (state.dataLoopNodes->Node(SecInNode).MassFlowRate * state.dataLoopNodes->Node(SecInNode).GenContam +
    5540            0 :                  state.dataLoopNodes->Node(PriInNode).MassFlowRate * state.dataLoopNodes->Node(PriInNode).GenContam) /
    5541            0 :                 state.dataLoopNodes->Node(MixedAirOutNode).MassFlowRate;
    5542              :         }
    5543              :     }
    5544              : 
    5545              :     // update ADU flow data - because SimATMixer is called from the various zone equipment so the updates in SimZoneAirLoopEquipment won't work
    5546      1862128 :     int aduNum = state.dataSingleDuct->SysATMixer(SysNum).ADUNum;
    5547      1862128 :     state.dataDefineEquipment->AirDistUnit(aduNum).MassFlowRateTU = state.dataLoopNodes->Node(PriInNode).MassFlowRate;
    5548      1862128 :     state.dataDefineEquipment->AirDistUnit(aduNum).MassFlowRateZSup = state.dataLoopNodes->Node(PriInNode).MassFlowRate;
    5549      1862128 :     state.dataDefineEquipment->AirDistUnit(aduNum).MassFlowRateSup = state.dataLoopNodes->Node(PriInNode).MassFlowRate;
    5550      1862128 : }
    5551              : 
    5552          931 : void GetATMixer(EnergyPlusData &state,
    5553              :                 std::string const &ZoneEquipName, // zone unit name name
    5554              :                 std::string &ATMixerName,         // air terminal mixer name
    5555              :                 int &ATMixerNum,                  // air terminal mixer index
    5556              :                 HVAC::MixerType &ATMixerType,     // air teminal mixer type
    5557              :                 int &ATMixerPriNode,              // air terminal mixer primary air node number
    5558              :                 int &ATMixerSecNode,              // air terminal mixer secondary air node number
    5559              :                 int &ATMixerOutNode,              // air terminal mixer outlet air node number
    5560              :                 int const ZoneEquipOutletNode     // zone equipment outlet node (used with inlet side mixers)
    5561              : )
    5562              : {
    5563              : 
    5564              :     // SUBROUTINE INFORMATION:
    5565              :     //       AUTHOR         Fred Buhl
    5566              :     //       DATE WRITTEN   April 2012
    5567              : 
    5568              :     // PURPOSE OF THIS SUBROUTINE:
    5569              :     // This subroutine gets: 1) the index of the named AT Mixer in the SysATMixer data array
    5570              :     //                       2) the node number of the primary air inlet node of the AT Mixer
    5571              :     //                       3) set the AT Mixer ultimate zone inlet node
    5572              : 
    5573              :     int ATMixerIndex; // local air terminal mixer index
    5574              : 
    5575          931 :     if (state.dataSingleDuct->GetATMixerFlag) {
    5576          193 :         GetATMixers(state);
    5577          193 :         state.dataSingleDuct->GetATMixerFlag = false;
    5578              :     }
    5579              : 
    5580          931 :     if (state.dataSingleDuct->NumATMixers <= 0) {
    5581          871 :         ATMixerNum = 0;
    5582          871 :         ATMixerName = "";
    5583          871 :         ATMixerPriNode = 0;
    5584          871 :         ATMixerSecNode = 0;
    5585          871 :         ATMixerOutNode = 0;
    5586          871 :         ATMixerType = HVAC::MixerType::Invalid;
    5587          871 :         return;
    5588              :     }
    5589              : 
    5590           60 :     ATMixerIndex = Util::FindItemInList(ZoneEquipName, state.dataSingleDuct->SysATMixer, &AirTerminalMixerData::ZoneHVACUnitName);
    5591           60 :     if (ATMixerIndex > 0) {
    5592           59 :         ATMixerNum = ATMixerIndex;
    5593           59 :         ATMixerName = state.dataSingleDuct->SysATMixer(ATMixerIndex).Name;
    5594           59 :         ATMixerPriNode = state.dataSingleDuct->SysATMixer(ATMixerIndex).PriInNode;
    5595           59 :         ATMixerSecNode = state.dataSingleDuct->SysATMixer(ATMixerIndex).SecInNode;
    5596           59 :         ATMixerOutNode = state.dataSingleDuct->SysATMixer(ATMixerIndex).MixedAirOutNode;
    5597           59 :         ATMixerType = state.dataSingleDuct->SysATMixer(ATMixerIndex).type;
    5598           59 :         if (ATMixerType == HVAC::MixerType::InletSide) {
    5599           35 :             state.dataSingleDuct->SysATMixer(ATMixerIndex).ZoneInletNode = ZoneEquipOutletNode;
    5600              :         } else {
    5601           24 :             state.dataSingleDuct->SysATMixer(ATMixerIndex).ZoneInletNode = ATMixerOutNode;
    5602              :         }
    5603           59 :         state.dataSingleDuct->SysATMixer(ATMixerNum).InitATMixer(state, false);
    5604              :     } else {
    5605            1 :         ATMixerNum = 0;
    5606            1 :         ATMixerName = "";
    5607            1 :         ATMixerPriNode = 0;
    5608            1 :         ATMixerSecNode = 0;
    5609            1 :         ATMixerOutNode = 0;
    5610            1 :         ATMixerType = HVAC::MixerType::Invalid;
    5611              :     }
    5612              : }
    5613              : 
    5614           93 : void setATMixerSizingProperties(EnergyPlusData &state,
    5615              :                                 int const inletATMixerIndex, // index to ATMixer at inlet of zone equipment
    5616              :                                 int const controlledZoneNum, // controlled zone number
    5617              :                                 int const curZoneEqNum       // current zone equipment being simulated
    5618              : )
    5619              : {
    5620              : 
    5621           93 :     if (inletATMixerIndex == 0) {
    5622           37 :         return; // protect this function from bad inputs
    5623              :     }
    5624           93 :     if (controlledZoneNum == 0) {
    5625            0 :         return;
    5626              :     }
    5627           93 :     if (curZoneEqNum == 0) {
    5628            0 :         return;
    5629              :     }
    5630           93 :     if (state.dataSingleDuct->SysATMixer(inletATMixerIndex).type == HVAC::MixerType::Invalid) {
    5631            0 :         return;
    5632              :     }
    5633              : 
    5634              :     // ATMixer properties only affect coil sizing when the mixer is on the inlet side of zone equipment
    5635           93 :     if (state.dataSingleDuct->SysATMixer(inletATMixerIndex).type == HVAC::MixerType::SupplySide) {
    5636              :         // check if user has selected No to account for DOAS system
    5637           37 :         if (state.dataSize->FinalZoneSizing.allocated() && state.dataSingleDuct->SysATMixer(inletATMixerIndex).printWarning) {
    5638           24 :             auto const &finalZoneSizing = state.dataSize->FinalZoneSizing(curZoneEqNum);
    5639           24 :             if (!finalZoneSizing.AccountForDOAS && finalZoneSizing.DOASControlStrategy != DOASControl::NeutralSup) {
    5640            2 :                 ShowWarningError(state, format("AirTerminal:SingleDuct:Mixer: {}", state.dataSingleDuct->SysATMixer(inletATMixerIndex).Name));
    5641            4 :                 ShowContinueError(
    5642              :                     state,
    5643              :                     " Supply side Air Terminal Mixer does not adjust zone equipment coil sizing and may result in inappropriately sized coils.");
    5644            4 :                 ShowContinueError(
    5645              :                     state,
    5646            4 :                     format(" Set Account for Dedicated Outdoor Air System = Yes in Sizing:Zone object for zone = {}", finalZoneSizing.ZoneName));
    5647              :             }
    5648           24 :             state.dataSingleDuct->SysATMixer(inletATMixerIndex).printWarning = false;
    5649              :         }
    5650           37 :         return; // do nothing else if this is a supply side ATMixer
    5651              :     }
    5652              :     // check if user has selected Yes to account for DOAS system
    5653           56 :     if (state.dataSize->FinalZoneSizing.allocated() && state.dataSingleDuct->SysATMixer(inletATMixerIndex).printWarning) {
    5654           56 :         auto const &finalZoneSizing = state.dataSize->FinalZoneSizing(curZoneEqNum);
    5655           56 :         if (finalZoneSizing.AccountForDOAS && finalZoneSizing.DOASControlStrategy != DOASControl::NeutralSup) {
    5656            0 :             ShowWarningError(state, format("AirTerminal:SingleDuct:Mixer: {}", state.dataSingleDuct->SysATMixer(inletATMixerIndex).Name));
    5657            0 :             ShowContinueError(state, " Inlet side Air Terminal Mixer automatically adjusts zone equipment coil sizing.");
    5658            0 :             ShowContinueError(
    5659            0 :                 state, format(" Set Account for Dedicated Outdoor Air System = No in Sizing:Zone object for zone = {}", finalZoneSizing.ZoneName));
    5660            0 :             state.dataSingleDuct->SysATMixer(inletATMixerIndex).printWarning = false;
    5661              :         }
    5662              :     }
    5663              : 
    5664              :     // proceed to set ATMixer properties used for sizing coils
    5665              : 
    5666              :     int airLoopIndex = // find air loop associated with ATMixer
    5667           56 :         state.dataZoneEquip->ZoneEquipConfig(controlledZoneNum)
    5668           56 :             .InletNodeAirLoopNum(state.dataSingleDuct->SysATMixer(inletATMixerIndex).CtrlZoneInNodeIndex);
    5669              : 
    5670              :     // must be a system sizing run or calculations are not possible
    5671           56 :     bool SizingDesRunThisAirSys = false;                                      // Sizing:System object found flag
    5672           56 :     CheckThisAirSystemForSizing(state, airLoopIndex, SizingDesRunThisAirSys); // check for Sizing:System object
    5673              : 
    5674           56 :     if (SizingDesRunThisAirSys) {
    5675           56 :         auto &finalSysSizing = state.dataSize->FinalSysSizing(airLoopIndex);
    5676           56 :         auto &zoneEqSizing = state.dataSize->ZoneEqSizing(curZoneEqNum);
    5677              : 
    5678              :         // set ATMixer outlet air flow rate in ZoneEqSizing array for ATMixer. If this value > 0, then the Sizer will know an ATMixer exists
    5679           56 :         zoneEqSizing.ATMixerVolFlow = state.dataSingleDuct->SysATMixer(inletATMixerIndex).DesignPrimaryAirVolRate;
    5680              : 
    5681              :         // If air loop has heating coil use SA conditions, else if OA sys has coils then use precool conditions, else use OA conditions
    5682           56 :         if (state.dataAirSystemsData->PrimaryAirSystems(airLoopIndex).CentralHeatCoilExists) {
    5683              :             // if central heating coil exists, ATMixer outlet is assumed to be at supply air conditions described in sizing input
    5684            5 :             zoneEqSizing.ATMixerHeatPriDryBulb = finalSysSizing.HeatSupTemp;
    5685            5 :             zoneEqSizing.ATMixerHeatPriHumRat = finalSysSizing.HeatSupHumRat;
    5686           51 :         } else if (state.dataAirSystemsData->PrimaryAirSystems(airLoopIndex).NumOAHeatCoils > 0) {
    5687              :             // if no central heating coil exists and an outdoor air coil does exist, then ATMixer outlet is mixture of preheat and return
    5688            0 :             if (finalSysSizing.DesMainVolFlow == 0.0) { // protect divide by 0
    5689              :                 // doesn't matter, just pick a condition
    5690            0 :                 zoneEqSizing.ATMixerHeatPriDryBulb = finalSysSizing.PreheatTemp;
    5691            0 :                 zoneEqSizing.ATMixerHeatPriHumRat = finalSysSizing.PreheatHumRat;
    5692              :             } else {
    5693              :                 // mix preheat condition with return air condition based on OA frac. OA frac should nearly always be 1.
    5694              :                 // OA frac is based on air loop fraction, not ATMixer flow fraction since air loop can serve multiple ATMixers
    5695            0 :                 Real64 OutAirFrac = finalSysSizing.DesOutAirVolFlow / finalSysSizing.DesMainVolFlow;
    5696            0 :                 OutAirFrac = min(1.0, max(0.0, OutAirFrac));
    5697              : 
    5698              :                 // calculate humrat based on simple mixing
    5699            0 :                 Real64 CoilInHumRatForSizing = OutAirFrac * finalSysSizing.PreheatHumRat + (1 - OutAirFrac) * finalSysSizing.HeatRetHumRat;
    5700              : 
    5701              :                 // calculate enthalpy based on simple mixing
    5702              :                 Real64 CoilInEnthalpyForSizing =
    5703            0 :                     OutAirFrac * Psychrometrics::PsyHFnTdbW(finalSysSizing.PreheatTemp, finalSysSizing.PreheatHumRat) +
    5704            0 :                     (1 - OutAirFrac) * Psychrometrics::PsyHFnTdbW(finalSysSizing.HeatRetTemp, finalSysSizing.HeatRetHumRat);
    5705              : 
    5706              :                 // back calculate temperature based on humrat and enthalpy state points
    5707            0 :                 Real64 CoilInTempForSizing = Psychrometrics::PsyTdbFnHW(CoilInEnthalpyForSizing, CoilInHumRatForSizing);
    5708              : 
    5709            0 :                 zoneEqSizing.ATMixerHeatPriDryBulb = CoilInTempForSizing;
    5710            0 :                 zoneEqSizing.ATMixerHeatPriHumRat = CoilInHumRatForSizing;
    5711              :             }
    5712              :         } else {
    5713              :             // else no coils exist in air loop so mix OA condition with return air condition
    5714           51 :             if (finalSysSizing.DesMainVolFlow == 0.0) { // protect divide by 0
    5715              :                 // doesn't matter, just pick a condition
    5716            0 :                 zoneEqSizing.ATMixerHeatPriDryBulb = finalSysSizing.HeatOutTemp;
    5717            0 :                 zoneEqSizing.ATMixerHeatPriHumRat = finalSysSizing.HeatOutHumRat;
    5718              :             } else {
    5719              :                 // OA frac is based on air loop fraction, not ATMixer flow fraction since air loop can serve multiple ATMixers
    5720           51 :                 Real64 OutAirFrac = finalSysSizing.DesOutAirVolFlow / finalSysSizing.DesMainVolFlow;
    5721           51 :                 OutAirFrac = min(1.0, max(0.0, OutAirFrac));
    5722              : 
    5723              :                 // calculate humrat based on simple mixing
    5724           51 :                 Real64 CoilInHumRatForSizing = OutAirFrac * finalSysSizing.HeatOutHumRat + (1 - OutAirFrac) * finalSysSizing.HeatRetHumRat;
    5725              : 
    5726              :                 // calculate enthalpy based on simple mixing
    5727              :                 Real64 CoilInEnthalpyForSizing =
    5728           51 :                     OutAirFrac * Psychrometrics::PsyHFnTdbW(finalSysSizing.HeatOutTemp, finalSysSizing.HeatOutHumRat) +
    5729           51 :                     (1 - OutAirFrac) * Psychrometrics::PsyHFnTdbW(finalSysSizing.HeatRetTemp, finalSysSizing.HeatRetHumRat);
    5730              : 
    5731              :                 // back calculate temperature based on humrat and enthalpy state points
    5732           51 :                 Real64 CoilInTempForSizing = Psychrometrics::PsyTdbFnHW(CoilInEnthalpyForSizing, CoilInHumRatForSizing);
    5733              : 
    5734           51 :                 zoneEqSizing.ATMixerHeatPriDryBulb = CoilInTempForSizing;
    5735           51 :                 zoneEqSizing.ATMixerHeatPriHumRat = CoilInHumRatForSizing;
    5736              :             }
    5737              :         }
    5738              : 
    5739              :         // If air loop has cooling coil use SA conditions, else if OA sys has coils then use precool conditions, else use OA conditions
    5740           56 :         if (state.dataAirSystemsData->PrimaryAirSystems(airLoopIndex).CentralCoolCoilExists) {
    5741              :             // if central cooling coil exists, ATMixer outlet is assumed to be at supply air conditions described in sizing input
    5742            5 :             zoneEqSizing.ATMixerCoolPriDryBulb = finalSysSizing.CoolSupTemp;
    5743            5 :             zoneEqSizing.ATMixerCoolPriHumRat = finalSysSizing.CoolSupHumRat;
    5744           51 :         } else if (state.dataAirSystemsData->PrimaryAirSystems(airLoopIndex).NumOACoolCoils > 0) {
    5745              :             // if no central cooling coil exists and an outdoor air coil does exist, then ATMixer outlet is mixture of precool and return
    5746            0 :             if (finalSysSizing.DesMainVolFlow == 0.0) { // protect divide by 0
    5747              :                 // doesn't matter, just pick a condition
    5748            0 :                 zoneEqSizing.ATMixerCoolPriDryBulb = finalSysSizing.PrecoolTemp;
    5749            0 :                 zoneEqSizing.ATMixerCoolPriHumRat = finalSysSizing.PrecoolHumRat;
    5750              :             } else {
    5751              :                 // mix precool condition with return air condition based on OA frac. OA frac should nearly always be 1.
    5752              :                 // OA frac is based on air loop fraction, not ATMixer flow fraction since air loop can serve multiple ATMixers
    5753            0 :                 Real64 OutAirFrac = finalSysSizing.DesOutAirVolFlow / finalSysSizing.DesMainVolFlow;
    5754            0 :                 OutAirFrac = min(1.0, max(0.0, OutAirFrac));
    5755              : 
    5756              :                 // calculate humrat based on simple mixing
    5757            0 :                 Real64 CoilInHumRatForSizing = OutAirFrac * finalSysSizing.PrecoolHumRat + (1 - OutAirFrac) * finalSysSizing.RetHumRatAtCoolPeak;
    5758              : 
    5759              :                 // calculate enthalpy based on simple mixing
    5760              :                 Real64 CoilInEnthalpyForSizing =
    5761            0 :                     OutAirFrac * Psychrometrics::PsyHFnTdbW(finalSysSizing.PrecoolTemp, finalSysSizing.PrecoolHumRat) +
    5762            0 :                     (1 - OutAirFrac) * Psychrometrics::PsyHFnTdbW(finalSysSizing.RetTempAtCoolPeak, finalSysSizing.RetHumRatAtCoolPeak);
    5763              : 
    5764              :                 // back calculate temperature based on humrat and enthalpy state points
    5765            0 :                 Real64 CoilInTempForSizing = Psychrometrics::PsyTdbFnHW(CoilInEnthalpyForSizing, CoilInHumRatForSizing);
    5766              : 
    5767            0 :                 zoneEqSizing.ATMixerCoolPriDryBulb = CoilInTempForSizing;
    5768            0 :                 zoneEqSizing.ATMixerCoolPriHumRat = CoilInHumRatForSizing;
    5769              :             }
    5770              :         } else {
    5771              :             // else no coils exist in air loop so mix OA condition with return air condition
    5772           51 :             if (finalSysSizing.DesMainVolFlow == 0.0) { // protect divide by 0
    5773              :                 // doesn't matter, just pick a condition
    5774            0 :                 zoneEqSizing.ATMixerCoolPriDryBulb = finalSysSizing.OutTempAtCoolPeak;
    5775            0 :                 zoneEqSizing.ATMixerCoolPriHumRat = finalSysSizing.OutHumRatAtCoolPeak;
    5776              :             } else {
    5777              :                 // OA frac is based on air loop fraction, not ATMixer flow fraction since air loop can serve multiple ATMixers
    5778           51 :                 Real64 OutAirFrac = finalSysSizing.DesOutAirVolFlow / finalSysSizing.DesMainVolFlow;
    5779           51 :                 OutAirFrac = min(1.0, max(0.0, OutAirFrac));
    5780              : 
    5781              :                 // calculate humrat based on simple mixing
    5782           51 :                 Real64 CoilInHumRatForSizing =
    5783           51 :                     OutAirFrac * finalSysSizing.OutHumRatAtCoolPeak + (1 - OutAirFrac) * finalSysSizing.RetHumRatAtCoolPeak;
    5784              : 
    5785              :                 // calculate enthalpy based on simple mixing
    5786              :                 Real64 CoilInEnthalpyForSizing =
    5787           51 :                     OutAirFrac * Psychrometrics::PsyHFnTdbW(finalSysSizing.OutTempAtCoolPeak, finalSysSizing.OutHumRatAtCoolPeak) +
    5788           51 :                     (1 - OutAirFrac) * Psychrometrics::PsyHFnTdbW(finalSysSizing.RetTempAtCoolPeak, finalSysSizing.RetHumRatAtCoolPeak);
    5789              : 
    5790              :                 // back calculate temperature based on humrat and enthalpy state points
    5791           51 :                 Real64 CoilInTempForSizing = Psychrometrics::PsyTdbFnHW(CoilInEnthalpyForSizing, CoilInHumRatForSizing);
    5792              : 
    5793           51 :                 zoneEqSizing.ATMixerCoolPriDryBulb = CoilInTempForSizing;
    5794           51 :                 zoneEqSizing.ATMixerCoolPriHumRat = CoilInHumRatForSizing;
    5795              :             }
    5796              :         }
    5797              : 
    5798              :     } else {
    5799              :         // warn user that system sizing is needed to size coils when AT Mixer is used ?
    5800              :         // if there were a message here then this function should only be called when SizingDesRunThisZone is true
    5801              :     }
    5802              : }
    5803              : 
    5804     37322114 : void SingleDuctAirTerminal::CalcOutdoorAirVolumeFlowRate(EnergyPlusData &state)
    5805              : {
    5806              :     // calculates zone outdoor air volume flow rate using the supply air flow rate and OA fraction
    5807     37322114 :     if (this->AirLoopNum > 0) {
    5808     37312860 :         this->OutdoorAirFlowRate =
    5809     37312860 :             (this->sd_airterminalOutlet.AirMassFlowRate / state.dataEnvrn->StdRhoAir) * state.dataAirLoop->AirLoopFlow(this->AirLoopNum).OAFrac;
    5810              :     } else {
    5811         9254 :         this->OutdoorAirFlowRate = 0.0;
    5812              :     }
    5813     37322114 : }
    5814              : 
    5815         3597 : void SingleDuctAirTerminal::reportTerminalUnit(EnergyPlusData &state)
    5816              : {
    5817              :     // populate the predefined equipment summary report related to air terminals
    5818         3597 :     auto &orp = state.dataOutRptPredefined;
    5819         3597 :     auto &adu = state.dataDefineEquipment->AirDistUnit(this->ADUNum);
    5820         3597 :     if (!state.dataSize->TermUnitFinalZoneSizing.empty()) {
    5821         3082 :         auto &sizing = state.dataSize->TermUnitFinalZoneSizing(adu.TermUnitSizingNum);
    5822         3082 :         OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermMinFlow, adu.Name, sizing.DesCoolVolFlowMin);
    5823         3082 :         OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermMinOutdoorFlow, adu.Name, sizing.MinOA);
    5824         3082 :         OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermSupCoolingSP, adu.Name, sizing.CoolDesTemp);
    5825         3082 :         OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermSupHeatingSP, adu.Name, sizing.HeatDesTemp);
    5826         3082 :         OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermHeatingCap, adu.Name, sizing.DesHeatLoad);
    5827         3082 :         OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermCoolingCap, adu.Name, sizing.DesCoolLoad);
    5828              :     }
    5829         3597 :     OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermTypeInp, adu.Name, this->sysType);
    5830         3597 :     OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermPrimFlow, adu.Name, this->MaxAirVolFlowRate);
    5831         3597 :     OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermSecdFlow, adu.Name, "n/a");
    5832         3597 :     if (this->zoneMinAirFracSched != nullptr) {
    5833          163 :         OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermMinFlowSch, adu.Name, this->zoneMinAirFracSched->Name);
    5834              :     } else {
    5835         3434 :         OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermMinFlowSch, adu.Name, "n/a");
    5836              :     }
    5837         3597 :     OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermMaxFlowReh, adu.Name, this->MaxAirVolFlowRateDuringReheat);
    5838         3597 :     std::string schName = "n/a";
    5839         3597 :     if (this->OARequirementsPtr > 0) {
    5840          422 :         auto const *minOASched = state.dataSize->OARequirements(this->OARequirementsPtr).oaFlowFracSched;
    5841          422 :         if (minOASched != nullptr) {
    5842          422 :             schName = minOASched->Name;
    5843              :         }
    5844              :     }
    5845         3597 :     OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermMinOAflowSch, adu.Name, schName);
    5846         3597 :     OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermHeatCoilType, adu.Name, this->ReheatComp);
    5847         3597 :     OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermCoolCoilType, adu.Name, "n/a");
    5848         3597 :     if (this->fanType != HVAC::FanType::Invalid) {
    5849            8 :         OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermFanType, adu.Name, HVAC::fanTypeNames[(int)this->fanType]);
    5850              :     } else {
    5851         3589 :         OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermFanType, adu.Name, "n/a");
    5852              :     }
    5853         3597 :     OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermFanName, adu.Name, this->FanName);
    5854         3597 : }
    5855              : 
    5856              : //        End of Reporting subroutines for the Sys Module
    5857              : // *****************************************************************************
    5858              : 
    5859              : } // namespace EnergyPlus::SingleDuct
        

Generated by: LCOV version 2.0-1