LCOV - code coverage report
Current view: top level - EnergyPlus - HVACSingleDuctInduc.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 533 747 71.4 %
Date: 2024-08-24 18:31:18 Functions: 12 12 100.0 %

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

Generated by: LCOV version 1.14