LCOV - code coverage report
Current view: top level - EnergyPlus - HVACSingleDuctInduc.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 71.1 % 744 529
Test Date: 2025-06-02 07:23:51 Functions: 100.0 % 12 12

            Line data    Source code
       1              : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
       2              : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
       3              : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
       4              : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
       5              : // contributors. All rights reserved.
       6              : //
       7              : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
       8              : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
       9              : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
      10              : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
      11              : // derivative works, and perform publicly and display publicly, and to permit others to do so.
      12              : //
      13              : // Redistribution and use in source and binary forms, with or without modification, are permitted
      14              : // provided that the following conditions are met:
      15              : //
      16              : // (1) Redistributions of source code must retain the above copyright notice, this list of
      17              : //     conditions and the following disclaimer.
      18              : //
      19              : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
      20              : //     conditions and the following disclaimer in the documentation and/or other materials
      21              : //     provided with the distribution.
      22              : //
      23              : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
      24              : //     the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
      25              : //     used to endorse or promote products derived from this software without specific prior
      26              : //     written permission.
      27              : //
      28              : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
      29              : //     without changes from the version obtained under this License, or (ii) Licensee makes a
      30              : //     reference solely to the software portion of its product, Licensee must refer to the
      31              : //     software as "EnergyPlus version X" software, where "X" is the version number Licensee
      32              : //     obtained under this License and may not use a different name for the software. Except as
      33              : //     specifically required in this Section (4), Licensee shall not use in a company name, a
      34              : //     product name, in advertising, publicity, or other promotional activities any name, trade
      35              : //     name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
      36              : //     similar designation, without the U.S. Department of Energy's prior written consent.
      37              : //
      38              : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
      39              : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
      40              : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
      41              : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      42              : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      43              : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      44              : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      45              : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      46              : // POSSIBILITY OF SUCH DAMAGE.
      47              : 
      48              : // C++ Headers
      49              : #include <cmath>
      50              : 
      51              : // ObjexxFCL Headers
      52              : #include <ObjexxFCL/Array.functions.hh>
      53              : #include <ObjexxFCL/Fmath.hh>
      54              : 
      55              : // EnergyPlus Headers
      56              : #include <EnergyPlus/Autosizing/Base.hh>
      57              : #include <EnergyPlus/BranchNodeConnections.hh>
      58              : #include <EnergyPlus/Data/EnergyPlusData.hh>
      59              : #include <EnergyPlus/DataDefineEquip.hh>
      60              : #include <EnergyPlus/DataEnvironment.hh>
      61              : #include <EnergyPlus/DataHVACGlobals.hh>
      62              : #include <EnergyPlus/DataLoopNode.hh>
      63              : #include <EnergyPlus/DataSizing.hh>
      64              : #include <EnergyPlus/DataZoneEnergyDemands.hh>
      65              : #include <EnergyPlus/DataZoneEquipment.hh>
      66              : #include <EnergyPlus/FluidProperties.hh>
      67              : #include <EnergyPlus/General.hh>
      68              : #include <EnergyPlus/GeneralRoutines.hh>
      69              : #include <EnergyPlus/HVACSingleDuctInduc.hh>
      70              : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      71              : #include <EnergyPlus/MixerComponent.hh>
      72              : #include <EnergyPlus/NodeInputManager.hh>
      73              : #include <EnergyPlus/OutputProcessor.hh>
      74              : #include <EnergyPlus/OutputReportPredefined.hh>
      75              : #include <EnergyPlus/Plant/DataPlant.hh>
      76              : #include <EnergyPlus/PlantUtilities.hh>
      77              : #include <EnergyPlus/Psychrometrics.hh>
      78              : #include <EnergyPlus/ScheduleManager.hh>
      79              : #include <EnergyPlus/UtilityRoutines.hh>
      80              : #include <EnergyPlus/WaterCoils.hh>
      81              : 
      82              : namespace EnergyPlus {
      83              : 
      84              : namespace HVACSingleDuctInduc {
      85              : 
      86              :     // Module containing routines dealing terminal 4 pipe induction terminal units
      87              : 
      88              :     // MODULE INFORMATION:
      89              :     //       AUTHOR         Fred Buhl
      90              :     //       DATE WRITTEN   June 15 2004
      91              :     //       MODIFIED       Brent Griffith, Sept 2010, plant upgrades, fluid props
      92              : 
      93              :     // PURPOSE OF THIS MODULE:
      94              :     // To encapsulate the data and algorithms needed to simulate 4 pipe induction terminal units
      95              : 
      96              :     // METHODOLOGY EMPLOYED:
      97              :     // The terminal boxes are modeled as compound components: heating coil, cooling coil and
      98              :     // mixer. The combined components are controlled to meet the zone load.
      99              : 
     100        11976 :     void SimIndUnit(EnergyPlusData &state,
     101              :                     std::string_view CompName,     // name of the terminal unit
     102              :                     bool const FirstHVACIteration, // TRUE if first HVAC iteration in time step
     103              :                     int const ZoneNum,             // index of zone served by the terminal unit
     104              :                     int const ZoneNodeNum,         // zone node number of zone served by the terminal unit
     105              :                     int &CompIndex                 // which terminal unit in data structure
     106              :     )
     107              :     {
     108              : 
     109              :         // SUBROUTINE INFORMATION:
     110              :         //       AUTHOR         Fred Buhl
     111              :         //       DATE WRITTEN   June 18 2004
     112              : 
     113              :         // PURPOSE OF THIS SUBROUTINE:
     114              :         // Manages the simulation of a passive (no fan) induction terminal unit.
     115              :         // Called from SimZoneAirLoopEquipment in module ZoneAirLoopEquipmentManager.
     116              : 
     117              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     118              :         int IUNum; // index of terminal unit being simulated
     119              : 
     120              :         // First time SimIndUnit is called, get the input for all the passive terminal induction units
     121        11976 :         if (state.dataHVACSingleDuctInduc->GetIUInputFlag) {
     122            1 :             GetIndUnits(state);
     123            1 :             state.dataHVACSingleDuctInduc->GetIUInputFlag = false;
     124              :         }
     125              : 
     126              :         // Get the induction unit index
     127        11976 :         if (CompIndex == 0) {
     128            4 :             IUNum = Util::FindItemInList(CompName, state.dataHVACSingleDuctInduc->IndUnit);
     129            4 :             if (IUNum == 0) {
     130            0 :                 ShowFatalError(state, format("SimIndUnit: Induction Unit not found={}", CompName));
     131              :             }
     132            4 :             CompIndex = IUNum;
     133              :         } else {
     134        11972 :             IUNum = CompIndex;
     135        11972 :             if (IUNum > state.dataHVACSingleDuctInduc->NumIndUnits || IUNum < 1) {
     136            0 :                 ShowFatalError(state,
     137            0 :                                format("SimIndUnit: Invalid CompIndex passed={}, Number of Induction Units={}, System name={}",
     138              :                                       CompIndex,
     139            0 :                                       state.dataHVACSingleDuctInduc->NumIndUnits,
     140              :                                       CompName));
     141              :             }
     142        11972 :             if (state.dataHVACSingleDuctInduc->CheckEquipName(IUNum)) {
     143            4 :                 if (CompName != state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name) {
     144            0 :                     ShowFatalError(state,
     145            0 :                                    format("SimIndUnit: Invalid CompIndex passed={}, Induction Unit name={}, stored Induction Unit for that index={}",
     146              :                                           CompIndex,
     147              :                                           CompName,
     148            0 :                                           state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name));
     149              :                 }
     150            4 :                 state.dataHVACSingleDuctInduc->CheckEquipName(IUNum) = false;
     151              :             }
     152              :         }
     153              : 
     154        11976 :         auto &indUnit = state.dataHVACSingleDuctInduc->IndUnit(IUNum);
     155              : 
     156        11976 :         state.dataSize->CurTermUnitSizingNum = state.dataDefineEquipment->AirDistUnit(indUnit.ADUNum).TermUnitSizingNum;
     157              :         // initialize the unit
     158        11976 :         InitIndUnit(state, IUNum, FirstHVACIteration);
     159              : 
     160        11976 :         state.dataSize->TermUnitIU = true;
     161              : 
     162              :         // Select the correct unit type
     163        11976 :         switch (indUnit.UnitType_Num) {
     164        11976 :         case SingleDuct_CV::FourPipeInduc: {
     165        11976 :             SimFourPipeIndUnit(state, IUNum, ZoneNum, ZoneNodeNum, FirstHVACIteration);
     166        11976 :         } break;
     167            0 :         default: {
     168            0 :             ShowSevereError(state, format("Illegal Induction Unit Type used={}", indUnit.UnitType));
     169            0 :             ShowContinueError(state, format("Occurs in Induction Unit={}", indUnit.Name));
     170            0 :             ShowFatalError(state, "Preceding condition causes termination.");
     171            0 :         } break;
     172              :         }
     173              : 
     174        11976 :         state.dataSize->TermUnitIU = false;
     175              : 
     176              :         // the tasks usually done by the Update and Report routines are not required in a compound terminal unit.
     177              : 
     178              :         // Update the current unit's outlet nodes. No update needed
     179              : 
     180              :         // Fill the report variables. There are no report variables
     181        11976 :         indUnit.ReportIndUnit(state);
     182        11976 :     }
     183              : 
     184            2 :     void GetIndUnits(EnergyPlusData &state)
     185              :     {
     186              : 
     187              :         // SUBROUTINE INFORMATION:
     188              :         //       AUTHOR         Fred Buhl
     189              :         //       DATE WRITTEN   June 15 2004
     190              : 
     191              :         // PURPOSE OF THIS SUBROUTINE:
     192              :         // Obtains input data for passive induction air terminal units and stores it in the
     193              :         // induction terminal unit data structures
     194              : 
     195              :         // METHODOLOGY EMPLOYED:
     196              :         // Uses "Get" routines to read in data.
     197              : 
     198              :         // SUBROUTINE PARAMETER DEFINITIONS:
     199              :         static constexpr std::string_view RoutineName("GetIndUnits "); // include trailing blank space
     200              :         static constexpr std::string_view routineName = "GetIndUnits";
     201              : 
     202            2 :         Array1D_string Alphas;         // Alpha input items for object
     203            2 :         Array1D_string cAlphaFields;   // Alpha field names
     204            2 :         Array1D_string cNumericFields; // Numeric field names
     205            2 :         Array1D<Real64> Numbers;       // Numeric input items for object
     206            2 :         Array1D_bool lAlphaBlanks;     // Logical array, alpha field input BLANK = .TRUE.
     207            2 :         Array1D_bool lNumericBlanks;   // Logical array, numeric field input BLANK = .TRUE.
     208            2 :         int NumAlphas(0);              // Number of Alphas for each GetObjectItem call
     209            2 :         int NumNumbers(0);             // Number of Numbers for each GetObjectItem call
     210            2 :         int TotalArgs(0);              // Total number of alpha and numeric arguments (max) for a
     211              :         //  certain object in the input file
     212              :         int IOStatus;            // Used in GetObjectItem
     213            2 :         bool ErrorsFound(false); // Set to true if errors in input, fatal at end of routine
     214              : 
     215              :         // find the number of each type of induction unit
     216            2 :         std::string CurrentModuleObject = "AirTerminal:SingleDuct:ConstantVolume:FourPipeInduction";
     217            2 :         state.dataHVACSingleDuctInduc->NumFourPipes = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
     218            2 :         state.dataHVACSingleDuctInduc->NumIndUnits = state.dataHVACSingleDuctInduc->NumFourPipes;
     219              :         // allocate the data structures
     220            2 :         state.dataHVACSingleDuctInduc->IndUnit.allocate(state.dataHVACSingleDuctInduc->NumIndUnits);
     221            2 :         state.dataHVACSingleDuctInduc->CheckEquipName.dimension(state.dataHVACSingleDuctInduc->NumIndUnits, true);
     222              : 
     223            2 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, TotalArgs, NumAlphas, NumNumbers);
     224              : 
     225            2 :         Alphas.allocate(NumAlphas);
     226            2 :         cAlphaFields.allocate(NumAlphas);
     227            2 :         cNumericFields.allocate(NumNumbers);
     228            2 :         Numbers.dimension(NumNumbers, 0.0);
     229            2 :         lAlphaBlanks.dimension(NumAlphas, true);
     230            2 :         lNumericBlanks.dimension(NumNumbers, true);
     231              : 
     232              :         // loop over Series PIUs; get and load the input data
     233            6 :         for (int IUIndex = 1; IUIndex <= state.dataHVACSingleDuctInduc->NumFourPipes; ++IUIndex) {
     234              : 
     235            4 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     236              :                                                                      CurrentModuleObject,
     237              :                                                                      IUIndex,
     238              :                                                                      Alphas,
     239              :                                                                      NumAlphas,
     240              :                                                                      Numbers,
     241              :                                                                      NumNumbers,
     242              :                                                                      IOStatus,
     243              :                                                                      lNumericBlanks,
     244              :                                                                      lAlphaBlanks,
     245              :                                                                      cAlphaFields,
     246              :                                                                      cNumericFields);
     247              : 
     248            4 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
     249              : 
     250            4 :             int IUNum = IUIndex;
     251            4 :             Util::IsNameEmpty(state, Alphas(1), CurrentModuleObject, ErrorsFound);
     252              : 
     253            4 :             state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name = Alphas(1);
     254            4 :             state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType = CurrentModuleObject;
     255            4 :             state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType_Num = SingleDuct_CV::FourPipeInduc;
     256              : 
     257            4 :             if (lAlphaBlanks(2)) {
     258            0 :                 state.dataHVACSingleDuctInduc->IndUnit(IUNum).availSched = Sched::GetScheduleAlwaysOn(state);
     259            4 :             } else if ((state.dataHVACSingleDuctInduc->IndUnit(IUNum).availSched = Sched::GetSchedule(state, Alphas(2))) == nullptr) {
     260            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(2), Alphas(2));
     261            0 :                 ErrorsFound = true;
     262              :             }
     263            4 :             state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxTotAirVolFlow = Numbers(1);
     264            4 :             state.dataHVACSingleDuctInduc->IndUnit(IUNum).InducRatio = Numbers(2);
     265            4 :             if (lNumericBlanks(2)) {
     266            0 :                 state.dataHVACSingleDuctInduc->IndUnit(IUNum).InducRatio = 2.5;
     267              :             }
     268              : 
     269            4 :             state.dataHVACSingleDuctInduc->IndUnit(IUNum).PriAirInNode =
     270            4 :                 GetOnlySingleNode(state,
     271            4 :                                   Alphas(3),
     272              :                                   ErrorsFound,
     273              :                                   DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctConstantVolumeFourPipeInduction,
     274            4 :                                   Alphas(1),
     275              :                                   DataLoopNode::NodeFluidType::Air,
     276              :                                   DataLoopNode::ConnectionType::Inlet,
     277              :                                   NodeInputManager::CompFluidStream::Primary,
     278              :                                   DataLoopNode::ObjectIsParent,
     279            4 :                                   cAlphaFields(3));
     280            4 :             state.dataHVACSingleDuctInduc->IndUnit(IUNum).SecAirInNode =
     281            4 :                 GetOnlySingleNode(state,
     282            4 :                                   Alphas(4),
     283              :                                   ErrorsFound,
     284              :                                   DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctConstantVolumeFourPipeInduction,
     285            4 :                                   Alphas(1),
     286              :                                   DataLoopNode::NodeFluidType::Air,
     287              :                                   DataLoopNode::ConnectionType::Inlet,
     288              :                                   NodeInputManager::CompFluidStream::Primary,
     289              :                                   DataLoopNode::ObjectIsParent,
     290            4 :                                   cAlphaFields(4));
     291            4 :             state.dataHVACSingleDuctInduc->IndUnit(IUNum).OutAirNode =
     292            4 :                 GetOnlySingleNode(state,
     293            4 :                                   Alphas(5),
     294              :                                   ErrorsFound,
     295              :                                   DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctConstantVolumeFourPipeInduction,
     296            4 :                                   Alphas(1),
     297              :                                   DataLoopNode::NodeFluidType::Air,
     298              :                                   DataLoopNode::ConnectionType::Outlet,
     299              :                                   NodeInputManager::CompFluidStream::Primary,
     300              :                                   DataLoopNode::ObjectIsParent,
     301            4 :                                   cAlphaFields(5));
     302              : 
     303            4 :             state.dataHVACSingleDuctInduc->IndUnit(IUNum).HCoilType = Alphas(6); // type (key) of heating coil
     304            4 :             if (Util::SameString(state.dataHVACSingleDuctInduc->IndUnit(IUNum).HCoilType, "Coil:Heating:Water")) {
     305            4 :                 state.dataHVACSingleDuctInduc->IndUnit(IUNum).HeatingCoilType = DataPlant::PlantEquipmentType::CoilWaterSimpleHeating;
     306              :             }
     307              : 
     308            4 :             state.dataHVACSingleDuctInduc->IndUnit(IUNum).HCoil = Alphas(7); // name of heating coil object
     309            4 :             bool IsNotOK = false;
     310            4 :             state.dataHVACSingleDuctInduc->IndUnit(IUNum).HWControlNode = WaterCoils::GetCoilWaterInletNode(
     311            4 :                 state, state.dataHVACSingleDuctInduc->IndUnit(IUNum).HCoilType, state.dataHVACSingleDuctInduc->IndUnit(IUNum).HCoil, IsNotOK);
     312            4 :             if (IsNotOK) {
     313            0 :                 ShowContinueError(state, format("In {} = {}", CurrentModuleObject, state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name));
     314            0 :                 ShowContinueError(state, "..Only Coil:Heating:Water is allowed.");
     315            0 :                 ErrorsFound = true;
     316              :             }
     317            4 :             state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxVolHotWaterFlow = Numbers(3);
     318            4 :             state.dataHVACSingleDuctInduc->IndUnit(IUNum).MinVolHotWaterFlow = Numbers(4);
     319            4 :             state.dataHVACSingleDuctInduc->IndUnit(IUNum).HotControlOffset = Numbers(5);
     320              : 
     321            4 :             state.dataHVACSingleDuctInduc->IndUnit(IUNum).CCoilType = Alphas(8); // type (key) of cooling coil
     322              : 
     323            4 :             if (Util::SameString(state.dataHVACSingleDuctInduc->IndUnit(IUNum).CCoilType, "Coil:Cooling:Water")) {
     324            4 :                 state.dataHVACSingleDuctInduc->IndUnit(IUNum).CoolingCoilType = DataPlant::PlantEquipmentType::CoilWaterCooling;
     325            0 :             } else if (Util::SameString(state.dataHVACSingleDuctInduc->IndUnit(IUNum).CCoilType, "Coil:Cooling:Water:DetailedGeometry")) {
     326            0 :                 state.dataHVACSingleDuctInduc->IndUnit(IUNum).CoolingCoilType = DataPlant::PlantEquipmentType::CoilWaterDetailedFlatCooling;
     327              :             }
     328              : 
     329            4 :             state.dataHVACSingleDuctInduc->IndUnit(IUNum).CCoil = Alphas(9); // name of cooling coil object
     330            4 :             IsNotOK = false;
     331            4 :             state.dataHVACSingleDuctInduc->IndUnit(IUNum).CWControlNode = WaterCoils::GetCoilWaterInletNode(
     332            4 :                 state, state.dataHVACSingleDuctInduc->IndUnit(IUNum).CCoilType, state.dataHVACSingleDuctInduc->IndUnit(IUNum).CCoil, IsNotOK);
     333            4 :             if (IsNotOK) {
     334            0 :                 ShowContinueError(state, format("In {} = {}", CurrentModuleObject, state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name));
     335            0 :                 ShowContinueError(state, "..Only Coil:Cooling:Water or Coil:Cooling:Water:DetailedGeometry is allowed.");
     336            0 :                 ErrorsFound = true;
     337              :             }
     338            4 :             state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxVolColdWaterFlow = Numbers(6);
     339            4 :             state.dataHVACSingleDuctInduc->IndUnit(IUNum).MinVolColdWaterFlow = Numbers(7);
     340            4 :             state.dataHVACSingleDuctInduc->IndUnit(IUNum).ColdControlOffset = Numbers(8);
     341              : 
     342              :             // Get the Zone Mixer name and check that it is OK
     343            4 :             bool errFlag = false;
     344            4 :             state.dataHVACSingleDuctInduc->IndUnit(IUNum).MixerName = Alphas(10);
     345            4 :             MixerComponent::GetZoneMixerIndex(state,
     346            4 :                                               state.dataHVACSingleDuctInduc->IndUnit(IUNum).MixerName,
     347            4 :                                               state.dataHVACSingleDuctInduc->IndUnit(IUNum).Mixer_Num,
     348              :                                               errFlag,
     349              :                                               CurrentModuleObject);
     350            4 :             if (errFlag) {
     351            0 :                 ShowContinueError(state, format("...specified in {} = {}", CurrentModuleObject, state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name));
     352            0 :                 ErrorsFound = true;
     353              :             }
     354              : 
     355              :             // Add heating coil to component sets array
     356            8 :             BranchNodeConnections::SetUpCompSets(state,
     357            4 :                                                  state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
     358            4 :                                                  state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name,
     359            4 :                                                  state.dataHVACSingleDuctInduc->IndUnit(IUNum).HCoilType,
     360            4 :                                                  state.dataHVACSingleDuctInduc->IndUnit(IUNum).HCoil,
     361            4 :                                                  Alphas(4),
     362              :                                                  "UNDEFINED");
     363              :             // Add cooling coil to component sets array
     364            8 :             BranchNodeConnections::SetUpCompSets(state,
     365            4 :                                                  state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
     366            4 :                                                  state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name,
     367            4 :                                                  state.dataHVACSingleDuctInduc->IndUnit(IUNum).CCoilType,
     368            4 :                                                  state.dataHVACSingleDuctInduc->IndUnit(IUNum).CCoil,
     369              :                                                  "UNDEFINED",
     370              :                                                  "UNDEFINED");
     371              : 
     372              :             // Register component set data
     373            8 :             BranchNodeConnections::TestCompSet(state,
     374            4 :                                                state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
     375            4 :                                                state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name,
     376            4 :                                                state.dataLoopNodes->NodeID(state.dataHVACSingleDuctInduc->IndUnit(IUNum).PriAirInNode),
     377            4 :                                                state.dataLoopNodes->NodeID(state.dataHVACSingleDuctInduc->IndUnit(IUNum).OutAirNode),
     378              :                                                "Air Nodes");
     379              : 
     380           24 :             for (int ADUNum = 1; ADUNum <= (int)state.dataDefineEquipment->AirDistUnit.size(); ++ADUNum) {
     381           20 :                 if (state.dataHVACSingleDuctInduc->IndUnit(IUNum).OutAirNode == state.dataDefineEquipment->AirDistUnit(ADUNum).OutletNodeNum) {
     382            4 :                     state.dataHVACSingleDuctInduc->IndUnit(IUNum).ADUNum = ADUNum;
     383              :                 }
     384              :             }
     385              :             // one assumes if there isn't one assigned, it's an error?
     386            4 :             if (state.dataHVACSingleDuctInduc->IndUnit(IUNum).ADUNum == 0) {
     387            0 :                 ShowSevereError(state,
     388            0 :                                 format("{}No matching Air Distribution Unit, for Unit = [{},{}].",
     389              :                                        RoutineName,
     390            0 :                                        state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
     391            0 :                                        state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name));
     392            0 :                 ShowContinueError(
     393              :                     state,
     394            0 :                     format("...should have outlet node={}", state.dataLoopNodes->NodeID(state.dataHVACSingleDuctInduc->IndUnit(IUNum).OutAirNode)));
     395            0 :                 ErrorsFound = true;
     396              :             } else {
     397              :                 // Fill the Zone Equipment data with the supply air inlet node number of this unit.
     398            4 :                 bool AirNodeFound = false;
     399           28 :                 for (int CtrlZone = 1; CtrlZone <= state.dataGlobal->NumOfZones; ++CtrlZone) {
     400           24 :                     auto &zoneEquipConfig = state.dataZoneEquip->ZoneEquipConfig(CtrlZone);
     401              : 
     402           24 :                     if (!zoneEquipConfig.IsControlled) {
     403            4 :                         continue;
     404              :                     }
     405           36 :                     for (int SupAirIn = 1; SupAirIn <= zoneEquipConfig.NumInletNodes; ++SupAirIn) {
     406           20 :                         if (state.dataHVACSingleDuctInduc->IndUnit(IUNum).OutAirNode == zoneEquipConfig.InletNode(SupAirIn)) {
     407            4 :                             if (zoneEquipConfig.AirDistUnitCool(SupAirIn).OutNode > 0) {
     408            0 :                                 ShowSevereError(state, "Error in connecting a terminal unit to a zone");
     409            0 :                                 ShowContinueError(state,
     410            0 :                                                   format("{} already connects to another zone",
     411            0 :                                                          state.dataLoopNodes->NodeID(state.dataHVACSingleDuctInduc->IndUnit(IUNum).OutAirNode)));
     412            0 :                                 ShowContinueError(state,
     413            0 :                                                   format("Occurs for terminal unit {} = {}",
     414            0 :                                                          state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
     415            0 :                                                          state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name));
     416            0 :                                 ShowContinueError(state, "Check terminal unit node names for errors");
     417            0 :                                 ErrorsFound = true;
     418              :                             } else {
     419            4 :                                 zoneEquipConfig.AirDistUnitCool(SupAirIn).InNode = state.dataHVACSingleDuctInduc->IndUnit(IUNum).PriAirInNode;
     420            4 :                                 zoneEquipConfig.AirDistUnitCool(SupAirIn).OutNode = state.dataHVACSingleDuctInduc->IndUnit(IUNum).OutAirNode;
     421            4 :                                 state.dataDefineEquipment->AirDistUnit(state.dataHVACSingleDuctInduc->IndUnit(IUNum).ADUNum).TermUnitSizingNum =
     422            4 :                                     zoneEquipConfig.AirDistUnitCool(SupAirIn).TermUnitSizingIndex;
     423            4 :                                 state.dataDefineEquipment->AirDistUnit(state.dataHVACSingleDuctInduc->IndUnit(IUNum).ADUNum).ZoneEqNum = CtrlZone;
     424            4 :                                 state.dataHVACSingleDuctInduc->IndUnit(IUNum).CtrlZoneNum = CtrlZone;
     425              :                             }
     426            4 :                             state.dataHVACSingleDuctInduc->IndUnit(IUNum).CtrlZoneInNodeIndex = SupAirIn;
     427            4 :                             AirNodeFound = true;
     428            4 :                             break;
     429              :                         }
     430              :                     }
     431              :                 }
     432            4 :                 if (!AirNodeFound) {
     433            0 :                     ShowSevereError(
     434              :                         state,
     435            0 :                         format("The outlet air node from the {} = {}", CurrentModuleObject, state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name));
     436            0 :                     ShowContinueError(state, format("did not have a matching Zone Equipment Inlet Node, Node ={}", Alphas(3)));
     437            0 :                     ErrorsFound = true;
     438              :                 }
     439              :             }
     440              :             // report variable for all single duct air terminals
     441            8 :             SetupOutputVariable(state,
     442              :                                 "Zone Air Terminal Outdoor Air Volume Flow Rate",
     443              :                                 Constant::Units::m3_s,
     444            4 :                                 state.dataHVACSingleDuctInduc->IndUnit(IUNum).OutdoorAirFlowRate,
     445              :                                 OutputProcessor::TimeStepType::System,
     446              :                                 OutputProcessor::StoreType::Average,
     447            4 :                                 state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name);
     448              :         }
     449              : 
     450            2 :         Alphas.deallocate();
     451            2 :         cAlphaFields.deallocate();
     452            2 :         cNumericFields.deallocate();
     453            2 :         Numbers.deallocate();
     454            2 :         lAlphaBlanks.deallocate();
     455            2 :         lNumericBlanks.deallocate();
     456            2 :         if (ErrorsFound) {
     457            0 :             ShowFatalError(state, format("{}Errors found in getting input. Preceding conditions cause termination.", RoutineName));
     458              :         }
     459            2 :     }
     460              : 
     461        11976 :     void InitIndUnit(EnergyPlusData &state,
     462              :                      int const IUNum,              // number of the current induction unit being simulated
     463              :                      bool const FirstHVACIteration // TRUE if first air loop solution this HVAC step
     464              :     )
     465              :     {
     466              : 
     467              :         // SUBROUTINE INFORMATION:
     468              :         //       AUTHOR         Fred Buhl
     469              :         //       DATE WRITTEN   June 21 2004
     470              : 
     471              :         // PURPOSE OF THIS SUBROUTINE:
     472              :         // This subroutine is for initialization of the passive induction terminal boxes
     473              : 
     474              :         // METHODOLOGY EMPLOYED:
     475              :         // Uses the status flags to trigger initializations.
     476              : 
     477              :         // SUBROUTINE PARAMETER DEFINITIONS:
     478              :         static constexpr std::string_view RoutineName("InitIndUnit");
     479              : 
     480              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     481              :         int PriNode;   // primary air inlet node number
     482              :         int SecNode;   // secondary air inlet node number
     483              :         Real64 IndRat; // unit induction ratio
     484              :         Real64 RhoAir; // air density at outside pressure and standard temperature and humidity
     485              :         Real64 rho;    // local fluid density
     486              : 
     487        11976 :         auto &ZoneEquipmentListChecked = state.dataHVACSingleDuctInduc->ZoneEquipmentListChecked;
     488              : 
     489              :         // Do the one time initializations
     490        11976 :         if (state.dataHVACSingleDuctInduc->MyOneTimeFlag) {
     491              : 
     492            1 :             state.dataHVACSingleDuctInduc->MyEnvrnFlag.allocate(state.dataHVACSingleDuctInduc->NumIndUnits);
     493            1 :             state.dataHVACSingleDuctInduc->MySizeFlag.allocate(state.dataHVACSingleDuctInduc->NumIndUnits);
     494            1 :             state.dataHVACSingleDuctInduc->MyPlantScanFlag.allocate(state.dataHVACSingleDuctInduc->NumIndUnits);
     495            1 :             state.dataHVACSingleDuctInduc->MyAirDistInitFlag.allocate(state.dataHVACSingleDuctInduc->NumIndUnits);
     496            1 :             state.dataHVACSingleDuctInduc->MyEnvrnFlag = true;
     497            1 :             state.dataHVACSingleDuctInduc->MySizeFlag = true;
     498            1 :             state.dataHVACSingleDuctInduc->MyPlantScanFlag = true;
     499            1 :             state.dataHVACSingleDuctInduc->MyAirDistInitFlag = true;
     500            1 :             state.dataHVACSingleDuctInduc->MyOneTimeFlag = false;
     501              :         }
     502              : 
     503        11976 :         if (state.dataHVACSingleDuctInduc->MyPlantScanFlag(IUNum) && allocated(state.dataPlnt->PlantLoop)) {
     504            4 :             bool errFlag = false;
     505            4 :             if (state.dataHVACSingleDuctInduc->IndUnit(IUNum).HeatingCoilType == DataPlant::PlantEquipmentType::CoilWaterSimpleHeating) {
     506            4 :                 errFlag = false;
     507            8 :                 PlantUtilities::ScanPlantLoopsForObject(state,
     508            4 :                                                         state.dataHVACSingleDuctInduc->IndUnit(IUNum).HCoil,
     509            4 :                                                         state.dataHVACSingleDuctInduc->IndUnit(IUNum).HeatingCoilType,
     510            4 :                                                         state.dataHVACSingleDuctInduc->IndUnit(IUNum).HWPlantLoc,
     511              :                                                         errFlag,
     512              :                                                         _,
     513              :                                                         _,
     514              :                                                         _,
     515              :                                                         _,
     516              :                                                         _);
     517              :             }
     518            4 :             if (errFlag) {
     519            0 :                 ShowContinueError(state,
     520            0 :                                   format("Reference Unit=\"{}\", type={}",
     521            0 :                                          state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name,
     522            0 :                                          state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType));
     523              :             }
     524            4 :             if (state.dataHVACSingleDuctInduc->IndUnit(IUNum).CoolingCoilType == DataPlant::PlantEquipmentType::CoilWaterCooling ||
     525            0 :                 state.dataHVACSingleDuctInduc->IndUnit(IUNum).CoolingCoilType == DataPlant::PlantEquipmentType::CoilWaterDetailedFlatCooling) {
     526            4 :                 errFlag = false;
     527            8 :                 PlantUtilities::ScanPlantLoopsForObject(state,
     528            4 :                                                         state.dataHVACSingleDuctInduc->IndUnit(IUNum).CCoil,
     529            4 :                                                         state.dataHVACSingleDuctInduc->IndUnit(IUNum).CoolingCoilType,
     530            4 :                                                         state.dataHVACSingleDuctInduc->IndUnit(IUNum).CWPlantLoc,
     531              :                                                         errFlag,
     532              :                                                         _,
     533              :                                                         _,
     534              :                                                         _,
     535              :                                                         _,
     536              :                                                         _);
     537              :             }
     538            4 :             if (errFlag) {
     539            0 :                 ShowContinueError(state,
     540            0 :                                   format("Reference Unit=\"{}\", type={}",
     541            0 :                                          state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name,
     542            0 :                                          state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType));
     543            0 :                 ShowFatalError(state, "InitIndUnit: Program terminated for previous conditions.");
     544              :             }
     545            4 :             state.dataHVACSingleDuctInduc->MyPlantScanFlag(IUNum) = false;
     546        11972 :         } else if (state.dataHVACSingleDuctInduc->MyPlantScanFlag(IUNum) && !state.dataGlobal->AnyPlantInModel) {
     547            0 :             state.dataHVACSingleDuctInduc->MyPlantScanFlag(IUNum) = false;
     548              :         }
     549              : 
     550        11976 :         if (state.dataHVACSingleDuctInduc->MyAirDistInitFlag(IUNum)) {
     551              :             // save the induction ratio in the term unit sizing array for use in the system sizing calculation
     552           12 :             if (state.dataSize->CurTermUnitSizingNum > 0) {
     553           12 :                 state.dataSize->TermUnitSizing(state.dataSize->CurTermUnitSizingNum).InducRat =
     554           12 :                     state.dataHVACSingleDuctInduc->IndUnit(IUNum).InducRatio;
     555              :             }
     556           12 :             if (state.dataHVACSingleDuctInduc->IndUnit(IUNum).AirLoopNum == 0) {
     557           16 :                 if ((state.dataHVACSingleDuctInduc->IndUnit(IUNum).CtrlZoneNum > 0) &&
     558            8 :                     (state.dataHVACSingleDuctInduc->IndUnit(IUNum).CtrlZoneInNodeIndex > 0)) {
     559            8 :                     state.dataHVACSingleDuctInduc->IndUnit(IUNum).AirLoopNum =
     560            8 :                         state.dataZoneEquip->ZoneEquipConfig(state.dataHVACSingleDuctInduc->IndUnit(IUNum).CtrlZoneNum)
     561            8 :                             .InletNodeAirLoopNum(state.dataHVACSingleDuctInduc->IndUnit(IUNum).CtrlZoneInNodeIndex);
     562            8 :                     state.dataDefineEquipment->AirDistUnit(state.dataHVACSingleDuctInduc->IndUnit(IUNum).ADUNum).AirLoopNum =
     563            8 :                         state.dataHVACSingleDuctInduc->IndUnit(IUNum).AirLoopNum;
     564              :                 }
     565              :             } else {
     566            4 :                 state.dataHVACSingleDuctInduc->MyAirDistInitFlag(IUNum) = false;
     567              :             }
     568              :         }
     569        11976 :         if (!ZoneEquipmentListChecked && state.dataZoneEquip->ZoneEquipInputsFilled) {
     570            1 :             ZoneEquipmentListChecked = true;
     571              :             // Check to see if there is a Air Distribution Unit on the Zone Equipment List
     572            5 :             for (int Loop = 1; Loop <= state.dataHVACSingleDuctInduc->NumIndUnits; ++Loop) {
     573            4 :                 if (state.dataHVACSingleDuctInduc->IndUnit(Loop).ADUNum == 0) {
     574            0 :                     continue;
     575              :                 }
     576            8 :                 if (DataZoneEquipment::CheckZoneEquipmentList(
     577              :                         state,
     578              :                         "ZONEHVAC:AIRDISTRIBUTIONUNIT",
     579            4 :                         state.dataDefineEquipment->AirDistUnit(state.dataHVACSingleDuctInduc->IndUnit(Loop).ADUNum).Name)) {
     580            4 :                     continue;
     581              :                 }
     582            0 :                 ShowSevereError(state,
     583            0 :                                 format("InitIndUnit: ADU=[Air Distribution Unit,{}] is not on any ZoneHVAC:EquipmentList.",
     584            0 :                                        state.dataDefineEquipment->AirDistUnit(state.dataHVACSingleDuctInduc->IndUnit(Loop).ADUNum).Name));
     585            0 :                 ShowContinueError(state,
     586            0 :                                   format("...Unit=[{},{}] will not be simulated.",
     587            0 :                                          state.dataHVACSingleDuctInduc->IndUnit(Loop).UnitType,
     588            0 :                                          state.dataHVACSingleDuctInduc->IndUnit(Loop).Name));
     589              :             }
     590              :         }
     591              : 
     592        11976 :         if (!state.dataGlobal->SysSizingCalc && state.dataHVACSingleDuctInduc->MySizeFlag(IUNum)) {
     593              : 
     594            4 :             SizeIndUnit(state, IUNum);
     595            4 :             state.dataHVACSingleDuctInduc->MySizeFlag(IUNum) = false;
     596              :         }
     597              : 
     598              :         // Do the Begin Environment initializations
     599        11976 :         if (state.dataGlobal->BeginEnvrnFlag && state.dataHVACSingleDuctInduc->MyEnvrnFlag(IUNum)) {
     600           24 :             RhoAir = state.dataEnvrn->StdRhoAir;
     601           24 :             PriNode = state.dataHVACSingleDuctInduc->IndUnit(IUNum).PriAirInNode;
     602           24 :             SecNode = state.dataHVACSingleDuctInduc->IndUnit(IUNum).SecAirInNode;
     603           24 :             int OutletNode = state.dataHVACSingleDuctInduc->IndUnit(IUNum).OutAirNode;
     604           24 :             IndRat = state.dataHVACSingleDuctInduc->IndUnit(IUNum).InducRatio;
     605              :             // set the mass flow rates from the input volume flow rates
     606           24 :             if (Util::SameString(state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType, "AirTerminal:SingleDuct:ConstantVolume:FourPipeInduction")) {
     607           24 :                 state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxTotAirMassFlow =
     608           24 :                     RhoAir * state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxTotAirVolFlow;
     609           24 :                 state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxPriAirMassFlow =
     610           24 :                     state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxTotAirMassFlow / (1.0 + IndRat);
     611           24 :                 state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxSecAirMassFlow =
     612           24 :                     IndRat * state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxTotAirMassFlow / (1.0 + IndRat);
     613           24 :                 state.dataLoopNodes->Node(PriNode).MassFlowRateMax = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxPriAirMassFlow;
     614           24 :                 state.dataLoopNodes->Node(PriNode).MassFlowRateMin = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxPriAirMassFlow;
     615           24 :                 state.dataLoopNodes->Node(SecNode).MassFlowRateMax = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxSecAirMassFlow;
     616           24 :                 state.dataLoopNodes->Node(SecNode).MassFlowRateMin = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxSecAirMassFlow;
     617           24 :                 state.dataLoopNodes->Node(OutletNode).MassFlowRateMax = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxTotAirMassFlow;
     618              :             }
     619              : 
     620           24 :             int HotConNode = state.dataHVACSingleDuctInduc->IndUnit(IUNum).HWControlNode;
     621           24 :             if (HotConNode > 0 && !state.dataHVACSingleDuctInduc->MyPlantScanFlag(IUNum)) {
     622              : 
     623           24 :                 rho = state.dataPlnt->PlantLoop(state.dataHVACSingleDuctInduc->IndUnit(IUNum).HWPlantLoc.loopNum)
     624           24 :                           .glycol->getDensity(state, Constant::HWInitConvTemp, RoutineName);
     625           24 :                 state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxHotWaterFlow =
     626           24 :                     rho * state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxVolHotWaterFlow;
     627           24 :                 state.dataHVACSingleDuctInduc->IndUnit(IUNum).MinHotWaterFlow =
     628           24 :                     rho * state.dataHVACSingleDuctInduc->IndUnit(IUNum).MinVolHotWaterFlow;
     629              :                 // get component outlet node from plant structure
     630           24 :                 int HWOutletNode = DataPlant::CompData::getPlantComponent(state, state.dataHVACSingleDuctInduc->IndUnit(IUNum).HWPlantLoc).NodeNumOut;
     631           48 :                 PlantUtilities::InitComponentNodes(state,
     632           24 :                                                    state.dataHVACSingleDuctInduc->IndUnit(IUNum).MinHotWaterFlow,
     633           24 :                                                    state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxHotWaterFlow,
     634              :                                                    HotConNode,
     635              :                                                    HWOutletNode);
     636              :             }
     637              : 
     638           24 :             int ColdConNode = state.dataHVACSingleDuctInduc->IndUnit(IUNum).CWControlNode;
     639           24 :             if (ColdConNode > 0) {
     640           24 :                 rho = state.dataPlnt->PlantLoop(state.dataHVACSingleDuctInduc->IndUnit(IUNum).CWPlantLoc.loopNum)
     641           24 :                           .glycol->getDensity(state, Constant::CWInitConvTemp, RoutineName);
     642           24 :                 state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxColdWaterFlow =
     643           24 :                     rho * state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxVolColdWaterFlow;
     644           24 :                 state.dataHVACSingleDuctInduc->IndUnit(IUNum).MinColdWaterFlow =
     645           24 :                     rho * state.dataHVACSingleDuctInduc->IndUnit(IUNum).MinVolColdWaterFlow;
     646              : 
     647           24 :                 int CWOutletNode = DataPlant::CompData::getPlantComponent(state, state.dataHVACSingleDuctInduc->IndUnit(IUNum).CWPlantLoc).NodeNumOut;
     648           48 :                 PlantUtilities::InitComponentNodes(state,
     649           24 :                                                    state.dataHVACSingleDuctInduc->IndUnit(IUNum).MinColdWaterFlow,
     650           24 :                                                    state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxColdWaterFlow,
     651              :                                                    ColdConNode,
     652              :                                                    CWOutletNode);
     653              :             }
     654              : 
     655           24 :             state.dataHVACSingleDuctInduc->MyEnvrnFlag(IUNum) = false;
     656              :         } // end one time inits
     657              : 
     658        11976 :         if (!state.dataGlobal->BeginEnvrnFlag) {
     659        11836 :             state.dataHVACSingleDuctInduc->MyEnvrnFlag(IUNum) = true;
     660              :         }
     661              : 
     662        11976 :         PriNode = state.dataHVACSingleDuctInduc->IndUnit(IUNum).PriAirInNode;
     663        11976 :         SecNode = state.dataHVACSingleDuctInduc->IndUnit(IUNum).SecAirInNode;
     664              : 
     665              :         // Do the start of HVAC time step initializations
     666        11976 :         if (FirstHVACIteration) {
     667              :             // check for upstream zero flow. If nonzero and schedule ON, set primary flow to max
     668        11992 :             if (state.dataHVACSingleDuctInduc->IndUnit(IUNum).availSched->getCurrentVal() > 0.0 &&
     669         5988 :                 state.dataLoopNodes->Node(PriNode).MassFlowRate > 0.0) {
     670         5968 :                 if (Util::SameString(state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
     671              :                                      "AirTerminal:SingleDuct:ConstantVolume:FourPipeInduction")) {
     672         5968 :                     state.dataLoopNodes->Node(PriNode).MassFlowRate = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxPriAirMassFlow;
     673         5968 :                     state.dataLoopNodes->Node(SecNode).MassFlowRate = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxSecAirMassFlow;
     674              :                 }
     675              :             } else {
     676           36 :                 state.dataLoopNodes->Node(PriNode).MassFlowRate = 0.0;
     677           36 :                 state.dataLoopNodes->Node(SecNode).MassFlowRate = 0.0;
     678              :             }
     679              :             // reset the max and min avail flows
     680        11992 :             if (state.dataHVACSingleDuctInduc->IndUnit(IUNum).availSched->getCurrentVal() > 0.0 &&
     681         5988 :                 state.dataLoopNodes->Node(PriNode).MassFlowRateMaxAvail > 0.0) {
     682         5968 :                 if (Util::SameString(state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
     683              :                                      "AirTerminal:SingleDuct:ConstantVolume:FourPipeInduction")) {
     684         5968 :                     state.dataLoopNodes->Node(PriNode).MassFlowRateMaxAvail = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxPriAirMassFlow;
     685         5968 :                     state.dataLoopNodes->Node(PriNode).MassFlowRateMinAvail = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxPriAirMassFlow;
     686         5968 :                     state.dataLoopNodes->Node(SecNode).MassFlowRateMaxAvail = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxSecAirMassFlow;
     687         5968 :                     state.dataLoopNodes->Node(SecNode).MassFlowRateMinAvail = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxSecAirMassFlow;
     688              :                 }
     689              :             } else {
     690           36 :                 state.dataLoopNodes->Node(PriNode).MassFlowRateMaxAvail = 0.0;
     691           36 :                 state.dataLoopNodes->Node(PriNode).MassFlowRateMinAvail = 0.0;
     692           36 :                 state.dataLoopNodes->Node(SecNode).MassFlowRateMaxAvail = 0.0;
     693           36 :                 state.dataLoopNodes->Node(SecNode).MassFlowRateMinAvail = 0.0;
     694              :             }
     695              :         }
     696        11976 :     }
     697              : 
     698            4 :     void SizeIndUnit(EnergyPlusData &state, int const IUNum)
     699              :     {
     700              : 
     701              :         // SUBROUTINE INFORMATION:
     702              :         //       AUTHOR         Fred Buhl
     703              :         //       DATE WRITTEN   June 22 2004
     704              :         //       MODIFIED       August 2013 Daeho Kang, add component sizing table entries
     705              : 
     706              :         // PURPOSE OF THIS SUBROUTINE:
     707              :         // This subroutine is for sizing induction terminal units for which flow rates have not been
     708              :         // specified in the input
     709              : 
     710              :         // METHODOLOGY EMPLOYED:
     711              :         // Accesses zone sizing array for air flow rates and zone and plant sizing arrays to
     712              :         // calculate coil water flow rates.
     713              : 
     714              :         // SUBROUTINE PARAMETER DEFINITIONS:
     715              :         static constexpr std::string_view RoutineName("SizeIndUnit");
     716              : 
     717              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     718              :         Real64 DesCoilLoad;
     719              :         Real64 Cp;  // local fluid specific heat
     720              :         Real64 rho; // local fluid density
     721              : 
     722            4 :         Real64 DesPriVolFlow = 0.0;
     723            4 :         Real64 CpAir = 0.0;
     724            4 :         Real64 RhoAir = state.dataEnvrn->StdRhoAir;
     725            4 :         bool ErrorsFound = false;
     726            4 :         bool IsAutoSize = false;
     727            4 :         Real64 MaxTotAirVolFlowDes = 0.0;     // Design size maximum air volume flow for reporting
     728            4 :         Real64 MaxTotAirVolFlowUser = 0.0;    // User hard-sized maximum air volume flow for reporting
     729            4 :         Real64 MaxVolHotWaterFlowDes = 0.0;   // Design size maximum hot water flow for reporting
     730            4 :         Real64 MaxVolHotWaterFlowUser = 0.0;  // User hard-sized maximum hot water flow for reporting
     731            4 :         Real64 MaxVolColdWaterFlowDes = 0.0;  // Design size maximum cold water flow for reporting
     732            4 :         Real64 MaxVolColdWaterFlowUser = 0.0; // User hard-sized maximum cold water flow for reporting
     733              : 
     734            4 :         if (state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxTotAirVolFlow == DataSizing::AutoSize) {
     735            4 :             IsAutoSize = true;
     736              :         }
     737              : 
     738            4 :         if (state.dataSize->CurZoneEqNum > 0) {
     739            4 :             if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // simulation continue
     740            0 :                 if (state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxTotAirVolFlow > 0.0) {
     741            0 :                     BaseSizer::reportSizerOutput(state,
     742            0 :                                                  state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
     743            0 :                                                  state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name,
     744              :                                                  "User-Specified Maximum Total Air Flow Rate [m3/s]",
     745            0 :                                                  state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxTotAirVolFlow);
     746              :                 }
     747              :             } else {
     748            4 :                 CheckZoneSizing(state, state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType, state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name);
     749            4 :                 if (state.dataSize->CurTermUnitSizingNum > 0) {
     750            4 :                     MaxTotAirVolFlowDes = max(state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesCoolVolFlow,
     751            4 :                                               state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatVolFlow);
     752              :                 } else {
     753            0 :                     MaxTotAirVolFlowDes = 0.0;
     754              :                 }
     755            4 :                 if (MaxTotAirVolFlowDes < HVAC::SmallAirVolFlow) {
     756            0 :                     MaxTotAirVolFlowDes = 0.0;
     757              :                 }
     758            4 :                 if (IsAutoSize) {
     759            4 :                     state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxTotAirVolFlow = MaxTotAirVolFlowDes;
     760            8 :                     BaseSizer::reportSizerOutput(state,
     761            4 :                                                  state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
     762            4 :                                                  state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name,
     763              :                                                  "Design Size Maximum Total Air Flow Rate [m3/s]",
     764              :                                                  MaxTotAirVolFlowDes);
     765              :                 } else {
     766            0 :                     if (state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxTotAirVolFlow > 0.0 && MaxTotAirVolFlowDes > 0.0) {
     767            0 :                         MaxTotAirVolFlowUser = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxTotAirVolFlow;
     768            0 :                         BaseSizer::reportSizerOutput(state,
     769            0 :                                                      state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
     770            0 :                                                      state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name,
     771              :                                                      "Design Size Maximum Total Air Flow Rate [m3/s]",
     772              :                                                      MaxTotAirVolFlowDes,
     773              :                                                      "User-Specified Maximum Total Air Flow Rate [m3/s]",
     774              :                                                      MaxTotAirVolFlowUser);
     775            0 :                         if (state.dataGlobal->DisplayExtraWarnings) {
     776            0 :                             if ((std::abs(MaxTotAirVolFlowDes - MaxTotAirVolFlowUser) / MaxTotAirVolFlowUser) >
     777            0 :                                 state.dataSize->AutoVsHardSizingThreshold) {
     778            0 :                                 ShowMessage(state,
     779            0 :                                             format("SizeHVACSingleDuctInduction: Potential issue with equipment sizing for {} = \"{}\".",
     780            0 :                                                    state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
     781            0 :                                                    state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name));
     782            0 :                                 ShowContinueError(state, format("User-Specified Maximum Total Air Flow Rate of {:.5R} [m3/s]", MaxTotAirVolFlowUser));
     783            0 :                                 ShowContinueError(
     784            0 :                                     state, format("differs from Design Size Maximum Total Air Flow Rate of {:.5R} [m3/s]", MaxTotAirVolFlowDes));
     785            0 :                                 ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
     786            0 :                                 ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
     787              :                             }
     788              :                         }
     789              :                     }
     790              :                 }
     791              :             }
     792              :         }
     793              : 
     794            4 :         IsAutoSize = false;
     795            4 :         if (state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxVolHotWaterFlow == DataSizing::AutoSize) {
     796            4 :             IsAutoSize = true;
     797              :         }
     798            4 :         if ((state.dataSize->CurZoneEqNum > 0) && (state.dataSize->CurTermUnitSizingNum > 0)) {
     799            4 :             if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // simulation continue
     800            0 :                 if (state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxVolHotWaterFlow > 0.0) {
     801            0 :                     BaseSizer::reportSizerOutput(state,
     802            0 :                                                  state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
     803            0 :                                                  state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name,
     804              :                                                  "User-Specified Maximum Hot Water Flow Rate [m3/s]",
     805            0 :                                                  state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxVolHotWaterFlow);
     806              :                 }
     807              :             } else {
     808            4 :                 CheckZoneSizing(state, state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType, state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name);
     809              : 
     810            4 :                 if (Util::SameString(state.dataHVACSingleDuctInduc->IndUnit(IUNum).HCoilType, "Coil:Heating:Water")) {
     811              : 
     812            4 :                     int CoilWaterInletNode = WaterCoils::GetCoilWaterInletNode(
     813            4 :                         state, "Coil:Heating:Water", state.dataHVACSingleDuctInduc->IndUnit(IUNum).HCoil, ErrorsFound);
     814            4 :                     int CoilWaterOutletNode = WaterCoils::GetCoilWaterOutletNode(
     815            4 :                         state, "Coil:Heating:Water", state.dataHVACSingleDuctInduc->IndUnit(IUNum).HCoil, ErrorsFound);
     816            4 :                     if (IsAutoSize) {
     817            4 :                         int PltSizHeatNum = PlantUtilities::MyPlantSizingIndex(state,
     818              :                                                                                "Coil:Heating:Water",
     819            4 :                                                                                state.dataHVACSingleDuctInduc->IndUnit(IUNum).HCoil,
     820              :                                                                                CoilWaterInletNode,
     821              :                                                                                CoilWaterOutletNode,
     822              :                                                                                ErrorsFound);
     823            4 :                         if (PltSizHeatNum > 0) {
     824              : 
     825            4 :                             if (state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatMassFlow >=
     826              :                                 HVAC::SmallAirVolFlow) {
     827            4 :                                 DesPriVolFlow = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxTotAirVolFlow /
     828            4 :                                                 (1.0 + state.dataHVACSingleDuctInduc->IndUnit(IUNum).InducRatio);
     829            4 :                                 CpAir = Psychrometrics::PsyCpAirFnW(
     830            4 :                                     state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).HeatDesHumRat);
     831              :                                 // the design heating coil load is the zone load minus whatever the central system does. Note that
     832              :                                 // DesHeatCoilInTempTU is really the primary air inlet temperature for the unit.
     833            4 :                                 if (state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).ZoneTempAtHeatPeak > 0.0) {
     834            4 :                                     DesCoilLoad =
     835            4 :                                         state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).NonAirSysDesHeatLoad -
     836            8 :                                         CpAir * RhoAir * DesPriVolFlow *
     837            4 :                                             (state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatCoilInTempTU -
     838            4 :                                              state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).ZoneTempAtHeatPeak);
     839              :                                 } else {
     840            0 :                                     DesCoilLoad = CpAir * RhoAir * DesPriVolFlow *
     841            0 :                                                   (state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).ZoneSizThermSetPtLo -
     842            0 :                                                    state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatCoilInTempTU);
     843              :                                 }
     844            4 :                                 state.dataHVACSingleDuctInduc->IndUnit(IUNum).DesHeatingLoad = DesCoilLoad;
     845            4 :                                 Cp = state.dataPlnt->PlantLoop(state.dataHVACSingleDuctInduc->IndUnit(IUNum).HWPlantLoc.loopNum)
     846            4 :                                          .glycol->getSpecificHeat(state, Constant::HWInitConvTemp, RoutineName);
     847              : 
     848            4 :                                 rho = state.dataPlnt->PlantLoop(state.dataHVACSingleDuctInduc->IndUnit(IUNum).HWPlantLoc.loopNum)
     849            4 :                                           .glycol->getDensity(state, Constant::HWInitConvTemp, RoutineName);
     850              : 
     851            4 :                                 MaxVolHotWaterFlowDes = DesCoilLoad / (state.dataSize->PlantSizData(PltSizHeatNum).DeltaT * Cp * rho);
     852            4 :                                 MaxVolHotWaterFlowDes = max(MaxVolHotWaterFlowDes, 0.0);
     853              :                             } else {
     854            0 :                                 MaxVolHotWaterFlowDes = 0.0;
     855              :                             }
     856              :                         } else {
     857            0 :                             ShowSevereError(state, "Autosizing of water flow requires a heating loop Sizing:Plant object");
     858            0 :                             ShowContinueError(state,
     859            0 :                                               format("Occurs in{} Object={}",
     860            0 :                                                      state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
     861            0 :                                                      state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name));
     862            0 :                             ErrorsFound = true;
     863              :                         }
     864            4 :                         state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxVolHotWaterFlow = MaxVolHotWaterFlowDes;
     865            8 :                         BaseSizer::reportSizerOutput(state,
     866            4 :                                                      state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
     867            4 :                                                      state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name,
     868              :                                                      "Design Size Maximum Hot Water Flow Rate [m3/s]",
     869              :                                                      MaxVolHotWaterFlowDes);
     870            8 :                         BaseSizer::reportSizerOutput(
     871              :                             state,
     872            4 :                             state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
     873            4 :                             state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name,
     874              :                             "Design Size Inlet Air Temperature [C]",
     875            4 :                             state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatCoilInTempTU);
     876            8 :                         BaseSizer::reportSizerOutput(
     877              :                             state,
     878            4 :                             state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
     879            4 :                             state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name,
     880              :                             "Design Size Inlet Air Humidity Ratio [kgWater/kgDryAir]",
     881            4 :                             state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatCoilInHumRatTU);
     882              :                     } else {
     883            0 :                         if (state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxVolHotWaterFlow > 0.0 && MaxVolHotWaterFlowDes > 0.0) {
     884            0 :                             MaxVolHotWaterFlowUser = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxVolHotWaterFlow;
     885            0 :                             BaseSizer::reportSizerOutput(state,
     886            0 :                                                          state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
     887            0 :                                                          state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name,
     888              :                                                          "Design Size Maximum Hot Water Flow Rate [m3/s]",
     889              :                                                          MaxVolHotWaterFlowDes,
     890              :                                                          "User-Specified Maximum Hot Water Flow Rate [m3/s]",
     891              :                                                          MaxVolHotWaterFlowUser);
     892            0 :                             if (state.dataGlobal->DisplayExtraWarnings) {
     893            0 :                                 if ((std::abs(MaxVolHotWaterFlowDes - MaxVolHotWaterFlowUser) / MaxVolHotWaterFlowUser) >
     894            0 :                                     state.dataSize->AutoVsHardSizingThreshold) {
     895            0 :                                     ShowMessage(state,
     896            0 :                                                 format("SizeHVACSingleDuctInduction: Potential issue with equipment sizing for {} = \"{}\".",
     897            0 :                                                        state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
     898            0 :                                                        state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name));
     899            0 :                                     ShowContinueError(state,
     900            0 :                                                       format("User-Specified Maximum Hot Water Flow Rate of {:.5R} [m3/s]", MaxVolHotWaterFlowUser));
     901            0 :                                     ShowContinueError(
     902              :                                         state,
     903            0 :                                         format("differs from Design Size Maximum Hot Water Flow Rate of {:.5R} [m3/s]", MaxVolHotWaterFlowDes));
     904            0 :                                     ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
     905            0 :                                     ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
     906              :                                 }
     907              :                             }
     908              :                         }
     909              :                     }
     910              :                 } else {
     911            0 :                     state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxVolHotWaterFlow = 0.0;
     912              :                 }
     913              :             }
     914              :         }
     915              : 
     916            4 :         IsAutoSize = false;
     917            4 :         if (state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxVolColdWaterFlow == DataSizing::AutoSize) {
     918            4 :             IsAutoSize = true;
     919              :         }
     920            4 :         if ((state.dataSize->CurZoneEqNum > 0) && (state.dataSize->CurTermUnitSizingNum > 0)) {
     921            4 :             if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // simulation continue
     922            0 :                 if (state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxVolColdWaterFlow > 0.0) {
     923            0 :                     BaseSizer::reportSizerOutput(state,
     924            0 :                                                  state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
     925            0 :                                                  state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name,
     926              :                                                  "User-Specified Maximum Cold Water Flow Rate [m3/s]",
     927            0 :                                                  state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxVolColdWaterFlow);
     928              :                 }
     929              :             } else {
     930            4 :                 CheckZoneSizing(state, state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType, state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name);
     931              : 
     932            4 :                 if (Util::SameString(state.dataHVACSingleDuctInduc->IndUnit(IUNum).CCoilType, "Coil:Cooling:Water") ||
     933            4 :                     Util::SameString(state.dataHVACSingleDuctInduc->IndUnit(IUNum).CCoilType, "Coil:Cooling:Water:DetailedGeometry")) {
     934              : 
     935            4 :                     int CoilWaterInletNode = WaterCoils::GetCoilWaterInletNode(state,
     936            4 :                                                                                state.dataHVACSingleDuctInduc->IndUnit(IUNum).CCoilType,
     937            4 :                                                                                state.dataHVACSingleDuctInduc->IndUnit(IUNum).CCoil,
     938              :                                                                                ErrorsFound);
     939            4 :                     int CoilWaterOutletNode = WaterCoils::GetCoilWaterOutletNode(state,
     940            4 :                                                                                  state.dataHVACSingleDuctInduc->IndUnit(IUNum).CCoilType,
     941            4 :                                                                                  state.dataHVACSingleDuctInduc->IndUnit(IUNum).CCoil,
     942              :                                                                                  ErrorsFound);
     943            4 :                     if (IsAutoSize) {
     944            4 :                         int PltSizCoolNum = PlantUtilities::MyPlantSizingIndex(state,
     945            4 :                                                                                state.dataHVACSingleDuctInduc->IndUnit(IUNum).CCoilType,
     946            4 :                                                                                state.dataHVACSingleDuctInduc->IndUnit(IUNum).CCoil,
     947              :                                                                                CoilWaterInletNode,
     948              :                                                                                CoilWaterOutletNode,
     949              :                                                                                ErrorsFound);
     950            4 :                         if (PltSizCoolNum > 0) {
     951              : 
     952            4 :                             if (state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesCoolMassFlow >=
     953              :                                 HVAC::SmallAirVolFlow) {
     954            4 :                                 DesPriVolFlow = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxTotAirVolFlow /
     955            4 :                                                 (1.0 + state.dataHVACSingleDuctInduc->IndUnit(IUNum).InducRatio);
     956            4 :                                 CpAir = Psychrometrics::PsyCpAirFnW(
     957            4 :                                     state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).CoolDesHumRat);
     958              :                                 // the design cooling coil load is the zone load minus whatever the central system does. Note that
     959              :                                 // DesCoolCoilInTempTU is really the primary air inlet temperature for the unit.
     960            4 :                                 if (state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).ZoneTempAtCoolPeak > 0.0) {
     961            4 :                                     DesCoilLoad =
     962            4 :                                         state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).NonAirSysDesCoolLoad -
     963            8 :                                         CpAir * RhoAir * DesPriVolFlow *
     964            4 :                                             (state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).ZoneTempAtCoolPeak -
     965            4 :                                              state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesCoolCoilInTempTU);
     966              :                                 } else {
     967            0 :                                     DesCoilLoad = CpAir * RhoAir * DesPriVolFlow *
     968            0 :                                                   (state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesCoolCoilInTempTU -
     969            0 :                                                    state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).ZoneSizThermSetPtHi);
     970              :                                 }
     971            4 :                                 state.dataHVACSingleDuctInduc->IndUnit(IUNum).DesCoolingLoad = DesCoilLoad;
     972            4 :                                 Cp = state.dataPlnt->PlantLoop(state.dataHVACSingleDuctInduc->IndUnit(IUNum).CWPlantLoc.loopNum)
     973            4 :                                          .glycol->getSpecificHeat(state, 5.0, RoutineName);
     974              : 
     975            4 :                                 rho = state.dataPlnt->PlantLoop(state.dataHVACSingleDuctInduc->IndUnit(IUNum).CWPlantLoc.loopNum)
     976            4 :                                           .glycol->getDensity(state, 5.0, RoutineName);
     977              : 
     978            4 :                                 MaxVolColdWaterFlowDes = DesCoilLoad / (state.dataSize->PlantSizData(PltSizCoolNum).DeltaT * Cp * rho);
     979            4 :                                 MaxVolColdWaterFlowDes = max(MaxVolColdWaterFlowDes, 0.0);
     980              :                             } else {
     981            0 :                                 MaxVolColdWaterFlowDes = 0.0;
     982              :                             }
     983              :                         } else {
     984            0 :                             ShowSevereError(state, "Autosizing of water flow requires a cooling loop Sizing:Plant object");
     985            0 :                             ShowContinueError(state,
     986            0 :                                               format("Occurs in{} Object={}",
     987            0 :                                                      state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
     988            0 :                                                      state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name));
     989            0 :                             ErrorsFound = true;
     990              :                         }
     991            4 :                         state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxVolColdWaterFlow = MaxVolColdWaterFlowDes;
     992            8 :                         BaseSizer::reportSizerOutput(state,
     993            4 :                                                      state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
     994            4 :                                                      state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name,
     995              :                                                      "Design Size Maximum Cold Water Flow Rate [m3/s]",
     996              :                                                      MaxVolColdWaterFlowDes);
     997              :                     } else {
     998            0 :                         if (state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxVolColdWaterFlow > 0.0 && MaxVolColdWaterFlowDes > 0.0) {
     999            0 :                             MaxVolColdWaterFlowUser = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxVolColdWaterFlow;
    1000            0 :                             BaseSizer::reportSizerOutput(state,
    1001            0 :                                                          state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
    1002            0 :                                                          state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name,
    1003              :                                                          "Design Size Maximum Cold Water Flow Rate [m3/s]",
    1004              :                                                          MaxVolColdWaterFlowDes,
    1005              :                                                          "User-Specified Maximum Cold Water Flow Rate [m3/s]",
    1006              :                                                          MaxVolColdWaterFlowUser);
    1007            0 :                             if (state.dataGlobal->DisplayExtraWarnings) {
    1008            0 :                                 if ((std::abs(MaxVolColdWaterFlowDes - MaxVolColdWaterFlowUser) / MaxVolColdWaterFlowUser) >
    1009            0 :                                     state.dataSize->AutoVsHardSizingThreshold) {
    1010            0 :                                     ShowMessage(state,
    1011            0 :                                                 format("SizeHVACSingleDuctInduction: Potential issue with equipment sizing for {} = \"{}\".",
    1012            0 :                                                        state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
    1013            0 :                                                        state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name));
    1014            0 :                                     ShowContinueError(
    1015            0 :                                         state, format("User-Specified Maximum Cold Water Flow Rate of {:.5R} [m3/s]", MaxVolColdWaterFlowUser));
    1016            0 :                                     ShowContinueError(
    1017              :                                         state,
    1018            0 :                                         format("differs from Design Size Maximum Cold Water Flow Rate of {:.5R} [m3/s]", MaxVolColdWaterFlowDes));
    1019            0 :                                     ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
    1020            0 :                                     ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
    1021              :                                 }
    1022              :                             }
    1023              :                         }
    1024              :                     }
    1025              :                 } else {
    1026            0 :                     state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxVolColdWaterFlow = 0.0;
    1027              :                 }
    1028              :             }
    1029              :         }
    1030              : 
    1031            4 :         if (state.dataSize->CurTermUnitSizingNum > 0) {
    1032            4 :             auto &termUnitSizing = state.dataSize->TermUnitSizing(state.dataSize->CurTermUnitSizingNum);
    1033              : 
    1034              :             // note we save the induced air flow for use by the hw and cw coil sizing routines
    1035            4 :             termUnitSizing.AirVolFlow = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxTotAirVolFlow *
    1036            4 :                                         state.dataHVACSingleDuctInduc->IndUnit(IUNum).InducRatio /
    1037            4 :                                         (1.0 + state.dataHVACSingleDuctInduc->IndUnit(IUNum).InducRatio);
    1038              :             // save the max hot and cold water flows for use in coil sizing
    1039            4 :             termUnitSizing.MaxHWVolFlow = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxVolHotWaterFlow;
    1040            4 :             termUnitSizing.MaxCWVolFlow = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxVolColdWaterFlow;
    1041              :             // save the design load used for reporting
    1042            4 :             termUnitSizing.DesCoolingLoad = state.dataHVACSingleDuctInduc->IndUnit(IUNum).DesCoolingLoad;
    1043            4 :             termUnitSizing.DesHeatingLoad = state.dataHVACSingleDuctInduc->IndUnit(IUNum).DesHeatingLoad;
    1044              :             // save the induction ratio for use in subsequent sizing calcs
    1045            4 :             termUnitSizing.InducRat = state.dataHVACSingleDuctInduc->IndUnit(IUNum).InducRatio;
    1046            4 :             if (Util::SameString(state.dataHVACSingleDuctInduc->IndUnit(IUNum).HCoilType, "Coil:Heating:Water")) {
    1047            4 :                 WaterCoils::SetCoilDesFlow(state,
    1048            4 :                                            state.dataHVACSingleDuctInduc->IndUnit(IUNum).HCoilType,
    1049            4 :                                            state.dataHVACSingleDuctInduc->IndUnit(IUNum).HCoil,
    1050              :                                            termUnitSizing.AirVolFlow,
    1051              :                                            ErrorsFound);
    1052              :             }
    1053            4 :             if (Util::SameString(state.dataHVACSingleDuctInduc->IndUnit(IUNum).CCoilType, "Coil:Cooling:Water:DetailedGeometry")) {
    1054            0 :                 WaterCoils::SetCoilDesFlow(state,
    1055            0 :                                            state.dataHVACSingleDuctInduc->IndUnit(IUNum).CCoilType,
    1056            0 :                                            state.dataHVACSingleDuctInduc->IndUnit(IUNum).CCoil,
    1057              :                                            termUnitSizing.AirVolFlow,
    1058              :                                            ErrorsFound);
    1059              :             }
    1060              :         }
    1061            4 :     }
    1062              : 
    1063        11976 :     void SimFourPipeIndUnit(EnergyPlusData &state,
    1064              :                             int const IUNum,              // number of the current unit being simulated
    1065              :                             int const ZoneNum,            // number of zone being served
    1066              :                             int const ZoneNodeNum,        // zone node number
    1067              :                             bool const FirstHVACIteration // TRUE if 1st HVAC simulation of system timestep
    1068              :     )
    1069              :     {
    1070              : 
    1071              :         // SUBROUTINE INFORMATION:
    1072              :         //       AUTHOR         Fred Buhl
    1073              :         //       DATE WRITTEN   June 23 2004
    1074              : 
    1075              :         // PURPOSE OF THIS SUBROUTINE:
    1076              :         // Simulate a 4 pipe induction unit; adjust its heating or cooling
    1077              :         // coil outputs to match the zone load.
    1078              : 
    1079              :         // METHODOLOGY EMPLOYED:
    1080              :         // (1) From the zone load and the primary air inlet conditions calculate the coil load
    1081              :         //     in the secondary air stream
    1082              :         // (2) If there is a cooling coil load, set the heating coil off and control the cooling
    1083              :         //     coil to meet the coil load
    1084              :         // (3) If there is a heating coil load, control the heating coil to meet the load and keep
    1085              :         //     the cooling coil off.
    1086              : 
    1087              :         // SUBROUTINE PARAMETER DEFINITIONS:
    1088        11976 :         int constexpr SolveMaxIter(50);
    1089              : 
    1090              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1091              :         Real64 HWFlow;   // hot water flow [kg/s]
    1092              :         Real64 CWFlow;   // cold water flow [kg/s]
    1093              :         Real64 QPriOnly; // unit output with no zone coils active
    1094              :         Real64 ErrTolerance;
    1095              : 
    1096        11976 :         bool UnitOn = true;
    1097        11976 :         Real64 PowerMet = 0.0;
    1098        11976 :         Real64 InducRat = state.dataHVACSingleDuctInduc->IndUnit(IUNum).InducRatio;
    1099        11976 :         int PriNode = state.dataHVACSingleDuctInduc->IndUnit(IUNum).PriAirInNode;
    1100        11976 :         int SecNode = state.dataHVACSingleDuctInduc->IndUnit(IUNum).SecAirInNode;
    1101        11976 :         int OutletNode = state.dataHVACSingleDuctInduc->IndUnit(IUNum).OutAirNode;
    1102        11976 :         int HotControlNode = state.dataHVACSingleDuctInduc->IndUnit(IUNum).HWControlNode;
    1103        11976 :         int HWOutletNode = DataPlant::CompData::getPlantComponent(state, state.dataHVACSingleDuctInduc->IndUnit(IUNum).HWPlantLoc).NodeNumOut;
    1104        11976 :         int ColdControlNode = state.dataHVACSingleDuctInduc->IndUnit(IUNum).CWControlNode;
    1105        11976 :         int CWOutletNode = DataPlant::CompData::getPlantComponent(state, state.dataHVACSingleDuctInduc->IndUnit(IUNum).CWPlantLoc).NodeNumOut;
    1106        11976 :         Real64 PriAirMassFlow = state.dataLoopNodes->Node(PriNode).MassFlowRateMaxAvail;
    1107        11976 :         Real64 SecAirMassFlow = InducRat * PriAirMassFlow;
    1108        11976 :         Real64 QToHeatSetPt = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).RemainingOutputReqToHeatSP;
    1109        11976 :         Real64 QToCoolSetPt = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).RemainingOutputReqToCoolSP;
    1110              :         // On the first HVAC iteration the system values are given to the controller, but after that
    1111              :         // the demand limits are in place and there needs to be feedback to the Zone Equipment
    1112              : 
    1113        11976 :         Real64 MaxHotWaterFlow = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxHotWaterFlow;
    1114        11976 :         PlantUtilities::SetComponentFlowRate(
    1115        11976 :             state, MaxHotWaterFlow, HotControlNode, HWOutletNode, state.dataHVACSingleDuctInduc->IndUnit(IUNum).HWPlantLoc);
    1116              : 
    1117        11976 :         Real64 MinHotWaterFlow = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MinHotWaterFlow;
    1118        11976 :         PlantUtilities::SetComponentFlowRate(
    1119        11976 :             state, MinHotWaterFlow, HotControlNode, HWOutletNode, state.dataHVACSingleDuctInduc->IndUnit(IUNum).HWPlantLoc);
    1120              : 
    1121        11976 :         Real64 MaxColdWaterFlow = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxColdWaterFlow;
    1122        11976 :         PlantUtilities::SetComponentFlowRate(
    1123        11976 :             state, MaxColdWaterFlow, ColdControlNode, CWOutletNode, state.dataHVACSingleDuctInduc->IndUnit(IUNum).CWPlantLoc);
    1124              : 
    1125        11976 :         Real64 MinColdWaterFlow = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MinColdWaterFlow;
    1126        11976 :         PlantUtilities::SetComponentFlowRate(
    1127        11976 :             state, MinColdWaterFlow, ColdControlNode, CWOutletNode, state.dataHVACSingleDuctInduc->IndUnit(IUNum).CWPlantLoc);
    1128              : 
    1129        11976 :         if (state.dataHVACSingleDuctInduc->IndUnit(IUNum).availSched->getCurrentVal() <= 0.0) {
    1130           28 :             UnitOn = false;
    1131              :         }
    1132        11976 :         if (PriAirMassFlow <= HVAC::SmallMassFlow) {
    1133           48 :             UnitOn = false;
    1134              :         }
    1135              : 
    1136              :         // Set the unit's air inlet nodes mass flow rates
    1137        11976 :         state.dataLoopNodes->Node(PriNode).MassFlowRate = PriAirMassFlow;
    1138        11976 :         state.dataLoopNodes->Node(SecNode).MassFlowRate = SecAirMassFlow;
    1139              :         // initialize the water inlet nodes to minimum
    1140              :         // fire the unit at min water flow
    1141        11976 :         CalcFourPipeIndUnit(state, IUNum, FirstHVACIteration, ZoneNodeNum, MinHotWaterFlow, MinColdWaterFlow, QPriOnly);
    1142              :         // the load to be met by the secondary air stream coils is QZnReq-PowerMet
    1143              : 
    1144        11976 :         if (UnitOn) {
    1145              : 
    1146        11928 :             int SolFlag = 0;
    1147        11928 :             if (QToHeatSetPt - QPriOnly > HVAC::SmallLoad) {
    1148              :                 // heating coil
    1149              :                 // check that it can meet the load
    1150        10099 :                 CalcFourPipeIndUnit(state, IUNum, FirstHVACIteration, ZoneNodeNum, MaxHotWaterFlow, MinColdWaterFlow, PowerMet);
    1151        10099 :                 if (PowerMet > QToHeatSetPt + HVAC::SmallLoad) {
    1152        10095 :                     ErrTolerance = state.dataHVACSingleDuctInduc->IndUnit(IUNum).HotControlOffset;
    1153              :                     auto f = // (AUTO_OK_LAMBDA)
    1154        97363 :                         [&state, IUNum, FirstHVACIteration, ZoneNodeNum, MinColdWaterFlow, QToHeatSetPt, QPriOnly, PowerMet](Real64 const HWFlow) {
    1155              :                             Real64 UnitOutput;
    1156        97363 :                             CalcFourPipeIndUnit(state, IUNum, FirstHVACIteration, ZoneNodeNum, HWFlow, MinColdWaterFlow, UnitOutput);
    1157        97363 :                             return (QToHeatSetPt - UnitOutput) / (PowerMet - QPriOnly);
    1158        10095 :                         };
    1159        10095 :                     General::SolveRoot(state, ErrTolerance, SolveMaxIter, SolFlag, HWFlow, f, MinHotWaterFlow, MaxHotWaterFlow);
    1160        10095 :                     if (SolFlag == -1) {
    1161            0 :                         if (state.dataHVACSingleDuctInduc->IndUnit(IUNum).HWCoilFailNum1 == 0) {
    1162            0 :                             ShowWarningMessage(state,
    1163            0 :                                                format("SimFourPipeIndUnit: Hot water coil control failed for {}=\"{}\"",
    1164            0 :                                                       state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
    1165            0 :                                                       state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name));
    1166            0 :                             ShowContinueErrorTimeStamp(state, "");
    1167            0 :                             ShowContinueError(state, format("  Iteration limit [{}] exceeded in calculating hot water mass flow rate", SolveMaxIter));
    1168              :                         }
    1169            0 :                         ShowRecurringWarningErrorAtEnd(
    1170              :                             state,
    1171            0 :                             format("SimFourPipeIndUnit: Hot water coil control failed (iteration limit [{}]) for {}=\"{}\"",
    1172              :                                    SolveMaxIter,
    1173            0 :                                    state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
    1174            0 :                                    state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name),
    1175            0 :                             state.dataHVACSingleDuctInduc->IndUnit(IUNum).HWCoilFailNum1);
    1176        10095 :                     } else if (SolFlag == -2) {
    1177            0 :                         if (state.dataHVACSingleDuctInduc->IndUnit(IUNum).HWCoilFailNum2 == 0) {
    1178            0 :                             ShowWarningMessage(state,
    1179            0 :                                                format("SimFourPipeIndUnit: Hot water coil control failed (maximum flow limits) for {}=\"{}\"",
    1180            0 :                                                       state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
    1181            0 :                                                       state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name));
    1182            0 :                             ShowContinueErrorTimeStamp(state, "");
    1183            0 :                             ShowContinueError(state, "...Bad hot water maximum flow rate limits");
    1184            0 :                             ShowContinueError(state, format("...Given minimum water flow rate={:.3R} kg/s", MinHotWaterFlow));
    1185            0 :                             ShowContinueError(state, format("...Given maximum water flow rate={:.3R} kg/s", MaxHotWaterFlow));
    1186              :                         }
    1187            0 :                         ShowRecurringWarningErrorAtEnd(state,
    1188            0 :                                                        "SimFourPipeIndUnit: Hot water coil control failed (flow limits) for " +
    1189            0 :                                                            state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType + "=\"" +
    1190            0 :                                                            state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name + "\"",
    1191            0 :                                                        state.dataHVACSingleDuctInduc->IndUnit(IUNum).HWCoilFailNum2,
    1192              :                                                        MaxHotWaterFlow,
    1193              :                                                        MinHotWaterFlow,
    1194              :                                                        _,
    1195              :                                                        "[kg/s]",
    1196              :                                                        "[kg/s]");
    1197              :                     }
    1198              :                 }
    1199         1829 :             } else if (QToCoolSetPt - QPriOnly < -HVAC::SmallLoad) {
    1200              :                 // cooling coil
    1201              :                 // check that it can meet the load
    1202         1801 :                 CalcFourPipeIndUnit(state, IUNum, FirstHVACIteration, ZoneNodeNum, MinHotWaterFlow, MaxColdWaterFlow, PowerMet);
    1203         1801 :                 if (PowerMet < QToCoolSetPt - HVAC::SmallLoad) {
    1204         1714 :                     ErrTolerance = state.dataHVACSingleDuctInduc->IndUnit(IUNum).ColdControlOffset;
    1205              :                     auto f = // (AUTO_OK_LAMBDA)
    1206         9327 :                         [&state, IUNum, FirstHVACIteration, ZoneNodeNum, MinHotWaterFlow, QToCoolSetPt, QPriOnly, PowerMet](Real64 const CWFlow) {
    1207              :                             Real64 UnitOutput;
    1208         9327 :                             CalcFourPipeIndUnit(state, IUNum, FirstHVACIteration, ZoneNodeNum, MinHotWaterFlow, CWFlow, UnitOutput);
    1209         9327 :                             return (QToCoolSetPt - UnitOutput) / (PowerMet - QPriOnly);
    1210         1714 :                         };
    1211         1714 :                     General::SolveRoot(state, ErrTolerance, SolveMaxIter, SolFlag, CWFlow, f, MinColdWaterFlow, MaxColdWaterFlow);
    1212         1714 :                     if (SolFlag == -1) {
    1213            0 :                         if (state.dataHVACSingleDuctInduc->IndUnit(IUNum).CWCoilFailNum1 == 0) {
    1214            0 :                             ShowWarningMessage(state,
    1215            0 :                                                format("SimFourPipeIndUnit: Cold water coil control failed for {}=\"{}\"",
    1216            0 :                                                       state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
    1217            0 :                                                       state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name));
    1218            0 :                             ShowContinueErrorTimeStamp(state, "");
    1219            0 :                             ShowContinueError(state,
    1220            0 :                                               format("  Iteration limit [{}] exceeded in calculating cold water mass flow rate", SolveMaxIter));
    1221              :                         }
    1222            0 :                         ShowRecurringWarningErrorAtEnd(state,
    1223            0 :                                                        format("SimFourPipeIndUnit: Cold water coil control failed (iteration limit [{}]) for {}=\"{}",
    1224              :                                                               SolveMaxIter,
    1225            0 :                                                               state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
    1226            0 :                                                               state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name),
    1227            0 :                                                        state.dataHVACSingleDuctInduc->IndUnit(IUNum).CWCoilFailNum1);
    1228         1714 :                     } else if (SolFlag == -2) {
    1229            0 :                         if (state.dataHVACSingleDuctInduc->IndUnit(IUNum).CWCoilFailNum2 == 0) {
    1230            0 :                             ShowWarningMessage(state,
    1231            0 :                                                format("SimFourPipeIndUnit: Cold water coil control failed (maximum flow limits) for {}=\"{}\"",
    1232            0 :                                                       state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
    1233            0 :                                                       state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name));
    1234            0 :                             ShowContinueErrorTimeStamp(state, "");
    1235            0 :                             ShowContinueError(state, "...Bad cold water maximum flow rate limits");
    1236            0 :                             ShowContinueError(state, format("...Given minimum water flow rate={:.3R} kg/s", MinColdWaterFlow));
    1237            0 :                             ShowContinueError(state, format("...Given maximum water flow rate={:.3R} kg/s", MaxColdWaterFlow));
    1238              :                         }
    1239            0 :                         ShowRecurringWarningErrorAtEnd(state,
    1240            0 :                                                        "SimFourPipeIndUnit: Cold water coil control failed (flow limits) for " +
    1241            0 :                                                            state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType + "=\"" +
    1242            0 :                                                            state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name + "\"",
    1243            0 :                                                        state.dataHVACSingleDuctInduc->IndUnit(IUNum).CWCoilFailNum2,
    1244              :                                                        MaxColdWaterFlow,
    1245              :                                                        MinColdWaterFlow,
    1246              :                                                        _,
    1247              :                                                        "[kg/s]",
    1248              :                                                        "[kg/s]");
    1249              :                     }
    1250              :                 }
    1251              :             } else {
    1252           28 :                 CalcFourPipeIndUnit(state, IUNum, FirstHVACIteration, ZoneNodeNum, MinHotWaterFlow, MinColdWaterFlow, PowerMet);
    1253              :             }
    1254              : 
    1255              :         } else {
    1256              :             // unit off
    1257           48 :             CalcFourPipeIndUnit(state, IUNum, FirstHVACIteration, ZoneNodeNum, MinHotWaterFlow, MinColdWaterFlow, PowerMet);
    1258              :         }
    1259        11976 :         state.dataLoopNodes->Node(OutletNode).MassFlowRateMax = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxTotAirMassFlow;
    1260              : 
    1261              :         // At this point we are done. There is no output to report or pass back up: the output provided is calculated
    1262              :         // one level up in the calling routine SimZoneAirLoopEquipment. All the inlet and outlet flow rates and
    1263              :         // conditions have been set by CalcFourPipeIndUnit either explicitly or as a result of the simple component calls.
    1264        11976 :     }
    1265              : 
    1266       130642 :     void CalcFourPipeIndUnit(EnergyPlusData &state,
    1267              :                              int const IUNum,               // Unit index
    1268              :                              bool const FirstHVACIteration, // flag for 1st HVAV iteration in the time step
    1269              :                              int const ZoneNode,            // zone node number
    1270              :                              Real64 const HWFlow,           // hot water flow (kg/s)
    1271              :                              Real64 const CWFlow,           // cold water flow (kg/s)
    1272              :                              Real64 &LoadMet                // load met by unit (watts)
    1273              :     )
    1274              :     {
    1275              : 
    1276              :         // SUBROUTINE INFORMATION:
    1277              :         //       AUTHOR         Fred Buhl
    1278              :         //       DATE WRITTEN   June 2004
    1279              : 
    1280              :         // PURPOSE OF THIS SUBROUTINE:
    1281              :         // Simulate the components making up the 4 pipe induction unit.
    1282              : 
    1283              :         // METHODOLOGY EMPLOYED:
    1284              :         // Simulates the unit components sequentially in the air flow direction.
    1285              : 
    1286              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1287              :         int OutletNode;        // unit air outlet node
    1288              :         int PriNode;           // unit primary air inlet node
    1289              :         int HotControlNode;    // the hot water inlet node
    1290              :         int ColdControlNode;   // the cold water inlet node
    1291              :         Real64 PriAirMassFlow; // primary air mass flow rate [kg/s]
    1292              :         Real64 SecAirMassFlow; // secondary air mass flow rate [kg/s]
    1293              :         Real64 TotAirMassFlow; // total air mass flow rate [kg/s]
    1294              :         Real64 InducRat;       // induction ratio
    1295              :         Real64 mdotHW;         // local temporary hot water flow rate [kg/s]
    1296              :         Real64 mdotCW;         // local temporary cold water flow rate [kg/s]
    1297              :         int HWOutletNode;
    1298              :         int CWOutletNode;
    1299              : 
    1300       130642 :         PriNode = state.dataHVACSingleDuctInduc->IndUnit(IUNum).PriAirInNode;
    1301       130642 :         OutletNode = state.dataHVACSingleDuctInduc->IndUnit(IUNum).OutAirNode;
    1302       130642 :         PriAirMassFlow = state.dataLoopNodes->Node(PriNode).MassFlowRateMaxAvail;
    1303       130642 :         InducRat = state.dataHVACSingleDuctInduc->IndUnit(IUNum).InducRatio;
    1304       130642 :         SecAirMassFlow = InducRat * PriAirMassFlow;
    1305       130642 :         TotAirMassFlow = PriAirMassFlow + SecAirMassFlow;
    1306       130642 :         HotControlNode = state.dataHVACSingleDuctInduc->IndUnit(IUNum).HWControlNode;
    1307       130642 :         HWOutletNode = DataPlant::CompData::getPlantComponent(state, state.dataHVACSingleDuctInduc->IndUnit(IUNum).HWPlantLoc).NodeNumOut;
    1308              : 
    1309       130642 :         ColdControlNode = state.dataHVACSingleDuctInduc->IndUnit(IUNum).CWControlNode;
    1310       130642 :         CWOutletNode = DataPlant::CompData::getPlantComponent(state, state.dataHVACSingleDuctInduc->IndUnit(IUNum).CWPlantLoc).NodeNumOut;
    1311              : 
    1312       130642 :         mdotHW = HWFlow;
    1313       130642 :         PlantUtilities::SetComponentFlowRate(state, mdotHW, HotControlNode, HWOutletNode, state.dataHVACSingleDuctInduc->IndUnit(IUNum).HWPlantLoc);
    1314              : 
    1315              :         //  Node(HotControlNode)%MassFlowRate = HWFlow
    1316              : 
    1317       130642 :         mdotCW = CWFlow;
    1318       130642 :         PlantUtilities::SetComponentFlowRate(state, mdotCW, ColdControlNode, CWOutletNode, state.dataHVACSingleDuctInduc->IndUnit(IUNum).CWPlantLoc);
    1319              :         //  Node(ColdControlNode)%MassFlowRate = CWFlow
    1320              : 
    1321       261284 :         WaterCoils::SimulateWaterCoilComponents(
    1322       130642 :             state, state.dataHVACSingleDuctInduc->IndUnit(IUNum).HCoil, FirstHVACIteration, state.dataHVACSingleDuctInduc->IndUnit(IUNum).HCoil_Num);
    1323       261284 :         WaterCoils::SimulateWaterCoilComponents(
    1324       130642 :             state, state.dataHVACSingleDuctInduc->IndUnit(IUNum).CCoil, FirstHVACIteration, state.dataHVACSingleDuctInduc->IndUnit(IUNum).CCoil_Num);
    1325       130642 :         MixerComponent::SimAirMixer(
    1326       130642 :             state, state.dataHVACSingleDuctInduc->IndUnit(IUNum).MixerName, state.dataHVACSingleDuctInduc->IndUnit(IUNum).Mixer_Num);
    1327       130642 :         LoadMet = TotAirMassFlow * Psychrometrics::PsyDeltaHSenFnTdb2W2Tdb1W1(state.dataLoopNodes->Node(OutletNode).Temp,
    1328       130642 :                                                                               state.dataLoopNodes->Node(OutletNode).HumRat,
    1329       130642 :                                                                               state.dataLoopNodes->Node(ZoneNode).Temp,
    1330       130642 :                                                                               state.dataLoopNodes->Node(ZoneNode).HumRat);
    1331       130642 :     }
    1332              : 
    1333            6 :     bool FourPipeInductionUnitHasMixer(EnergyPlusData &state, std::string_view CompName) // component (mixer) name
    1334              :     {
    1335              : 
    1336              :         // FUNCTION INFORMATION:
    1337              :         //       AUTHOR         Linda Lawrie
    1338              :         //       DATE WRITTEN   September 2011
    1339              : 
    1340              :         // PURPOSE OF THIS FUNCTION:
    1341              :         // Given a mixer name, this routine determines if that mixer is found on PIUnits.
    1342              : 
    1343            6 :         if (state.dataHVACSingleDuctInduc->GetIUInputFlag) {
    1344            1 :             GetIndUnits(state);
    1345            1 :             state.dataHVACSingleDuctInduc->GetIUInputFlag = false;
    1346              :         }
    1347              : 
    1348            6 :         if (state.dataHVACSingleDuctInduc->NumIndUnits > 0) {
    1349            4 :             int ItemNum = Util::FindItemInList(CompName, state.dataHVACSingleDuctInduc->IndUnit, &IndUnitData::MixerName);
    1350            4 :             if (ItemNum > 0) {
    1351            4 :                 return true;
    1352              :             }
    1353              :         }
    1354              : 
    1355            2 :         return false;
    1356              :     }
    1357              : 
    1358        11976 :     void IndUnitData::ReportIndUnit(EnergyPlusData &state)
    1359              :     {
    1360              :         // set zone OA volume flow rate
    1361        11976 :         this->CalcOutdoorAirVolumeFlowRate(state);
    1362        11976 :     }
    1363              : 
    1364        11976 :     void IndUnitData::CalcOutdoorAirVolumeFlowRate(EnergyPlusData &state)
    1365              :     {
    1366              :         // calculates zone outdoor air volume flow rate using the supply air flow rate and OA fraction
    1367        11976 :         if (this->AirLoopNum > 0) {
    1368        11972 :             this->OutdoorAirFlowRate = (state.dataLoopNodes->Node(this->PriAirInNode).MassFlowRate / state.dataEnvrn->StdRhoAir) *
    1369        11972 :                                        state.dataAirLoop->AirLoopFlow(this->AirLoopNum).OAFrac;
    1370              :         } else {
    1371            4 :             this->OutdoorAirFlowRate = 0.0;
    1372              :         }
    1373        11976 :     }
    1374              : 
    1375            4 :     void IndUnitData::reportTerminalUnit(EnergyPlusData &state)
    1376              :     {
    1377              :         // populate the predefined equipment summary report related to air terminals
    1378            4 :         auto &orp = state.dataOutRptPredefined;
    1379            4 :         auto &adu = state.dataDefineEquipment->AirDistUnit(this->ADUNum);
    1380            4 :         if (!state.dataSize->TermUnitFinalZoneSizing.empty()) {
    1381            4 :             auto &sizing = state.dataSize->TermUnitFinalZoneSizing(adu.TermUnitSizingNum);
    1382            4 :             OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermMinFlow, adu.Name, sizing.DesCoolVolFlowMin);
    1383            4 :             OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermMinOutdoorFlow, adu.Name, sizing.MinOA);
    1384            4 :             OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermSupCoolingSP, adu.Name, sizing.CoolDesTemp);
    1385            4 :             OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermSupHeatingSP, adu.Name, sizing.HeatDesTemp);
    1386            4 :             OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermHeatingCap, adu.Name, sizing.DesHeatLoad);
    1387            4 :             OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermCoolingCap, adu.Name, sizing.DesCoolLoad);
    1388              :         }
    1389            4 :         OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermTypeInp, adu.Name, this->UnitType);
    1390            4 :         OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermPrimFlow, adu.Name, this->MaxPriAirMassFlow);
    1391            4 :         OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermSecdFlow, adu.Name, this->MaxSecAirMassFlow);
    1392            4 :         OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermMinFlowSch, adu.Name, "n/a");
    1393            4 :         OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermMaxFlowReh, adu.Name, "n/a");
    1394            4 :         OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermMinOAflowSch, adu.Name, "n/a");
    1395            4 :         OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermHeatCoilType, adu.Name, this->HCoilType);
    1396            4 :         OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermCoolCoilType, adu.Name, this->CCoilType);
    1397            4 :         OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermFanType, adu.Name, "n/a");
    1398            4 :         OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermFanName, adu.Name, "n/a");
    1399            4 :     }
    1400              : 
    1401              : } // namespace HVACSingleDuctInduc
    1402              : 
    1403              : } // namespace EnergyPlus
        

Generated by: LCOV version 2.0-1