LCOV - code coverage report
Current view: top level - EnergyPlus - HVACSingleDuctInduc.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 525 738 71.1 %
Date: 2023-01-17 19:17:23 Functions: 13 13 100.0 %

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

Generated by: LCOV version 1.13