LCOV - code coverage report
Current view: top level - EnergyPlus - ZonePlenum.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 586 688 85.2 %
Date: 2023-01-17 19:17:23 Functions: 15 15 100.0 %

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

Generated by: LCOV version 1.13