LCOV - code coverage report
Current view: top level - EnergyPlus - ZonePlenum.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 550 644 85.4 %
Date: 2024-08-24 18:31:18 Functions: 13 13 100.0 %

          Line data    Source code
       1             : // EnergyPlus, Copyright (c) 1996-2024, The Board of Trustees of the University of Illinois,
       2             : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
       3             : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
       4             : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
       5             : // contributors. All rights reserved.
       6             : //
       7             : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
       8             : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
       9             : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
      10             : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
      11             : // derivative works, and perform publicly and display publicly, and to permit others to do so.
      12             : //
      13             : // Redistribution and use in source and binary forms, with or without modification, are permitted
      14             : // provided that the following conditions are met:
      15             : //
      16             : // (1) Redistributions of source code must retain the above copyright notice, this list of
      17             : //     conditions and the following disclaimer.
      18             : //
      19             : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
      20             : //     conditions and the following disclaimer in the documentation and/or other materials
      21             : //     provided with the distribution.
      22             : //
      23             : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
      24             : //     the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
      25             : //     used to endorse or promote products derived from this software without specific prior
      26             : //     written permission.
      27             : //
      28             : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
      29             : //     without changes from the version obtained under this License, or (ii) Licensee makes a
      30             : //     reference solely to the software portion of its product, Licensee must refer to the
      31             : //     software as "EnergyPlus version X" software, where "X" is the version number Licensee
      32             : //     obtained under this License and may not use a different name for the software. Except as
      33             : //     specifically required in this Section (4), Licensee shall not use in a company name, a
      34             : //     product name, in advertising, publicity, or other promotional activities any name, trade
      35             : //     name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
      36             : //     similar designation, without the U.S. Department of Energy's prior written consent.
      37             : //
      38             : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
      39             : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
      40             : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
      41             : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      42             : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      43             : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      44             : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      45             : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      46             : // POSSIBILITY OF SUCH DAMAGE.
      47             : 
      48             : // C++ Headers
      49             : #include <algorithm>
      50             : #include <cmath>
      51             : 
      52             : // ObjexxFCL Headers
      53             : #include <ObjexxFCL/Fmath.hh>
      54             : 
      55             : // EnergyPlus Headers
      56             : #include <EnergyPlus/Data/EnergyPlusData.hh>
      57             : #include <EnergyPlus/DataContaminantBalance.hh>
      58             : #include <EnergyPlus/DataEnvironment.hh>
      59             : #include <EnergyPlus/DataHeatBalance.hh>
      60             : #include <EnergyPlus/DataLoopNode.hh>
      61             : #include <EnergyPlus/DataZoneEquipment.hh>
      62             : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      63             : #include <EnergyPlus/NodeInputManager.hh>
      64             : #include <EnergyPlus/PoweredInductionUnits.hh>
      65             : #include <EnergyPlus/Psychrometrics.hh>
      66             : #include <EnergyPlus/PurchasedAirManager.hh>
      67             : #include <EnergyPlus/UtilityRoutines.hh>
      68             : #include <EnergyPlus/ZonePlenum.hh>
      69             : 
      70             : namespace EnergyPlus::ZonePlenum {
      71             : // Module containing simulation routines for both zone return and zone supply plenums
      72             : 
      73             : // MODULE INFORMATION:
      74             : //       AUTHOR         Peter Graham Ellis
      75             : //       DATE WRITTEN   November 2000
      76             : //       MODIFIED       na
      77             : //       RE-ENGINEERED  na
      78             : 
      79             : // PURPOSE OF THIS MODULE:
      80             : // To encapsulate the data and algorithms required to
      81             : // manage Air Path Zone Return Plenum Components
      82             : 
      83             : // METHODOLOGY EMPLOYED:
      84             : // The Zone Plenum
      85             : 
      86             : // Using/Aliasing
      87             : using namespace DataLoopNode;
      88             : using Psychrometrics::PsyHFnTdbW;
      89             : using Psychrometrics::PsyTdbFnHW;
      90             : 
      91             : // Functions
      92             : 
      93     2687292 : void SimAirZonePlenum(EnergyPlusData &state,
      94             :                       std::string_view CompName,
      95             :                       DataZoneEquipment::AirLoopHVACZone const iCompType,
      96             :                       int &CompIndex,
      97             :                       ObjexxFCL::Optional_bool_const FirstHVACIteration, // Autodesk:OPTIONAL Used without PRESENT check
      98             :                       ObjexxFCL::Optional_bool_const FirstCall,          // Autodesk:OPTIONAL Used without PRESENT check
      99             :                       ObjexxFCL::Optional_bool PlenumInletChanged        // Autodesk:OPTIONAL Used without PRESENT check
     100             : )
     101             : {
     102             : 
     103             :     // SUBROUTINE INFORMATION:
     104             :     //       AUTHOR         Peter Graham Ellis
     105             :     //       DATE WRITTEN   November 2000
     106             :     //       MODIFIED       March 2000
     107             :     //       RE-ENGINEERED  na
     108             : 
     109             :     // PURPOSE OF THIS SUBROUTINE:
     110             :     // This subroutine manages the ZonePlenum component simulation for both
     111             :     // return and supply plenums.
     112             :     // It is called from the SimAirLoopComponent at the system time step.
     113             : 
     114             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     115             :     int ZonePlenumNum; // The ZonePlenum that you are currently loading input into
     116             : 
     117             :     // Obtains and Allocates ZonePlenum related parameters from input file
     118     2687292 :     if (state.dataZonePlenum->GetInputFlag) { // First time subroutine has been entered
     119         192 :         GetZonePlenumInput(state);
     120         192 :         state.dataZonePlenum->GetInputFlag = false;
     121             :     }
     122             : 
     123     2687292 :     if (iCompType == DataZoneEquipment::AirLoopHVACZone::ReturnPlenum) { // 'AirLoopHVAC:ReturnPlenum'
     124             :         // Find the correct ZonePlenumNumber
     125     2609056 :         if (CompIndex == 0) {
     126         283 :             ZonePlenumNum = Util::FindItemInList(CompName, state.dataZonePlenum->ZoneRetPlenCond, &ZoneReturnPlenumConditions::ZonePlenumName);
     127         283 :             if (ZonePlenumNum == 0) {
     128           0 :                 ShowFatalError(state, format("SimAirZonePlenum: AirLoopHVAC:ReturnPlenum not found={}", CompName));
     129             :             }
     130         283 :             CompIndex = ZonePlenumNum;
     131             :         } else {
     132     2608773 :             ZonePlenumNum = CompIndex;
     133     2608773 :             if (ZonePlenumNum > state.dataZonePlenum->NumZoneReturnPlenums || ZonePlenumNum < 1) {
     134           0 :                 ShowFatalError(
     135             :                     state,
     136           0 :                     format("SimAirZonePlenum: Invalid CompIndex passed={}, Number of AirLoopHVAC:ReturnPlenum={}, AirLoopHVAC:ReturnPlenum name={}",
     137             :                            ZonePlenumNum,
     138           0 :                            state.dataZonePlenum->NumZoneReturnPlenums,
     139             :                            CompName));
     140             :             }
     141     2608773 :             if (state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).checkEquipName) {
     142         284 :                 if (CompName != state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).ZonePlenumName) {
     143           0 :                     ShowFatalError(state,
     144           0 :                                    format("SimAirZonePlenum: Invalid CompIndex passed={}, AirLoopHVAC:ReturnPlenum name={}, stored "
     145             :                                           "AirLoopHVAC:ReturnPlenum Name for that index={}",
     146             :                                           ZonePlenumNum,
     147             :                                           CompName,
     148           0 :                                           state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).ZonePlenumName));
     149             :                 }
     150         284 :                 state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).checkEquipName = false;
     151             :             }
     152             :         }
     153             : 
     154     2609056 :         InitAirZoneReturnPlenum(state, ZonePlenumNum); // Initialize all ZonePlenum related parameters
     155             : 
     156     2609056 :         CalcAirZoneReturnPlenum(state, ZonePlenumNum);
     157             : 
     158     2609056 :         UpdateAirZoneReturnPlenum(state, ZonePlenumNum); // Update the current ZonePlenum to the outlet nodes
     159             : 
     160       78236 :     } else if (iCompType == DataZoneEquipment::AirLoopHVACZone::SupplyPlenum) { // 'AirLoopHVAC:SupplyPlenum'
     161             :         // Find the correct ZonePlenumNumber
     162       78236 :         if (CompIndex == 0) {
     163           8 :             ZonePlenumNum = Util::FindItemInList(CompName, state.dataZonePlenum->ZoneSupPlenCond, &ZoneSupplyPlenumConditions::ZonePlenumName);
     164           8 :             if (ZonePlenumNum == 0) {
     165           0 :                 ShowFatalError(state, format("SimAirZonePlenum: AirLoopHVAC:SupplyPlenum not found={}", CompName));
     166             :             }
     167           8 :             CompIndex = ZonePlenumNum;
     168             :         } else {
     169       78228 :             ZonePlenumNum = CompIndex;
     170       78228 :             if (ZonePlenumNum > state.dataZonePlenum->NumZoneSupplyPlenums || ZonePlenumNum < 1) {
     171           0 :                 ShowFatalError(
     172             :                     state,
     173           0 :                     format("SimAirZonePlenum: Invalid CompIndex passed={}, Number of AirLoopHVAC:SupplyPlenum={}, AirLoopHVAC:SupplyPlenum name={}",
     174             :                            ZonePlenumNum,
     175           0 :                            state.dataZonePlenum->NumZoneReturnPlenums,
     176             :                            CompName));
     177             :             }
     178       78228 :             if (state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).checkEquipName) {
     179           8 :                 if (CompName != state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).ZonePlenumName) {
     180           0 :                     ShowFatalError(state,
     181           0 :                                    format("SimAirZonePlenum: Invalid CompIndex passed={}, AirLoopHVAC:SupplyPlenum name={}, stored "
     182             :                                           "AirLoopHVAC:SupplyPlenum Name for that index={}",
     183             :                                           ZonePlenumNum,
     184             :                                           CompName,
     185           0 :                                           state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).ZonePlenumName));
     186             :                 }
     187           8 :                 state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).checkEquipName = false;
     188             :             }
     189             :         }
     190             : 
     191       78236 :         InitAirZoneSupplyPlenum(state, ZonePlenumNum, FirstHVACIteration, FirstCall); // Initialize all ZonePlenum related parameters
     192             : 
     193       78236 :         CalcAirZoneSupplyPlenum(state, ZonePlenumNum, FirstCall);
     194             :         // Update the current ZonePlenum to the outlet nodes
     195       78236 :         UpdateAirZoneSupplyPlenum(state, ZonePlenumNum, PlenumInletChanged, FirstCall);
     196             : 
     197             :     } else {
     198           0 :         ShowSevereError(state, format("SimAirZonePlenum: Errors in Plenum={}", CompName));
     199           0 :         ShowContinueError(state, format("ZonePlenum: Unhandled plenum type found:{}", iCompType));
     200           0 :         ShowFatalError(state, "Preceding conditions cause termination.");
     201             :     }
     202     2687292 : }
     203             : 
     204         198 : void GetZonePlenumInput(EnergyPlusData &state)
     205             : {
     206             : 
     207             :     // SUBROUTINE INFORMATION:
     208             :     //       AUTHOR         Peter Graham Ellis
     209             :     //       DATE WRITTEN   November 2000
     210             :     //       MODIFIED       August 2003, FCW: For each zone with a return air plenum put the ZoneRetPlenCond
     211             :     //                       number for the return air plenum in the ZoneEquipConfig array for the zone
     212             :     //                       for later access to the zone's return air plenum conditions.
     213             :     //       RE-ENGINEERED  na
     214             : 
     215             :     // PURPOSE OF THIS SUBROUTINE:
     216             :     // This subroutine is the main routine to call other input routines and Get routines
     217             : 
     218             :     // METHODOLOGY EMPLOYED:
     219             :     // Uses the status flags to trigger events.
     220             : 
     221             :     // Using/Aliasing
     222             :     using DataZoneEquipment::EquipConfiguration;
     223             :     using NodeInputManager::CheckUniqueNodeNumbers;
     224             :     using NodeInputManager::EndUniqueNodeCheck;
     225             :     using NodeInputManager::GetNodeNums;
     226             :     using NodeInputManager::GetOnlySingleNode;
     227             :     using NodeInputManager::InitUniqueNodeCheck;
     228             :     using PoweredInductionUnits::PIUInducesPlenumAir;
     229             :     using PurchasedAirManager::CheckPurchasedAirForReturnPlenum;
     230             : 
     231             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     232             :     int ZoneEquipConfigLoop;
     233             :     int NumAlphas;
     234             :     int NumNums;
     235             :     int NumArgs;
     236             :     int NumNodes;
     237         198 :     Array1D_int NodeNums;
     238             :     int MaxNums;
     239             :     int MaxAlphas;
     240             :     int NodeNum;
     241             :     int IOStat;
     242         198 :     Array1D<Real64> NumArray;        // Numeric input items for object
     243         198 :     std::string CurrentModuleObject; // for ease in getting objects
     244         198 :     Array1D_string AlphArray;        // Alpha input items for object
     245         198 :     Array1D_string cAlphaFields;     // Alpha field names
     246         198 :     Array1D_string cNumericFields;   // Numeric field names
     247         198 :     Array1D_bool lAlphaBlanks;       // Logical array, alpha field input BLANK = .TRUE.
     248         198 :     Array1D_bool lNumericBlanks;     // Logical array, numeric field input BLANK = .TRUE.
     249         198 :     bool ErrorsFound(false);
     250             :     bool NodeListError; // Flag for node list error
     251             :     bool UniqueNodeError;
     252             :     static constexpr std::string_view RoutineName("GetZonePlenumInput: "); // include trailing blank space
     253         198 :     std::string InducedNodeListName;
     254             : 
     255         198 :     state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, "AirLoopHVAC:ReturnPlenum", NumArgs, NumAlphas, NumNums);
     256         198 :     MaxNums = NumNums;
     257         198 :     MaxAlphas = NumAlphas;
     258         198 :     state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, "AirLoopHVAC:SupplyPlenum", NumArgs, NumAlphas, NumNums);
     259         198 :     MaxNums = max(NumNums, MaxNums);
     260         198 :     MaxAlphas = max(NumAlphas, MaxAlphas);
     261         198 :     AlphArray.allocate(MaxAlphas);
     262         198 :     cAlphaFields.allocate(MaxAlphas);
     263         198 :     cNumericFields.allocate(MaxNums);
     264         198 :     NumArray.dimension(MaxNums, 0.0);
     265         198 :     lAlphaBlanks.dimension(MaxAlphas, true);
     266         198 :     lNumericBlanks.dimension(MaxNums, true);
     267         198 :     state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, "NodeList", NumArgs, NumAlphas, NumNums);
     268         198 :     NodeNums.dimension(NumArgs, 0);
     269             : 
     270         198 :     InducedNodeListName = "";
     271             : 
     272         198 :     state.dataZonePlenum->NumZoneReturnPlenums = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "AirLoopHVAC:ReturnPlenum");
     273         198 :     state.dataZonePlenum->NumZoneSupplyPlenums = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "AirLoopHVAC:SupplyPlenum");
     274             : 
     275         198 :     if (state.dataZonePlenum->NumZoneReturnPlenums > 0) {
     276         190 :         state.dataZonePlenum->ZoneRetPlenCond.allocate(state.dataZonePlenum->NumZoneReturnPlenums);
     277             :     }
     278         198 :     if (state.dataZonePlenum->NumZoneSupplyPlenums > 0) {
     279           6 :         state.dataZonePlenum->ZoneSupPlenCond.allocate(state.dataZonePlenum->NumZoneSupplyPlenums);
     280             :     }
     281             : 
     282         198 :     InitUniqueNodeCheck(state, "AirLoopHVAC:ReturnPlenum");
     283         482 :     for (int ZonePlenumNum = 1; ZonePlenumNum <= state.dataZonePlenum->NumZoneReturnPlenums; ++ZonePlenumNum) {
     284             : 
     285         284 :         CurrentModuleObject = "AirLoopHVAC:ReturnPlenum";
     286             : 
     287         284 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     288             :                                                                  CurrentModuleObject,
     289             :                                                                  ZonePlenumNum,
     290             :                                                                  AlphArray,
     291             :                                                                  NumAlphas,
     292             :                                                                  NumArray,
     293             :                                                                  NumNums,
     294             :                                                                  IOStat,
     295             :                                                                  lNumericBlanks,
     296             :                                                                  lAlphaBlanks,
     297             :                                                                  cAlphaFields,
     298             :                                                                  cNumericFields);
     299         284 :         Util::IsNameEmpty(state, AlphArray(1), CurrentModuleObject, ErrorsFound);
     300             : 
     301         284 :         auto &thisRetPlenum = state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum);
     302         284 :         thisRetPlenum.ZonePlenumName = AlphArray(1);
     303             : 
     304             :         // Check if this zone is also used in another return plenum
     305         284 :         IOStat = Util::FindItemInList(AlphArray(2), state.dataZonePlenum->ZoneRetPlenCond, &ZoneReturnPlenumConditions::ZoneName, ZonePlenumNum - 1);
     306         284 :         if (IOStat != 0) {
     307           0 :             ShowSevereError(state,
     308           0 :                             format("{}{} \"{}\" is used more than once as a {}.", RoutineName, cAlphaFields(2), AlphArray(2), CurrentModuleObject));
     309           0 :             ShowContinueError(state, format("..Only one {} object may be connected to a given zone.", CurrentModuleObject));
     310           0 :             ShowContinueError(state, format("..occurs in {} = {}", CurrentModuleObject, AlphArray(1)));
     311           0 :             ErrorsFound = true;
     312             :         }
     313         284 :         thisRetPlenum.ZoneName = AlphArray(2);
     314             :         // put the X-Ref to the zone heat balance data structure
     315         284 :         thisRetPlenum.ActualZoneNum = Util::FindItemInList(AlphArray(2), state.dataHeatBal->Zone);
     316         284 :         if (thisRetPlenum.ActualZoneNum == 0) {
     317           0 :             ShowSevereError(state, format("For {} = {}, {} = {} not found.", CurrentModuleObject, AlphArray(1), cAlphaFields(2), AlphArray(2)));
     318           0 :             ErrorsFound = true;
     319           0 :             continue;
     320             :         } else {
     321         284 :             state.dataHeatBal->Zone(thisRetPlenum.ActualZoneNum).IsReturnPlenum = true;
     322         284 :             state.dataHeatBal->Zone(thisRetPlenum.ActualZoneNum).PlenumCondNum = ZonePlenumNum;
     323             :         }
     324             :         //  Check if this zone is used as a controlled zone
     325         284 :         ZoneEquipConfigLoop = Util::FindItemInList(AlphArray(2), state.dataZoneEquip->ZoneEquipConfig, &EquipConfiguration::ZoneName);
     326         284 :         if (ZoneEquipConfigLoop != 0) {
     327           0 :             ShowSevereError(
     328             :                 state,
     329           0 :                 format(
     330             :                     "{}{} \"{}\" is a controlled zone. It cannot be used as a {}", RoutineName, cAlphaFields(2), AlphArray(2), CurrentModuleObject));
     331           0 :             ShowContinueError(state, format("..occurs in {} = {}", CurrentModuleObject, AlphArray(1)));
     332           0 :             ErrorsFound = true;
     333             :         }
     334             : 
     335         284 :         thisRetPlenum.ZoneNodeName = AlphArray(3);
     336         284 :         thisRetPlenum.ZoneNodeNum = GetOnlySingleNode(state,
     337         284 :                                                       AlphArray(3),
     338             :                                                       ErrorsFound,
     339             :                                                       DataLoopNode::ConnectionObjectType::AirLoopHVACReturnPlenum,
     340         284 :                                                       AlphArray(1),
     341             :                                                       DataLoopNode::NodeFluidType::Air,
     342             :                                                       DataLoopNode::ConnectionType::ZoneNode,
     343             :                                                       NodeInputManager::CompFluidStream::Primary,
     344             :                                                       ObjectIsNotParent);
     345             :         // Insert the Plenum Zone Number into the Zone Heat Balance data structure for later reference
     346         284 :         state.dataHeatBal->Zone(thisRetPlenum.ActualZoneNum).SystemZoneNodeNumber = thisRetPlenum.ZoneNodeNum;
     347             :         // SpaceHB TODO: For now, assign the same system node to the spaces in the zone
     348         568 :         for (int spaceNum : state.dataHeatBal->Zone(thisRetPlenum.ActualZoneNum).spaceIndexes) {
     349         284 :             state.dataHeatBal->space(spaceNum).SystemZoneNodeNumber = thisRetPlenum.ZoneNodeNum;
     350         284 :         }
     351             : 
     352         284 :         thisRetPlenum.OutletNode = GetOnlySingleNode(state,
     353         284 :                                                      AlphArray(4),
     354             :                                                      ErrorsFound,
     355             :                                                      DataLoopNode::ConnectionObjectType::AirLoopHVACReturnPlenum,
     356         284 :                                                      AlphArray(1),
     357             :                                                      DataLoopNode::NodeFluidType::Air,
     358             :                                                      DataLoopNode::ConnectionType::Outlet,
     359             :                                                      NodeInputManager::CompFluidStream::Primary,
     360             :                                                      ObjectIsNotParent);
     361             : 
     362         284 :         InducedNodeListName = AlphArray(5);
     363         284 :         NodeListError = false;
     364         568 :         GetNodeNums(state,
     365             :                     InducedNodeListName,
     366             :                     NumNodes,
     367             :                     NodeNums,
     368             :                     NodeListError,
     369             :                     DataLoopNode::NodeFluidType::Air,
     370             :                     DataLoopNode::ConnectionObjectType::AirLoopHVACReturnPlenum,
     371         284 :                     thisRetPlenum.ZonePlenumName,
     372             :                     DataLoopNode::ConnectionType::InducedAir,
     373             :                     NodeInputManager::CompFluidStream::Primary,
     374             :                     ObjectIsNotParent,
     375             :                     false,
     376         284 :                     cAlphaFields(5));
     377             : 
     378         284 :         if (!NodeListError) {
     379         284 :             thisRetPlenum.NumInducedNodes = NumNodes;
     380         284 :             thisRetPlenum.InducedNode.allocate(thisRetPlenum.NumInducedNodes);
     381         284 :             thisRetPlenum.InducedMassFlowRate.allocate(thisRetPlenum.NumInducedNodes);
     382         284 :             thisRetPlenum.InducedMassFlowRateMaxAvail.allocate(thisRetPlenum.NumInducedNodes);
     383         284 :             thisRetPlenum.InducedMassFlowRateMinAvail.allocate(thisRetPlenum.NumInducedNodes);
     384         284 :             thisRetPlenum.InducedTemp.allocate(thisRetPlenum.NumInducedNodes);
     385         284 :             thisRetPlenum.InducedHumRat.allocate(thisRetPlenum.NumInducedNodes);
     386         284 :             thisRetPlenum.InducedEnthalpy.allocate(thisRetPlenum.NumInducedNodes);
     387         284 :             thisRetPlenum.InducedPressure.allocate(thisRetPlenum.NumInducedNodes);
     388         284 :             thisRetPlenum.InducedCO2.allocate(thisRetPlenum.NumInducedNodes);
     389         284 :             thisRetPlenum.InducedGenContam.allocate(thisRetPlenum.NumInducedNodes);
     390         284 :             thisRetPlenum.InducedMassFlowRate = 0.0;
     391         284 :             thisRetPlenum.InducedMassFlowRateMaxAvail = 0.0;
     392         284 :             thisRetPlenum.InducedMassFlowRateMinAvail = 0.0;
     393         284 :             thisRetPlenum.InducedTemp = 0.0;
     394         284 :             thisRetPlenum.InducedHumRat = 0.0;
     395         284 :             thisRetPlenum.InducedEnthalpy = 0.0;
     396         284 :             thisRetPlenum.InducedPressure = 0.0;
     397         284 :             thisRetPlenum.InducedCO2 = 0.0;
     398         284 :             thisRetPlenum.InducedGenContam = 0.0;
     399         310 :             for (NodeNum = 1; NodeNum <= NumNodes; ++NodeNum) {
     400          26 :                 thisRetPlenum.InducedNode(NodeNum) = NodeNums(NodeNum);
     401          26 :                 UniqueNodeError = false;
     402          26 :                 if (!CheckPurchasedAirForReturnPlenum(state, ZonePlenumNum)) {
     403          26 :                     CheckUniqueNodeNumbers(state, "Return Plenum Induced Air Nodes", UniqueNodeError, NodeNums(NodeNum), CurrentModuleObject);
     404          26 :                     if (UniqueNodeError) {
     405           0 :                         ShowContinueError(state, format("Occurs for ReturnPlenum = {}", AlphArray(1)));
     406           0 :                         ErrorsFound = true;
     407             :                     }
     408          26 :                     PIUInducesPlenumAir(state, thisRetPlenum.InducedNode(NodeNum), ZonePlenumNum);
     409             :                 }
     410             :             }
     411             :         } else {
     412           0 :             ShowContinueError(
     413             :                 state,
     414           0 :                 format("Invalid Induced Air Outlet Node or NodeList name in AirLoopHVAC:ReturnPlenum object = {}", thisRetPlenum.ZonePlenumName));
     415           0 :             ErrorsFound = true;
     416             :         }
     417             : 
     418         284 :         thisRetPlenum.NumInletNodes = NumAlphas - 5;
     419             : 
     420         974 :         for (auto &e : state.dataZonePlenum->ZoneRetPlenCond) {
     421         690 :             e.InitFlag = true;
     422         284 :         }
     423             : 
     424         284 :         thisRetPlenum.InletNode.allocate(thisRetPlenum.NumInletNodes);
     425         284 :         thisRetPlenum.InletMassFlowRate.allocate(thisRetPlenum.NumInletNodes);
     426         284 :         thisRetPlenum.InletMassFlowRateMaxAvail.allocate(thisRetPlenum.NumInletNodes);
     427         284 :         thisRetPlenum.InletMassFlowRateMinAvail.allocate(thisRetPlenum.NumInletNodes);
     428         284 :         thisRetPlenum.InletTemp.allocate(thisRetPlenum.NumInletNodes);
     429         284 :         thisRetPlenum.InletHumRat.allocate(thisRetPlenum.NumInletNodes);
     430         284 :         thisRetPlenum.InletEnthalpy.allocate(thisRetPlenum.NumInletNodes);
     431         284 :         thisRetPlenum.InletPressure.allocate(thisRetPlenum.NumInletNodes);
     432         284 :         thisRetPlenum.ZoneEqNum.allocate(thisRetPlenum.NumInletNodes);
     433             : 
     434         284 :         thisRetPlenum.InletNode = 0;
     435         284 :         thisRetPlenum.InletMassFlowRate = 0.0;
     436         284 :         thisRetPlenum.InletMassFlowRateMaxAvail = 0.0;
     437         284 :         thisRetPlenum.InletMassFlowRateMinAvail = 0.0;
     438         284 :         thisRetPlenum.InletTemp = 0.0;
     439         284 :         thisRetPlenum.InletHumRat = 0.0;
     440         284 :         thisRetPlenum.InletEnthalpy = 0.0;
     441         284 :         thisRetPlenum.InletPressure = 0.0;
     442         284 :         thisRetPlenum.OutletMassFlowRate = 0.0;
     443         284 :         thisRetPlenum.OutletMassFlowRateMaxAvail = 0.0;
     444         284 :         thisRetPlenum.OutletMassFlowRateMinAvail = 0.0;
     445         284 :         thisRetPlenum.OutletTemp = 0.0;
     446         284 :         thisRetPlenum.OutletHumRat = 0.0;
     447         284 :         thisRetPlenum.OutletEnthalpy = 0.0;
     448         284 :         thisRetPlenum.OutletPressure = 0.0;
     449         284 :         thisRetPlenum.ZoneTemp = 0.0;
     450         284 :         thisRetPlenum.ZoneHumRat = 0.0;
     451         284 :         thisRetPlenum.ZoneEnthalpy = 0.0;
     452             : 
     453        1599 :         for (NodeNum = 1; NodeNum <= thisRetPlenum.NumInletNodes; ++NodeNum) {
     454             : 
     455        2630 :             thisRetPlenum.InletNode(NodeNum) = GetOnlySingleNode(state,
     456        1315 :                                                                  AlphArray(5 + NodeNum),
     457             :                                                                  ErrorsFound,
     458             :                                                                  DataLoopNode::ConnectionObjectType::AirLoopHVACReturnPlenum,
     459        1315 :                                                                  AlphArray(1),
     460             :                                                                  DataLoopNode::NodeFluidType::Air,
     461             :                                                                  DataLoopNode::ConnectionType::Inlet,
     462             :                                                                  NodeInputManager::CompFluidStream::Primary,
     463             :                                                                  ObjectIsNotParent);
     464             :         }
     465             : 
     466             :     } // end AirLoopHVAC:ReturnPlenum Loop
     467         198 :     EndUniqueNodeCheck(state, "AirLoopHVAC:ReturnPlenum");
     468             : 
     469         206 :     for (int ZonePlenumNum = 1; ZonePlenumNum <= state.dataZonePlenum->NumZoneSupplyPlenums; ++ZonePlenumNum) {
     470           8 :         CurrentModuleObject = "AirLoopHVAC:SupplyPlenum";
     471             : 
     472           8 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     473             :                                                                  CurrentModuleObject,
     474             :                                                                  ZonePlenumNum,
     475             :                                                                  AlphArray,
     476             :                                                                  NumAlphas,
     477             :                                                                  NumArray,
     478             :                                                                  NumNums,
     479             :                                                                  IOStat,
     480             :                                                                  lNumericBlanks,
     481             :                                                                  lAlphaBlanks,
     482             :                                                                  cAlphaFields,
     483             :                                                                  cNumericFields);
     484           8 :         Util::IsNameEmpty(state, AlphArray(1), CurrentModuleObject, ErrorsFound);
     485             : 
     486           8 :         auto &thisSupPlenum = state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum);
     487           8 :         thisSupPlenum.ZonePlenumName = AlphArray(1);
     488             : 
     489             :         // Check if this zone is also used in another plenum
     490           8 :         IOStat = Util::FindItemInList(AlphArray(2), state.dataZonePlenum->ZoneSupPlenCond, &ZoneSupplyPlenumConditions::ZoneName, ZonePlenumNum - 1);
     491           8 :         if (IOStat != 0) {
     492           0 :             ShowSevereError(state,
     493           0 :                             format("{}{} \"{}\" is used more than once as a {}.", RoutineName, cAlphaFields(2), AlphArray(2), CurrentModuleObject));
     494           0 :             ShowContinueError(state, format("..Only one {} object may be connected to a given zone.", CurrentModuleObject));
     495           0 :             ShowContinueError(state, format("..occurs in {} = {}", CurrentModuleObject, AlphArray(1)));
     496           0 :             ErrorsFound = true;
     497             :         }
     498           8 :         if (state.dataZonePlenum->NumZoneReturnPlenums > 0) { // Check if this zone is also used in another plenum
     499           2 :             IOStat = Util::FindItemInList(AlphArray(2), state.dataZonePlenum->ZoneRetPlenCond, &ZoneReturnPlenumConditions::ZoneName);
     500           2 :             if (IOStat != 0) {
     501           0 :                 ShowSevereError(state,
     502           0 :                                 format("{}{} \"{}\" is used more than once as a {} or AirLoopHVAC:ReturnPlenum.",
     503             :                                        RoutineName,
     504             :                                        cAlphaFields(2),
     505             :                                        AlphArray(2),
     506             :                                        CurrentModuleObject));
     507           0 :                 ShowContinueError(state,
     508           0 :                                   format("..Only one {} or AirLoopHVAC:ReturnPlenum object may be connected to a given zone.", CurrentModuleObject));
     509           0 :                 ShowContinueError(state, format("..occurs in {} = {}", CurrentModuleObject, AlphArray(1)));
     510           0 :                 ErrorsFound = true;
     511             :             }
     512             :         }
     513           8 :         thisSupPlenum.ZoneName = AlphArray(2);
     514             :         // put the X-Ref to the zone heat balance data structure
     515           8 :         thisSupPlenum.ActualZoneNum = Util::FindItemInList(AlphArray(2), state.dataHeatBal->Zone);
     516           8 :         if (thisSupPlenum.ActualZoneNum == 0) {
     517           0 :             ShowSevereError(state, format("For {} = {}, {} = {} not found.", CurrentModuleObject, AlphArray(1), cAlphaFields(2), AlphArray(2)));
     518           0 :             ErrorsFound = true;
     519           0 :             continue;
     520             :         } else {
     521           8 :             state.dataHeatBal->Zone(thisSupPlenum.ActualZoneNum).IsSupplyPlenum = true;
     522           8 :             state.dataHeatBal->Zone(thisSupPlenum.ActualZoneNum).PlenumCondNum = ZonePlenumNum;
     523             :         }
     524             :         //  Check if this zone is used as a controlled zone
     525           8 :         if (std::any_of(state.dataZoneEquip->ZoneEquipConfig.begin(), state.dataZoneEquip->ZoneEquipConfig.end(), [](EquipConfiguration const &e) {
     526          10 :                 return e.IsControlled;
     527             :             })) {
     528           8 :             ZoneEquipConfigLoop = Util::FindItemInList(AlphArray(2), state.dataZoneEquip->ZoneEquipConfig, &EquipConfiguration::ZoneName);
     529           8 :             if (ZoneEquipConfigLoop != 0) {
     530           0 :                 ShowSevereError(state,
     531           0 :                                 format("{}{} \"{}\" is a controlled zone. It cannot be used as a {} or AirLoopHVAC:ReturnPlenum.",
     532             :                                        RoutineName,
     533             :                                        cAlphaFields(2),
     534             :                                        AlphArray(2),
     535             :                                        CurrentModuleObject));
     536           0 :                 ShowContinueError(state, format("..occurs in {} = {}", CurrentModuleObject, AlphArray(1)));
     537           0 :                 ErrorsFound = true;
     538             :             }
     539             :         }
     540             :         // Check if this is also used as a return plenum
     541             :         //  *** This next IF loop looks wrong.  Sent e-mail to Peter/Brent 8/14/08 for clarification ****
     542             :         //      IF (NumZoneReturnPlenums > 0) THEN
     543             :         //        IOSTAT=Util::FindItemInList(AlphArray(1),ZoneRetPlenCond%ZoneName,NumZoneReturnPlenums)
     544             :         //        IF (IOStat /= 0) THEN
     545             :         //          CALL ShowSevereError(state, RoutineName//'Plenum "'//TRIM(AlphArray(2))//  &
     546             :         //                               '" is a controlled zone.  It cannot be used as a '//  &
     547             :         //                               'SUPPLY PLENUM or RETURN PLENUM.')
     548             :         //          CALL ShowContinueError(state, '..occurs in '//TRIM(CurrentModuleObject)//' = '//TRIM(AlphArray(1)))
     549             :         //          ErrorsFound=.TRUE.
     550             :         //        ENDIF
     551             :         //      ENDIF
     552             : 
     553           8 :         thisSupPlenum.ZoneNodeName = AlphArray(3);
     554           8 :         thisSupPlenum.ZoneNodeNum = GetOnlySingleNode(state,
     555           8 :                                                       AlphArray(3),
     556             :                                                       ErrorsFound,
     557             :                                                       DataLoopNode::ConnectionObjectType::AirLoopHVACSupplyPlenum,
     558           8 :                                                       AlphArray(1),
     559             :                                                       DataLoopNode::NodeFluidType::Air,
     560             :                                                       DataLoopNode::ConnectionType::ZoneNode,
     561             :                                                       NodeInputManager::CompFluidStream::Primary,
     562             :                                                       ObjectIsNotParent);
     563             :         // Insert the Plenum Zone Number into the Zone Heat Balance data structure for later reference
     564           8 :         state.dataHeatBal->Zone(thisSupPlenum.ActualZoneNum).SystemZoneNodeNumber = thisSupPlenum.ZoneNodeNum;
     565             :         // SpaceHB TODO: For now, assign the same system node to the spaces in the zone
     566          16 :         for (int spaceNum : state.dataHeatBal->Zone(thisSupPlenum.ActualZoneNum).spaceIndexes) {
     567           8 :             state.dataHeatBal->space(spaceNum).SystemZoneNodeNumber = thisSupPlenum.ZoneNodeNum;
     568           8 :         }
     569             : 
     570           8 :         thisSupPlenum.InletNode = GetOnlySingleNode(state,
     571           8 :                                                     AlphArray(4),
     572             :                                                     ErrorsFound,
     573             :                                                     DataLoopNode::ConnectionObjectType::AirLoopHVACSupplyPlenum,
     574           8 :                                                     AlphArray(1),
     575             :                                                     DataLoopNode::NodeFluidType::Air,
     576             :                                                     DataLoopNode::ConnectionType::Inlet,
     577             :                                                     NodeInputManager::CompFluidStream::Primary,
     578             :                                                     ObjectIsNotParent);
     579             : 
     580           8 :         thisSupPlenum.NumOutletNodes = NumAlphas - 4;
     581             : 
     582          20 :         for (auto &e : state.dataZonePlenum->ZoneSupPlenCond) {
     583          12 :             e.InitFlag = true;
     584           8 :         }
     585             : 
     586           8 :         thisSupPlenum.OutletNode.allocate(thisSupPlenum.NumOutletNodes);
     587           8 :         thisSupPlenum.OutletMassFlowRate.allocate(thisSupPlenum.NumOutletNodes);
     588           8 :         thisSupPlenum.OutletMassFlowRateMaxAvail.allocate(thisSupPlenum.NumOutletNodes);
     589           8 :         thisSupPlenum.OutletMassFlowRateMinAvail.allocate(thisSupPlenum.NumOutletNodes);
     590           8 :         thisSupPlenum.OutletTemp.allocate(thisSupPlenum.NumOutletNodes);
     591           8 :         thisSupPlenum.OutletHumRat.allocate(thisSupPlenum.NumOutletNodes);
     592           8 :         thisSupPlenum.OutletEnthalpy.allocate(thisSupPlenum.NumOutletNodes);
     593           8 :         thisSupPlenum.OutletPressure.allocate(thisSupPlenum.NumOutletNodes);
     594             : 
     595           8 :         thisSupPlenum.OutletNode = 0;
     596           8 :         thisSupPlenum.OutletMassFlowRate = 0.0;
     597           8 :         thisSupPlenum.OutletMassFlowRateMaxAvail = 0.0;
     598           8 :         thisSupPlenum.OutletMassFlowRateMinAvail = 0.0;
     599           8 :         thisSupPlenum.OutletTemp = 0.0;
     600           8 :         thisSupPlenum.OutletHumRat = 0.0;
     601           8 :         thisSupPlenum.OutletEnthalpy = 0.0;
     602           8 :         thisSupPlenum.OutletPressure = 0.0;
     603           8 :         thisSupPlenum.InletMassFlowRate = 0.0;
     604           8 :         thisSupPlenum.InletMassFlowRateMaxAvail = 0.0;
     605           8 :         thisSupPlenum.InletMassFlowRateMinAvail = 0.0;
     606           8 :         thisSupPlenum.InletTemp = 0.0;
     607           8 :         thisSupPlenum.InletHumRat = 0.0;
     608           8 :         thisSupPlenum.InletEnthalpy = 0.0;
     609           8 :         thisSupPlenum.InletPressure = 0.0;
     610           8 :         thisSupPlenum.ZoneTemp = 0.0;
     611           8 :         thisSupPlenum.ZoneHumRat = 0.0;
     612           8 :         thisSupPlenum.ZoneEnthalpy = 0.0;
     613             : 
     614          20 :         for (NodeNum = 1; NodeNum <= thisSupPlenum.NumOutletNodes; ++NodeNum) {
     615             : 
     616          24 :             thisSupPlenum.OutletNode(NodeNum) = GetOnlySingleNode(state,
     617          12 :                                                                   AlphArray(4 + NodeNum),
     618             :                                                                   ErrorsFound,
     619             :                                                                   DataLoopNode::ConnectionObjectType::AirLoopHVACSupplyPlenum,
     620          12 :                                                                   AlphArray(1),
     621             :                                                                   DataLoopNode::NodeFluidType::Air,
     622             :                                                                   DataLoopNode::ConnectionType::Outlet,
     623             :                                                                   NodeInputManager::CompFluidStream::Primary,
     624             :                                                                   ObjectIsNotParent);
     625             :         }
     626             : 
     627             :     } // end AirLoopHVAC:SupplyPlenum Loop
     628             : 
     629         198 :     AlphArray.deallocate();
     630         198 :     NumArray.deallocate();
     631         198 :     cAlphaFields.deallocate();
     632         198 :     cNumericFields.deallocate();
     633         198 :     lAlphaBlanks.deallocate();
     634         198 :     lNumericBlanks.deallocate();
     635         198 :     NodeNums.deallocate();
     636             : 
     637         198 :     if (ErrorsFound) {
     638           0 :         ShowFatalError(state, format("{}Errors found in input.  Preceding condition(s) cause termination.", RoutineName));
     639             :     }
     640         198 : }
     641             : 
     642     2609056 : void InitAirZoneReturnPlenum(EnergyPlusData &state, int const ZonePlenumNum)
     643             : {
     644             : 
     645             :     // SUBROUTINE INFORMATION:
     646             :     //       AUTHOR         Peter Graham Ellis
     647             :     //       DATE WRITTEN   November 2000
     648             :     //       MODIFIED       na
     649             :     //       RE-ENGINEERED  na
     650             : 
     651             :     // PURPOSE OF THIS SUBROUTINE:
     652             :     // This subroutine is for initializations of the ZonePlenum components.
     653             : 
     654             :     // METHODOLOGY EMPLOYED:
     655             :     // Uses the status flags to trigger events.
     656             : 
     657             :     // Using/Aliasing
     658             : 
     659             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     660             :     int InletNode;
     661     2609056 :     int InducedNode(0);
     662             :     int InletNodeLoop;
     663             :     int ZoneNodeNum;
     664             :     int NodeNum;
     665             :     int ZonePlenumLoop;
     666             :     int PlenumZoneNum;
     667             :     int ZoneEquipConfigLoop; // Loop number of ZoneEquipConfig derived type
     668             :     int ADUNum;              // air distribution unit index
     669             :     int NumADUsToPlen;       // number of ADUs that might leak to this plenum
     670             :     int ADUsToPlenIndex;     // index of an ADU that might leak to this plenum in the plenum ADU list
     671             : 
     672             :     // Do the one time initializations
     673     2609056 :     if (state.dataZonePlenum->InitAirZoneReturnPlenumOneTimeFlag) {
     674             : 
     675             :         // For each zone with a return air plenum put the ZoneRetPlenCond number for the return air plenum
     676             :         // in the ZoneEquipConfig array for the zone. This allows direct access of the zone's return air
     677             :         // plenum conditions, such as plenum temperature and air flow. Also establish and save connections
     678             :         // to the Air Distribution Units. This is needed for the simple duct leakage calculation.
     679             : 
     680         474 :         for (ZonePlenumLoop = 1; ZonePlenumLoop <= state.dataZonePlenum->NumZoneReturnPlenums; ++ZonePlenumLoop) {
     681         284 :             ADUsToPlenIndex = 0;
     682         284 :             NumADUsToPlen = 0;
     683         284 :             if (state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumLoop).NumInletNodes > 0) {
     684        1599 :                 for (InletNodeLoop = 1; InletNodeLoop <= state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumLoop).NumInletNodes; ++InletNodeLoop) {
     685        1315 :                     InletNode = state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumLoop).InletNode(InletNodeLoop);
     686             :                     // Loop through ZoneEquipConfig's and look for return air node value = InletNode
     687       16780 :                     for (ZoneEquipConfigLoop = 1; ZoneEquipConfigLoop <= state.dataGlobal->NumOfZones; ++ZoneEquipConfigLoop) {
     688       15465 :                         if (!state.dataZoneEquip->ZoneEquipConfig(ZoneEquipConfigLoop).IsControlled) continue;
     689       25682 :                         for (int retNode = 1; retNode <= state.dataZoneEquip->ZoneEquipConfig(ZoneEquipConfigLoop).NumReturnNodes; ++retNode) {
     690       12841 :                             if (state.dataZoneEquip->ZoneEquipConfig(ZoneEquipConfigLoop).ReturnNode(retNode) == InletNode) {
     691        1310 :                                 state.dataZoneEquip->ZoneEquipConfig(ZoneEquipConfigLoop).ReturnNodePlenumNum = ZonePlenumLoop;
     692        1310 :                                 state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumLoop).ZoneEqNum(InletNodeLoop) = ZoneEquipConfigLoop;
     693             :                             }
     694             :                         }
     695             :                     }
     696             :                     // count the ADUs that can leak to this plenum
     697       14206 :                     for (ADUNum = 1; ADUNum <= (int)state.dataDefineEquipment->AirDistUnit.size(); ++ADUNum) {
     698       12891 :                         if (state.dataDefineEquipment->AirDistUnit(ADUNum).ZoneEqNum ==
     699       12891 :                             state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumLoop).ZoneEqNum(InletNodeLoop)) {
     700        1325 :                             state.dataDefineEquipment->AirDistUnit(ADUNum).RetPlenumNum = ZonePlenumLoop;
     701        1325 :                             ++NumADUsToPlen;
     702             :                         }
     703             :                     }
     704             :                 }
     705             :             }
     706         284 :             state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumLoop).ADUIndex.allocate(NumADUsToPlen);
     707         284 :             state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumLoop).NumADUs = NumADUsToPlen;
     708             :             // fill the list of air distribution units that can leak to this plenum
     709         284 :             if (NumADUsToPlen > 0) {
     710        3037 :                 for (ADUNum = 1; ADUNum <= (int)state.dataDefineEquipment->AirDistUnit.size(); ++ADUNum) {
     711        2754 :                     if (state.dataDefineEquipment->AirDistUnit(ADUNum).RetPlenumNum == ZonePlenumLoop) {
     712        1325 :                         ++ADUsToPlenIndex;
     713        1325 :                         state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumLoop).ADUIndex(ADUsToPlenIndex) = ADUNum;
     714             :                     }
     715             :                 }
     716             :             }
     717             :         }
     718             : 
     719             :         // Check that all ADUs with leakage found a return plenum
     720        1562 :         for (ADUNum = 1; ADUNum <= (int)state.dataDefineEquipment->AirDistUnit.size(); ++ADUNum) {
     721        1372 :             auto &thisADU(state.dataDefineEquipment->AirDistUnit(ADUNum));
     722             :             // TODO: the first half of this IF condition was a duplicated OR, if issues around this code, might want to check the history of this line
     723        1372 :             if (thisADU.DownStreamLeak && (thisADU.RetPlenumNum == 0)) {
     724           0 :                 ShowWarningError(state,
     725           0 :                                  format("No return plenum found for simple duct leakage for ZoneHVAC:AirDistributionUnit={} in Zone={}",
     726           0 :                                         thisADU.Name,
     727           0 :                                         state.dataZoneEquip->ZoneEquipConfig(thisADU.ZoneEqNum).ZoneName));
     728           0 :                 ShowContinueError(state, "Leakage will be ignored for this ADU.");
     729           0 :                 thisADU.UpStreamLeak = false;
     730           0 :                 thisADU.DownStreamLeak = false;
     731           0 :                 thisADU.UpStreamLeakFrac = 0.0;
     732           0 :                 thisADU.DownStreamLeakFrac = 0.0;
     733             :             }
     734             :         }
     735             : 
     736         190 :         state.dataZonePlenum->InitAirZoneReturnPlenumOneTimeFlag = false;
     737             :     }
     738             : 
     739             :     // Do the Begin Environment initializations
     740     2609056 :     if (state.dataZonePlenum->InitAirZoneReturnPlenumEnvrnFlag && state.dataGlobal->BeginEnvrnFlag) {
     741             : 
     742        3050 :         for (PlenumZoneNum = 1; PlenumZoneNum <= state.dataZonePlenum->NumZoneReturnPlenums; ++PlenumZoneNum) {
     743             : 
     744        1861 :             ZoneNodeNum = state.dataZonePlenum->ZoneRetPlenCond(PlenumZoneNum).ZoneNodeNum;
     745        1861 :             state.dataLoopNodes->Node(ZoneNodeNum).Temp = 20.0;
     746        1861 :             state.dataLoopNodes->Node(ZoneNodeNum).MassFlowRate = 0.0;
     747        1861 :             state.dataLoopNodes->Node(ZoneNodeNum).Quality = 1.0;
     748        1861 :             state.dataLoopNodes->Node(ZoneNodeNum).Press = state.dataEnvrn->OutBaroPress;
     749        1861 :             state.dataLoopNodes->Node(ZoneNodeNum).HumRat = state.dataEnvrn->OutHumRat;
     750        1861 :             state.dataLoopNodes->Node(ZoneNodeNum).Enthalpy =
     751        1861 :                 PsyHFnTdbW(state.dataLoopNodes->Node(ZoneNodeNum).Temp, state.dataLoopNodes->Node(ZoneNodeNum).HumRat);
     752             : 
     753        1861 :             state.dataZonePlenum->ZoneRetPlenCond(PlenumZoneNum).ZoneTemp = 20.0;
     754        1861 :             state.dataZonePlenum->ZoneRetPlenCond(PlenumZoneNum).ZoneHumRat = 0.0;
     755        1861 :             state.dataZonePlenum->ZoneRetPlenCond(PlenumZoneNum).ZoneEnthalpy = 0.0;
     756        1861 :             state.dataZonePlenum->ZoneRetPlenCond(PlenumZoneNum).InletTemp = 0.0;
     757        1861 :             state.dataZonePlenum->ZoneRetPlenCond(PlenumZoneNum).InletHumRat = 0.0;
     758        1861 :             state.dataZonePlenum->ZoneRetPlenCond(PlenumZoneNum).InletEnthalpy = 0.0;
     759        1861 :             state.dataZonePlenum->ZoneRetPlenCond(PlenumZoneNum).InletPressure = 0.0;
     760        1861 :             state.dataZonePlenum->ZoneRetPlenCond(PlenumZoneNum).InletMassFlowRate = 0.0;
     761        1861 :             state.dataZonePlenum->ZoneRetPlenCond(PlenumZoneNum).InletMassFlowRateMaxAvail = 0.0;
     762        1861 :             state.dataZonePlenum->ZoneRetPlenCond(PlenumZoneNum).InletMassFlowRateMinAvail = 0.0;
     763             :         }
     764             : 
     765        1189 :         state.dataZonePlenum->InitAirZoneReturnPlenumEnvrnFlag = false;
     766             :     }
     767             : 
     768     2609056 :     if (!state.dataGlobal->BeginEnvrnFlag) {
     769     2594528 :         state.dataZonePlenum->InitAirZoneReturnPlenumEnvrnFlag = true;
     770             :     }
     771             : 
     772             :     // Transfer the node data to ZoneRetPlenCond data structure
     773    15208538 :     for (NodeNum = 1; NodeNum <= state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).NumInletNodes; ++NodeNum) {
     774             : 
     775    12599482 :         InletNode = state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).InletNode(NodeNum);
     776             :         // Set all of the inlet mass flow variables from the nodes
     777    12599482 :         state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).InletMassFlowRate(NodeNum) = state.dataLoopNodes->Node(InletNode).MassFlowRate;
     778    12599482 :         state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).InletMassFlowRateMaxAvail(NodeNum) =
     779    12599482 :             state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail;
     780    12599482 :         state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).InletMassFlowRateMinAvail(NodeNum) =
     781    12599482 :             state.dataLoopNodes->Node(InletNode).MassFlowRateMinAvail;
     782             :         //    ! Set all of the inlet state variables from the inlet nodes
     783             :         //    ZoneRetPlenCond(ZonePlenumNum)%InletTemp(NodeNum)         = Node(InletNode)%Temp
     784             :         //    ZoneRetPlenCond(ZonePlenumNum)%InletHumRat(NodeNum)       = Node(InletNode)%HumRat
     785             :         //    ZoneRetPlenCond(ZonePlenumNum)%InletEnthalpy(NodeNum)     = Node(InletNode)%Enthalpy
     786    12599482 :         state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).InletPressure(NodeNum) = state.dataLoopNodes->Node(InletNode).Press;
     787             :     }
     788             : 
     789     2609056 :     ZoneNodeNum = state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).ZoneNodeNum;
     790             :     // Set the induced air flow rates and conditions
     791     2805427 :     for (NodeNum = 1; NodeNum <= state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).NumInducedNodes; ++NodeNum) {
     792      196371 :         InducedNode = state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).InducedNode(NodeNum);
     793      196371 :         state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).InducedMassFlowRate(NodeNum) = state.dataLoopNodes->Node(InducedNode).MassFlowRate;
     794      196371 :         state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).InducedMassFlowRateMaxAvail(NodeNum) =
     795      196371 :             state.dataLoopNodes->Node(InducedNode).MassFlowRateMaxAvail;
     796      196371 :         state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).InducedMassFlowRateMinAvail(NodeNum) =
     797      196371 :             state.dataLoopNodes->Node(InducedNode).MassFlowRateMinAvail;
     798             : 
     799      196371 :         state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).InducedTemp(NodeNum) = state.dataLoopNodes->Node(ZoneNodeNum).Temp;
     800      196371 :         state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).InducedHumRat(NodeNum) = state.dataLoopNodes->Node(ZoneNodeNum).HumRat;
     801      196371 :         state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).InducedEnthalpy(NodeNum) = state.dataLoopNodes->Node(ZoneNodeNum).Enthalpy;
     802      196371 :         state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).InducedPressure(NodeNum) = state.dataLoopNodes->Node(ZoneNodeNum).Press;
     803      196371 :         if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
     804           0 :             state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).InducedCO2(NodeNum) = state.dataLoopNodes->Node(ZoneNodeNum).CO2;
     805             :         }
     806      196371 :         if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
     807           0 :             state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).InducedGenContam(NodeNum) = state.dataLoopNodes->Node(ZoneNodeNum).GenContam;
     808             :         }
     809             :     }
     810             : 
     811             :     // Add stuff to calculate conduction inputs to the zone plenum
     812             :     // Now load the zone conditions
     813     2609056 :     state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).ZoneTemp = state.dataLoopNodes->Node(ZoneNodeNum).Temp;
     814     2609056 :     state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).ZoneHumRat = state.dataLoopNodes->Node(ZoneNodeNum).HumRat;
     815     2609056 :     state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).ZoneEnthalpy = state.dataLoopNodes->Node(ZoneNodeNum).Enthalpy;
     816     2609056 : }
     817             : 
     818       78236 : void InitAirZoneSupplyPlenum(EnergyPlusData &state, int const ZonePlenumNum, bool const FirstHVACIteration, bool const FirstCall)
     819             : {
     820             : 
     821             :     // SUBROUTINE INFORMATION:
     822             :     //       AUTHOR         Peter Graham Ellis
     823             :     //       DATE WRITTEN   March 2000
     824             :     //       MODIFIED       na
     825             :     //       RE-ENGINEERED  na
     826             : 
     827             :     // PURPOSE OF THIS SUBROUTINE:
     828             :     // This subroutine is for initializations of the ZonePlenum components.
     829             : 
     830             :     // METHODOLOGY EMPLOYED:
     831             :     // Similar to the Zone Splitter component but with interactions to the plenum zone.
     832             : 
     833             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     834             :     int InletNode;
     835             :     int OutletNode;
     836             :     int ZoneNodeNum;
     837             :     int PlenumZoneNum;
     838             :     int NodeIndex;
     839             : 
     840       78236 :     auto &Node(state.dataLoopNodes->Node);
     841             : 
     842             :     // Do the Begin Environment initializations
     843       78236 :     if (state.dataZonePlenum->MyEnvrnFlag && state.dataGlobal->BeginEnvrnFlag) {
     844             : 
     845          92 :         for (PlenumZoneNum = 1; PlenumZoneNum <= state.dataZonePlenum->NumZoneSupplyPlenums; ++PlenumZoneNum) {
     846             : 
     847          54 :             ZoneNodeNum = state.dataZonePlenum->ZoneSupPlenCond(PlenumZoneNum).ZoneNodeNum;
     848          54 :             Node(ZoneNodeNum).Temp = 20.0;
     849          54 :             Node(ZoneNodeNum).MassFlowRate = 0.0;
     850          54 :             Node(ZoneNodeNum).Quality = 1.0;
     851          54 :             Node(ZoneNodeNum).Press = state.dataEnvrn->OutBaroPress;
     852          54 :             Node(ZoneNodeNum).HumRat = state.dataEnvrn->OutHumRat;
     853          54 :             Node(ZoneNodeNum).Enthalpy = PsyHFnTdbW(Node(ZoneNodeNum).Temp, Node(ZoneNodeNum).HumRat);
     854             : 
     855          54 :             state.dataZonePlenum->ZoneSupPlenCond(PlenumZoneNum).ZoneTemp = 20.0;
     856          54 :             state.dataZonePlenum->ZoneSupPlenCond(PlenumZoneNum).ZoneHumRat = 0.0;
     857          54 :             state.dataZonePlenum->ZoneSupPlenCond(PlenumZoneNum).ZoneEnthalpy = 0.0;
     858          54 :             state.dataZonePlenum->ZoneSupPlenCond(PlenumZoneNum).InletTemp = 0.0;
     859          54 :             state.dataZonePlenum->ZoneSupPlenCond(PlenumZoneNum).InletHumRat = 0.0;
     860          54 :             state.dataZonePlenum->ZoneSupPlenCond(PlenumZoneNum).InletEnthalpy = 0.0;
     861          54 :             state.dataZonePlenum->ZoneSupPlenCond(PlenumZoneNum).InletPressure = 0.0;
     862          54 :             state.dataZonePlenum->ZoneSupPlenCond(PlenumZoneNum).InletMassFlowRate = 0.0;
     863          54 :             state.dataZonePlenum->ZoneSupPlenCond(PlenumZoneNum).InletMassFlowRateMaxAvail = 0.0;
     864          54 :             state.dataZonePlenum->ZoneSupPlenCond(PlenumZoneNum).InletMassFlowRateMinAvail = 0.0;
     865             :         }
     866             : 
     867          38 :         state.dataZonePlenum->MyEnvrnFlag = false;
     868             :     }
     869             : 
     870       78236 :     if (!state.dataGlobal->BeginEnvrnFlag) {
     871       77380 :         state.dataZonePlenum->MyEnvrnFlag = true;
     872             :     }
     873             : 
     874             :     // Do the following initializations (every time step): This should be the info from
     875             :     // the previous components outlets or the node data in this section.
     876             : 
     877       78236 :     InletNode = state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).InletNode;
     878       78236 :     ZoneNodeNum = state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).ZoneNodeNum;
     879             : 
     880       78236 :     if (FirstHVACIteration && FirstCall) {
     881       19592 :         if (Node(InletNode).MassFlowRate > 0.0) {
     882       14453 :             Node(ZoneNodeNum).MassFlowRate = Node(InletNode).MassFlowRate;
     883       36258 :             for (NodeIndex = 1; NodeIndex <= state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).NumOutletNodes; ++NodeIndex) {
     884       21805 :                 OutletNode = state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).OutletNode(NodeIndex);
     885       21805 :                 Node(OutletNode).MassFlowRate = Node(InletNode).MassFlowRate / state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).NumOutletNodes;
     886             :             }
     887             :         }
     888       19592 :         if (Node(InletNode).MassFlowRateMaxAvail > 0.0) {
     889       14453 :             Node(ZoneNodeNum).MassFlowRateMaxAvail = Node(InletNode).MassFlowRateMaxAvail;
     890       36258 :             for (NodeIndex = 1; NodeIndex <= state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).NumOutletNodes; ++NodeIndex) {
     891       21805 :                 OutletNode = state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).OutletNode(NodeIndex);
     892       21805 :                 Node(OutletNode).MassFlowRateMaxAvail =
     893       21805 :                     Node(InletNode).MassFlowRateMaxAvail / state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).NumOutletNodes;
     894             :             }
     895             :         }
     896             : 
     897             :     } // For FirstHVACIteration and FirstCall
     898             : 
     899       78236 :     if (FirstCall) {
     900             : 
     901       39118 :         if (Node(InletNode).MassFlowRateMaxAvail == 0.0) { // For Node inlet Max Avail = 0.0
     902             : 
     903       20522 :             for (NodeIndex = 1; NodeIndex <= state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).NumOutletNodes; ++NodeIndex) {
     904       10283 :                 OutletNode = state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).OutletNode(NodeIndex);
     905       10283 :                 Node(OutletNode).MassFlowRate = 0.0;
     906       10283 :                 Node(OutletNode).MassFlowRateMaxAvail = 0.0;
     907       10283 :                 Node(OutletNode).MassFlowRateMinAvail = 0.0;
     908             :             }
     909             : 
     910       10239 :             Node(ZoneNodeNum).MassFlowRate = 0.0;
     911       10239 :             Node(ZoneNodeNum).MassFlowRateMaxAvail = 0.0;
     912       10239 :             Node(ZoneNodeNum).MassFlowRateMinAvail = 0.0;
     913             : 
     914             :         } // For Node inlet Max Avail = 0.0
     915             : 
     916             :         // Add stuff to calculate conduction inputs to the zone plenum
     917             :         // Now load the zone conditions
     918       39118 :         state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).ZoneTemp = Node(ZoneNodeNum).Temp;
     919       39118 :         state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).ZoneHumRat = Node(ZoneNodeNum).HumRat;
     920       39118 :         state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).ZoneEnthalpy = Node(ZoneNodeNum).Enthalpy;
     921             : 
     922       92972 :         for (NodeIndex = 1; NodeIndex <= state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).NumOutletNodes; ++NodeIndex) {
     923       53854 :             OutletNode = state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).OutletNode(NodeIndex);
     924       53854 :             Node(OutletNode).Press = Node(InletNode).Press;
     925       53854 :             Node(OutletNode).Quality = Node(InletNode).Quality;
     926             :         }
     927             : 
     928       39118 :         Node(ZoneNodeNum).Press = Node(InletNode).Press;
     929       39118 :         Node(ZoneNodeNum).Quality = Node(InletNode).Quality;
     930             : 
     931             :     } else { // On the second call from the ZoneEquipManager this is where the flows are passed back to
     932             :         // the supply plenum inlet.
     933       92972 :         for (NodeIndex = 1; NodeIndex <= state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).NumOutletNodes; ++NodeIndex) {
     934       53854 :             OutletNode = state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).OutletNode(NodeIndex);
     935       53854 :             state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).OutletMassFlowRate(NodeIndex) = Node(OutletNode).MassFlowRate;
     936       53854 :             state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).OutletMassFlowRateMaxAvail(NodeIndex) = Node(OutletNode).MassFlowRateMaxAvail;
     937       53854 :             state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).OutletMassFlowRateMinAvail(NodeIndex) = Node(OutletNode).MassFlowRateMinAvail;
     938             :         }
     939             : 
     940             :     } // For FirstCall
     941       78236 : }
     942             : 
     943     2609056 : void CalcAirZoneReturnPlenum(EnergyPlusData &state, int const ZonePlenumNum)
     944             : {
     945             : 
     946             :     // SUBROUTINE INFORMATION:
     947             :     //       AUTHOR         Peter Graham Ellis
     948             :     //       DATE WRITTEN   November 2000
     949             :     //       MODIFIED       na
     950             :     //       RE-ENGINEERED  na
     951             : 
     952             :     // Using/Aliasing
     953             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     954     2609056 :     int InletNodeNum(0);            // inlet node number
     955     2609056 :     int IndNum(0);                  // induced air index
     956     2609056 :     int ADUNum(0);                  // air distribution unit number
     957     2609056 :     int ADUListIndex(0);            // air distribution unit index in zone return plenum data structure
     958     2609056 :     Real64 TotIndMassFlowRate(0.0); // total induced air mass flow rate [kg/s]
     959             : 
     960             :     // Reset the totals to zero before they are summed.
     961     2609056 :     state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).OutletMassFlowRate = 0.0;
     962     2609056 :     state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).OutletMassFlowRateMaxAvail = 0.0;
     963     2609056 :     state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).OutletMassFlowRateMinAvail = 0.0;
     964     2609056 :     state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).OutletTemp = 0.0;
     965     2609056 :     state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).OutletHumRat = 0.0;
     966     2609056 :     state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).OutletPressure = 0.0;
     967     2609056 :     state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).OutletEnthalpy = 0.0;
     968     2609056 :     TotIndMassFlowRate = 0.0;
     969             : 
     970    15208538 :     for (InletNodeNum = 1; InletNodeNum <= state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).NumInletNodes; ++InletNodeNum) {
     971    12599482 :         state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).OutletMassFlowRate +=
     972    12599482 :             state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).InletMassFlowRate(InletNodeNum);
     973    12599482 :         state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).OutletMassFlowRateMaxAvail +=
     974    12599482 :             state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).InletMassFlowRateMaxAvail(InletNodeNum);
     975    12599482 :         state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).OutletMassFlowRateMinAvail +=
     976    12599482 :             state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).InletMassFlowRateMinAvail(InletNodeNum);
     977             :     }
     978             : 
     979     2609056 :     if (state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).OutletMassFlowRate > 0.0) {
     980             : 
     981             :         // "Momentum balance" to get outlet air pressure
     982    12361606 :         for (InletNodeNum = 1; InletNodeNum <= state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).NumInletNodes; ++InletNodeNum) {
     983             : 
     984    10230250 :             state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).OutletPressure +=
     985    10230250 :                 state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).InletPressure(InletNodeNum) *
     986    10230250 :                 state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).InletMassFlowRate(InletNodeNum) /
     987    10230250 :                 state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).OutletMassFlowRate;
     988             :         }
     989             : 
     990             :     } else {
     991             :         // Mass Flow in air loop is zero and loop is not operating.
     992             :         // Arbitrarily set the output to the first inlet leg
     993      477700 :         state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).OutletPressure = state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).InletPressure(1);
     994             :     }
     995             : 
     996             :     // add in the leak flow rate, if any. Don't alter the pressure calc (it is not used anyway)
     997    15249108 :     for (ADUListIndex = 1; ADUListIndex <= state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).NumADUs; ++ADUListIndex) {
     998    12640052 :         ADUNum = state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).ADUIndex(ADUListIndex);
     999    12640052 :         if (state.dataDefineEquipment->AirDistUnit(ADUNum).UpStreamLeak || state.dataDefineEquipment->AirDistUnit(ADUNum).DownStreamLeak) {
    1000      253875 :             state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).OutletMassFlowRate +=
    1001      253875 :                 state.dataDefineEquipment->AirDistUnit(ADUNum).MassFlowRateUpStrLk +
    1002      253875 :                 state.dataDefineEquipment->AirDistUnit(ADUNum).MassFlowRateDnStrLk;
    1003      253875 :             state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).OutletMassFlowRateMaxAvail +=
    1004      253875 :                 state.dataDefineEquipment->AirDistUnit(ADUNum).MaxAvailDelta;
    1005      253875 :             state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).OutletMassFlowRateMinAvail +=
    1006      253875 :                 state.dataDefineEquipment->AirDistUnit(ADUNum).MinAvailDelta;
    1007             :         }
    1008             :     }
    1009             :     // Sum up induced air flow rate
    1010     2805427 :     for (IndNum = 1; IndNum <= state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).NumInducedNodes; ++IndNum) {
    1011      196371 :         TotIndMassFlowRate += state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).InducedMassFlowRate(IndNum);
    1012             :     }
    1013             : 
    1014     2609056 :     state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).OutletMassFlowRate -= TotIndMassFlowRate;
    1015             : 
    1016             :     // Set the Plenum Outlet to the Zone Node conditions
    1017     2609056 :     state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).OutletHumRat = state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).ZoneHumRat;
    1018     2609056 :     state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).OutletEnthalpy = state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).ZoneEnthalpy;
    1019     2609056 :     state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).OutletTemp = state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).ZoneTemp;
    1020             :     // make sure the MassFlowMaxAvail >= MassFlowRate
    1021     2609056 :     state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).OutletMassFlowRateMaxAvail =
    1022     2609056 :         max(state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).OutletMassFlowRateMaxAvail,
    1023     2609056 :             state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).OutletMassFlowRate);
    1024     2609056 : }
    1025             : 
    1026       78236 : void CalcAirZoneSupplyPlenum(EnergyPlusData &state, int const ZonePlenumNum, bool const FirstCall)
    1027             : {
    1028             : 
    1029             :     // SUBROUTINE INFORMATION:
    1030             :     //       AUTHOR         Peter Graham Ellis
    1031             :     //       DATE WRITTEN   March 2000
    1032             :     //       MODIFIED       na
    1033             :     //       RE-ENGINEERED  na
    1034             : 
    1035             :     // METHODOLOGY EMPLOYED:
    1036             :     // Similar to the Zone Splitter component but with interactions to the plenum zone.
    1037             : 
    1038             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1039             :     int NodeIndex;
    1040             : 
    1041             :     // The first time through the State properties are passed through
    1042       78236 :     if (FirstCall) {
    1043             :         // Moisture balance to get outlet air humidity ratio
    1044       92972 :         for (NodeIndex = 1; NodeIndex <= state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).NumOutletNodes; ++NodeIndex) {
    1045       53854 :             state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).OutletHumRat(NodeIndex) =
    1046       53854 :                 state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).ZoneHumRat;
    1047             :         }
    1048             : 
    1049             :         // Energy balance to get outlet air enthalpy
    1050       92972 :         for (NodeIndex = 1; NodeIndex <= state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).NumOutletNodes; ++NodeIndex) {
    1051       53854 :             state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).OutletEnthalpy(NodeIndex) =
    1052       53854 :                 state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).ZoneEnthalpy;
    1053             :         }
    1054             : 
    1055             :         // Set outlet temperatures equal to inlet temperature
    1056       92972 :         for (NodeIndex = 1; NodeIndex <= state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).NumOutletNodes; ++NodeIndex) {
    1057       53854 :             state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).OutletTemp(NodeIndex) =
    1058       53854 :                 state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).ZoneTemp;
    1059             :         }
    1060             : 
    1061             :     } else {
    1062             :         // This is the second time through and this is where the mass flows from the outlets are
    1063             :         // summed and then assigned upstream to the inlet node.
    1064       39118 :         state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).InletMassFlowRate = 0.0;
    1065       39118 :         state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).InletMassFlowRateMaxAvail = 0.0;
    1066       39118 :         state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).InletMassFlowRateMinAvail = 0.0;
    1067       92972 :         for (NodeIndex = 1; NodeIndex <= state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).NumOutletNodes; ++NodeIndex) {
    1068       53854 :             state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).InletMassFlowRate +=
    1069       53854 :                 state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).OutletMassFlowRate(NodeIndex);
    1070       53854 :             state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).InletMassFlowRateMaxAvail +=
    1071       53854 :                 state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).OutletMassFlowRateMaxAvail(NodeIndex);
    1072       53854 :             state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).InletMassFlowRateMinAvail +=
    1073       53854 :                 state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).OutletMassFlowRateMinAvail(NodeIndex);
    1074             :         }
    1075             :     }
    1076       78236 : }
    1077             : 
    1078             : // End Algorithm Section of the Module
    1079             : // *****************************************************************************
    1080             : 
    1081             : // Beginning of Update subroutines for the ZonePlenum Module
    1082             : // *****************************************************************************
    1083             : 
    1084     2609056 : void UpdateAirZoneReturnPlenum(EnergyPlusData &state, int const ZonePlenumNum)
    1085             : {
    1086             : 
    1087             :     // SUBROUTINE INFORMATION:
    1088             :     //       AUTHOR         Peter Graham Ellis
    1089             :     //       DATE WRITTEN   November 2000
    1090             :     //       MODIFIED       na
    1091             :     //       RE-ENGINEERED  na
    1092             : 
    1093             :     // Using/Aliasing
    1094             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1095             :     int OutletNode;
    1096             :     int InletNode;
    1097             :     int ZoneNode;
    1098             :     int InletNodeNum;
    1099             :     int InducedNode; // the node number of an induced air outlet node
    1100             :     int IndNum;      // the induced air outlet index in ZoneRetPlenCond
    1101             : 
    1102     2609056 :     auto &Node(state.dataLoopNodes->Node);
    1103             : 
    1104     2609056 :     OutletNode = state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).OutletNode;
    1105     2609056 :     InletNode = state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).InletNode(1);
    1106     2609056 :     ZoneNode = state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).ZoneNodeNum;
    1107             : 
    1108             :     // Set the outlet air nodes of the ZonePlenum
    1109     2609056 :     Node(OutletNode).MassFlowRate = state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).OutletMassFlowRate;
    1110     2609056 :     Node(OutletNode).MassFlowRateMaxAvail = state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).OutletMassFlowRateMaxAvail;
    1111     2609056 :     Node(OutletNode).MassFlowRateMinAvail = state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).OutletMassFlowRateMinAvail;
    1112             : 
    1113     2609056 :     Node(ZoneNode).MassFlowRate = state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).OutletMassFlowRate;
    1114     2609056 :     Node(ZoneNode).MassFlowRateMaxAvail = state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).OutletMassFlowRateMaxAvail;
    1115     2609056 :     Node(ZoneNode).MassFlowRateMinAvail = state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).OutletMassFlowRateMinAvail;
    1116     2609056 :     Node(ZoneNode).Press = state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).OutletPressure;
    1117             : 
    1118     2609056 :     Node(OutletNode).Temp = state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).OutletTemp;
    1119     2609056 :     Node(OutletNode).HumRat = state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).OutletHumRat;
    1120     2609056 :     Node(OutletNode).Enthalpy = state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).OutletEnthalpy;
    1121     2609056 :     Node(OutletNode).Press = state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).OutletPressure;
    1122     2805427 :     for (IndNum = 1; IndNum <= state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).NumInducedNodes; ++IndNum) {
    1123      196371 :         InducedNode = state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).InducedNode(IndNum);
    1124      196371 :         Node(InducedNode).Temp = state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).InducedTemp(IndNum);
    1125      196371 :         Node(InducedNode).HumRat = state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).InducedHumRat(IndNum);
    1126      196371 :         Node(InducedNode).Enthalpy = state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).InducedEnthalpy(IndNum);
    1127      196371 :         Node(InducedNode).Press = state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).InducedPressure(IndNum);
    1128      196371 :         if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    1129           0 :             Node(InducedNode).CO2 = state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).InducedCO2(IndNum);
    1130             :         }
    1131      196371 :         if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    1132           0 :             Node(InducedNode).GenContam = state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).InducedGenContam(IndNum);
    1133             :         }
    1134      196371 :         Node(InducedNode).Quality = Node(InletNode).Quality;
    1135             :     }
    1136             : 
    1137             :     // Set the outlet nodes for properties that are just pass through and not used
    1138     2609056 :     Node(OutletNode).Quality = Node(InletNode).Quality;
    1139     2609056 :     Node(ZoneNode).Quality = Node(InletNode).Quality;
    1140             : 
    1141             :     // Set the outlet node contaminant properties if needed. The zone contaminant conditions are calculated in ZoneContaminantPredictorCorrector
    1142     2609056 :     if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    1143           0 :         if (state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).OutletMassFlowRate > 0.0) {
    1144             :             // CO2 balance to get outlet air CO2
    1145           0 :             Node(OutletNode).CO2 = 0.0;
    1146           0 :             for (InletNodeNum = 1; InletNodeNum <= state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).NumInletNodes; ++InletNodeNum) {
    1147           0 :                 Node(OutletNode).CO2 += Node(state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).InletNode(InletNodeNum)).CO2 *
    1148           0 :                                         state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).InletMassFlowRate(InletNodeNum) /
    1149           0 :                                         state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).OutletMassFlowRate;
    1150             :             }
    1151           0 :             Node(ZoneNode).CO2 = Node(OutletNode).CO2;
    1152             :         } else {
    1153           0 :             Node(OutletNode).CO2 = Node(ZoneNode).CO2;
    1154             :         }
    1155             :     }
    1156     2609056 :     if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    1157           0 :         if (state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).OutletMassFlowRate > 0.0) {
    1158             :             // GenContam balance to get outlet air GenContam
    1159           0 :             Node(OutletNode).GenContam = 0.0;
    1160           0 :             for (InletNodeNum = 1; InletNodeNum <= state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).NumInletNodes; ++InletNodeNum) {
    1161           0 :                 Node(OutletNode).GenContam += Node(state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).InletNode(InletNodeNum)).GenContam *
    1162           0 :                                               state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).InletMassFlowRate(InletNodeNum) /
    1163           0 :                                               state.dataZonePlenum->ZoneRetPlenCond(ZonePlenumNum).OutletMassFlowRate;
    1164             :             }
    1165           0 :             Node(ZoneNode).GenContam = Node(OutletNode).GenContam;
    1166             :         } else {
    1167           0 :             Node(OutletNode).GenContam = Node(ZoneNode).GenContam;
    1168             :         }
    1169             :     }
    1170     2609056 : }
    1171             : 
    1172       78236 : void UpdateAirZoneSupplyPlenum(EnergyPlusData &state, int const ZonePlenumNum, bool &PlenumInletChanged, bool const FirstCall)
    1173             : {
    1174             : 
    1175             :     // SUBROUTINE INFORMATION:
    1176             :     //       AUTHOR         Peter Graham Ellis
    1177             :     //       DATE WRITTEN   March 2000
    1178             :     //       MODIFIED       na
    1179             :     //       RE-ENGINEERED  na
    1180             : 
    1181             :     // METHODOLOGY EMPLOYED:
    1182             :     // Similar to the Zone Splitter component but with interactions to the plenum zone.
    1183             : 
    1184             :     // Using/Aliasing
    1185             :     // SUBROUTINE PARAMETER DEFINITIONS:
    1186       78236 :     Real64 constexpr FlowRateToler(0.01); // Tolerance for mass flow rate convergence (in kg/s)
    1187             : 
    1188             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1189             :     int OutletNode;
    1190             :     int InletNode;
    1191             :     int ZoneNode;
    1192             :     int NodeIndex;
    1193             : 
    1194       78236 :     auto &Node(state.dataLoopNodes->Node);
    1195             : 
    1196       78236 :     OutletNode = state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).OutletNode(1);
    1197       78236 :     InletNode = state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).InletNode;
    1198       78236 :     ZoneNode = state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).ZoneNodeNum;
    1199             : 
    1200             :     // On the FirstCall the State properties are passed through and the mass flows are not dealt with
    1201       78236 :     if (FirstCall) {
    1202             :         // Set the outlet nodes for properties that just pass through and not used
    1203       92972 :         for (NodeIndex = 1; NodeIndex <= state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).NumOutletNodes; ++NodeIndex) {
    1204       53854 :             OutletNode = state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).OutletNode(NodeIndex);
    1205       53854 :             Node(OutletNode).Temp = state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).OutletTemp(NodeIndex);
    1206       53854 :             Node(OutletNode).HumRat = state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).OutletHumRat(NodeIndex);
    1207       53854 :             Node(OutletNode).Enthalpy = state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).OutletEnthalpy(NodeIndex);
    1208       53854 :             if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    1209           0 :                 Node(OutletNode).CO2 = Node(InletNode).CO2;
    1210             :             }
    1211       53854 :             if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    1212           0 :                 Node(OutletNode).GenContam = Node(InletNode).GenContam;
    1213             :             }
    1214             :         }
    1215             : 
    1216       39118 :         if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    1217           0 :             Node(ZoneNode).CO2 = Node(InletNode).CO2;
    1218             :         }
    1219       39118 :         if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    1220           0 :             Node(ZoneNode).GenContam = Node(InletNode).GenContam;
    1221             :         }
    1222             : 
    1223             :     } else {
    1224             :         // The second time through just updates the mass flow conditions back upstream
    1225             :         // to the inlet.
    1226             : 
    1227       39118 :         if (std::abs(Node(InletNode).MassFlowRate - state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).InletMassFlowRate) > FlowRateToler) {
    1228       10027 :             PlenumInletChanged = true;
    1229             :         }
    1230             : 
    1231       39118 :         Node(InletNode).MassFlowRate = state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).InletMassFlowRate;
    1232       39118 :         Node(InletNode).MassFlowRateMaxAvail = state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).InletMassFlowRateMaxAvail;
    1233       39118 :         Node(InletNode).MassFlowRateMinAvail = state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).InletMassFlowRateMinAvail;
    1234             : 
    1235       39118 :         Node(ZoneNode).MassFlowRate = state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).InletMassFlowRate;
    1236       39118 :         Node(ZoneNode).MassFlowRateMaxAvail = state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).InletMassFlowRateMaxAvail;
    1237       39118 :         Node(ZoneNode).MassFlowRateMinAvail = state.dataZonePlenum->ZoneSupPlenCond(ZonePlenumNum).InletMassFlowRateMinAvail;
    1238             : 
    1239             :     } // For FirstCall
    1240       78236 : }
    1241             : 
    1242           5 : int GetReturnPlenumIndex(EnergyPlusData &state, int const ExNodeNum)
    1243             : {
    1244             : 
    1245             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1246             :     int PlenumNum;      // loop counter
    1247             :     int InducedNodeNum; // loop counter
    1248             :     int WhichPlenum;    // index to return plenum
    1249             : 
    1250             :     // Obtains and Allocates ZonePlenum related parameters from input file
    1251           5 :     if (state.dataZonePlenum->GetInputFlag) { // First time subroutine has been entered
    1252           1 :         GetZonePlenumInput(state);
    1253           1 :         state.dataZonePlenum->GetInputFlag = false;
    1254             :     }
    1255             : 
    1256           5 :     WhichPlenum = 0;
    1257           5 :     if (state.dataZonePlenum->NumZoneReturnPlenums > 0) {
    1258           9 :         for (PlenumNum = 1; PlenumNum <= state.dataZonePlenum->NumZoneReturnPlenums; ++PlenumNum) {
    1259           5 :             if (ExNodeNum != state.dataZonePlenum->ZoneRetPlenCond(PlenumNum).OutletNode) continue;
    1260           1 :             WhichPlenum = PlenumNum;
    1261           1 :             break;
    1262             :         }
    1263           5 :         if (WhichPlenum == 0) {
    1264           4 :             for (PlenumNum = 1; PlenumNum <= state.dataZonePlenum->NumZoneReturnPlenums; ++PlenumNum) {
    1265          10 :                 for (InducedNodeNum = 1; InducedNodeNum <= state.dataZonePlenum->ZoneRetPlenCond(PlenumNum).NumInducedNodes; ++InducedNodeNum) {
    1266          10 :                     if (ExNodeNum != state.dataZonePlenum->ZoneRetPlenCond(PlenumNum).InducedNode(InducedNodeNum)) continue;
    1267           4 :                     WhichPlenum = PlenumNum;
    1268           4 :                     break;
    1269             :                 }
    1270           4 :                 if (WhichPlenum > 0) break;
    1271             :             }
    1272             :         }
    1273             :     }
    1274             : 
    1275           5 :     return WhichPlenum;
    1276             : }
    1277             : 
    1278           5 : void GetReturnPlenumName(EnergyPlusData &state, int const ReturnPlenumIndex, std::string &ReturnPlenumName)
    1279             : {
    1280             : 
    1281             :     // Obtains and Allocates ZonePlenum related parameters from input file
    1282           5 :     if (state.dataZonePlenum->GetInputFlag) { // First time subroutine has been entered
    1283           0 :         GetZonePlenumInput(state);
    1284           0 :         state.dataZonePlenum->GetInputFlag = false;
    1285             :     }
    1286             : 
    1287           5 :     ReturnPlenumName = " ";
    1288           5 :     if (state.dataZonePlenum->NumZoneReturnPlenums > 0) {
    1289           5 :         ReturnPlenumName = state.dataZonePlenum->ZoneRetPlenCond(ReturnPlenumIndex).ZonePlenumName;
    1290             :     }
    1291           5 : }
    1292             : 
    1293           4 : int getReturnPlenumIndexFromInletNode(EnergyPlusData &state, int const InNodeNum)
    1294             : {
    1295             : 
    1296             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1297             :     int PlenumNum; // loop counter
    1298             :     int InNodeCtr; // loop counter
    1299             :     int thisPlenum;
    1300             : 
    1301             :     // Obtains and Allocates ZonePlenum related parameters from input file
    1302           4 :     if (state.dataZonePlenum->GetInputFlag) { // First time subroutine has been entered
    1303           4 :         GetZonePlenumInput(state);
    1304           4 :         state.dataZonePlenum->GetInputFlag = false;
    1305             :     }
    1306             : 
    1307           4 :     thisPlenum = 0;
    1308           4 :     if (state.dataZonePlenum->NumZoneReturnPlenums > 0) {
    1309           0 :         for (PlenumNum = 1; PlenumNum <= state.dataZonePlenum->NumZoneReturnPlenums; ++PlenumNum) {
    1310           0 :             for (InNodeCtr = 1; InNodeCtr <= state.dataZonePlenum->ZoneRetPlenCond(PlenumNum).NumInletNodes; ++InNodeCtr) {
    1311           0 :                 if (InNodeNum != state.dataZonePlenum->ZoneRetPlenCond(PlenumNum).InletNode(InNodeCtr)) continue;
    1312           0 :                 thisPlenum = PlenumNum;
    1313           0 :                 break;
    1314             :             }
    1315           0 :             if (thisPlenum > 0) break;
    1316             :         }
    1317             :     }
    1318             : 
    1319           4 :     return thisPlenum;
    1320             : }
    1321             : 
    1322           3 : bool ValidateInducedNode(EnergyPlusData &state, int const InduceNodeNum, int const NumReturnNodes, Array1D<int> const &ReturnNode)
    1323             : {
    1324             :     // Ensure induced node is used as inlet node of zoe equipment
    1325             :     int PlenumNum;     // loop counter
    1326             :     int InNodeCtr;     // loop counter
    1327             :     int InduceNodeCtr; // loop counter
    1328           3 :     bool Nodefound = false;
    1329             : 
    1330             :     // Obtains and Allocates ZonePlenum related parameters from input file
    1331           3 :     if (state.dataZonePlenum->GetInputFlag) { // First time subroutine has been entered
    1332           1 :         GetZonePlenumInput(state);
    1333           1 :         state.dataZonePlenum->GetInputFlag = false;
    1334             :     }
    1335             : 
    1336           3 :     if (state.dataZonePlenum->NumZoneReturnPlenums > 0) {
    1337           3 :         for (PlenumNum = 1; PlenumNum <= state.dataZonePlenum->NumZoneReturnPlenums; ++PlenumNum) {
    1338           6 :             for (InduceNodeCtr = 1; InduceNodeCtr <= state.dataZonePlenum->ZoneRetPlenCond(PlenumNum).NumInducedNodes; ++InduceNodeCtr) {
    1339           6 :                 if (InduceNodeNum == state.dataZonePlenum->ZoneRetPlenCond(PlenumNum).InducedNode(InduceNodeCtr)) {
    1340          10 :                     for (InNodeCtr = 1; InNodeCtr <= state.dataZonePlenum->ZoneRetPlenCond(PlenumNum).NumInletNodes; ++InNodeCtr) {
    1341          17 :                         for (int ReturnNodeNum = 1; ReturnNodeNum <= NumReturnNodes; ++ReturnNodeNum) {
    1342          10 :                             if (ReturnNode(ReturnNodeNum) != state.dataZonePlenum->ZoneRetPlenCond(PlenumNum).InletNode(InNodeCtr)) continue;
    1343           3 :                             Nodefound = true;
    1344           3 :                             break;
    1345             :                         }
    1346          10 :                         if (Nodefound) break;
    1347             :                     }
    1348             :                 }
    1349           6 :                 if (Nodefound) break;
    1350             :             }
    1351           3 :             if (Nodefound) break;
    1352             :         }
    1353             :     }
    1354             : 
    1355           3 :     return Nodefound;
    1356             : }
    1357             : 
    1358             : } // namespace EnergyPlus::ZonePlenum

Generated by: LCOV version 1.14