LCOV - code coverage report
Current view: top level - EnergyPlus - HVACSingleDuctInduc.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 20.2 % 738 149
Test Date: 2025-05-22 16:09:37 Functions: 16.7 % 12 2

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

Generated by: LCOV version 2.0-1