LCOV - code coverage report
Current view: top level - EnergyPlus - DataZoneEquipment.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 1010 1364 74.0 %
Date: 2024-08-24 18:31:18 Functions: 31 31 100.0 %

          Line data    Source code
       1             : // EnergyPlus, Copyright (c) 1996-2024, The Board of Trustees of the University of Illinois,
       2             : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
       3             : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
       4             : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
       5             : // contributors. All rights reserved.
       6             : //
       7             : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
       8             : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
       9             : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
      10             : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
      11             : // derivative works, and perform publicly and display publicly, and to permit others to do so.
      12             : //
      13             : // Redistribution and use in source and binary forms, with or without modification, are permitted
      14             : // provided that the following conditions are met:
      15             : //
      16             : // (1) Redistributions of source code must retain the above copyright notice, this list of
      17             : //     conditions and the following disclaimer.
      18             : //
      19             : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
      20             : //     conditions and the following disclaimer in the documentation and/or other materials
      21             : //     provided with the distribution.
      22             : //
      23             : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
      24             : //     the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
      25             : //     used to endorse or promote products derived from this software without specific prior
      26             : //     written permission.
      27             : //
      28             : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
      29             : //     without changes from the version obtained under this License, or (ii) Licensee makes a
      30             : //     reference solely to the software portion of its product, Licensee must refer to the
      31             : //     software as "EnergyPlus version X" software, where "X" is the version number Licensee
      32             : //     obtained under this License and may not use a different name for the software. Except as
      33             : //     specifically required in this Section (4), Licensee shall not use in a company name, a
      34             : //     product name, in advertising, publicity, or other promotional activities any name, trade
      35             : //     name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
      36             : //     similar designation, without the U.S. Department of Energy's prior written consent.
      37             : //
      38             : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
      39             : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
      40             : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
      41             : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      42             : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      43             : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      44             : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      45             : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      46             : // POSSIBILITY OF SUCH DAMAGE.
      47             : 
      48             : // ObjexxFCL Headers
      49             : #include <ObjexxFCL/Array.functions.hh>
      50             : #include <ObjexxFCL/Fmath.hh>
      51             : 
      52             : // EnergyPlus Headers
      53             : #include <EnergyPlus/Autosizing/Base.hh>
      54             : #include <EnergyPlus/BranchNodeConnections.hh>
      55             : #include <EnergyPlus/Data/EnergyPlusData.hh>
      56             : #include <EnergyPlus/DataContaminantBalance.hh>
      57             : #include <EnergyPlus/DataDefineEquip.hh>
      58             : #include <EnergyPlus/DataEnvironment.hh>
      59             : #include <EnergyPlus/DataHVACGlobals.hh>
      60             : #include <EnergyPlus/DataHeatBalance.hh>
      61             : #include <EnergyPlus/DataLoopNode.hh>
      62             : #include <EnergyPlus/DataSizing.hh>
      63             : #include <EnergyPlus/DataZoneEquipment.hh>
      64             : #include <EnergyPlus/General.hh>
      65             : #include <EnergyPlus/GeneralRoutines.hh>
      66             : #include <EnergyPlus/GlobalNames.hh>
      67             : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      68             : #include <EnergyPlus/NodeInputManager.hh>
      69             : #include <EnergyPlus/Psychrometrics.hh>
      70             : #include <EnergyPlus/ScheduleManager.hh>
      71             : #include <EnergyPlus/UnitarySystem.hh>
      72             : #include <EnergyPlus/UtilityRoutines.hh>
      73             : #include <EnergyPlus/ZoneEquipmentManager.hh>
      74             : #include <EnergyPlus/ZoneTempPredictorCorrector.hh>
      75             : 
      76             : namespace EnergyPlus::DataZoneEquipment {
      77             : 
      78             : // MODULE INFORMATION
      79             : //             AUTHOR:  Russ Taylor
      80             : //       DATE WRITTEN:  June 1998
      81             : 
      82             : // PURPOSE OF THIS MODULE:
      83             : // This module contains variable declarations for zone equipment configuration data
      84             : 
      85             : Array1D_string const cValidSysAvailManagerCompTypes(NumValidSysAvailZoneComponents,
      86             :                                                     {"ZoneHVAC:FourPipeFanCoil",
      87             :                                                      "ZoneHVAC:PackagedTerminalHeatPump",
      88             :                                                      "ZoneHVAC:PackagedTerminalAirConditioner",
      89             :                                                      "ZoneHVAC:WaterToAirHeatPump",
      90             :                                                      "ZoneHVAC:WindowAirConditioner",
      91             :                                                      "ZoneHVAC:UnitHeater",
      92             :                                                      "ZoneHVAC:UnitVentilator",
      93             :                                                      "ZoneHVAC:EnergyRecoveryVentilator",
      94             :                                                      "ZoneHVAC:VentilatedSlab",
      95             :                                                      "ZoneHVAC:OutdoorAirUnit",
      96             :                                                      "ZoneHVAC:TerminalUnit:VariableRefrigerantFlow",
      97             :                                                      "ZoneHVAC:IdealLoadsAirSystem",
      98             :                                                      "ZoneHVAC:EvaporativeCoolerUnit",
      99             :                                                      "ZoneHVAC:HybridUnitaryHVAC"});
     100             : 
     101             : constexpr std::array<std::string_view, static_cast<int>(ZoneEquipType::Num)> zoneEquipTypeNamesUC = {
     102             :     "DUMMY", // DUMMY,
     103             : 
     104             :     "ZONEHVAC:FOURPIPEFANCOIL",                      // FanCoilFourPipe
     105             :     "ZONEHVAC:PACKAGEDTERMINALHEATPUMP",             //   PackagedTerminalHeatPump
     106             :     "ZONEHVAC:PACKAGEDTERMINALAIRCONDITIONER",       //  PackagedTerminalAirConditioner
     107             :     "ZONEHVAC:WATERTOAIRHEATPUMP",                   //   PackagedTerminalHeatPumpWaterToAir
     108             :     "ZONEHVAC:WINDOWAIRCONDITIONER",                 //  WindowAirConditioner
     109             :     "ZONEHVAC:UNITHEATER",                           //  UnitHeater
     110             :     "ZONEHVAC:UNITVENTILATOR",                       //  UnitVentilator
     111             :     "ZONEHVAC:ENERGYRECOVERYVENTILATOR",             // EnergyRecoveryVentilator
     112             :     "ZONEHVAC:VENTILATEDSLAB",                       // VentilatedSlab
     113             :     "ZONEHVAC:OUTDOORAIRUNIT",                       // OutdoorAirUnit
     114             :     "ZONEHVAC:TERMINALUNIT:VARIABLEREFRIGERANTFLOW", //  VariableRefrigerantFlowTerminal
     115             :     "ZONEHVAC:IDEALLOADSAIRSYSTEM",                  // IdealLoadsAirSystem
     116             :     "ZONEHVAC:EVAPORATIVECOOLERUNIT",                // EvaporativeCooler
     117             :     "ZONEHVAC:HYBRIDUNITARYHVAC",                    // HybridEvaporativeCooler,
     118             : 
     119             :     // last zone equipment type to use zone availability manager. The above list must not change or
     120             :     // NumValidSysAvailZoneComponents must also change.
     121             : 
     122             :     "ZONEHVAC:AIRDISTRIBUTIONUNIT",                            // AirDistributionUnit
     123             :     "ZONEHVAC:BASEBOARD:CONVECTIVE:WATER",                     // BaseboardWaterConvective
     124             :     "ZONEHVAC:BASEBOARD:CONVECTIVE:ELECTRIC",                  // BaseboardElectricConvective
     125             :     "ZONEHVAC:BASEBOARD:RADIANTCONVECTIVE:STEAM",              // BaseboardSteam
     126             :     "ZONEHVAC:BASEBOARD:RADIANTCONVECTIVE:WATER",              // BaseboardWater
     127             :     "ZONEHVAC:BASEBOARD:RADIANTCONVECTIVE:ELECTRIC",           // BaseboardElectric
     128             :     "ZONEHVAC:HIGHTEMPERATURERADIANT",                         // HighTempRadiant
     129             :     "ZONEHVAC:LOWTEMPERATURERADIANT:VARIABLEFLOW",             //  LowTempRadiant
     130             :     "FAN:ZONEEXHAUST",                                         // ExhaustFan
     131             :     "HEATEXCHANGER:AIRTOAIR:FLATPLATE",                        // HeatExchanger
     132             :     "WATERHEATER:HEATPUMP:PUMPEDCONDENSER",                    //  HeatPumpWaterHeater
     133             :     "ZONEHVAC:DEHUMIDIFIER:DX",                                //  DXDehumidifier
     134             :     "ZONEHVAC:REFRIGERATIONCHILLERSET",                        // RefrigerationAirChillerSet
     135             :     "ZONEHVAC:FORCEDAIR:USERDEFINED",                          // UserDefinedVACForcedAir
     136             :     "ZONEHVAC:COOLINGPANEL:RADIANTCONVECTIVE:WATER",           // CoolingPanel
     137             :     "AIRLOOPHVAC:UNITARYSYSTEM",                               // UnitarySystem
     138             :     "AIRTERMINAL:DUALDUCT:CONSTANTVOLUME",                     // AirTerminalDualDuctConstantVolume
     139             :     "AIRTERMINAL:DUALDUCT:VAV",                                // AirTerminalDualDuctVAV
     140             :     "AIRTERMINAL:SINGLEDUCT:CONSTANTVOLUME:REHEAT",            // AirTerminalSingleDuctConstantVolumeReheat
     141             :     "AIRTERMINAL:SINGLEDUCT:CONSTANTVOLUME:NOREHEAT",          // AirTerminalSingleDuctConstantVolumeNoReheat
     142             :     "AIRTERMINAL:SINGLEDUCT:VAV:REHEAT",                       // AirTerminalSingleDuctVAVReheat
     143             :     "AIRTERMINAL:SINGLEDUCT:VAV:NOREHEAT",                     // AirTerminalSingleDuctVAVNoReheat
     144             :     "AIRTERMINAL:SINGLEDUCT:SERIESPIU:REHEAT",                 // AirTerminalSingleDuctSeriesPIUReheat
     145             :     "AIRTERMINAL:SINGLEDUCT:PARALLELPIU:REHEAT",               // AirTerminalSingleDuctParallelPIUReheat
     146             :     "AIRTERMINAL:SINGLEDUCT:CONSTANTVOLUME:FOURPIPEINDUCTION", // AirTerminalSingleDuctCAVFourPipeInduction
     147             :     "AIRTERMINAL:SINGLEDUCT:VAV:REHEAT:VARIABLESPEEDFAN",      // AirTerminalSingleDuctVAVReheatVariableSpeedFan
     148             :     "AIRTERMINAL:SINGLEDUCT:VAV:HEATANDCOOL:REHEAT",           // AirTerminalSingleDuctVAVHeatAndCoolReheat
     149             :     "AIRTERMINAL:SINGLEDUCT:VAV:HEATANDCOOL:NOREHEAT",         // AirTerminalSingleDuctVAVHeatAndCoolNoReheat
     150             :     "AIRTERMINAL:SINGLEDUCT:CONSTANTVOLUME:COOLEDBEAM",        // AirTerminalSingleDuctConstantVolumeCooledBeam
     151             :     "AIRTERMINAL:DUALDUCT:VAV:OUTDOORAIR",                     // AirTerminalDualDuctVAVOutdoorAir
     152             :     "AIRLOOPHVACRETURNAIR"                                     // AirLoopHVACReturnAir
     153             : };
     154             : 
     155             : static constexpr std::array<std::string_view, static_cast<int>(LoadDist::Num)> LoadDistNamesUC = {
     156             :     "SEQUENTIALLOAD", "UNIFORMLOAD", "UNIFORMPLR", "SEQUENTIALUNIFORMPLR"};
     157             : 
     158             : static constexpr std::array<std::string_view, static_cast<int>(ZoneEquipTstatControl::Num)> zoneEquipTstatControlNamesUC = {
     159             :     "SINGLESPACE", "MAXIMUM", "IDEAL"};
     160             : 
     161             : static constexpr std::array<std::string_view, static_cast<int>(SpaceEquipSizingBasis::Num)> spaceEquipSizingBasisNamesUC = {
     162             :     "DESIGNCOOLINGLOAD", "DESIGNHEATINGLOAD", "FLOORAREA", "VOLUME", "PERIMETERLENGTH"};
     163             : 
     164         796 : void GetZoneEquipmentData(EnergyPlusData &state)
     165             : {
     166             : 
     167             :     // SUBROUTINE INFORMATION:
     168             :     //       AUTHOR         Russ Taylor
     169             :     //       DATE WRITTEN   June 1997
     170             :     //       MODIFIED       Aug 2003, FCW: set ZoneEquipConfig number for each zone
     171             : 
     172             :     // PURPOSE OF THIS SUBROUTINE:
     173             :     // Get all the system related equipment which may be attached to
     174             :     // a zone
     175             : 
     176             :     // Using/Aliasing
     177             :     using NodeInputManager::CheckUniqueNodeNames;
     178             :     using NodeInputManager::CheckUniqueNodeNumbers;
     179             :     using NodeInputManager::EndUniqueNodeCheck;
     180             :     using NodeInputManager::GetNodeNums;
     181             :     using NodeInputManager::GetOnlySingleNode;
     182             :     using NodeInputManager::InitUniqueNodeCheck;
     183             :     using namespace DataLoopNode;
     184             :     using namespace ScheduleManager;
     185             : 
     186             :     // SUBROUTINE PARAMETER DEFINITIONS:
     187             :     static constexpr std::string_view RoutineName("GetZoneEquipmentData: "); // include trailing blank space
     188             : 
     189             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     190             :     int NumAlphas;
     191             :     int NumNums;
     192             :     int IOStat;
     193         796 :     Array1D_string AlphArray;
     194         796 :     Array1D<Real64> NumArray;
     195             :     int MaxAlphas;
     196             :     int MaxNums;
     197             :     int NumParams;
     198         796 :     Array1D_int NodeNums;
     199             :     bool IsNotOK;                    // Flag to verify nam
     200         796 :     std::string CurrentModuleObject; // Object type for getting and error messages
     201         796 :     Array1D_string cAlphaFields;     // Alpha field names
     202         796 :     Array1D_string cNumericFields;   // Numeric field names
     203         796 :     Array1D_bool lAlphaBlanks;       // Logical array, alpha field input BLANK = .TRUE.
     204         796 :     Array1D_bool lNumericBlanks;     // Logical array, numeric field input BLANK = .TRUE.
     205             : 
     206             :     struct EquipListAudit
     207             :     {
     208             :         // Members
     209             :         std::string ObjectType;
     210             :         std::string ObjectName;
     211             :         int OnListNum;
     212             : 
     213             :         // Default Constructor
     214         698 :         EquipListAudit() : OnListNum(0)
     215             :         {
     216         698 :         }
     217             :     };
     218             :     // Object Data
     219         796 :     Array1D<EquipListAudit> ZoneEquipListAcct;
     220             : 
     221             :     // Look in the input file for zones with air loop and zone equipment attached
     222             : 
     223         796 :     int numControlledZones = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "ZoneHVAC:EquipmentConnections");
     224         796 :     int numControlledSpaces = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "SpaceHVAC:EquipmentConnections");
     225         796 :     state.dataZoneEquip->NumOfZoneEquipLists = state.dataInputProcessing->inputProcessor->getNumObjectsFound(
     226             :         state, "ZoneHVAC:EquipmentList"); // Look for lists of equipment data - there should
     227             :     // be as many of these as there are controlled zones
     228         796 :     state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, "NodeList", NumParams, NumAlphas, NumNums);
     229         796 :     NodeNums.dimension(NumParams, 0);
     230         796 :     state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, "ZoneHVAC:EquipmentList", NumParams, NumAlphas, NumNums);
     231         796 :     MaxAlphas = NumAlphas;
     232         796 :     MaxNums = NumNums;
     233         796 :     state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, "ZoneHVAC:EquipmentConnections", NumParams, NumAlphas, NumNums);
     234         796 :     MaxAlphas = max(MaxAlphas, NumAlphas);
     235         796 :     MaxNums = max(MaxNums, NumNums);
     236         796 :     state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, "SpaceHVAC:EquipmentConnections", NumParams, NumAlphas, NumNums);
     237         796 :     MaxAlphas = max(MaxAlphas, NumAlphas);
     238         796 :     MaxNums = max(MaxNums, NumNums);
     239         796 :     state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, "AirLoopHVAC:SupplyPath", NumParams, NumAlphas, NumNums);
     240         796 :     MaxAlphas = max(MaxAlphas, NumAlphas);
     241         796 :     MaxNums = max(MaxNums, NumNums);
     242         796 :     state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, "AirLoopHVAC:ReturnPath", NumParams, NumAlphas, NumNums);
     243         796 :     MaxAlphas = max(MaxAlphas, NumAlphas);
     244         796 :     MaxNums = max(MaxNums, NumNums);
     245         796 :     AlphArray.allocate(MaxAlphas);
     246         796 :     NumArray.dimension(MaxNums, 0.0);
     247         796 :     cAlphaFields.allocate(MaxAlphas);
     248         796 :     cNumericFields.allocate(MaxNums);
     249         796 :     lAlphaBlanks.dimension(MaxAlphas, true);
     250         796 :     lNumericBlanks.dimension(MaxNums, true);
     251             : 
     252         796 :     if (!allocated(state.dataZoneEquip->SupplyAirPath)) {
     253             :         // Look for and read in the air supply path
     254             :         // component (splitters) information for each zone
     255         796 :         state.dataZoneEquip->NumSupplyAirPaths = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "AirLoopHVAC:SupplyPath");
     256         796 :         state.dataZoneEquip->SupplyAirPath.allocate(state.dataZoneEquip->NumSupplyAirPaths);
     257             :     }
     258             : 
     259         796 :     if (!allocated(state.dataZoneEquip->ReturnAirPath)) {
     260             :         // Look for and read in the air return path
     261             :         // component (mixers & plenums) information for each zone
     262         796 :         state.dataZoneEquip->NumReturnAirPaths = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "AirLoopHVAC:ReturnPath");
     263         796 :         state.dataZoneEquip->ReturnAirPath.allocate(state.dataZoneEquip->NumReturnAirPaths);
     264             :     }
     265             : 
     266         796 :     state.dataZoneEquip->ZoneEquipConfig.allocate(state.dataGlobal->NumOfZones); // Allocate the array containing the configuration data for each zone
     267         796 :     if (state.dataHeatBal->doSpaceHeatBalanceSizing || state.dataHeatBal->doSpaceHeatBalanceSimulation) {
     268           4 :         state.dataZoneEquip->spaceEquipConfig.allocate(
     269           2 :             state.dataGlobal->numSpaces); // Allocate the array containing the configuration data for each space
     270             :     }
     271         796 :     state.dataZoneEquip->ZoneEquipList.allocate(state.dataGlobal->NumOfZones);
     272         796 :     state.dataZoneEquip->ZoneEquipAvail.dimension(state.dataGlobal->NumOfZones, Avail::Status::NoAction);
     273         796 :     state.dataZoneEquip->UniqueZoneEquipListNames.reserve(state.dataGlobal->NumOfZones);
     274             : 
     275         796 :     if (state.dataZoneEquip->NumOfZoneEquipLists != numControlledZones) {
     276           0 :         ShowSevereError(state,
     277           0 :                         format("{}Number of Zone Equipment lists [{}] not equal Number of Controlled Zones [{}]",
     278             :                                RoutineName,
     279           0 :                                state.dataZoneEquip->NumOfZoneEquipLists,
     280             :                                numControlledZones));
     281           0 :         ShowContinueError(state, "..Each Controlled Zone [ZoneHVAC:EquipmentConnections] must have a corresponding (unique) ZoneHVAC:EquipmentList");
     282           0 :         ShowFatalError(state, "GetZoneEquipment: Incorrect number of zone equipment lists");
     283             :     }
     284             : 
     285         796 :     if (numControlledZones > state.dataGlobal->NumOfZones) {
     286           0 :         ShowSevereError(state,
     287           0 :                         format("{}Number of Controlled Zone objects [{}] greater than Number of Zones [{}]",
     288             :                                RoutineName,
     289             :                                numControlledZones,
     290           0 :                                state.dataGlobal->NumOfZones));
     291           0 :         ShowFatalError(state, format("{}Too many ZoneHVAC:EquipmentConnections objects.", RoutineName));
     292             :     }
     293             : 
     294         796 :     InitUniqueNodeCheck(state, "ZoneHVAC:EquipmentConnections");
     295             : 
     296         796 :     int overallEquipCount = 0;
     297         796 :     int locTermUnitSizingCounter = 0; // will increment for every zone inlet node
     298             : 
     299             :     // auto &Zone(state.dataHeatBal->Zone);
     300             : 
     301        5115 :     for (int controlledZoneLoop = 1; controlledZoneLoop <= numControlledZones; ++controlledZoneLoop) {
     302        4319 :         CurrentModuleObject = "ZoneHVAC:EquipmentConnections";
     303        4319 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     304             :                                                                  CurrentModuleObject,
     305             :                                                                  controlledZoneLoop,
     306             :                                                                  AlphArray,
     307             :                                                                  NumAlphas,
     308             :                                                                  NumArray,
     309             :                                                                  NumNums,
     310             :                                                                  IOStat,
     311             :                                                                  lNumericBlanks,
     312             :                                                                  lAlphaBlanks,
     313             :                                                                  cAlphaFields,
     314             :                                                                  cNumericFields); // Get Equipment | data for one zone
     315             : 
     316        4319 :         int zoneOrSpaceNum = Util::FindItemInList(AlphArray(1), state.dataHeatBal->Zone);
     317        4319 :         std::string_view zsString = "Zone";
     318             : 
     319        4319 :         if (zoneOrSpaceNum == 0) {
     320           0 :             ShowSevereError(state, format("{}{}: {}=\"{}\"", RoutineName, CurrentModuleObject, cAlphaFields(1), AlphArray(1)));
     321           0 :             ShowContinueError(state,
     322           0 :                               format("..Requested Controlled {} not among {}s, remaining items for this object not processed.", zsString, zsString));
     323           0 :             state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
     324           0 :             continue;
     325             :         }
     326        4319 :         bool isControlledAlready = state.dataHeatBal->Zone(zoneOrSpaceNum).IsControlled;
     327        4319 :         if (isControlledAlready) {
     328           0 :             ShowSevereError(state, format("{}{}: {}=\"{}\"", RoutineName, CurrentModuleObject, cAlphaFields(1), AlphArray(1)));
     329           0 :             ShowContinueError(state,
     330           0 :                               format("..Duplicate Controlled {} entered, only one {} per {} is allowed.", zsString, CurrentModuleObject, zsString));
     331           0 :             state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
     332           0 :             continue;
     333             :         }
     334        4319 :         state.dataHeatBal->Zone(zoneOrSpaceNum).IsControlled = true;
     335        4319 :         bool isSpace = false;
     336        4319 :         processZoneEquipmentInput(state,
     337             :                                   CurrentModuleObject,
     338             :                                   zoneOrSpaceNum,
     339             :                                   isSpace,
     340             :                                   locTermUnitSizingCounter,
     341             :                                   overallEquipCount,
     342        4319 :                                   state.dataZoneEquip->ZoneEquipConfig(zoneOrSpaceNum),
     343             :                                   AlphArray,
     344             :                                   cAlphaFields,
     345             :                                   lAlphaBlanks,
     346             :                                   NodeNums);
     347        4319 :         state.dataHeatBal->Zone(zoneOrSpaceNum).SystemZoneNodeNumber = state.dataZoneEquip->ZoneEquipConfig(zoneOrSpaceNum).ZoneNode;
     348             :     } // end loop over controlled zones
     349         799 :     for (int controlledSpaceLoop = 1; controlledSpaceLoop <= numControlledSpaces; ++controlledSpaceLoop) {
     350           3 :         CurrentModuleObject = "SpaceHVAC:EquipmentConnections";
     351           3 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     352             :                                                                  CurrentModuleObject,
     353             :                                                                  controlledSpaceLoop,
     354             :                                                                  AlphArray,
     355             :                                                                  NumAlphas,
     356             :                                                                  NumArray,
     357             :                                                                  NumNums,
     358             :                                                                  IOStat,
     359             :                                                                  lNumericBlanks,
     360             :                                                                  lAlphaBlanks,
     361             :                                                                  cAlphaFields,
     362             :                                                                  cNumericFields); // Get Equipment | data for one zone
     363             : 
     364           3 :         int zoneOrSpaceNum = Util::FindItemInList(AlphArray(1), state.dataHeatBal->space);
     365           3 :         std::string_view zsString = "Space";
     366             : 
     367           3 :         if (zoneOrSpaceNum == 0) {
     368           0 :             ShowSevereError(state, format("{}{}: {}=\"{}\"", RoutineName, CurrentModuleObject, cAlphaFields(1), AlphArray(1)));
     369           0 :             ShowContinueError(state,
     370           0 :                               format("..Requested Controlled {} not among {}s, remaining items for this object not processed.", zsString, zsString));
     371           0 :             state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
     372           0 :             continue;
     373             :         }
     374           3 :         bool isControlledAlready = state.dataHeatBal->space(zoneOrSpaceNum).IsControlled;
     375           3 :         if (isControlledAlready) {
     376           0 :             ShowSevereError(state, format("{}{}: {}=\"{}\"", RoutineName, CurrentModuleObject, cAlphaFields(1), AlphArray(1)));
     377           0 :             ShowContinueError(state,
     378           0 :                               format("..Duplicate Controlled {} entered, only one {} per {} is allowed.", zsString, CurrentModuleObject, zsString));
     379           0 :             state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
     380           0 :             continue;
     381             :         }
     382           3 :         state.dataHeatBal->space(zoneOrSpaceNum).IsControlled = true;
     383           3 :         bool isSpace = true;
     384           3 :         processZoneEquipmentInput(state,
     385             :                                   CurrentModuleObject,
     386             :                                   zoneOrSpaceNum,
     387             :                                   isSpace,
     388             :                                   locTermUnitSizingCounter,
     389             :                                   overallEquipCount,
     390           3 :                                   state.dataZoneEquip->spaceEquipConfig(zoneOrSpaceNum),
     391             :                                   AlphArray,
     392             :                                   cAlphaFields,
     393             :                                   lAlphaBlanks,
     394             :                                   NodeNums);
     395           3 :         state.dataHeatBal->space(zoneOrSpaceNum).SystemZoneNodeNumber = state.dataZoneEquip->spaceEquipConfig(zoneOrSpaceNum).ZoneNode;
     396             :     } // end loop over controlled spaces
     397             : 
     398         796 :     if (state.dataHeatBal->doSpaceHeatBalanceSizing || state.dataHeatBal->doSpaceHeatBalanceSimulation) {
     399             :         // Auto-assign the system node name for spaces in controlled zones that do not have a SpaceHVAC:EquipmentConnections input
     400          14 :         for (auto &thisZone : state.dataHeatBal->Zone) {
     401          12 :             if (!thisZone.IsControlled) continue;
     402          10 :             int spaceCount = 0;
     403          24 :             for (int spaceNum : thisZone.spaceIndexes) {
     404          14 :                 ++spaceCount;
     405          14 :                 if (state.dataHeatBal->space(spaceNum).SystemZoneNodeNumber == 0) {
     406          11 :                     std::string spaceNodeName = format("{}-Space {}", state.dataLoopNodes->NodeID(thisZone.SystemZoneNodeNumber), spaceCount);
     407          11 :                     int spaceNodeNum = GetOnlySingleNode(state,
     408             :                                                          spaceNodeName,
     409          11 :                                                          state.dataZoneEquip->GetZoneEquipmentDataErrorsFound,
     410             :                                                          DataLoopNode::ConnectionObjectType::ZoneHVACEquipmentConnections,
     411          11 :                                                          AlphArray(1),
     412             :                                                          DataLoopNode::NodeFluidType::Air,
     413             :                                                          DataLoopNode::ConnectionType::ZoneNode,
     414             :                                                          NodeInputManager::CompFluidStream::Primary,
     415             :                                                          DataLoopNode::ObjectIsNotParent);
     416          11 :                     state.dataHeatBal->space(spaceNum).SystemZoneNodeNumber = spaceNodeNum;
     417          11 :                 }
     418          10 :             }
     419           2 :         }
     420             :     }
     421             :     // Allocate TermUnitSizing array and set zone number
     422         796 :     if (locTermUnitSizingCounter > 0) {
     423         672 :         state.dataSize->NumAirTerminalUnits = locTermUnitSizingCounter;
     424         672 :         state.dataSize->TermUnitSizing.allocate(state.dataSize->NumAirTerminalUnits);
     425        5476 :         for (int loopZoneNum = 1; loopZoneNum <= state.dataGlobal->NumOfZones; ++loopZoneNum) {
     426             :             {
     427        4804 :                 auto &thisZoneEqConfig = state.dataZoneEquip->ZoneEquipConfig(loopZoneNum);
     428        9277 :                 for (int loopNodeNum = 1; loopNodeNum <= thisZoneEqConfig.NumInletNodes; ++loopNodeNum) {
     429        4473 :                     state.dataSize->TermUnitSizing(thisZoneEqConfig.AirDistUnitCool(loopNodeNum).TermUnitSizingIndex).CtrlZoneNum = loopZoneNum;
     430             :                 }
     431             :             }
     432             :         }
     433             :     }
     434         796 :     if (state.dataZoneEquip->GetZoneEquipmentDataErrorsFound) {
     435           0 :         ShowWarningError(state, format("{}{}, duplicate items NOT CHECKED due to previous errors.", RoutineName, CurrentModuleObject));
     436           0 :         overallEquipCount = 0;
     437             :     }
     438         796 :     if (overallEquipCount > 0) {
     439         698 :         ZoneEquipListAcct.allocate(overallEquipCount);
     440         698 :         overallEquipCount = 0;
     441        5017 :         for (int Loop1 = 1; Loop1 <= numControlledZones; ++Loop1) {
     442        8815 :             for (int Loop2 = 1; Loop2 <= state.dataZoneEquip->ZoneEquipList(Loop1).NumOfEquipTypes; ++Loop2) {
     443        4496 :                 ++overallEquipCount;
     444        4496 :                 ZoneEquipListAcct(overallEquipCount).ObjectType = state.dataZoneEquip->ZoneEquipList(Loop1).EquipType(Loop2);
     445        4496 :                 ZoneEquipListAcct(overallEquipCount).ObjectName = state.dataZoneEquip->ZoneEquipList(Loop1).EquipName(Loop2);
     446        4496 :                 ZoneEquipListAcct(overallEquipCount).OnListNum = Loop1;
     447             :             }
     448             :         }
     449             :         // Now check for uniqueness
     450        5194 :         for (int Loop1 = 1; Loop1 <= overallEquipCount; ++Loop1) {
     451       76422 :             for (int Loop2 = Loop1 + 1; Loop2 <= overallEquipCount; ++Loop2) {
     452      124818 :                 if (ZoneEquipListAcct(Loop1).ObjectType != ZoneEquipListAcct(Loop2).ObjectType ||
     453       52892 :                     ZoneEquipListAcct(Loop1).ObjectName != ZoneEquipListAcct(Loop2).ObjectName)
     454       71926 :                     continue;
     455             :                 // Duplicated -- not allowed
     456           0 :                 ShowSevereError(state, format("{}{}, duplicate items in ZoneHVAC:EquipmentList.", RoutineName, CurrentModuleObject));
     457           0 :                 ShowContinueError(state,
     458           0 :                                   format("Equipment: Type={}, Name={}", ZoneEquipListAcct(Loop1).ObjectType, ZoneEquipListAcct(Loop1).ObjectName));
     459           0 :                 ShowContinueError(state,
     460           0 :                                   format("Found on List=\"{}\".", state.dataZoneEquip->ZoneEquipList(ZoneEquipListAcct(Loop1).OnListNum).Name));
     461           0 :                 ShowContinueError(
     462             :                     state,
     463           0 :                     format("Equipment Duplicated on List=\"{}\".", state.dataZoneEquip->ZoneEquipList(ZoneEquipListAcct(Loop2).OnListNum).Name));
     464           0 :                 state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
     465             :             }
     466             :         }
     467         698 :         ZoneEquipListAcct.deallocate();
     468             :     }
     469             : 
     470             :     // map ZoneEquipConfig%EquipListIndex to ZoneEquipList%Name
     471             : 
     472        5852 :     for (int ControlledZoneLoop = 1; ControlledZoneLoop <= state.dataGlobal->NumOfZones; ++ControlledZoneLoop) {
     473        5056 :         state.dataZoneEquip->GetZoneEquipmentDataFound = Util::FindItemInList(
     474        5056 :             state.dataZoneEquip->ZoneEquipList(ControlledZoneLoop).Name, state.dataZoneEquip->ZoneEquipConfig, &EquipConfiguration::EquipListName);
     475        5056 :         if (state.dataZoneEquip->GetZoneEquipmentDataFound > 0)
     476        5056 :             state.dataZoneEquip->ZoneEquipConfig(state.dataZoneEquip->GetZoneEquipmentDataFound).EquipListIndex = ControlledZoneLoop;
     477             :     } // end loop over controlled zones
     478             : 
     479         796 :     EndUniqueNodeCheck(state, "ZoneHVAC:EquipmentConnections");
     480             : 
     481         796 :     auto &ip = state.dataInputProcessing->inputProcessor;
     482             : 
     483         796 :     CurrentModuleObject = "SpaceHVAC:ZoneEquipmentSplitter";
     484         796 :     auto instances = ip->epJSON.find(CurrentModuleObject);
     485         796 :     if (instances != ip->epJSON.end()) {
     486           1 :         auto const &objectSchemaProps = ip->getObjectSchemaProps(state, CurrentModuleObject);
     487           1 :         auto &instancesValue = instances.value();
     488           1 :         int numZoneEqSplitters = instancesValue.size();
     489           1 :         state.dataZoneEquip->zoneEquipSplitter.resize(numZoneEqSplitters);
     490           1 :         int zeqSplitterNum = -1;
     491           2 :         for (auto instance = instancesValue.begin(); instance != instancesValue.end(); ++instance) {
     492           1 :             ++zeqSplitterNum;
     493           1 :             auto const &objectFields = instance.value();
     494           1 :             auto &thisZeqSplitter = state.dataZoneEquip->zoneEquipSplitter[zeqSplitterNum];
     495           1 :             thisZeqSplitter.Name = Util::makeUPPER(instance.key());
     496           1 :             thisZeqSplitter.spaceEquipType = DataLoopNode::ConnectionObjectType::SpaceHVACZoneEquipmentSplitter;
     497           1 :             ip->markObjectAsUsed(CurrentModuleObject, instance.key());
     498             : 
     499           2 :             std::string zoneName = ip->getAlphaFieldValue(objectFields, objectSchemaProps, "zone_name");
     500           1 :             int zoneNum = Util::FindItemInList(zoneName, state.dataHeatBal->Zone);
     501           1 :             if (zoneNum == 0) {
     502           0 :                 ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, CurrentModuleObject, thisZeqSplitter.Name));
     503           0 :                 ShowContinueError(state, format("..Zone Name={} not found, remaining items for this object not processed.", zoneName));
     504           0 :                 state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
     505           0 :                 continue;
     506             :             }
     507           1 :             if (!state.dataHeatBal->Zone(zoneNum).IsControlled) {
     508           0 :                 ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, CurrentModuleObject, thisZeqSplitter.Name));
     509           0 :                 ShowContinueError(
     510             :                     state,
     511           0 :                     format("..Zone Name={} is not a controlled zone. A ZoneHVAC:EquipmentConfiguration object is required for this zone.", zoneName));
     512           0 :                 state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
     513           0 :                 continue;
     514             :             }
     515             : 
     516           1 :             processZoneEquipSplitterInput(state, CurrentModuleObject, zeqSplitterNum, zoneNum, objectSchemaProps, objectFields, thisZeqSplitter);
     517           2 :         }
     518             :     } // end loop over zone equipment splitters
     519             : 
     520         796 :     CurrentModuleObject = "SpaceHVAC:ZoneEquipmentMixer";
     521         796 :     instances = ip->epJSON.find(CurrentModuleObject);
     522         796 :     if (instances != ip->epJSON.end()) {
     523           1 :         auto const &objectSchemaProps = ip->getObjectSchemaProps(state, CurrentModuleObject);
     524           1 :         auto &instancesValue = instances.value();
     525           1 :         int numZoneEqMixers = instancesValue.size();
     526           1 :         state.dataZoneEquip->zoneEquipMixer.resize(numZoneEqMixers);
     527           1 :         int zeqMixerNum = -1;
     528           2 :         for (auto instance = instancesValue.begin(); instance != instancesValue.end(); ++instance) {
     529           1 :             ++zeqMixerNum;
     530           1 :             auto const &objectFields = instance.value();
     531           1 :             auto &thisZeqMixer = state.dataZoneEquip->zoneEquipMixer[zeqMixerNum];
     532           1 :             thisZeqMixer.Name = Util::makeUPPER(instance.key());
     533           1 :             thisZeqMixer.spaceEquipType = DataLoopNode::ConnectionObjectType::SpaceHVACZoneEquipmentMixer;
     534           1 :             ip->markObjectAsUsed(CurrentModuleObject, instance.key());
     535             : 
     536           2 :             std::string zoneName = ip->getAlphaFieldValue(objectFields, objectSchemaProps, "zone_name");
     537           1 :             int zoneNum = Util::FindItemInList(zoneName, state.dataHeatBal->Zone);
     538           1 :             if (zoneNum == 0) {
     539           0 :                 ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, CurrentModuleObject, thisZeqMixer.Name));
     540           0 :                 ShowContinueError(state, format("..Zone Name={} not found, remaining items for this object not processed.", zoneName));
     541           0 :                 state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
     542           0 :                 continue;
     543             :             }
     544           1 :             if (!state.dataHeatBal->Zone(zoneNum).IsControlled) {
     545           0 :                 ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, CurrentModuleObject, thisZeqMixer.Name));
     546           0 :                 ShowContinueError(
     547             :                     state,
     548           0 :                     format("..Zone Name={} is not a controlled zone. A ZoneHVAC:EquipmentConfiguration object is required for this zone.", zoneName));
     549           0 :                 state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
     550           0 :                 continue;
     551             :             }
     552             : 
     553           1 :             processZoneEquipMixerInput(state, CurrentModuleObject, zoneNum, objectSchemaProps, objectFields, thisZeqMixer);
     554           2 :         }
     555             :     } // end loop over zone equipment mixers
     556             : 
     557         796 :     CurrentModuleObject = "SpaceHVAC:ZoneReturnMixer";
     558         796 :     instances = ip->epJSON.find(CurrentModuleObject);
     559         796 :     if (instances != ip->epJSON.end()) {
     560           1 :         auto const &objectSchemaProps = ip->getObjectSchemaProps(state, CurrentModuleObject);
     561           1 :         auto &instancesValue = instances.value();
     562           1 :         int numZoneRetMixers = instancesValue.size();
     563           1 :         state.dataZoneEquip->zoneReturnMixer.resize(numZoneRetMixers);
     564           1 :         int zeqRetNum = -1;
     565           2 :         for (auto instance = instancesValue.begin(); instance != instancesValue.end(); ++instance) {
     566           1 :             ++zeqRetNum;
     567           1 :             auto const &objectFields = instance.value();
     568           1 :             auto &thisZretMixer = state.dataZoneEquip->zoneReturnMixer[zeqRetNum];
     569           1 :             thisZretMixer.Name = Util::makeUPPER(instance.key());
     570           1 :             thisZretMixer.spaceEquipType = DataLoopNode::ConnectionObjectType::SpaceHVACZoneReturnMixer;
     571           1 :             ip->markObjectAsUsed(CurrentModuleObject, instance.key());
     572             : 
     573           2 :             std::string zoneName = ip->getAlphaFieldValue(objectFields, objectSchemaProps, "zone_name");
     574           1 :             int zoneNum = Util::FindItemInList(zoneName, state.dataHeatBal->Zone);
     575           1 :             if (zoneNum == 0) {
     576           0 :                 ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, CurrentModuleObject, thisZretMixer.Name));
     577           0 :                 ShowContinueError(state, format("..Zone Name={} not found, remaining items for this object not processed.", zoneName));
     578           0 :                 state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
     579           0 :                 continue;
     580             :             }
     581           1 :             if (!state.dataHeatBal->Zone(zoneNum).IsControlled) {
     582           0 :                 ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, CurrentModuleObject, thisZretMixer.Name));
     583           0 :                 ShowContinueError(
     584             :                     state,
     585           0 :                     format("..Zone Name={} is not a controlled zone. A ZoneHVAC:EquipmentConfiguration object is required for this zone.", zoneName));
     586           0 :                 state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
     587           0 :                 continue;
     588             :             }
     589             : 
     590           1 :             processZoneReturnMixerInput(state, CurrentModuleObject, zoneNum, objectSchemaProps, objectFields, zeqRetNum);
     591           2 :         }
     592             :     } // end loop over zone return mixers
     593             : 
     594         796 :     CurrentModuleObject = "AirLoopHVAC:SupplyPath";
     595        2012 :     for (int PathNum = 1; PathNum <= state.dataZoneEquip->NumSupplyAirPaths; ++PathNum) {
     596             : 
     597        1216 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     598             :                                                                  CurrentModuleObject,
     599             :                                                                  PathNum,
     600             :                                                                  AlphArray,
     601             :                                                                  NumAlphas,
     602             :                                                                  NumArray,
     603             :                                                                  NumNums,
     604             :                                                                  IOStat,
     605             :                                                                  lNumericBlanks,
     606             :                                                                  lAlphaBlanks,
     607             :                                                                  cAlphaFields,
     608             :                                                                  cNumericFields); //  data for one zone
     609        1216 :         state.dataZoneEquip->SupplyAirPath(PathNum).Name = AlphArray(1);
     610        1216 :         state.dataZoneEquip->SupplyAirPath(PathNum).NumOfComponents = nint((double(NumAlphas) - 2.0) / 2.0);
     611             : 
     612        2432 :         state.dataZoneEquip->SupplyAirPath(PathNum).InletNodeNum = GetOnlySingleNode(state,
     613        1216 :                                                                                      AlphArray(2),
     614        1216 :                                                                                      state.dataZoneEquip->GetZoneEquipmentDataErrorsFound,
     615             :                                                                                      DataLoopNode::ConnectionObjectType::AirLoopHVACSupplyPath,
     616        1216 :                                                                                      AlphArray(1),
     617             :                                                                                      DataLoopNode::NodeFluidType::Air,
     618             :                                                                                      DataLoopNode::ConnectionType::Inlet,
     619             :                                                                                      NodeInputManager::CompFluidStream::Primary,
     620             :                                                                                      ObjectIsParent);
     621             : 
     622        1216 :         state.dataZoneEquip->SupplyAirPath(PathNum).ComponentType.allocate(state.dataZoneEquip->SupplyAirPath(PathNum).NumOfComponents);
     623        1216 :         state.dataZoneEquip->SupplyAirPath(PathNum).ComponentTypeEnum.allocate(state.dataZoneEquip->SupplyAirPath(PathNum).NumOfComponents);
     624        1216 :         state.dataZoneEquip->SupplyAirPath(PathNum).ComponentTypeEnum = DataZoneEquipment::AirLoopHVACZone::Invalid;
     625        1216 :         state.dataZoneEquip->SupplyAirPath(PathNum).ComponentName.allocate(state.dataZoneEquip->SupplyAirPath(PathNum).NumOfComponents);
     626        1216 :         state.dataZoneEquip->SupplyAirPath(PathNum).ComponentIndex.allocate(state.dataZoneEquip->SupplyAirPath(PathNum).NumOfComponents);
     627        1216 :         state.dataZoneEquip->SupplyAirPath(PathNum).SplitterIndex.allocate(state.dataZoneEquip->SupplyAirPath(PathNum).NumOfComponents);
     628        1216 :         state.dataZoneEquip->SupplyAirPath(PathNum).PlenumIndex.allocate(state.dataZoneEquip->SupplyAirPath(PathNum).NumOfComponents);
     629             : 
     630        1216 :         int Counter = 3;
     631             : 
     632        2439 :         for (int CompNum = 1; CompNum <= state.dataZoneEquip->SupplyAirPath(PathNum).NumOfComponents; ++CompNum) {
     633             : 
     634        1223 :             if ((AlphArray(Counter) == "AIRLOOPHVAC:ZONESPLITTER") || (AlphArray(Counter) == "AIRLOOPHVAC:SUPPLYPLENUM")) {
     635             : 
     636        1223 :                 state.dataZoneEquip->SupplyAirPath(PathNum).ComponentType(CompNum) = AlphArray(Counter);
     637        1223 :                 state.dataZoneEquip->SupplyAirPath(PathNum).ComponentName(CompNum) = AlphArray(Counter + 1);
     638        2446 :                 ValidateComponent(state,
     639        1223 :                                   state.dataZoneEquip->SupplyAirPath(PathNum).ComponentType(CompNum),
     640        1223 :                                   state.dataZoneEquip->SupplyAirPath(PathNum).ComponentName(CompNum),
     641             :                                   IsNotOK,
     642             :                                   CurrentModuleObject);
     643        1223 :                 state.dataZoneEquip->SupplyAirPath(PathNum).ComponentIndex(CompNum) = 0;
     644        1223 :                 state.dataZoneEquip->SupplyAirPath(PathNum).SplitterIndex(CompNum) = 0;
     645        1223 :                 state.dataZoneEquip->SupplyAirPath(PathNum).PlenumIndex(CompNum) = 0;
     646        1223 :                 state.dataZoneEquip->SupplyAirPath(PathNum).ComponentTypeEnum(CompNum) =
     647        2446 :                     (AirLoopHVACZone)getEnumValue(AirLoopHVACTypeNamesUC, AlphArray(Counter));
     648             :             } else {
     649           0 :                 ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, cAlphaFields(1), state.dataZoneEquip->SupplyAirPath(PathNum).Name));
     650           0 :                 ShowContinueError(state, format("Unhandled component type =\"{}\".", AlphArray(Counter)));
     651           0 :                 ShowContinueError(state, R"(Must be "AirLoopHVAC:ZoneSplitter" or "AirLoopHVAC:SupplyPlenum")");
     652           0 :                 state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
     653             :             }
     654             : 
     655        1223 :             Counter += 2;
     656             :         }
     657             : 
     658        1216 :         state.dataZoneEquip->SupplyAirPath(PathNum).NumOutletNodes = 0;
     659        1216 :         state.dataZoneEquip->SupplyAirPath(PathNum).NumNodes = 0;
     660             : 
     661             :     } // end loop over supply air paths
     662             : 
     663         796 :     CurrentModuleObject = "AirLoopHVAC:ReturnPath";
     664        1995 :     for (int PathNum = 1; PathNum <= state.dataZoneEquip->NumReturnAirPaths; ++PathNum) {
     665             : 
     666        1199 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     667             :                                                                  CurrentModuleObject,
     668             :                                                                  PathNum,
     669             :                                                                  AlphArray,
     670             :                                                                  NumAlphas,
     671             :                                                                  NumArray,
     672             :                                                                  NumNums,
     673             :                                                                  IOStat,
     674             :                                                                  lNumericBlanks,
     675             :                                                                  lAlphaBlanks,
     676             :                                                                  cAlphaFields,
     677             :                                                                  cNumericFields); //  data for one zone
     678        1199 :         state.dataZoneEquip->ReturnAirPath(PathNum).Name = AlphArray(1);
     679        1199 :         state.dataZoneEquip->ReturnAirPath(PathNum).NumOfComponents = nint((double(NumAlphas) - 2.0) / 2.0);
     680             : 
     681        2398 :         state.dataZoneEquip->ReturnAirPath(PathNum).OutletNodeNum = GetOnlySingleNode(state,
     682        1199 :                                                                                       AlphArray(2),
     683        1199 :                                                                                       state.dataZoneEquip->GetZoneEquipmentDataErrorsFound,
     684             :                                                                                       DataLoopNode::ConnectionObjectType::AirLoopHVACReturnPath,
     685        1199 :                                                                                       AlphArray(1),
     686             :                                                                                       DataLoopNode::NodeFluidType::Air,
     687             :                                                                                       DataLoopNode::ConnectionType::Outlet,
     688             :                                                                                       NodeInputManager::CompFluidStream::Primary,
     689             :                                                                                       ObjectIsParent);
     690             : 
     691        1199 :         state.dataZoneEquip->ReturnAirPath(PathNum).ComponentType.allocate(state.dataZoneEquip->ReturnAirPath(PathNum).NumOfComponents);
     692        1199 :         state.dataZoneEquip->ReturnAirPath(PathNum).ComponentTypeEnum.allocate(state.dataZoneEquip->ReturnAirPath(PathNum).NumOfComponents);
     693        1199 :         state.dataZoneEquip->ReturnAirPath(PathNum).ComponentTypeEnum = DataZoneEquipment::AirLoopHVACZone::Invalid;
     694        1199 :         state.dataZoneEquip->ReturnAirPath(PathNum).ComponentName.allocate(state.dataZoneEquip->ReturnAirPath(PathNum).NumOfComponents);
     695        1199 :         state.dataZoneEquip->ReturnAirPath(PathNum).ComponentIndex.allocate(state.dataZoneEquip->ReturnAirPath(PathNum).NumOfComponents);
     696             : 
     697        1199 :         int Counter = 3;
     698             : 
     699        2513 :         for (int CompNum = 1; CompNum <= state.dataZoneEquip->ReturnAirPath(PathNum).NumOfComponents; ++CompNum) {
     700             : 
     701        1314 :             if ((AlphArray(Counter) == "AIRLOOPHVAC:ZONEMIXER") || (AlphArray(Counter) == "AIRLOOPHVAC:RETURNPLENUM")) {
     702             : 
     703        1314 :                 state.dataZoneEquip->ReturnAirPath(PathNum).ComponentType(CompNum) = AlphArray(Counter);
     704        1314 :                 state.dataZoneEquip->ReturnAirPath(PathNum).ComponentName(CompNum) = AlphArray(Counter + 1);
     705        1314 :                 state.dataZoneEquip->ReturnAirPath(PathNum).ComponentIndex(CompNum) = 0;
     706        2628 :                 ValidateComponent(state,
     707        1314 :                                   state.dataZoneEquip->ReturnAirPath(PathNum).ComponentType(CompNum),
     708        1314 :                                   state.dataZoneEquip->ReturnAirPath(PathNum).ComponentName(CompNum),
     709             :                                   IsNotOK,
     710             :                                   CurrentModuleObject);
     711        1314 :                 if (IsNotOK) {
     712           0 :                     ShowContinueError(state, format("In {} = {}", CurrentModuleObject, state.dataZoneEquip->ReturnAirPath(PathNum).Name));
     713           0 :                     state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
     714             :                 }
     715        1314 :                 state.dataZoneEquip->ReturnAirPath(PathNum).ComponentTypeEnum(CompNum) =
     716        2628 :                     static_cast<AirLoopHVACZone>(getEnumValue(AirLoopHVACTypeNamesUC, AlphArray(Counter)));
     717             :             } else {
     718           0 :                 ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, cAlphaFields(1), state.dataZoneEquip->ReturnAirPath(PathNum).Name));
     719           0 :                 ShowContinueError(state, format("Unhandled component type =\"{}\".", AlphArray(Counter)));
     720           0 :                 ShowContinueError(state, R"(Must be "AirLoopHVAC:ZoneMixer" or "AirLoopHVAC:ReturnPlenum")");
     721           0 :                 state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
     722             :             }
     723             : 
     724        1314 :             Counter += 2;
     725             :         }
     726             : 
     727             :     } // end loop over return air paths
     728             : 
     729         796 :     AlphArray.deallocate();
     730         796 :     NumArray.deallocate();
     731         796 :     cAlphaFields.deallocate();
     732         796 :     cNumericFields.deallocate();
     733         796 :     lAlphaBlanks.deallocate();
     734         796 :     lNumericBlanks.deallocate();
     735             : 
     736         796 :     if (state.dataZoneEquip->GetZoneEquipmentDataErrorsFound) {
     737           0 :         ShowFatalError(state, format("{}Errors found in getting Zone Equipment input.", RoutineName));
     738             :     }
     739         796 : }
     740             : 
     741        4322 : void processZoneEquipmentInput(EnergyPlusData &state,
     742             :                                std::string_view zoneEqModuleObject,
     743             :                                int const zoneOrSpaceNum,
     744             :                                bool const isSpace,
     745             :                                int &locTermUnitSizingCounter,
     746             :                                int &overallEquipCount,
     747             :                                DataZoneEquipment::EquipConfiguration &thisEquipConfig,
     748             :                                Array1D_string &AlphArray,
     749             :                                Array1D_string &cAlphaFields, // Alpha field names
     750             :                                Array1D_bool &lAlphaBlanks,   // Logical array, alpha field input BLANK = .TRUE.
     751             :                                Array1D_int &NodeNums)
     752             : {
     753             :     static constexpr std::string_view RoutineName("processZoneEquipmentInput: "); // include trailing blank space
     754        4322 :     std::string_view zsString = "Zone";
     755        4322 :     int spaceFieldShift = 0;
     756        4322 :     if (isSpace) {
     757           3 :         zsString = "Space";
     758           3 :         spaceFieldShift = -1;
     759             :     }
     760             : 
     761        4322 :     thisEquipConfig.IsControlled = true;
     762        4322 :     thisEquipConfig.ZoneName = AlphArray(1); // for x-referencing with the geometry data
     763             : 
     764        4322 :     bool IsNotOK = false;
     765        8644 :     GlobalNames::IntraObjUniquenessCheck(
     766        4322 :         state, AlphArray(2), zoneEqModuleObject, cAlphaFields(2), state.dataZoneEquip->UniqueZoneEquipListNames, IsNotOK);
     767        4322 :     if (IsNotOK) {
     768           0 :         ShowContinueError(state, format("..another Controlled Zone has been assigned that {}.", cAlphaFields(2)));
     769           0 :         state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
     770             :     }
     771        4322 :     thisEquipConfig.EquipListName = AlphArray(2); // the name of the list containing all the zone eq.
     772        4322 :     std::string const InletNodeListName = AlphArray(3 + spaceFieldShift);
     773        4322 :     std::string const ExhaustNodeListName = AlphArray(4 + spaceFieldShift);
     774        4322 :     thisEquipConfig.ZoneNode = GetOnlySingleNode(state,
     775        4322 :                                                  AlphArray(5 + spaceFieldShift),
     776        4322 :                                                  state.dataZoneEquip->GetZoneEquipmentDataErrorsFound,
     777             :                                                  DataLoopNode::ConnectionObjectType::ZoneHVACEquipmentConnections,
     778        4322 :                                                  AlphArray(1),
     779             :                                                  DataLoopNode::NodeFluidType::Air,
     780             :                                                  DataLoopNode::ConnectionType::ZoneNode,
     781             :                                                  NodeInputManager::CompFluidStream::Primary,
     782             :                                                  DataLoopNode::ObjectIsNotParent); // all zone air state variables are
     783        4322 :     if (thisEquipConfig.ZoneNode == 0) {
     784           0 :         ShowSevereError(state, format("{}{}: {}=\"{}\", invalid", RoutineName, zoneEqModuleObject, cAlphaFields(1), AlphArray(1)));
     785           0 :         ShowContinueError(state, format("{} must be present.", cAlphaFields(5 + spaceFieldShift)));
     786           0 :         state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
     787             :     } else {
     788        4322 :         bool UniqueNodeError = false;
     789        4322 :         NodeInputManager::CheckUniqueNodeNames(
     790        4322 :             state, cAlphaFields(5 + spaceFieldShift), UniqueNodeError, AlphArray(5 + spaceFieldShift), AlphArray(1));
     791        4322 :         if (UniqueNodeError) {
     792             :             // ShowContinueError(state, format("Occurs for {} = {}", trim( cAlphaFields( 1 ) ), trim( AlphArray( 1 ) )));
     793           0 :             state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
     794             :         }
     795             :     }
     796             : 
     797        4322 :     std::string ReturnNodeListName = AlphArray(6 + spaceFieldShift);
     798        4322 :     if (lAlphaBlanks(7)) {
     799        4317 :         thisEquipConfig.ReturnFlowSchedPtrNum = ScheduleManager::ScheduleAlwaysOn;
     800             :     } else {
     801           5 :         thisEquipConfig.ReturnFlowSchedPtrNum = ScheduleManager::GetScheduleIndex(state, AlphArray(7 + spaceFieldShift));
     802           5 :         if (thisEquipConfig.ReturnFlowSchedPtrNum == 0) {
     803           0 :             ShowSevereError(state,
     804           0 :                             format("{}{}: invalid {} entered ={} for {}={}",
     805             :                                    RoutineName,
     806             :                                    zoneEqModuleObject,
     807             :                                    cAlphaFields(7),
     808             :                                    AlphArray(7),
     809             :                                    cAlphaFields(1),
     810             :                                    AlphArray(1)));
     811           0 :             state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
     812             :         }
     813             :     }
     814        4322 :     std::string ReturnFlowBasisNodeListName = AlphArray(8 + spaceFieldShift);
     815             : 
     816             :     // Read in the equipment type, name and sequence information
     817             :     // for each equipment list
     818             : 
     819        4322 :     if (!isSpace) {
     820        4319 :         std::string CurrentModuleObject = "ZoneHVAC:EquipmentList";
     821        4319 :         auto &ip = state.dataInputProcessing->inputProcessor;
     822             : 
     823        4319 :         int ZoneEquipListNum = ip->getObjectItemNum(state, CurrentModuleObject, thisEquipConfig.EquipListName);
     824             : 
     825        4319 :         if (ZoneEquipListNum <= 0) {
     826           0 :             ShowSevereError(state, format("{}{} not found = {}", RoutineName, CurrentModuleObject, thisEquipConfig.EquipListName));
     827           0 :             ShowContinueError(state, format("In ZoneHVAC:EquipmentConnections object, for Zone = {}", thisEquipConfig.ZoneName));
     828           0 :             state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
     829             :         } else {
     830        4319 :             auto const &epListFields = ip->getJSONObjectItem(state, CurrentModuleObject, thisEquipConfig.EquipListName);
     831             : 
     832        4319 :             auto const &objectSchemaProps = ip->getObjectSchemaProps(state, CurrentModuleObject);
     833             : 
     834        4319 :             EquipList &thisZoneEquipList = state.dataZoneEquip->ZoneEquipList(zoneOrSpaceNum);
     835             : 
     836        4319 :             thisZoneEquipList.Name = thisEquipConfig.EquipListName;
     837             : 
     838        8638 :             std::string loadDistName = ip->getAlphaFieldValue(epListFields, objectSchemaProps, "load_distribution_scheme");
     839        4319 :             thisZoneEquipList.LoadDistScheme =
     840        4319 :                 static_cast<DataZoneEquipment::LoadDist>(getEnumValue(DataZoneEquipment::LoadDistNamesUC, Util::makeUPPER(loadDistName)));
     841        4319 :             if (thisZoneEquipList.LoadDistScheme == DataZoneEquipment::LoadDist::Invalid) {
     842           0 :                 ShowSevereError(state, format("{}{} = \"{}, Invalid choice\".", RoutineName, CurrentModuleObject, thisZoneEquipList.Name));
     843           0 :                 ShowContinueError(state, format("...load_distribution_scheme=\"{}\".", loadDistName));
     844           0 :                 state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
     845             :             }
     846             : 
     847        4319 :             auto extensibles = epListFields.find("equipment");
     848        4319 :             if (extensibles != epListFields.end()) {
     849        4319 :                 auto &extensiblesArray = extensibles.value();
     850        4319 :                 thisZoneEquipList.NumOfEquipTypes = static_cast<int>(extensiblesArray.size());
     851             : 
     852             :                 // Increment overall count of equipment
     853        4319 :                 overallEquipCount += thisZoneEquipList.NumOfEquipTypes;
     854             : 
     855        4319 :                 thisZoneEquipList.EquipTypeName.allocate(thisZoneEquipList.NumOfEquipTypes);
     856        4319 :                 thisZoneEquipList.EquipType.allocate(thisZoneEquipList.NumOfEquipTypes);
     857        4319 :                 thisZoneEquipList.compPointer.resize(thisZoneEquipList.NumOfEquipTypes + 1);
     858        4319 :                 thisZoneEquipList.EquipName.allocate(thisZoneEquipList.NumOfEquipTypes);
     859        4319 :                 thisZoneEquipList.EquipIndex.allocate(thisZoneEquipList.NumOfEquipTypes);
     860        4319 :                 thisZoneEquipList.zoneEquipSplitterIndex.allocate(thisZoneEquipList.NumOfEquipTypes);
     861        4319 :                 thisZoneEquipList.EquipData.allocate(thisZoneEquipList.NumOfEquipTypes);
     862        4319 :                 thisZoneEquipList.CoolingPriority.allocate(thisZoneEquipList.NumOfEquipTypes);
     863        4319 :                 thisZoneEquipList.HeatingPriority.allocate(thisZoneEquipList.NumOfEquipTypes);
     864        4319 :                 thisZoneEquipList.CoolingCapacity.allocate(thisZoneEquipList.NumOfEquipTypes);
     865        4319 :                 thisZoneEquipList.HeatingCapacity.allocate(thisZoneEquipList.NumOfEquipTypes);
     866        4319 :                 thisZoneEquipList.SequentialCoolingFractionSchedPtr.allocate(thisZoneEquipList.NumOfEquipTypes);
     867        4319 :                 thisZoneEquipList.SequentialHeatingFractionSchedPtr.allocate(thisZoneEquipList.NumOfEquipTypes);
     868        9217 :                 for (int eqNum = 1; eqNum <= thisZoneEquipList.NumOfEquipTypes; ++eqNum) {
     869        4898 :                     thisZoneEquipList.EquipTypeName(eqNum) = "";
     870        4898 :                     thisZoneEquipList.EquipType(eqNum) = DataZoneEquipment::ZoneEquipType::Invalid;
     871        4898 :                     thisZoneEquipList.EquipName(eqNum) = "";
     872        4898 :                     thisZoneEquipList.EquipIndex(eqNum) = 0;
     873        4898 :                     thisZoneEquipList.zoneEquipSplitterIndex(eqNum) = -1;
     874        4898 :                     thisZoneEquipList.compPointer[eqNum] = nullptr;
     875        4898 :                     thisZoneEquipList.CoolingPriority(eqNum) = 0;
     876        4898 :                     thisZoneEquipList.HeatingPriority(eqNum) = 0;
     877        4898 :                     thisZoneEquipList.CoolingCapacity(eqNum) = 0;
     878        4898 :                     thisZoneEquipList.HeatingCapacity(eqNum) = 0;
     879        4898 :                     thisZoneEquipList.SequentialCoolingFractionSchedPtr(eqNum) = 0;
     880        4898 :                     thisZoneEquipList.SequentialHeatingFractionSchedPtr(eqNum) = 0;
     881             :                 }
     882             : 
     883        4319 :                 auto const &extensionSchemaProps = objectSchemaProps["equipment"]["items"]["properties"];
     884             : 
     885        4319 :                 int ZoneEquipTypeNum = 0;
     886        9217 :                 for (auto &extensibleInstance : extensiblesArray) {
     887        4898 :                     ++ZoneEquipTypeNum;
     888             : 
     889        4898 :                     thisZoneEquipList.EquipTypeName(ZoneEquipTypeNum) =
     890        9796 :                         ip->getAlphaFieldValue(extensibleInstance, extensionSchemaProps, "zone_equipment_object_type");
     891        4898 :                     thisZoneEquipList.EquipName(ZoneEquipTypeNum) =
     892        9796 :                         ip->getAlphaFieldValue(extensibleInstance, extensionSchemaProps, "zone_equipment_name");
     893             : 
     894        9796 :                     ValidateComponent(state,
     895        4898 :                                       thisZoneEquipList.EquipTypeName(ZoneEquipTypeNum),
     896        4898 :                                       thisZoneEquipList.EquipName(ZoneEquipTypeNum),
     897             :                                       IsNotOK,
     898             :                                       CurrentModuleObject);
     899        4898 :                     if (IsNotOK) {
     900           0 :                         ShowContinueError(state, format("In {}={}", CurrentModuleObject, thisZoneEquipList.Name));
     901           0 :                         state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
     902             :                     }
     903             : 
     904             :                     // If not present, this return 0
     905        9796 :                     thisZoneEquipList.CoolingPriority(ZoneEquipTypeNum) =
     906        4898 :                         ip->getIntFieldValue(extensibleInstance, extensionSchemaProps, "zone_equipment_cooling_sequence");
     907             : 
     908        9796 :                     if ((thisZoneEquipList.CoolingPriority(ZoneEquipTypeNum) < 0) ||
     909        4898 :                         (thisZoneEquipList.CoolingPriority(ZoneEquipTypeNum) > thisZoneEquipList.NumOfEquipTypes)) {
     910           0 :                         ShowSevereError(state, format("{}{} = \"{}\".", RoutineName, CurrentModuleObject, thisZoneEquipList.Name));
     911           0 :                         ShowContinueError(
     912           0 :                             state, format("invalid zone_equipment_cooling_sequence=[{}].", thisZoneEquipList.CoolingPriority(ZoneEquipTypeNum)));
     913           0 :                         ShowContinueError(state, "equipment sequence must be > 0 and <= number of equipments in the list.");
     914           0 :                         if (thisZoneEquipList.CoolingPriority(ZoneEquipTypeNum) > 0) {
     915           0 :                             ShowContinueError(state, format("only {} in the list.", thisZoneEquipList.NumOfEquipTypes));
     916             :                         }
     917           0 :                         state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
     918             :                     }
     919             : 
     920        9796 :                     thisZoneEquipList.HeatingPriority(ZoneEquipTypeNum) =
     921        4898 :                         ip->getIntFieldValue(extensibleInstance, extensionSchemaProps, "zone_equipment_heating_or_no_load_sequence");
     922        9796 :                     if ((thisZoneEquipList.HeatingPriority(ZoneEquipTypeNum) < 0) ||
     923        4898 :                         (thisZoneEquipList.HeatingPriority(ZoneEquipTypeNum) > thisZoneEquipList.NumOfEquipTypes)) {
     924           0 :                         ShowSevereError(state, format("{}{} = \"{}\".", RoutineName, CurrentModuleObject, thisZoneEquipList.Name));
     925           0 :                         ShowContinueError(
     926           0 :                             state, format("invalid zone_equipment_heating_sequence=[{}].", thisZoneEquipList.HeatingPriority(ZoneEquipTypeNum)));
     927           0 :                         ShowContinueError(state, "equipment sequence must be > 0 and <= number of equipments in the list.");
     928           0 :                         if (thisZoneEquipList.HeatingPriority(ZoneEquipTypeNum) > 0) {
     929           0 :                             ShowContinueError(state, format("only {} in the list.", thisZoneEquipList.NumOfEquipTypes));
     930             :                         }
     931           0 :                         state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
     932             :                     }
     933             : 
     934             :                     std::string coolingSchName =
     935        9796 :                         ip->getAlphaFieldValue(extensibleInstance, extensionSchemaProps, "zone_equipment_sequential_cooling_fraction_schedule_name");
     936        4898 :                     if (coolingSchName.empty()) {
     937        4879 :                         thisZoneEquipList.SequentialCoolingFractionSchedPtr(ZoneEquipTypeNum) = ScheduleManager::ScheduleAlwaysOn;
     938             :                     } else {
     939          38 :                         thisZoneEquipList.SequentialCoolingFractionSchedPtr(ZoneEquipTypeNum) =
     940          19 :                             ScheduleManager::GetScheduleIndex(state, coolingSchName);
     941          19 :                         if (thisZoneEquipList.SequentialCoolingFractionSchedPtr(ZoneEquipTypeNum) == 0) {
     942           0 :                             ShowSevereError(state, format("{}{} = \"{}\".", RoutineName, CurrentModuleObject, thisZoneEquipList.Name));
     943           0 :                             ShowContinueError(state,
     944           0 :                                               format("invalid zone_equipment_sequential_cooling_fraction_schedule_name=[{}].", coolingSchName));
     945           0 :                             ShowContinueError(state, "Schedule does not exist.");
     946           0 :                             state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
     947             :                         }
     948             :                     }
     949             : 
     950             :                     std::string heatingSchName =
     951        9796 :                         ip->getAlphaFieldValue(extensibleInstance, extensionSchemaProps, "zone_equipment_sequential_heating_fraction_schedule_name");
     952        4898 :                     if (heatingSchName.empty()) {
     953        4879 :                         thisZoneEquipList.SequentialHeatingFractionSchedPtr(ZoneEquipTypeNum) = ScheduleManager::ScheduleAlwaysOn;
     954             :                     } else {
     955          38 :                         thisZoneEquipList.SequentialHeatingFractionSchedPtr(ZoneEquipTypeNum) =
     956          19 :                             ScheduleManager::GetScheduleIndex(state, heatingSchName);
     957          19 :                         if (thisZoneEquipList.SequentialHeatingFractionSchedPtr(ZoneEquipTypeNum) == 0) {
     958           0 :                             ShowSevereError(state, format("{}{} = \"{}\".", RoutineName, CurrentModuleObject, thisZoneEquipList.Name));
     959           0 :                             ShowContinueError(state,
     960           0 :                                               format("invalid zone_equipment_sequential_heating_fraction_schedule_name=[{}].", coolingSchName));
     961           0 :                             ShowContinueError(state, "Schedule does not exist.");
     962           0 :                             state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
     963             :                         }
     964             :                     }
     965             : 
     966             :                     // do this here for initial prototype, but later will call all the equipment in a separate function to see who is on - maybe
     967        4898 :                     if (thisZoneEquipList.HeatingPriority(ZoneEquipTypeNum) > 0) {
     968        4898 :                         ++thisZoneEquipList.NumAvailHeatEquip;
     969             :                     }
     970        4898 :                     if (thisZoneEquipList.CoolingPriority(ZoneEquipTypeNum) > 0) {
     971        4898 :                         ++thisZoneEquipList.NumAvailCoolEquip;
     972             :                     }
     973             : 
     974        9796 :                     thisZoneEquipList.EquipType(ZoneEquipTypeNum) = static_cast<ZoneEquipType>(
     975        4898 :                         getEnumValue(zoneEquipTypeNamesUC, Util::makeUPPER(thisZoneEquipList.EquipTypeName(ZoneEquipTypeNum))));
     976             : 
     977        4898 :                     if (thisZoneEquipList.EquipType(ZoneEquipTypeNum) == ZoneEquipType::UnitarySystem ||
     978        4877 :                         thisZoneEquipList.EquipType(ZoneEquipTypeNum) == ZoneEquipType::PackagedTerminalAirConditioner ||
     979       14482 :                         thisZoneEquipList.EquipType(ZoneEquipTypeNum) == ZoneEquipType::PackagedTerminalHeatPump ||
     980        4707 :                         thisZoneEquipList.EquipType(ZoneEquipTypeNum) == ZoneEquipType::PackagedTerminalHeatPumpWaterToAir) {
     981             :                         // loop index accesses correct pointer to equipment on this equipment list
     982             :                         // EquipIndex is used to access specific equipment for a single class of equipment (e.g., PTAC 1, 2 and 3)
     983         218 :                         thisZoneEquipList.compPointer[ZoneEquipTypeNum] = UnitarySystems::UnitarySys::factory(
     984         218 :                             state, HVAC::UnitarySysType::Unitary_AnyCoilType, thisZoneEquipList.EquipName(ZoneEquipTypeNum), true, 0);
     985         218 :                         thisZoneEquipList.EquipIndex(ZoneEquipTypeNum) = thisZoneEquipList.compPointer[ZoneEquipTypeNum]->getEquipIndex();
     986             :                     }
     987             : 
     988        4898 :                     if (thisZoneEquipList.EquipType(ZoneEquipTypeNum) == ZoneEquipType::Invalid) {
     989          49 :                         if (thisZoneEquipList.EquipTypeName(ZoneEquipTypeNum) == "ZONEHVAC:LOWTEMPERATURERADIANT:CONSTANTFLOW" ||
     990          11 :                             thisZoneEquipList.EquipTypeName(ZoneEquipTypeNum) == "ZONEHVAC:LOWTEMPERATURERADIANT:ELECTRIC") {
     991          36 :                             thisZoneEquipList.EquipType(ZoneEquipTypeNum) = ZoneEquipType::LowTemperatureRadiant;
     992           2 :                         } else if (thisZoneEquipList.EquipTypeName(ZoneEquipTypeNum) == "WATERHEATER:HEATPUMP:WRAPPEDCONDENSER") {
     993           2 :                             thisZoneEquipList.EquipType(ZoneEquipTypeNum) = DataZoneEquipment::ZoneEquipType::HeatPumpWaterHeater;
     994             :                         } else {
     995           0 :                             ShowSevereError(state, format("{}{} = {}", RoutineName, CurrentModuleObject, thisZoneEquipList.Name));
     996           0 :                             ShowContinueError(state, format("..Invalid Equipment Type = {}", thisZoneEquipList.EquipType(ZoneEquipTypeNum)));
     997           0 :                             state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
     998             :                         }
     999             :                     }
    1000        9217 :                 }
    1001             :             } // End parsing all extensible Zone Equipment info
    1002             : 
    1003             :             // Check for multiple assignments
    1004        9217 :             for (int ZoneEquipTypeNum = 1; ZoneEquipTypeNum <= thisZoneEquipList.NumOfEquipTypes; ++ZoneEquipTypeNum) {
    1005        4898 :                 if (count_eq(thisZoneEquipList.CoolingPriority, ZoneEquipTypeNum) > 1) {
    1006           0 :                     ShowSevereError(state, format("{}{} = {}", RoutineName, CurrentModuleObject, thisZoneEquipList.Name));
    1007           0 :                     ShowContinueError(state,
    1008           0 :                                       format("...multiple assignments for Zone Equipment Cooling Sequence={}, must be 1-1 correspondence between "
    1009             :                                              "sequence assignments and number of equipments.",
    1010             :                                              ZoneEquipTypeNum));
    1011           0 :                     state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
    1012        4898 :                 } else if (count_eq(thisZoneEquipList.CoolingPriority, ZoneEquipTypeNum) == 0) {
    1013           0 :                     ShowWarningError(state, format("{}{} = {}", RoutineName, CurrentModuleObject, thisZoneEquipList.Name));
    1014           0 :                     ShowContinueError(state,
    1015           0 :                                       format("...zero assigned to Zone Equipment Cooling Sequence={}, apparent gap in sequence assignments in "
    1016             :                                              "this equipment list.",
    1017             :                                              ZoneEquipTypeNum));
    1018             :                 }
    1019        4898 :                 if (count_eq(thisZoneEquipList.HeatingPriority, ZoneEquipTypeNum) > 1) {
    1020           0 :                     ShowSevereError(state, format("{}{} = {}", RoutineName, CurrentModuleObject, thisZoneEquipList.Name));
    1021           0 :                     ShowContinueError(state,
    1022           0 :                                       format("...multiple assignments for Zone Equipment Heating or No-Load Sequence={}, must be 1-1 "
    1023             :                                              "correspondence between sequence assignments and number of equipments.",
    1024             :                                              ZoneEquipTypeNum));
    1025           0 :                     state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
    1026        4898 :                 } else if (count_eq(thisZoneEquipList.HeatingPriority, ZoneEquipTypeNum) == 0) {
    1027           0 :                     ShowWarningError(state, format("{}{} = {}", RoutineName, CurrentModuleObject, thisZoneEquipList.Name));
    1028           0 :                     ShowContinueError(state,
    1029           0 :                                       format("...zero assigned to Zone Equipment Heating or No-Load Sequence={}, apparent gap in sequence "
    1030             :                                              "assignments in this equipment list.",
    1031             :                                              ZoneEquipTypeNum));
    1032             :                 }
    1033             :             }
    1034        4319 :         } // End ZoneHVAC:EquipmentList
    1035        4319 :     }
    1036        4322 :     bool NodeListError = false;
    1037        4322 :     int NumNodes = 0;
    1038        8644 :     GetNodeNums(state,
    1039             :                 InletNodeListName,
    1040             :                 NumNodes,
    1041             :                 NodeNums,
    1042             :                 NodeListError,
    1043             :                 DataLoopNode::NodeFluidType::Air,
    1044             :                 (isSpace ? DataLoopNode::ConnectionObjectType::SpaceHVACEquipmentConnections
    1045             :                          : DataLoopNode::ConnectionObjectType::ZoneHVACEquipmentConnections),
    1046        4322 :                 thisEquipConfig.ZoneName,
    1047             :                 DataLoopNode::ConnectionType::ZoneInlet,
    1048             :                 NodeInputManager::CompFluidStream::Primary,
    1049             :                 DataLoopNode::ObjectIsNotParent);
    1050             : 
    1051        4322 :     if (!NodeListError) {
    1052        4322 :         thisEquipConfig.NumInletNodes = NumNodes;
    1053             : 
    1054        4322 :         thisEquipConfig.InletNode.allocate(NumNodes);
    1055        4322 :         thisEquipConfig.InletNodeAirLoopNum.allocate(NumNodes);
    1056        4322 :         thisEquipConfig.InletNodeADUNum.allocate(NumNodes);
    1057        4322 :         thisEquipConfig.AirDistUnitCool.allocate(NumNodes);
    1058        4322 :         thisEquipConfig.AirDistUnitHeat.allocate(NumNodes);
    1059             : 
    1060        8798 :         for (int NodeNum = 1; NodeNum <= NumNodes; ++NodeNum) {
    1061        4476 :             thisEquipConfig.InletNode(NodeNum) = NodeNums(NodeNum);
    1062        4476 :             bool UniqueNodeError = false;
    1063        4476 :             NodeInputManager::CheckUniqueNodeNumbers(state, "Zone Air Inlet Nodes", UniqueNodeError, NodeNums(NodeNum), thisEquipConfig.ZoneName);
    1064        4476 :             if (UniqueNodeError) {
    1065           0 :                 state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
    1066             :             }
    1067        4476 :             thisEquipConfig.InletNodeAirLoopNum(NodeNum) = 0;
    1068        4476 :             thisEquipConfig.InletNodeADUNum(NodeNum) = 0;
    1069        4476 :             thisEquipConfig.AirDistUnitCool(NodeNum).InNode = 0;
    1070        4476 :             thisEquipConfig.AirDistUnitHeat(NodeNum).InNode = 0;
    1071        4476 :             thisEquipConfig.AirDistUnitCool(NodeNum).OutNode = 0;
    1072        4476 :             thisEquipConfig.AirDistUnitHeat(NodeNum).OutNode = 0;
    1073        4476 :             if (!isSpace) {
    1074        4473 :                 ++locTermUnitSizingCounter;
    1075        4473 :                 thisEquipConfig.AirDistUnitCool(NodeNum).TermUnitSizingIndex = locTermUnitSizingCounter;
    1076        4473 :                 thisEquipConfig.AirDistUnitHeat(NodeNum).TermUnitSizingIndex = locTermUnitSizingCounter;
    1077             :             }
    1078             :         }
    1079             :     } else {
    1080           0 :         ShowContinueError(
    1081             :             state,
    1082           0 :             format("Invalid Zone Air Inlet Node or NodeList Name in ZoneHVAC:EquipmentConnections object, for Zone = {}", thisEquipConfig.ZoneName));
    1083           0 :         state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
    1084             :     }
    1085             : 
    1086        4322 :     NodeListError = false;
    1087        8644 :     GetNodeNums(state,
    1088             :                 ExhaustNodeListName,
    1089             :                 NumNodes,
    1090             :                 NodeNums,
    1091             :                 NodeListError,
    1092             :                 DataLoopNode::NodeFluidType::Air,
    1093             :                 (isSpace ? DataLoopNode::ConnectionObjectType::SpaceHVACEquipmentConnections
    1094             :                          : DataLoopNode::ConnectionObjectType::ZoneHVACEquipmentConnections),
    1095        4322 :                 thisEquipConfig.ZoneName,
    1096             :                 DataLoopNode::ConnectionType::ZoneExhaust,
    1097             :                 NodeInputManager::CompFluidStream::Primary,
    1098             :                 DataLoopNode::ObjectIsNotParent);
    1099             : 
    1100        4322 :     if (!NodeListError) {
    1101        4322 :         thisEquipConfig.NumExhaustNodes = NumNodes;
    1102             : 
    1103        4322 :         thisEquipConfig.ExhaustNode.allocate(NumNodes);
    1104             : 
    1105        5170 :         for (int NodeNum = 1; NodeNum <= NumNodes; ++NodeNum) {
    1106         848 :             thisEquipConfig.ExhaustNode(NodeNum) = NodeNums(NodeNum);
    1107         848 :             bool UniqueNodeError = false;
    1108         848 :             NodeInputManager::CheckUniqueNodeNumbers(state, "Zone Air Exhaust Nodes", UniqueNodeError, NodeNums(NodeNum), thisEquipConfig.ZoneName);
    1109         848 :             if (UniqueNodeError) {
    1110             :                 // ShowContinueError(state, format("Occurs for Zone = {}", trim( AlphArray( 1 ) )));
    1111           0 :                 state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
    1112             :             }
    1113             :         }
    1114             :     } else {
    1115           0 :         ShowContinueError(
    1116             :             state,
    1117           0 :             format("Invalid Zone Air Exhaust Node or NodeList Name in ZoneHVAC:EquipmentConnections object, for Zone={}", thisEquipConfig.ZoneName));
    1118           0 :         state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
    1119             :     }
    1120             : 
    1121        4322 :     NodeListError = false;
    1122        8644 :     GetNodeNums(state,
    1123             :                 ReturnNodeListName,
    1124             :                 NumNodes,
    1125             :                 NodeNums,
    1126             :                 NodeListError,
    1127             :                 DataLoopNode::NodeFluidType::Air,
    1128             :                 (isSpace ? DataLoopNode::ConnectionObjectType::SpaceHVACEquipmentConnections
    1129             :                          : DataLoopNode::ConnectionObjectType::ZoneHVACEquipmentConnections),
    1130        4322 :                 thisEquipConfig.ZoneName,
    1131             :                 DataLoopNode::ConnectionType::ZoneReturn,
    1132             :                 NodeInputManager::CompFluidStream::Primary,
    1133             :                 DataLoopNode::ObjectIsNotParent);
    1134             : 
    1135        4322 :     if (!NodeListError) {
    1136        4322 :         thisEquipConfig.NumReturnNodes = NumNodes;
    1137             : 
    1138        4322 :         thisEquipConfig.ReturnNode.allocate(NumNodes);
    1139        4322 :         thisEquipConfig.returnNodeSpaceMixerIndex.allocate(NumNodes);
    1140        8648 :         for (int &mixIndex : thisEquipConfig.returnNodeSpaceMixerIndex) {
    1141        4326 :             mixIndex = -1;
    1142             :         }
    1143        4322 :         thisEquipConfig.ReturnNodeAirLoopNum.allocate(NumNodes);
    1144        4322 :         thisEquipConfig.ReturnNodeRetPathNum.allocate(NumNodes);
    1145        4322 :         thisEquipConfig.ReturnNodeRetPathCompNum.allocate(NumNodes);
    1146        4322 :         thisEquipConfig.ReturnNodeInletNum.allocate(NumNodes);
    1147        4322 :         thisEquipConfig.FixedReturnFlow.allocate(NumNodes);
    1148        4322 :         thisEquipConfig.ReturnNodePlenumNum.allocate(NumNodes);
    1149        4322 :         thisEquipConfig.ReturnNodeExhaustNodeNum.allocate(NumNodes);
    1150        4322 :         thisEquipConfig.SharedExhaustNode.allocate(NumNodes);
    1151        4322 :         thisEquipConfig.ReturnNode = 0;           // initialize to zero here
    1152        4322 :         thisEquipConfig.ReturnNodeAirLoopNum = 0; // initialize to zero here
    1153        4322 :         thisEquipConfig.ReturnNodeInletNum = 0;   // initialize to zero here
    1154        4322 :         thisEquipConfig.ReturnNodeRetPathNum = 0;
    1155        4322 :         thisEquipConfig.ReturnNodeRetPathCompNum = 0;
    1156        4322 :         thisEquipConfig.FixedReturnFlow = false;                                // initialize to false here
    1157        4322 :         thisEquipConfig.ReturnNodePlenumNum = 0;                                // initialize to zero here
    1158        4322 :         thisEquipConfig.ReturnNodeExhaustNodeNum = 0;                           // initialize to zero here
    1159        4322 :         thisEquipConfig.SharedExhaustNode = LightReturnExhaustConfig::NoExhast; // initialize to zero here
    1160             : 
    1161        8648 :         for (int NodeNum = 1; NodeNum <= NumNodes; ++NodeNum) {
    1162        4326 :             thisEquipConfig.ReturnNode(NodeNum) = NodeNums(NodeNum);
    1163        4326 :             bool UniqueNodeError = false;
    1164        4326 :             NodeInputManager::CheckUniqueNodeNumbers(state, "Zone Return Air Nodes", UniqueNodeError, NodeNums(NodeNum), thisEquipConfig.ZoneName);
    1165        4326 :             if (UniqueNodeError) {
    1166             :                 // ShowContinueError(state, format("Occurs for Zone = {}", trim( AlphArray( 1 ) )));
    1167           0 :                 state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
    1168             :             }
    1169             :         }
    1170             :     } else {
    1171           0 :         ShowContinueError(
    1172             :             state,
    1173           0 :             format("Invalid Zone Return Air Node or NodeList Name in ZoneHVAC:EquipmentConnections object, for Zone={}", thisEquipConfig.ZoneName));
    1174           0 :         state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
    1175             :     }
    1176             : 
    1177        4322 :     NodeListError = false;
    1178        8644 :     GetNodeNums(state,
    1179             :                 ReturnFlowBasisNodeListName,
    1180             :                 NumNodes,
    1181             :                 NodeNums,
    1182             :                 NodeListError,
    1183             :                 DataLoopNode::NodeFluidType::Air,
    1184             :                 (isSpace ? DataLoopNode::ConnectionObjectType::SpaceHVACEquipmentConnections
    1185             :                          : DataLoopNode::ConnectionObjectType::ZoneHVACEquipmentConnections),
    1186        4322 :                 thisEquipConfig.ZoneName,
    1187             :                 DataLoopNode::ConnectionType::Sensor,
    1188             :                 NodeInputManager::CompFluidStream::Primary,
    1189             :                 DataLoopNode::ObjectIsNotParent);
    1190             : 
    1191        4322 :     if (!NodeListError) {
    1192        4322 :         thisEquipConfig.NumReturnFlowBasisNodes = NumNodes;
    1193             : 
    1194        4322 :         thisEquipConfig.ReturnFlowBasisNode.allocate(NumNodes);
    1195             : 
    1196        4322 :         for (int NodeNum = 1; NodeNum <= NumNodes; ++NodeNum) {
    1197           0 :             thisEquipConfig.ReturnFlowBasisNode(NodeNum) = NodeNums(NodeNum);
    1198             :         }
    1199             :     } else {
    1200           0 :         ShowContinueError(
    1201             :             state,
    1202           0 :             format("Invalid Zone Return Air Node 1 Flow Rate Basis Node or NodeList Name in ZoneHVAC:EquipmentConnections object, for Zone={}",
    1203           0 :                    thisEquipConfig.ZoneName));
    1204           0 :         state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
    1205             :     }
    1206        4322 : }
    1207             : 
    1208           1 : void processZoneEquipSplitterInput(EnergyPlusData &state,
    1209             :                                    std::string_view zeqSplitterModuleObject,
    1210             :                                    int const zeqSplitterNum,
    1211             :                                    int const zoneNum,
    1212             :                                    InputProcessor::json const objectSchemaProps,
    1213             :                                    InputProcessor::json const objectFields,
    1214             :                                    DataZoneEquipment::ZoneEquipmentSplitter &thisZeqSplitter)
    1215             : 
    1216             : {
    1217             :     static constexpr std::string_view RoutineName("processZoneEquipSplitterInput: "); // include trailing blank space
    1218           1 :     auto &ip = state.dataInputProcessing->inputProcessor;
    1219           2 :     std::string const zeqTypeName = ip->getAlphaFieldValue(objectFields, objectSchemaProps, "zone_equipment_object_type");
    1220           1 :     thisZeqSplitter.zoneEquipType = DataZoneEquipment::ZoneEquipType(getEnumValue(zoneEquipTypeNamesUC, zeqTypeName));
    1221             :     // SpaceHVAC TODO: Copied this block from processZoneEquipmentInput section for ZoneHVAC:EquipmentList - seems this could be simplified
    1222           1 :     if (thisZeqSplitter.zoneEquipType == ZoneEquipType::Invalid) {
    1223           0 :         if (zeqTypeName == "ZONEHVAC:LOWTEMPERATURERADIANT:CONSTANTFLOW" || zeqTypeName == "ZONEHVAC:LOWTEMPERATURERADIANT:ELECTRIC") {
    1224           0 :             thisZeqSplitter.zoneEquipType = ZoneEquipType::LowTemperatureRadiant;
    1225           0 :         } else if (zeqTypeName == "WATERHEATER:HEATPUMP:WRAPPEDCONDENSER") {
    1226           0 :             thisZeqSplitter.zoneEquipType = DataZoneEquipment::ZoneEquipType::HeatPumpWaterHeater;
    1227             :         } else {
    1228           0 :             ShowSevereError(state, format("{}{} = {}", RoutineName, zeqSplitterModuleObject, thisZeqSplitter.Name));
    1229           0 :             ShowContinueError(state, format("..Invalid Equipment Type = {}", zeqTypeName));
    1230           0 :             state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
    1231             :         }
    1232             :     }
    1233             : 
    1234           1 :     thisZeqSplitter.zoneEquipName = ip->getAlphaFieldValue(objectFields, objectSchemaProps, "zone_equipment_name");
    1235             : 
    1236             :     // Search zone equipment list for matching equip type and name
    1237           1 :     bool found = false;
    1238           1 :     auto &thisZoneEqList = state.dataZoneEquip->ZoneEquipList(state.dataZoneEquip->ZoneEquipConfig(zoneNum).EquipListIndex);
    1239           1 :     for (int eqCount = 1; eqCount <= thisZoneEqList.NumOfEquipTypes; ++eqCount) {
    1240           1 :         if (thisZeqSplitter.zoneEquipType == thisZoneEqList.EquipType(eqCount)) {
    1241           1 :             if (thisZeqSplitter.zoneEquipName == thisZoneEqList.EquipName(eqCount)) {
    1242           1 :                 found = true;
    1243             :                 // Set index in zone equipment list pointing to this SpaceHVAC:ZoneEquipmentSplitter
    1244           1 :                 thisZoneEqList.zoneEquipSplitterIndex = zeqSplitterNum;
    1245             :                 // SpaceHVAC TODO: Outletnodes aren't know yet - need to set this in a later init
    1246             :                 // thisZeqSplitter.zoneEquipOutletNodeNum = thisZoneEqList.EquipData(eqCount).OutletNodeNums(1);
    1247           1 :                 break;
    1248             :             }
    1249             :         }
    1250             :     }
    1251           1 :     if (!found) {
    1252           0 :         ShowSevereError(state, format("{}{} = {}", RoutineName, zeqSplitterModuleObject, thisZeqSplitter.Name));
    1253           0 :         ShowContinueError(
    1254           0 :             state, format(".. Zone Equipment Object Type={} and Zone Equipment Name={} not found", zeqTypeName, thisZeqSplitter.zoneEquipName));
    1255           0 :         ShowContinueError(state, format(".. in ZoneHVAC:EquipmentList={}", thisZoneEqList.Name));
    1256           0 :         state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
    1257           0 :         return;
    1258             :     }
    1259             : 
    1260           1 :     bool objectIsParent = true;
    1261           1 :     thisZeqSplitter.zoneEquipOutletNodeNum =
    1262           2 :         GetOnlySingleNode(state,
    1263           2 :                           ip->getAlphaFieldValue(objectFields, objectSchemaProps, "zone_equipment_outlet_node_name"),
    1264           1 :                           state.dataZoneEquip->GetZoneEquipmentDataErrorsFound,
    1265             :                           thisZeqSplitter.spaceEquipType,
    1266           1 :                           thisZeqSplitter.Name,
    1267             :                           DataLoopNode::NodeFluidType::Air,
    1268             :                           DataLoopNode::ConnectionType::Inlet,
    1269             :                           NodeInputManager::CompFluidStream::Primary,
    1270             :                           objectIsParent);
    1271             : 
    1272           1 :     thisZeqSplitter.tstatControl = DataZoneEquipment::ZoneEquipTstatControl(
    1273           1 :         getEnumValue(zoneEquipTstatControlNamesUC, ip->getAlphaFieldValue(objectFields, objectSchemaProps, "thermostat_control_method")));
    1274           1 :     if (thisZeqSplitter.tstatControl == DataZoneEquipment::ZoneEquipTstatControl::SingleSpace) {
    1275           2 :         std::string spaceName = ip->getAlphaFieldValue(objectFields, objectSchemaProps, "control_space_name");
    1276           1 :         thisZeqSplitter.controlSpaceIndex = Util::FindItemInList(spaceName, state.dataHeatBal->space);
    1277           1 :         if (thisZeqSplitter.controlSpaceIndex == 0) {
    1278           0 :             ShowSevereError(state, format("{}{}={}", RoutineName, zeqSplitterModuleObject, thisZeqSplitter.Name));
    1279           0 :             ShowContinueError(state, format("Space Name={} not found.", spaceName));
    1280           0 :             state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
    1281             :         }
    1282           1 :     }
    1283           1 :     thisZeqSplitter.spaceSizingBasis = DataZoneEquipment::SpaceEquipSizingBasis(
    1284           1 :         getEnumValue(spaceEquipSizingBasisNamesUC, ip->getAlphaFieldValue(objectFields, objectSchemaProps, "space_fraction_method")));
    1285             : 
    1286           1 :     auto extensibles = objectFields.find("spaces");
    1287           1 :     auto const &extensionSchemaProps = objectSchemaProps["spaces"]["items"]["properties"];
    1288           1 :     if (extensibles != objectFields.end()) {
    1289           1 :         auto &extensiblesArray = extensibles.value();
    1290           1 :         int const numSpaces = extensiblesArray.size();
    1291           1 :         thisZeqSplitter.spaces.resize(numSpaces);
    1292           1 :         int spaceCount = -1;
    1293           4 :         for (auto &extensibleInstance : extensiblesArray) {
    1294           3 :             ++spaceCount;
    1295           3 :             auto &thisZeqSpace = thisZeqSplitter.spaces[spaceCount];
    1296           6 :             std::string const spaceName = ip->getAlphaFieldValue(extensibleInstance, extensionSchemaProps, "space_name");
    1297           3 :             thisZeqSpace.spaceIndex = Util::FindItemInList(spaceName, state.dataHeatBal->space);
    1298           3 :             if (thisZeqSpace.spaceIndex == 0) {
    1299           0 :                 ShowSevereError(state, format("{}{}={}", RoutineName, zeqSplitterModuleObject, thisZeqSplitter.Name));
    1300           0 :                 ShowContinueError(state, format("Space Name={} not found.", spaceName));
    1301           0 :                 state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
    1302             :             } else {
    1303           3 :                 thisZeqSpace.fraction = ip->getRealFieldValue(extensibleInstance, extensionSchemaProps, "space_fraction");
    1304           3 :                 thisZeqSpace.spaceNodeNum =
    1305           6 :                     GetOnlySingleNode(state,
    1306           6 :                                       ip->getAlphaFieldValue(extensibleInstance, extensionSchemaProps, "space_supply_node_name"),
    1307           3 :                                       state.dataZoneEquip->GetZoneEquipmentDataErrorsFound,
    1308             :                                       thisZeqSplitter.spaceEquipType,
    1309           3 :                                       thisZeqSplitter.Name,
    1310             :                                       DataLoopNode::NodeFluidType::Air,
    1311             :                                       DataLoopNode::ConnectionType::Outlet,
    1312             :                                       NodeInputManager::CompFluidStream::Primary,
    1313             :                                       objectIsParent);
    1314           3 :                 if (thisZeqSplitter.controlSpaceIndex == thisZeqSpace.spaceIndex) {
    1315           1 :                     thisZeqSplitter.controlSpaceNumber = spaceCount;
    1316             :                 }
    1317             :             }
    1318           4 :         }
    1319             :     }
    1320           1 : }
    1321             : 
    1322           1 : void processZoneEquipMixerInput(EnergyPlusData &state,
    1323             :                                 std::string_view zeqMixerModuleObject,
    1324             :                                 int const zoneNum,
    1325             :                                 InputProcessor::json const objectSchemaProps,
    1326             :                                 InputProcessor::json const objectFields,
    1327             :                                 DataZoneEquipment::ZoneEquipmentMixer &thisZeqMixer)
    1328             : 
    1329             : {
    1330             :     static constexpr std::string_view RoutineName("processZoneEquipMixerInput: "); // include trailing blank space
    1331           1 :     auto &ip = state.dataInputProcessing->inputProcessor;
    1332           1 :     bool objectIsParent = true;
    1333           2 :     thisZeqMixer.outletNodeNum = GetOnlySingleNode(state,
    1334           2 :                                                    ip->getAlphaFieldValue(objectFields, objectSchemaProps, "zone_equipment_inlet_node_name"),
    1335           1 :                                                    state.dataZoneEquip->GetZoneEquipmentDataErrorsFound,
    1336             :                                                    thisZeqMixer.spaceEquipType,
    1337           1 :                                                    thisZeqMixer.Name,
    1338             :                                                    DataLoopNode::NodeFluidType::Air,
    1339             :                                                    DataLoopNode::ConnectionType::Outlet,
    1340             :                                                    NodeInputManager::CompFluidStream::Primary,
    1341             :                                                    objectIsParent);
    1342             :     // Check zone exhaust nodes
    1343           1 :     bool found = false;
    1344           1 :     auto &thisZoneEquipConfig = state.dataZoneEquip->ZoneEquipConfig(zoneNum);
    1345           1 :     for (int exhNodeNum : thisZoneEquipConfig.ExhaustNode) {
    1346           1 :         if (thisZeqMixer.outletNodeNum == exhNodeNum) {
    1347           1 :             found = true;
    1348           1 :             break;
    1349             :         }
    1350             :     }
    1351           1 :     if (!found) {
    1352           0 :         ShowSevereError(state, format("{}{}={}", RoutineName, zeqMixerModuleObject, thisZeqMixer.Name));
    1353           0 :         ShowContinueError(state,
    1354           0 :                           format("Zone Equipment Inlet Node Name={} is not an exhaust node for ZoneHVAC:EquipmentConnections={}.",
    1355           0 :                                  state.dataLoopNodes->NodeID(thisZeqMixer.outletNodeNum),
    1356           0 :                                  thisZoneEquipConfig.ZoneName));
    1357           0 :         state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
    1358             :     }
    1359             : 
    1360           1 :     thisZeqMixer.spaceSizingBasis = DataZoneEquipment::SpaceEquipSizingBasis(
    1361           1 :         getEnumValue(spaceEquipSizingBasisNamesUC, ip->getAlphaFieldValue(objectFields, objectSchemaProps, "space_fraction_method")));
    1362             : 
    1363           1 :     auto extensibles = objectFields.find("spaces");
    1364           1 :     auto const &extensionSchemaProps = objectSchemaProps["spaces"]["items"]["properties"];
    1365           1 :     if (extensibles != objectFields.end()) {
    1366           1 :         auto &extensiblesArray = extensibles.value();
    1367           1 :         int const numSpaces = extensiblesArray.size();
    1368           1 :         thisZeqMixer.spaces.resize(numSpaces);
    1369           1 :         int spaceCount = -1;
    1370           2 :         for (auto &extensibleInstance : extensiblesArray) {
    1371           1 :             ++spaceCount;
    1372           1 :             auto &thisZeqSpace = thisZeqMixer.spaces[spaceCount];
    1373           2 :             std::string const spaceName = ip->getAlphaFieldValue(extensibleInstance, extensionSchemaProps, "space_name");
    1374           1 :             thisZeqSpace.spaceIndex = Util::FindItemInList(spaceName, state.dataHeatBal->space);
    1375           1 :             if (thisZeqSpace.spaceIndex == 0) {
    1376           0 :                 ShowSevereError(state, format("{}{}={}", RoutineName, zeqMixerModuleObject, thisZeqMixer.Name));
    1377           0 :                 ShowContinueError(state, format("Space Name={} not found.", spaceName));
    1378           0 :                 state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
    1379             :             } else {
    1380           1 :                 thisZeqSpace.fraction = ip->getRealFieldValue(extensibleInstance, extensionSchemaProps, "space_fraction");
    1381           2 :                 thisZeqSpace.spaceNodeNum = GetOnlySingleNode(state,
    1382           2 :                                                               ip->getAlphaFieldValue(extensibleInstance, extensionSchemaProps, "space_node_name"),
    1383           1 :                                                               state.dataZoneEquip->GetZoneEquipmentDataErrorsFound,
    1384             :                                                               thisZeqMixer.spaceEquipType,
    1385           1 :                                                               thisZeqMixer.Name,
    1386             :                                                               DataLoopNode::NodeFluidType::Air,
    1387             :                                                               DataLoopNode::ConnectionType::Inlet,
    1388             :                                                               NodeInputManager::CompFluidStream::Primary,
    1389             :                                                               objectIsParent);
    1390             :                 // Check space exhaust nodes
    1391           1 :                 bool found = false;
    1392           1 :                 auto &thisSpaceEquipConfig = state.dataZoneEquip->spaceEquipConfig(thisZeqSpace.spaceIndex);
    1393           1 :                 for (int exhNodeNum : thisSpaceEquipConfig.ExhaustNode) {
    1394           1 :                     if (thisZeqSpace.spaceNodeNum == exhNodeNum) {
    1395           1 :                         found = true;
    1396           1 :                         break;
    1397             :                     }
    1398             :                 }
    1399           1 :                 if (!found) {
    1400           0 :                     ShowSevereError(state, format("{}{}={}", RoutineName, zeqMixerModuleObject, thisZeqMixer.Name));
    1401           0 :                     ShowContinueError(state,
    1402           0 :                                       format("Space Node Name={} is not an exhaust node for SpaceHVAC:EquipmentConnections={}.",
    1403           0 :                                              state.dataLoopNodes->NodeID(thisZeqSpace.spaceNodeNum),
    1404           0 :                                              thisSpaceEquipConfig.ZoneName));
    1405           0 :                     state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
    1406             :                 }
    1407             :             }
    1408           2 :         }
    1409             :     }
    1410           1 : }
    1411             : 
    1412           1 : void processZoneReturnMixerInput(EnergyPlusData &state,
    1413             :                                  std::string_view zeqMixerModuleObject,
    1414             :                                  int const zoneNum,
    1415             :                                  InputProcessor::json const objectSchemaProps,
    1416             :                                  InputProcessor::json const objectFields,
    1417             :                                  int mixerIndex)
    1418             : 
    1419             : {
    1420             :     static constexpr std::string_view RoutineName("processZoneReturnMixerInput: "); // include trailing blank space
    1421           1 :     auto &ip = state.dataInputProcessing->inputProcessor;
    1422           1 :     bool objectIsParent = true;
    1423           1 :     auto &thisZretMixer = state.dataZoneEquip->zoneReturnMixer[mixerIndex];
    1424           2 :     thisZretMixer.outletNodeNum = GetOnlySingleNode(state,
    1425           2 :                                                     ip->getAlphaFieldValue(objectFields, objectSchemaProps, "zone_return_air_node_name"),
    1426           1 :                                                     state.dataZoneEquip->GetZoneEquipmentDataErrorsFound,
    1427             :                                                     thisZretMixer.spaceEquipType,
    1428           1 :                                                     thisZretMixer.Name,
    1429             :                                                     DataLoopNode::NodeFluidType::Air,
    1430             :                                                     DataLoopNode::ConnectionType::Outlet,
    1431             :                                                     NodeInputManager::CompFluidStream::Primary,
    1432             :                                                     objectIsParent);
    1433             :     // Check zone return nodes
    1434           1 :     bool found = false;
    1435           1 :     auto &thisZoneEquipConfig = state.dataZoneEquip->ZoneEquipConfig(zoneNum);
    1436           1 :     int nodeCounter = 0;
    1437           1 :     for (int retNodeNum : thisZoneEquipConfig.ReturnNode) {
    1438           1 :         ++nodeCounter;
    1439           1 :         if (thisZretMixer.outletNodeNum == retNodeNum) {
    1440           1 :             found = true;
    1441             :             // Zone return node is fed by a space return mixer
    1442           1 :             thisZoneEquipConfig.returnNodeSpaceMixerIndex(nodeCounter) = mixerIndex;
    1443           1 :             break;
    1444             :         }
    1445             :     }
    1446           1 :     if (!found) {
    1447           0 :         ShowSevereError(state, format("{}{}={}", RoutineName, zeqMixerModuleObject, thisZretMixer.Name));
    1448           0 :         ShowContinueError(state,
    1449           0 :                           format("Zone Equipment Return Air Node Name={} is not a return air node for ZoneHVAC:EquipmentConnections={}.",
    1450           0 :                                  state.dataLoopNodes->NodeID(thisZretMixer.outletNodeNum),
    1451           0 :                                  thisZoneEquipConfig.ZoneName));
    1452           0 :         state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
    1453             :     }
    1454             : 
    1455           1 :     auto extensibles = objectFields.find("spaces");
    1456           1 :     auto const &extensionSchemaProps = objectSchemaProps["spaces"]["items"]["properties"];
    1457           1 :     if (extensibles != objectFields.end()) {
    1458           1 :         auto &extensiblesArray = extensibles.value();
    1459           1 :         int const numSpaces = extensiblesArray.size();
    1460           1 :         thisZretMixer.spaces.resize(numSpaces);
    1461           1 :         int spaceCount = -1;
    1462           4 :         for (auto &extensibleInstance : extensiblesArray) {
    1463           3 :             ++spaceCount;
    1464           3 :             auto &thisZeqSpace = thisZretMixer.spaces[spaceCount];
    1465           6 :             std::string const spaceName = ip->getAlphaFieldValue(extensibleInstance, extensionSchemaProps, "space_name");
    1466           3 :             thisZeqSpace.spaceIndex = Util::FindItemInList(spaceName, state.dataHeatBal->space);
    1467           3 :             if (thisZeqSpace.spaceIndex == 0) {
    1468           0 :                 ShowSevereError(state, format("{}{}={}", RoutineName, zeqMixerModuleObject, thisZretMixer.Name));
    1469           0 :                 ShowContinueError(state, format("Space Name={} not found.", spaceName));
    1470           0 :                 state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
    1471             :             } else {
    1472           3 :                 thisZeqSpace.spaceNodeNum =
    1473           6 :                     GetOnlySingleNode(state,
    1474           6 :                                       ip->getAlphaFieldValue(extensibleInstance, extensionSchemaProps, "space_return_air_node_name"),
    1475           3 :                                       state.dataZoneEquip->GetZoneEquipmentDataErrorsFound,
    1476             :                                       thisZretMixer.spaceEquipType,
    1477           3 :                                       thisZretMixer.Name,
    1478             :                                       DataLoopNode::NodeFluidType::Air,
    1479             :                                       DataLoopNode::ConnectionType::Inlet,
    1480             :                                       NodeInputManager::CompFluidStream::Primary,
    1481             :                                       objectIsParent);
    1482             :                 // Check space return nodes
    1483           3 :                 bool found = false;
    1484           3 :                 auto &thisSpaceEquipConfig = state.dataZoneEquip->spaceEquipConfig(thisZeqSpace.spaceIndex);
    1485           3 :                 for (int retNodeNum : thisSpaceEquipConfig.ReturnNode) {
    1486           3 :                     if (thisZeqSpace.spaceNodeNum == retNodeNum) {
    1487           3 :                         found = true;
    1488           3 :                         break;
    1489             :                     }
    1490             :                 }
    1491           3 :                 if (!found) {
    1492           0 :                     ShowSevereError(state, format("{}{}={}", RoutineName, zeqMixerModuleObject, thisZretMixer.Name));
    1493           0 :                     ShowContinueError(state,
    1494           0 :                                       format("Space Return Air Node Name={} is not a return air node for SpaceHVAC:EquipmentConnections={}.",
    1495           0 :                                              state.dataLoopNodes->NodeID(thisZeqSpace.spaceNodeNum),
    1496           0 :                                              thisSpaceEquipConfig.ZoneName));
    1497           0 :                     state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
    1498             :                 }
    1499             :             }
    1500           4 :         }
    1501             :     }
    1502           1 : }
    1503             : 
    1504        4415 : bool CheckZoneEquipmentList(EnergyPlusData &state,
    1505             :                             std::string_view const ComponentType, // Type of component
    1506             :                             std::string_view const ComponentName, // Name of component
    1507             :                             ObjexxFCL::Optional_int CtrlZoneNum)
    1508             : {
    1509             : 
    1510             :     // FUNCTION INFORMATION:
    1511             :     //       AUTHOR         Linda Lawrie
    1512             :     //       DATE WRITTEN   May 2007
    1513             :     //       MODIFIED       na
    1514             :     //       RE-ENGINEERED  na
    1515             : 
    1516             :     // PURPOSE OF THIS FUNCTION:
    1517             :     // Provides a way to check if a component name is listed on a zone equipment list.
    1518             : 
    1519             :     // Return value
    1520             :     bool IsOnList; // True if item is on a list, false if not.
    1521             : 
    1522             :     // FUNCTION LOCAL VARIABLE DECLARATIONS:
    1523             :     int Loop;
    1524             :     int ListLoop;
    1525             :     int CtrlZoneNumLocal;
    1526             : 
    1527        4415 :     CtrlZoneNumLocal = 0;
    1528        4415 :     IsOnList = false;
    1529       68535 :     for (Loop = 1; Loop <= state.dataGlobal->NumOfZones; ++Loop) {           // NumOfZoneEquipLists
    1530       68535 :         if (state.dataZoneEquip->ZoneEquipList(Loop).Name.empty()) continue; // dimensioned by NumOfZones.  Only valid ones have names.
    1531      138452 :         for (ListLoop = 1; ListLoop <= state.dataZoneEquip->ZoneEquipList(Loop).NumOfEquipTypes; ++ListLoop) {
    1532             : 
    1533       78080 :             if (!Util::SameString(state.dataZoneEquip->ZoneEquipList(Loop).EquipTypeName(ListLoop), ComponentType)) continue;
    1534       59453 :             if (ComponentName == "*") {
    1535           0 :                 IsOnList = true;
    1536           0 :                 CtrlZoneNumLocal = Loop;
    1537           0 :                 goto EquipList_exit;
    1538             :             }
    1539       59453 :             if (!Util::SameString(state.dataZoneEquip->ZoneEquipList(Loop).EquipName(ListLoop), ComponentName)) continue;
    1540        4415 :             IsOnList = true;
    1541        4415 :             CtrlZoneNumLocal = Loop;
    1542        4415 :             goto EquipList_exit;
    1543             :         }
    1544             :     }
    1545           0 : EquipList_exit:;
    1546        4415 :     if (present(CtrlZoneNum)) {
    1547           0 :         CtrlZoneNum = CtrlZoneNumLocal;
    1548             :     }
    1549        4415 :     return IsOnList;
    1550             : }
    1551             : 
    1552           7 : int GetControlledZoneIndex(EnergyPlusData &state, std::string const &ZoneName) // Zone name to match into Controlled Zone structure
    1553             : {
    1554             : 
    1555             :     // FUNCTION INFORMATION:
    1556             :     //       AUTHOR         Linda Lawrie
    1557             :     //       DATE WRITTEN   March 2008
    1558             : 
    1559             :     // PURPOSE OF THIS FUNCTION:
    1560             :     // This function returns the index into the Controlled Zone Equipment structure
    1561             :     // of the indicated zone.
    1562             : 
    1563           7 :     return Util::FindItemInList(ZoneName, state.dataZoneEquip->ZoneEquipConfig, &EquipConfiguration::ZoneName);
    1564             : }
    1565             : 
    1566           4 : int FindControlledZoneIndexFromSystemNodeNumberForZone(EnergyPlusData &state,
    1567             :                                                        int const TrialZoneNodeNum) // Node number to match into Controlled Zone structure
    1568             : {
    1569             : 
    1570             :     // FUNCTION INFORMATION:
    1571             :     //       AUTHOR         Brent Griffith
    1572             :     //       DATE WRITTEN   August 2013
    1573             : 
    1574             :     // PURPOSE OF THIS FUNCTION:
    1575             :     // This function returns the zone number for the indicated
    1576             :     // zone node num.  Returns 0 if did not find zone node in any Zone
    1577             : 
    1578           4 :     int ControlledZoneIndex = 0; // Index into Controlled Zone structure
    1579             : 
    1580          19 :     for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
    1581          16 :         if (state.dataZoneEquip->ZoneEquipConfig(ZoneNum).IsControlled) {
    1582          16 :             if (TrialZoneNodeNum == state.dataZoneEquip->ZoneEquipConfig(ZoneNum).ZoneNode) {
    1583             :                 // found it.
    1584           1 :                 ControlledZoneIndex = ZoneNum;
    1585           1 :                 break;
    1586             :             }
    1587             :         }
    1588             :     }
    1589             : 
    1590           4 :     return ControlledZoneIndex;
    1591             : }
    1592             : 
    1593         227 : int GetSystemNodeNumberForZone(EnergyPlusData &state, int const zoneNum)
    1594             : {
    1595             : 
    1596             :     // FUNCTION INFORMATION:
    1597             :     //       AUTHOR         Linda Lawrie
    1598             :     //       DATE WRITTEN   March 2008
    1599             : 
    1600             :     // PURPOSE OF THIS FUNCTION:
    1601             :     // This function returns the system node number for the indicated
    1602             :     // zone.  Returns 0 if the Zone is not a controlled zone.
    1603             : 
    1604         227 :     int SystemZoneNodeNumber = 0; // System node number for controlled zone
    1605             : 
    1606         227 :     if (zoneNum > 0) {
    1607         227 :         if (state.dataZoneEquip->ZoneEquipConfig(zoneNum).IsControlled) {
    1608         227 :             SystemZoneNodeNumber = state.dataZoneEquip->ZoneEquipConfig(zoneNum).ZoneNode;
    1609             :         }
    1610             :     }
    1611             : 
    1612         227 :     return SystemZoneNodeNumber;
    1613             : }
    1614             : 
    1615         122 : int GetReturnAirNodeForZone(EnergyPlusData &state,
    1616             :                             int const zoneNum,
    1617             :                             std::string const &NodeName,             // Return air node name to match (may be blank)
    1618             :                             std::string const &calledFromDescription // String identifying the calling function and object
    1619             : )
    1620             : {
    1621             : 
    1622             :     // FUNCTION INFORMATION:
    1623             :     //       AUTHOR         Linda Lawrie
    1624             :     //       DATE WRITTEN   March 2008
    1625             :     //       MODIFIED       Feb 2017 expanded for multiple return nodes in a zone
    1626             : 
    1627             :     // PURPOSE OF THIS FUNCTION:
    1628             :     // This function returns the return air node number for the indicated
    1629             :     // zone and node name.  If NodeName is blank, return the first return node number,
    1630             :     // otherwise return the node number of the matching return node name.
    1631             :     // Returns 0 if the Zone is not a controlled zone or the node name does not match.
    1632             : 
    1633             :     // Return value
    1634         122 :     int ReturnAirNodeNumber = 0; // Return Air node number for controlled zone
    1635             : 
    1636         122 :     ReturnAirNodeNumber = 0; // default is not found
    1637         122 :     if (zoneNum > 0) {
    1638             :         {
    1639         122 :             auto const &thisZoneEquip(state.dataZoneEquip->ZoneEquipConfig(zoneNum));
    1640         122 :             if (thisZoneEquip.IsControlled) {
    1641         122 :                 if (NodeName.empty()) {
    1642             :                     // If NodeName is blank, return first return node number, but warn if there are multiple return nodes for this zone
    1643         122 :                     ReturnAirNodeNumber = thisZoneEquip.ReturnNode(1);
    1644         122 :                     if (thisZoneEquip.NumReturnNodes > 1) {
    1645           0 :                         ShowWarningError(state,
    1646           0 :                                          format("GetReturnAirNodeForZone: {}, request for zone return node is ambiguous.", calledFromDescription));
    1647           0 :                         ShowContinueError(state,
    1648           0 :                                           format("Zone={} has {} return nodes. First return node will be used.",
    1649           0 :                                                  thisZoneEquip.ZoneName,
    1650           0 :                                                  thisZoneEquip.NumReturnNodes));
    1651             :                     }
    1652             :                 } else {
    1653           0 :                     for (int nodeCount = 1; nodeCount <= thisZoneEquip.NumReturnNodes; ++nodeCount) {
    1654           0 :                         int curNodeNum = thisZoneEquip.ReturnNode(nodeCount);
    1655           0 :                         if (NodeName == state.dataLoopNodes->NodeID(curNodeNum)) {
    1656           0 :                             ReturnAirNodeNumber = curNodeNum;
    1657             :                         }
    1658             :                     }
    1659             :                 }
    1660             :             }
    1661             :         }
    1662             :     }
    1663             : 
    1664         122 :     return ReturnAirNodeNumber;
    1665             : }
    1666             : 
    1667        4329 : int GetReturnNumForZone(EnergyPlusData &state,
    1668             :                         int const zoneNum,
    1669             :                         std::string const &NodeName // Return air node name to match (may be blank)
    1670             : )
    1671             : {
    1672             : 
    1673             :     // PURPOSE OF THIS FUNCTION:
    1674             :     // This function returns the zone return number (not the node number) for the indicated
    1675             :     // zone and node name.  If NodeName is blank, return 1 (the first return node)
    1676             :     // otherwise return the index of the matching return node name.
    1677             :     // Returns 0 if the Zone is not a controlled zone or the node name does not match.
    1678             : 
    1679             :     // Return value
    1680        4329 :     int ReturnIndex = 0; // Return number for the given zone (not the node number)
    1681             : 
    1682        4329 :     if (zoneNum > 0) {
    1683        4329 :         if (state.dataZoneEquip->ZoneEquipConfig(zoneNum).IsControlled) {
    1684        4195 :             if (NodeName.empty()) {
    1685             :                 // If NodeName is blank, return first return node number
    1686        4194 :                 ReturnIndex = 1;
    1687             :             } else {
    1688           2 :                 for (int nodeCount = 1; nodeCount <= state.dataZoneEquip->ZoneEquipConfig(zoneNum).NumReturnNodes; ++nodeCount) {
    1689           1 :                     int curNodeNum = state.dataZoneEquip->ZoneEquipConfig(zoneNum).ReturnNode(nodeCount);
    1690           1 :                     if (NodeName == state.dataLoopNodes->NodeID(curNodeNum)) {
    1691           1 :                         ReturnIndex = nodeCount;
    1692             :                     }
    1693             :                 }
    1694             :             }
    1695             :         }
    1696             :     }
    1697             : 
    1698        4329 :     return ReturnIndex;
    1699             : }
    1700             : 
    1701           1 : bool VerifyLightsExhaustNodeForZone(EnergyPlusData &state, int const ZoneNum, int const ZoneExhaustNodeNum)
    1702             : {
    1703           1 :     bool exhaustNodeError = true;
    1704             : 
    1705           1 :     for (int ExhaustNum = 1; ExhaustNum <= state.dataZoneEquip->ZoneEquipConfig(ZoneNum).NumExhaustNodes; ++ExhaustNum) {
    1706           1 :         if (ZoneExhaustNodeNum == state.dataZoneEquip->ZoneEquipConfig(ZoneNum).ExhaustNode(ExhaustNum)) {
    1707           1 :             exhaustNodeError = false;
    1708           1 :             break;
    1709             :         }
    1710             :     }
    1711             : 
    1712           1 :     return exhaustNodeError;
    1713             : }
    1714             : 
    1715         483 : void EquipList::getPrioritiesForInletNode(EnergyPlusData &state,
    1716             :                                           int const inletNodeNum, // Zone inlet node number to match
    1717             :                                           int &coolingPriority,   // Cooling priority num for matching equipment
    1718             :                                           int &heatingPriority    // Heating priority num for matching equipment
    1719             : )
    1720             : {
    1721         483 :     bool equipFound = false;
    1722         599 :     for (int equipNum = 1; equipNum <= this->NumOfEquipTypes; ++equipNum) {
    1723         599 :         if (this->EquipType(equipNum) == DataZoneEquipment::ZoneEquipType::AirDistributionUnit) {
    1724         488 :             if (inletNodeNum == state.dataDefineEquipment->AirDistUnit(this->EquipIndex(equipNum)).OutletNodeNum) {
    1725         483 :                 equipFound = true;
    1726             :             }
    1727             :         }
    1728         599 :         if (equipFound) {
    1729         483 :             coolingPriority = this->CoolingPriority(equipNum);
    1730         483 :             heatingPriority = this->HeatingPriority(equipNum);
    1731         483 :             break;
    1732             :         }
    1733             :     }
    1734             :     // Set MinAirLoopIterationsAfterFirst for equipment that uses sequenced loads, based on zone equip load distribution scheme
    1735         483 :     int minIterations = state.dataHVACGlobal->MinAirLoopIterationsAfterFirst;
    1736         483 :     if (this->LoadDistScheme == DataZoneEquipment::LoadDist::Sequential) {
    1737             :         // Sequential needs one extra iterations up to the highest airterminal unit equipment number
    1738         477 :         minIterations = max(coolingPriority, heatingPriority, minIterations);
    1739           6 :     } else if (this->LoadDistScheme == DataZoneEquipment::LoadDist::Uniform) {
    1740             :         // Uniform needs one extra iteration which is the default
    1741           4 :     } else if (this->LoadDistScheme == DataZoneEquipment::LoadDist::UniformPLR) {
    1742             :         // UniformPLR needs two extra iterations, regardless of unit equipment number
    1743           2 :         minIterations = max(2, minIterations);
    1744           2 :     } else if (this->LoadDistScheme == DataZoneEquipment::LoadDist::SequentialUniformPLR) {
    1745             :         // SequentialUniformPLR needs one extra iterations up to the highest airterminal unit equipment number plus one more
    1746           2 :         minIterations = max((coolingPriority + 1), (heatingPriority + 1), minIterations);
    1747             :     }
    1748         483 :     state.dataHVACGlobal->MinAirLoopIterationsAfterFirst = minIterations;
    1749         483 : }
    1750             : 
    1751    85427192 : Real64 EquipList::SequentialHeatingFraction(EnergyPlusData &state, const int equipNum)
    1752             : {
    1753    85427192 :     return ScheduleManager::GetCurrentScheduleValue(state, SequentialHeatingFractionSchedPtr(equipNum));
    1754             : }
    1755             : 
    1756    84790204 : Real64 EquipList::SequentialCoolingFraction(EnergyPlusData &state, const int equipNum)
    1757             : {
    1758    84790204 :     return ScheduleManager::GetCurrentScheduleValue(state, SequentialCoolingFractionSchedPtr(equipNum));
    1759             : }
    1760             : 
    1761         216 : int GetZoneEquipControlledZoneNum(EnergyPlusData &state, DataZoneEquipment::ZoneEquipType const zoneEquipType, std::string const &EquipmentName)
    1762             : {
    1763             :     static constexpr std::string_view RoutineName("GetZoneEquipControlledZoneNum: ");
    1764         216 :     int ControlZoneNum = 0;
    1765             : 
    1766        1045 :     for (int CtrlZone = 1; CtrlZone <= state.dataGlobal->NumOfZones; ++CtrlZone) {
    1767        1045 :         if (!state.dataZoneEquip->ZoneEquipConfig(CtrlZone).IsControlled) continue;
    1768        2395 :         for (int Num = 1; Num <= state.dataZoneEquip->ZoneEquipList(CtrlZone).NumOfEquipTypes; ++Num) {
    1769        2377 :             if (zoneEquipType == state.dataZoneEquip->ZoneEquipList(CtrlZone).EquipType(Num) &&
    1770         722 :                 Util::SameString(EquipmentName, state.dataZoneEquip->ZoneEquipList(CtrlZone).EquipName(Num))) {
    1771         216 :                 return ControlZoneNum = CtrlZone;
    1772             :             }
    1773             :         }
    1774             :     }
    1775           0 :     ShowSevereError(state,
    1776           0 :                     fmt::format("{}{}=\"{}\" is not on any ZoneHVAC:Equipmentlist. It will not be simulated.",
    1777             :                                 RoutineName,
    1778           0 :                                 zoneEquipTypeNamesUC[(int)zoneEquipType],
    1779             :                                 EquipmentName));
    1780           0 :     return ControlZoneNum;
    1781             : }
    1782             : 
    1783           1 : void CheckSharedExhaust(EnergyPlusData &state)
    1784             : {
    1785           1 :     int ExhastNodeNum = 0;
    1786           7 :     for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
    1787           6 :         if (state.dataZoneEquip->ZoneEquipConfig(ZoneNum).NumReturnNodes < 2) continue;
    1788           0 :         for (int nodeCount = 1; nodeCount <= state.dataZoneEquip->ZoneEquipConfig(ZoneNum).NumReturnNodes; ++nodeCount) {
    1789           0 :             if (state.dataZoneEquip->ZoneEquipConfig(ZoneNum).SharedExhaustNode(nodeCount) == LightReturnExhaustConfig::Shared) continue;
    1790           0 :             ExhastNodeNum = state.dataZoneEquip->ZoneEquipConfig(ZoneNum).ReturnNodeExhaustNodeNum(nodeCount);
    1791           0 :             if (ExhastNodeNum > 0) {
    1792           0 :                 state.dataZoneEquip->ZoneEquipConfig(ZoneNum).SharedExhaustNode(nodeCount) = LightReturnExhaustConfig::Single;
    1793           0 :                 for (int nodeCount1 = nodeCount + 1; nodeCount1 <= state.dataZoneEquip->ZoneEquipConfig(ZoneNum).NumReturnNodes; ++nodeCount1) {
    1794           0 :                     if (ExhastNodeNum == state.dataZoneEquip->ZoneEquipConfig(ZoneNum).ReturnNodeExhaustNodeNum(nodeCount1)) {
    1795           0 :                         state.dataZoneEquip->ZoneEquipConfig(ZoneNum).SharedExhaustNode(nodeCount) = LightReturnExhaustConfig::Multi;
    1796           0 :                         state.dataZoneEquip->ZoneEquipConfig(ZoneNum).SharedExhaustNode(nodeCount1) = LightReturnExhaustConfig::Shared;
    1797             :                     }
    1798             :                 }
    1799             :             }
    1800             :         }
    1801             :     }
    1802           1 : }
    1803             : 
    1804    51185428 : void EquipConfiguration::setTotalInletFlows(EnergyPlusData &state)
    1805             : {
    1806    51185428 :     this->TotInletAirMassFlowRate = 0.0;
    1807    51185428 :     Real64 TotInletAirMassFlowRateMax = 0.0;
    1808    51185428 :     Real64 TotInletAirMassFlowRateMaxAvail = 0.0;
    1809    51185428 :     Real64 TotInletAirMassFlowRateMin = 0.0;
    1810    51185428 :     Real64 TotInletAirMassFlowRateMinAvail = 0.0;
    1811   103475924 :     for (int NodeNum = 1; NodeNum <= this->NumInletNodes; ++NodeNum) {
    1812             :         {
    1813    52290496 :             auto const &thisNode(state.dataLoopNodes->Node(this->InletNode(NodeNum)));
    1814    52290496 :             this->TotInletAirMassFlowRate += thisNode.MassFlowRate;
    1815    52290496 :             TotInletAirMassFlowRateMax += thisNode.MassFlowRateMax;
    1816    52290496 :             TotInletAirMassFlowRateMaxAvail += thisNode.MassFlowRateMaxAvail;
    1817    52290496 :             TotInletAirMassFlowRateMin += thisNode.MassFlowRateMin;
    1818    52290496 :             TotInletAirMassFlowRateMinAvail += thisNode.MassFlowRateMinAvail;
    1819             :         }
    1820             :     }
    1821    51185428 :     auto &zoneSpaceNode = state.dataLoopNodes->Node(this->ZoneNode);
    1822    51185428 :     zoneSpaceNode.MassFlowRate = this->TotInletAirMassFlowRate;
    1823    51185428 :     zoneSpaceNode.MassFlowRateMax = TotInletAirMassFlowRateMax;
    1824    51185428 :     zoneSpaceNode.MassFlowRateMaxAvail = TotInletAirMassFlowRateMaxAvail;
    1825    51185428 :     zoneSpaceNode.MassFlowRateMin = TotInletAirMassFlowRateMin;
    1826    51185428 :     zoneSpaceNode.MassFlowRateMinAvail = TotInletAirMassFlowRateMinAvail;
    1827    51185428 : }
    1828             : 
    1829       83763 : void scaleInletFlows(EnergyPlusData &state, int const zoneNodeNum, int const spaceNodeNum, Real64 const frac)
    1830             : {
    1831       83763 :     assert(zoneNodeNum > 0);
    1832       83763 :     assert(spaceNodeNum > 0);
    1833       83763 :     auto &zoneNode = state.dataLoopNodes->Node(zoneNodeNum);
    1834       83763 :     auto &spaceNode = state.dataLoopNodes->Node(spaceNodeNum);
    1835       83763 :     spaceNode.MassFlowRate = zoneNode.MassFlowRate * frac;
    1836       83763 :     spaceNode.MassFlowRateMax = zoneNode.MassFlowRateMax * frac;
    1837       83763 :     spaceNode.MassFlowRateMaxAvail = zoneNode.MassFlowRateMaxAvail * frac;
    1838       83763 :     spaceNode.MassFlowRateMin = zoneNode.MassFlowRateMin * frac;
    1839       83763 :     spaceNode.MassFlowRateMinAvail = zoneNode.MassFlowRateMinAvail * frac;
    1840       83763 : }
    1841             : 
    1842           2 : void ZoneEquipmentSplitterMixer::size(EnergyPlusData &state)
    1843             : {
    1844           4 :     bool anyAutoSize = std::any_of(spaces.begin(), spaces.end(), [](ZoneEquipSplitterMixerSpace &s) { return s.fraction == DataSizing::AutoSize; });
    1845           2 :     if (!anyAutoSize) return;
    1846             : 
    1847             :     // Calculate total of space fraction basis value across all spaces for this splitter or mixer
    1848             :     // including spaces which are not autosized here.
    1849           2 :     Real64 spacesTotal = 0.0;
    1850           2 :     switch (this->spaceSizingBasis) {
    1851           2 :     case DataZoneEquipment::SpaceEquipSizingBasis::DesignCoolingLoad:
    1852           6 :         for (auto &thisSpace : this->spaces) {
    1853           4 :             spacesTotal += state.dataSize->FinalSpaceSizing(thisSpace.spaceIndex).DesCoolLoad;
    1854           2 :         }
    1855           2 :         break;
    1856           0 :     case DataZoneEquipment::SpaceEquipSizingBasis::DesignHeatingLoad:
    1857           0 :         for (auto &thisSpace : this->spaces) {
    1858           0 :             spacesTotal += state.dataSize->FinalSpaceSizing(thisSpace.spaceIndex).DesHeatLoad;
    1859           0 :         }
    1860           0 :         break;
    1861           0 :     case DataZoneEquipment::SpaceEquipSizingBasis::FloorArea:
    1862           0 :         for (auto &thisSpace : this->spaces) {
    1863           0 :             spacesTotal += state.dataHeatBal->space(thisSpace.spaceIndex).FloorArea;
    1864           0 :         }
    1865           0 :         break;
    1866           0 :     case DataZoneEquipment::SpaceEquipSizingBasis::Volume:
    1867           0 :         for (auto &thisSpace : this->spaces) {
    1868           0 :             spacesTotal += state.dataHeatBal->space(thisSpace.spaceIndex).Volume;
    1869           0 :         }
    1870           0 :         break;
    1871           0 :     case DataZoneEquipment::SpaceEquipSizingBasis::PerimeterLength:
    1872           0 :         ShowFatalError(state,
    1873           0 :                        format("ZoneEquipmentSplitterMixer::size: Space Fraction Method={} not supported for {}={}",
    1874           0 :                               DataZoneEquipment::spaceEquipSizingBasisNamesUC[(int)this->spaceSizingBasis],
    1875           0 :                               BranchNodeConnections::ConnectionObjectTypeNames[(int)this->spaceEquipType],
    1876           0 :                               this->Name));
    1877           0 :         break;
    1878           0 :     default:
    1879             :         // If method is not set, then return
    1880           0 :         return;
    1881             :         break;
    1882             :     }
    1883             : 
    1884           2 :     if (spacesTotal < 0.00001) {
    1885           0 :         ShowSevereError(state,
    1886           0 :                         format("ZoneEquipmentSplitterMixer::size: Total {} is zero for {}={}. Unable to autosize Space Fractions.",
    1887           0 :                                DataZoneEquipment::spaceEquipSizingBasisNamesUC[(int)this->spaceSizingBasis],
    1888           0 :                                BranchNodeConnections::ConnectionObjectTypeNames[(int)this->spaceEquipType],
    1889           0 :                                this->Name));
    1890           0 :         Real64 spaceFrac = 1.0 / (int)this->spaces.size();
    1891           0 :         ShowContinueError(state, format("Setting space fractions to 1/number of spaces = {}.", spaceFrac));
    1892           0 :         for (auto &thisSpace : this->spaces) {
    1893           0 :             thisSpace.fraction = spaceFrac;
    1894           0 :         }
    1895           0 :         return;
    1896             :     }
    1897             : 
    1898             :     // Calculate space fractions
    1899           2 :     int spaceCounter = 0;
    1900           6 :     for (auto &thisSpace : this->spaces) {
    1901           4 :         ++spaceCounter;
    1902           4 :         if (thisSpace.fraction == DataSizing::AutoSize) {
    1903           4 :             switch (this->spaceSizingBasis) {
    1904           4 :             case DataZoneEquipment::SpaceEquipSizingBasis::DesignCoolingLoad:
    1905           4 :                 thisSpace.fraction = state.dataSize->FinalSpaceSizing(thisSpace.spaceIndex).DesCoolLoad / spacesTotal;
    1906           4 :                 break;
    1907           0 :             case DataZoneEquipment::SpaceEquipSizingBasis::DesignHeatingLoad:
    1908           0 :                 thisSpace.fraction = state.dataSize->FinalSpaceSizing(thisSpace.spaceIndex).DesHeatLoad / spacesTotal;
    1909           0 :                 break;
    1910           0 :             case DataZoneEquipment::SpaceEquipSizingBasis::FloorArea:
    1911           0 :                 thisSpace.fraction = state.dataHeatBal->space(thisSpace.spaceIndex).FloorArea / spacesTotal;
    1912           0 :                 break;
    1913           0 :             case DataZoneEquipment::SpaceEquipSizingBasis::Volume:
    1914           0 :                 thisSpace.fraction = state.dataHeatBal->space(thisSpace.spaceIndex).Volume / spacesTotal;
    1915           0 :                 break;
    1916           0 :             case DataZoneEquipment::SpaceEquipSizingBasis::PerimeterLength:
    1917           0 :                 ShowFatalError(state,
    1918           0 :                                format("ZoneEquipmentSplitterMixer::size: Space Fraction Method={} not supported for {}={}",
    1919           0 :                                       DataZoneEquipment::spaceEquipSizingBasisNamesUC[(int)this->spaceSizingBasis],
    1920           0 :                                       BranchNodeConnections::ConnectionObjectTypeNames[(int)this->spaceEquipType],
    1921           0 :                                       this->Name));
    1922           0 :                 break;
    1923           0 :             default:
    1924           0 :                 break;
    1925             :             }
    1926          16 :             BaseSizer::reportSizerOutput(state,
    1927           4 :                                          BranchNodeConnections::ConnectionObjectTypeNames[(int)this->spaceEquipType],
    1928             :                                          this->Name,
    1929           8 :                                          format("Space {} Fraction", spaceCounter),
    1930             :                                          thisSpace.fraction);
    1931             :         }
    1932           2 :     }
    1933             : }
    1934             : 
    1935        8928 : void ZoneMixer::setOutletConditions(EnergyPlusData &state)
    1936             : {
    1937        8928 :     if (this->outletNodeNum == 0) return;
    1938             : 
    1939        8928 :     Real64 sumEnthalpy = 0.0;
    1940        8928 :     Real64 sumHumRat = 0.0;
    1941        8928 :     Real64 sumCO2 = 0.0;
    1942        8928 :     Real64 sumGenContam = 0.0;
    1943        8928 :     Real64 sumPressure = 0.0;
    1944        8928 :     Real64 sumFractions = 0.0;
    1945        8928 :     auto &outletNode = state.dataLoopNodes->Node(this->outletNodeNum);
    1946       26784 :     for (auto &mixerSpace : this->spaces) {
    1947       17856 :         auto &spaceOutletNode = state.dataLoopNodes->Node(mixerSpace.spaceNodeNum);
    1948       17856 :         sumEnthalpy += spaceOutletNode.Enthalpy * mixerSpace.fraction;
    1949       17856 :         sumHumRat += spaceOutletNode.HumRat * mixerSpace.fraction;
    1950       17856 :         if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    1951           0 :             sumCO2 += spaceOutletNode.CO2 * mixerSpace.fraction;
    1952             :         }
    1953       17856 :         if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    1954           0 :             sumGenContam += spaceOutletNode.GenContam * mixerSpace.fraction;
    1955             :         }
    1956       17856 :         sumPressure += spaceOutletNode.Press * mixerSpace.fraction;
    1957       17856 :         sumFractions += mixerSpace.fraction;
    1958        8928 :     }
    1959             : 
    1960             :     // For SpaceHVAC:ZoneReturnMixer, the fractions are dynamic and could be zero if there is no flow
    1961        8928 :     if (sumFractions > 0) {
    1962        8917 :         outletNode.Enthalpy = sumEnthalpy / sumFractions;
    1963        8917 :         outletNode.HumRat = sumHumRat / sumFractions;
    1964        8917 :         if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    1965           0 :             outletNode.CO2 = sumCO2 / sumFractions;
    1966             :         }
    1967        8917 :         if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    1968           0 :             outletNode.GenContam = sumGenContam / sumFractions;
    1969             :         }
    1970        8917 :         outletNode.Press = sumPressure / sumFractions;
    1971             : 
    1972             :         // Use Enthalpy and humidity ratio to get outlet temperature from psych chart
    1973        8917 :         outletNode.Temp = Psychrometrics::PsyTdbFnHW(outletNode.Enthalpy, outletNode.HumRat);
    1974             :     }
    1975             : }
    1976             : 
    1977        4464 : void ZoneReturnMixer::setInletConditions(EnergyPlusData &state)
    1978             : {
    1979       17856 :     for (auto &mixerSpace : this->spaces) {
    1980       13392 :         auto &spaceOutletNode = state.dataLoopNodes->Node(mixerSpace.spaceNodeNum);
    1981       13392 :         int spaceZoneNodeNum = state.dataZoneEquip->spaceEquipConfig(mixerSpace.spaceIndex).ZoneNode;
    1982       13392 :         auto &spaceNode = state.dataLoopNodes->Node(spaceZoneNodeNum);
    1983       13392 :         spaceOutletNode.Temp = spaceNode.Temp;
    1984       13392 :         spaceOutletNode.HumRat = spaceNode.HumRat;
    1985       13392 :         spaceOutletNode.Enthalpy = spaceNode.Enthalpy;
    1986       13392 :         spaceOutletNode.Press = spaceNode.Press;
    1987       13392 :         if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    1988           0 :             spaceOutletNode.CO2 = spaceNode.CO2;
    1989             :         }
    1990       13392 :         if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    1991           0 :             spaceOutletNode.GenContam = spaceNode.GenContam;
    1992             :         }
    1993        4464 :     }
    1994        4464 : }
    1995        4464 : void ZoneEquipmentMixer::setInletFlows(EnergyPlusData &state)
    1996             : {
    1997        4464 :     if (this->outletNodeNum == 0) return;
    1998             : 
    1999        4464 :     auto &equipInletNode = state.dataLoopNodes->Node(this->outletNodeNum);
    2000        8928 :     for (auto &mixerSpace : this->spaces) {
    2001        4464 :         auto &spaceOutletNode = state.dataLoopNodes->Node(mixerSpace.spaceNodeNum);
    2002        4464 :         spaceOutletNode.MassFlowRate = equipInletNode.MassFlowRate * mixerSpace.fraction;
    2003        4464 :         spaceOutletNode.MassFlowRateMaxAvail = equipInletNode.MassFlowRateMaxAvail * mixerSpace.fraction;
    2004        4464 :         spaceOutletNode.MassFlowRateMinAvail = equipInletNode.MassFlowRateMinAvail * mixerSpace.fraction;
    2005        4464 :     }
    2006             : }
    2007             : 
    2008        4464 : void ZoneReturnMixer::setInletFlows(EnergyPlusData &state)
    2009             : {
    2010        4464 :     if (this->outletNodeNum == 0) return;
    2011        4464 :     auto &outletNode = state.dataLoopNodes->Node(this->outletNodeNum);
    2012             : 
    2013        4464 :     Real64 sumMixerInletMassFlow = 0;
    2014       17856 :     for (auto const &mixerSpace : this->spaces) {
    2015             :         // calc return flows for spaces feeding this mixer
    2016       13392 :         auto &spaceEquipConfig = state.dataZoneEquip->spaceEquipConfig(mixerSpace.spaceIndex);
    2017       13392 :         Real64 outletMassFlowRate = outletNode.MassFlowRate; // calcReturnFlows might adjust this parameter value, so make a copy here
    2018       13392 :         Real64 spaceReturnFlow = 0.0;
    2019       13392 :         spaceEquipConfig.calcReturnFlows(state, outletMassFlowRate, spaceReturnFlow);
    2020       13392 :         sumMixerInletMassFlow += spaceReturnFlow;
    2021        4464 :     }
    2022             : 
    2023       17856 :     for (auto &mixerSpace : this->spaces) {
    2024       13392 :         auto &spaceOutletNode = state.dataLoopNodes->Node(mixerSpace.spaceNodeNum);
    2025             :         // For return mixer, fraction is calculated every time step, not a user input
    2026       13392 :         if (sumMixerInletMassFlow > 0.0) {
    2027       13359 :             mixerSpace.fraction = spaceOutletNode.MassFlowRate / sumMixerInletMassFlow;
    2028             :         } else {
    2029          33 :             mixerSpace.fraction = 0.0;
    2030             :         }
    2031       13392 :         spaceOutletNode.MassFlowRate = outletNode.MassFlowRate * mixerSpace.fraction;
    2032       13392 :         spaceOutletNode.MassFlowRateMaxAvail = outletNode.MassFlowRateMaxAvail * mixerSpace.fraction;
    2033       13392 :         spaceOutletNode.MassFlowRateMinAvail = outletNode.MassFlowRateMinAvail * mixerSpace.fraction;
    2034        4464 :     }
    2035             : }
    2036             : 
    2037        8928 : void ZoneEquipmentSplitter::adjustLoads(EnergyPlusData &state, int zoneNum, int equipTypeNum)
    2038             : {
    2039        8928 :     auto &thisZoneEnergyDemand = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(zoneNum);
    2040        8928 :     auto &thisZoneMoistureDemand = state.dataZoneEnergyDemand->ZoneSysMoistureDemand(zoneNum);
    2041        8928 :     Real64 sensibleRatio = 1.0;
    2042        8928 :     Real64 latentRatio = 1.0;
    2043        8928 :     switch (this->tstatControl) {
    2044           0 :     case DataZoneEquipment::ZoneEquipTstatControl::Ideal:
    2045           0 :         return;
    2046             :         break; // Do nothing
    2047        8928 :     case DataZoneEquipment::ZoneEquipTstatControl::SingleSpace: {
    2048        8928 :         Real64 controlSpaceFrac = this->spaces[this->controlSpaceNumber].fraction;
    2049        8928 :         if (controlSpaceFrac > 0.0) {
    2050        8928 :             if (thisZoneEnergyDemand.RemainingOutputRequired != 0.0) {
    2051        8900 :                 sensibleRatio = (state.dataZoneEnergyDemand->spaceSysEnergyDemand(this->controlSpaceIndex).RemainingOutputRequired /
    2052        8900 :                                  thisZoneEnergyDemand.RemainingOutputRequired) /
    2053             :                                 controlSpaceFrac;
    2054             :             }
    2055        8928 :             if (thisZoneMoistureDemand.RemainingOutputRequired != 0.0) {
    2056           0 :                 latentRatio = (state.dataZoneEnergyDemand->spaceSysMoistureDemand(this->controlSpaceIndex).RemainingOutputRequired /
    2057           0 :                                thisZoneMoistureDemand.RemainingOutputRequired) /
    2058             :                               controlSpaceFrac;
    2059             :             }
    2060             :         }
    2061        8928 :     } break;
    2062           0 :     case DataZoneEquipment::ZoneEquipTstatControl::Maximum: {
    2063           0 :         int maxSpaceIndex = 0;
    2064           0 :         Real64 maxDeltaTemp = 0.0; // Only positive deltaTemps are relevant
    2065           0 :         Real64 maxSpaceFrac = 1.0;
    2066           0 :         for (auto &splitterSpace : this->spaces) {
    2067             :             Real64 spaceTemp =
    2068           0 :                 state.dataZoneTempPredictorCorrector->spaceHeatBalance(splitterSpace.spaceIndex).T1; // Based on calcPredictedSystemLoad usage
    2069           0 :             Real64 spaceDeltaTemp = max((state.dataHeatBalFanSys->ZoneThermostatSetPointLo(zoneNum) - spaceTemp),
    2070           0 :                                         (spaceTemp - state.dataHeatBalFanSys->ZoneThermostatSetPointHi(zoneNum)));
    2071           0 :             if (spaceDeltaTemp > maxDeltaTemp) {
    2072           0 :                 maxSpaceIndex = splitterSpace.spaceIndex;
    2073           0 :                 maxSpaceFrac = splitterSpace.fraction;
    2074           0 :                 maxDeltaTemp = spaceDeltaTemp;
    2075             :             }
    2076           0 :         }
    2077           0 :         if ((maxSpaceIndex > 0) && (maxSpaceFrac > 0.0)) {
    2078           0 :             if (thisZoneEnergyDemand.RemainingOutputRequired != 0.0) {
    2079           0 :                 sensibleRatio = (state.dataZoneEnergyDemand->spaceSysEnergyDemand(maxSpaceIndex).RemainingOutputRequired /
    2080           0 :                                  thisZoneEnergyDemand.RemainingOutputRequired) /
    2081             :                                 maxSpaceFrac;
    2082             :             }
    2083           0 :             if (thisZoneMoistureDemand.RemainingOutputRequired != 0.0) {
    2084           0 :                 latentRatio = (state.dataZoneEnergyDemand->spaceSysMoistureDemand(maxSpaceIndex).RemainingOutputRequired /
    2085           0 :                                thisZoneMoistureDemand.RemainingOutputRequired) /
    2086             :                               maxSpaceFrac;
    2087             :             }
    2088             :         }
    2089           0 :     } break;
    2090           0 :     default:
    2091           0 :         break;
    2092             :     }
    2093             :     // Save unadjusted zone loads to restore later
    2094        8928 :     this->saveZoneSysSensibleDemand = thisZoneEnergyDemand;
    2095        8928 :     this->saveZoneSysMoistureDemand = thisZoneMoistureDemand;
    2096             :     // Apply zone load adjustment
    2097       17856 :     ZoneEquipmentManager::adjustSystemOutputRequired(sensibleRatio,
    2098             :                                                      latentRatio,
    2099        8928 :                                                      state.dataZoneEnergyDemand->ZoneSysEnergyDemand(zoneNum),
    2100        8928 :                                                      state.dataZoneEnergyDemand->ZoneSysMoistureDemand(zoneNum),
    2101             :                                                      equipTypeNum);
    2102             : }
    2103             : 
    2104        8928 : void ZoneEquipmentSplitter::distributeOutput(EnergyPlusData &state,
    2105             :                                              int const zoneNum,
    2106             :                                              Real64 const sysOutputProvided,
    2107             :                                              Real64 const latOutputProvided,
    2108             :                                              Real64 const nonAirSysOutput,
    2109             :                                              int const equipTypeNum)
    2110             : {
    2111       35712 :     for (auto &splitterSpace : this->spaces) {
    2112       26784 :         if (this->tstatControl != DataZoneEquipment::ZoneEquipTstatControl::Ideal) {
    2113             :             // Restore zone loads to unadjusted values (for all ZoneEquipTstatControl types except Ideal)
    2114       26784 :             state.dataZoneEnergyDemand->ZoneSysEnergyDemand(zoneNum) = this->saveZoneSysSensibleDemand;
    2115       26784 :             state.dataZoneEnergyDemand->ZoneSysMoistureDemand(zoneNum) = this->saveZoneSysMoistureDemand;
    2116             :         }
    2117             : 
    2118       26784 :         Real64 spaceFraction = splitterSpace.fraction;
    2119       26784 :         if (this->tstatControl == DataZoneEquipment::ZoneEquipTstatControl::Ideal) {
    2120             :             // Proportion output by sensible space load / zone load (varies every timestep, overrides outputFraction)
    2121           0 :             auto &thisZoneSysEnergyDemand = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(zoneNum);
    2122           0 :             if (thisZoneSysEnergyDemand.RemainingOutputRequired != 0.0) {
    2123           0 :                 spaceFraction = state.dataZoneEnergyDemand->spaceSysEnergyDemand(splitterSpace.spaceIndex).RemainingOutputRequired /
    2124           0 :                                 thisZoneSysEnergyDemand.RemainingOutputRequired;
    2125             :             }
    2126             :         }
    2127             : 
    2128       26784 :         Real64 spaceSysOutputProvided = sysOutputProvided * spaceFraction;
    2129       26784 :         Real64 spaceLatOutputProvided = latOutputProvided * spaceFraction;
    2130       26784 :         state.dataZoneTempPredictorCorrector->spaceHeatBalance(splitterSpace.spaceIndex).NonAirSystemResponse += nonAirSysOutput * spaceFraction;
    2131       26784 :         if (this->zoneEquipOutletNodeNum > 0 && splitterSpace.spaceNodeNum > 0) {
    2132       26784 :             auto &equipOutletNode = state.dataLoopNodes->Node(this->zoneEquipOutletNodeNum);
    2133       26784 :             auto &spaceInletNode = state.dataLoopNodes->Node(splitterSpace.spaceNodeNum);
    2134       26784 :             spaceInletNode.MassFlowRate = equipOutletNode.MassFlowRate * spaceFraction;
    2135       26784 :             spaceInletNode.MassFlowRateMaxAvail = equipOutletNode.MassFlowRateMaxAvail * spaceFraction;
    2136       26784 :             spaceInletNode.MassFlowRateMinAvail = equipOutletNode.MassFlowRateMinAvail * spaceFraction;
    2137       26784 :             spaceInletNode.Temp = equipOutletNode.Temp;
    2138       26784 :             spaceInletNode.HumRat = equipOutletNode.HumRat;
    2139       26784 :             spaceInletNode.CO2 = equipOutletNode.CO2;
    2140             :         }
    2141       26784 :         ZoneEquipmentManager::updateSystemOutputRequired(state,
    2142             :                                                          zoneNum,
    2143             :                                                          spaceSysOutputProvided,
    2144             :                                                          spaceLatOutputProvided,
    2145       26784 :                                                          state.dataZoneEnergyDemand->spaceSysEnergyDemand(splitterSpace.spaceIndex),
    2146       26784 :                                                          state.dataZoneEnergyDemand->spaceSysMoistureDemand(splitterSpace.spaceIndex),
    2147             :                                                          equipTypeNum);
    2148        8928 :     }
    2149        8928 : }
    2150             : 
    2151       42226 : void EquipConfiguration::beginEnvirnInit(EnergyPlusData &state)
    2152             : {
    2153       42226 :     auto &zoneNode = state.dataLoopNodes->Node(this->ZoneNode);
    2154       42226 :     zoneNode.Temp = 20.0;
    2155       42226 :     zoneNode.MassFlowRate = 0.0;
    2156       42226 :     zoneNode.Quality = 1.0;
    2157       42226 :     zoneNode.Press = state.dataEnvrn->OutBaroPress;
    2158       42226 :     zoneNode.HumRat = state.dataEnvrn->OutHumRat;
    2159       42226 :     zoneNode.Enthalpy = Psychrometrics::PsyHFnTdbW(zoneNode.Temp, zoneNode.HumRat);
    2160       42226 :     if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    2161         317 :         zoneNode.CO2 = state.dataContaminantBalance->OutdoorCO2;
    2162             :     }
    2163       42226 :     if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    2164         117 :         zoneNode.GenContam = state.dataContaminantBalance->OutdoorGC;
    2165             :     }
    2166             : 
    2167       86242 :     for (int const nodeNum : this->InletNode) {
    2168       44016 :         auto &inNode = state.dataLoopNodes->Node(nodeNum);
    2169       44016 :         inNode.Temp = 20.0;
    2170       44016 :         inNode.MassFlowRate = 0.0;
    2171       44016 :         inNode.Quality = 1.0;
    2172       44016 :         inNode.Press = state.dataEnvrn->OutBaroPress;
    2173       44016 :         inNode.HumRat = state.dataEnvrn->OutHumRat;
    2174       44016 :         inNode.Enthalpy = Psychrometrics::PsyHFnTdbW(inNode.Temp, inNode.HumRat);
    2175       44016 :         if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    2176         281 :             inNode.CO2 = state.dataContaminantBalance->OutdoorCO2;
    2177             :         }
    2178       44016 :         if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    2179          81 :             inNode.GenContam = state.dataContaminantBalance->OutdoorGC;
    2180             :         }
    2181             :     }
    2182             : 
    2183       50672 :     for (int const nodeNum : this->ExhaustNode) {
    2184        8446 :         auto &exhNode = state.dataLoopNodes->Node(nodeNum);
    2185        8446 :         exhNode.Temp = 20.0;
    2186        8446 :         exhNode.MassFlowRate = 0.0;
    2187        8446 :         exhNode.Quality = 1.0;
    2188        8446 :         exhNode.Press = state.dataEnvrn->OutBaroPress;
    2189        8446 :         exhNode.HumRat = state.dataEnvrn->OutHumRat;
    2190        8446 :         exhNode.Enthalpy = Psychrometrics::PsyHFnTdbW(exhNode.Temp, exhNode.HumRat);
    2191        8446 :         if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    2192         130 :             exhNode.CO2 = state.dataContaminantBalance->OutdoorCO2;
    2193             :         }
    2194        8446 :         if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    2195          30 :             exhNode.GenContam = state.dataContaminantBalance->OutdoorGC;
    2196             :         }
    2197             :     }
    2198             : 
    2199             :     // BG CR 7122 following resets return air node.
    2200       42226 :     int NumRetNodes = this->NumReturnNodes;
    2201       42226 :     if (NumRetNodes > 0) {
    2202       84489 :         for (int const nodeNum : this->ReturnNode) {
    2203       42272 :             auto &returnNode = state.dataLoopNodes->Node(nodeNum);
    2204       42272 :             returnNode.Temp = 20.0;
    2205       42272 :             returnNode.MassFlowRate = 0.0;
    2206       42272 :             returnNode.Quality = 1.0;
    2207       42272 :             returnNode.Press = state.dataEnvrn->OutBaroPress;
    2208       42272 :             returnNode.HumRat = state.dataEnvrn->OutHumRat;
    2209       42272 :             returnNode.Enthalpy = Psychrometrics::PsyHFnTdbW(returnNode.Temp, returnNode.HumRat);
    2210       42272 :             if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    2211         317 :                 returnNode.CO2 = state.dataContaminantBalance->OutdoorCO2;
    2212             :             }
    2213       42272 :             if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    2214         117 :                 returnNode.GenContam = state.dataContaminantBalance->OutdoorGC;
    2215             :             }
    2216             :         }
    2217             :     }
    2218       42226 : }
    2219             : 
    2220    50656903 : void EquipConfiguration::hvacTimeStepInit(EnergyPlusData &state, bool FirstHVACIteration)
    2221             : {
    2222    50656903 :     auto &zoneNode = state.dataLoopNodes->Node(this->ZoneNode);
    2223    50656903 :     this->ExcessZoneExh = 0.0;
    2224             : 
    2225    50656903 :     if (FirstHVACIteration) {
    2226    30216861 :         for (int const nodeNum : this->ExhaustNode) {
    2227     4466703 :             auto &exhNode = state.dataLoopNodes->Node(nodeNum);
    2228     4466703 :             exhNode.Temp = zoneNode.Temp;
    2229     4466703 :             exhNode.HumRat = zoneNode.HumRat;
    2230     4466703 :             exhNode.Enthalpy = zoneNode.Enthalpy;
    2231     4466703 :             exhNode.Press = zoneNode.Press;
    2232     4466703 :             exhNode.Quality = zoneNode.Quality;
    2233     4466703 :             exhNode.MassFlowRate = 0.0;
    2234     4466703 :             exhNode.MassFlowRateMaxAvail = 0.0;
    2235     4466703 :             exhNode.MassFlowRateMinAvail = 0.0;
    2236     4466703 :             if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    2237      113007 :                 exhNode.CO2 = zoneNode.CO2;
    2238             :             }
    2239     4466703 :             if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    2240       74282 :                 exhNode.GenContam = zoneNode.GenContam;
    2241             :             }
    2242             :         }
    2243             :     }
    2244    50656903 : }
    2245             : 
    2246    51174061 : void EquipConfiguration::calcReturnFlows(EnergyPlusData &state,
    2247             :                                          Real64 &ExpTotalReturnMassFlow,  // Expected total return air mass flow rate
    2248             :                                          Real64 &FinalTotalReturnMassFlow // Final total return air mass flow rate
    2249             : )
    2250             : {
    2251    51174061 :     int numRetNodes = this->NumReturnNodes;
    2252    51174061 :     Real64 totReturnFlow = 0.0; // Total flow to all return nodes in the zone (kg/s)
    2253    51174061 :     Real64 totVarReturnFlow =
    2254             :         0.0; // Total variable return flow, for return nodes connected to an airloop with an OA system or not with specified flow (kg/s)
    2255    51174061 :     Real64 returnSchedFrac = ScheduleManager::GetCurrentScheduleValue(state, this->ReturnFlowSchedPtrNum);
    2256    51174061 :     this->FixedReturnFlow = false;
    2257    51174061 :     FinalTotalReturnMassFlow = 0.0;
    2258    51174061 :     this->TotAvailAirLoopOA = 0.0;
    2259             : 
    2260             :     // Set initial flow rate for each return node
    2261   102435869 :     for (int returnNum = 1; returnNum <= numRetNodes; ++returnNum) {
    2262    51261808 :         int retNode = this->ReturnNode(returnNum);
    2263             : 
    2264    51261808 :         if (retNode > 0) {
    2265    51261808 :             Real64 returnNodeMassFlow = 0.0;
    2266    51261808 :             auto &retNodeData(state.dataLoopNodes->Node(retNode));
    2267             : 
    2268    51261808 :             int inletNum = this->ReturnNodeInletNum(returnNum); // which inlet node matches this return node (same airloop)
    2269    51261808 :             int ADUNum = 0;
    2270    51261808 :             if (inletNum > 0) ADUNum = this->InletNodeADUNum(inletNum);
    2271    51261808 :             int airLoop = this->ReturnNodeAirLoopNum(returnNum);
    2272    51261808 :             Real64 airLoopReturnFrac = 1.0;
    2273    51261808 :             if (airLoop > 0) {
    2274             :                 // Establish corresponding airloop inlet(s) mass flow rate and set return node max/min/maxavail
    2275    36327653 :                 Real64 inletMassFlow = 0.0;
    2276    36327653 :                 int maxMinNodeNum = 0;
    2277    36327653 :                 auto &thisAirLoopFlow(state.dataAirLoop->AirLoopFlow(airLoop));
    2278    36327653 :                 if (ADUNum > 0) {
    2279             :                     // Zone return node could carry supply flow to zone without leaks plus any induced flow from plenum (but don't include other
    2280             :                     // secondary flows from exhaust nodes)
    2281    36187676 :                     inletMassFlow = state.dataDefineEquipment->AirDistUnit(ADUNum).MassFlowRateZSup +
    2282    36187676 :                                     state.dataDefineEquipment->AirDistUnit(ADUNum).MassFlowRatePlenInd;
    2283    36187676 :                     maxMinNodeNum = state.dataDefineEquipment->AirDistUnit(ADUNum).OutletNodeNum;
    2284      139977 :                 } else if (inletNum > 0) {
    2285             :                     // If not connected to an ADU, then use the inlet node flow
    2286      139977 :                     inletMassFlow = state.dataLoopNodes->Node(this->InletNode(inletNum)).MassFlowRate;
    2287      139977 :                     maxMinNodeNum = this->InletNode(inletNum);
    2288             :                 }
    2289    36327653 :                 if (maxMinNodeNum > 0) {
    2290    36327653 :                     auto const &maxMinNodeData(state.dataLoopNodes->Node(maxMinNodeNum));
    2291    36327653 :                     retNodeData.MassFlowRateMax = maxMinNodeData.MassFlowRateMax;
    2292    36327653 :                     retNodeData.MassFlowRateMin = maxMinNodeData.MassFlowRateMin;
    2293    36327653 :                     retNodeData.MassFlowRateMaxAvail = maxMinNodeData.MassFlowRateMaxAvail;
    2294             :                 } else {
    2295           0 :                     auto const &zoneNodeData(state.dataLoopNodes->Node(this->ZoneNode));
    2296           0 :                     retNodeData.MassFlowRateMax = zoneNodeData.MassFlowRateMax;
    2297           0 :                     retNodeData.MassFlowRateMin = zoneNodeData.MassFlowRateMin;
    2298           0 :                     retNodeData.MassFlowRateMaxAvail = zoneNodeData.MassFlowRateMaxAvail;
    2299             :                 }
    2300             : 
    2301    36327653 :                 airLoopReturnFrac = thisAirLoopFlow.DesReturnFrac;
    2302    36327653 :                 if (state.dataAirSystemsData->PrimaryAirSystems(airLoop).OASysExists && (thisAirLoopFlow.MaxOutAir > 0.0)) {
    2303             :                     // Set return flow as fraction of matching inlet node flow if there is an OA system and available OA flow > 0.0
    2304    33903382 :                     returnNodeMassFlow = airLoopReturnFrac * inletMassFlow;
    2305    33903382 :                     this->TotAvailAirLoopOA += thisAirLoopFlow.MaxOutAir;
    2306             :                 } else {
    2307             :                     // Set return flow to matching inlet node flow
    2308     2424271 :                     returnNodeMassFlow = inletMassFlow;
    2309     2424271 :                     this->FixedReturnFlow(returnNum) = true;
    2310             :                 }
    2311             :             } else {
    2312    14934155 :                 returnNodeMassFlow = 0.0;
    2313             :             }
    2314             : 
    2315             :             // Return node 1 is special
    2316    51261808 :             if (returnNum == 1) {
    2317             :                 // Make no return air flow adjustments during sizing
    2318    51170413 :                 if ((state.dataGlobal->DoingSizing) && numRetNodes == 1) {
    2319     9371496 :                     returnNodeMassFlow = ExpTotalReturnMassFlow;
    2320     9371496 :                     if (airLoop > 0) {
    2321           0 :                         if (!state.dataAirSystemsData->PrimaryAirSystems(airLoop).OASysExists ||
    2322           0 :                             (state.dataAirLoop->AirLoopFlow(airLoop).MaxOutAir == 0.0)) {
    2323           0 :                             ExpTotalReturnMassFlow = max(0.0, ExpTotalReturnMassFlow - this->ZoneExhBalanced + this->ZoneExh);
    2324           0 :                             returnNodeMassFlow = ExpTotalReturnMassFlow;
    2325             :                         }
    2326             :                     }
    2327    41798917 :                 } else if (!state.dataGlobal->DoingSizing) {
    2328    41779347 :                     if (this->NumReturnFlowBasisNodes > 0) {
    2329             :                         // Set base return air flow rate for node 1 using basis node flow rates
    2330           0 :                         Real64 basisNodesMassFlow = 0.0;
    2331           0 :                         for (int nodeNum = 1; nodeNum <= this->NumReturnFlowBasisNodes; ++nodeNum) {
    2332           0 :                             basisNodesMassFlow += state.dataLoopNodes->Node(this->ReturnFlowBasisNode(nodeNum)).MassFlowRate;
    2333             :                         }
    2334           0 :                         returnNodeMassFlow = max(0.0, (basisNodesMassFlow * returnSchedFrac));
    2335           0 :                         this->FixedReturnFlow(returnNum) = true;
    2336             :                     } else {
    2337             :                         // If only 1 return node, use the standard return mass flow
    2338    41779347 :                         if ((numRetNodes == 1) && !this->FixedReturnFlow(returnNum)) {
    2339    39426901 :                             returnNodeMassFlow = max(0.0, (ExpTotalReturnMassFlow * returnSchedFrac * airLoopReturnFrac));
    2340             :                         }
    2341             :                     }
    2342             :                 }
    2343             :             }
    2344    51261808 :             totReturnFlow += returnNodeMassFlow;
    2345    51261808 :             retNodeData.MassFlowRate = returnNodeMassFlow;
    2346    51261808 :             retNodeData.MassFlowRateMinAvail = 0.0;
    2347    51261808 :             if (!this->FixedReturnFlow(returnNum)) totVarReturnFlow += returnNodeMassFlow;
    2348             :         }
    2349             :     }
    2350             : 
    2351             :     // if zone mass balance true, set to expected return flow
    2352    51174061 :     if (state.dataHeatBal->ZoneAirMassFlow.ZoneFlowAdjustment != DataHeatBalance::AdjustmentType::NoAdjustReturnAndMixing) {
    2353             :         // applies zone return flow schedule multiplier
    2354      597505 :         ExpTotalReturnMassFlow = returnSchedFrac * ExpTotalReturnMassFlow;
    2355             :         // set air flow rate for each return node
    2356      597505 :         Real64 zoneTotReturnFlow = 0.0;
    2357      597505 :         Real64 returnNodeMassFlow = 0.0;
    2358     1195010 :         for (int returnNum = 1; returnNum <= numRetNodes; ++returnNum) {
    2359      597505 :             int retNode = this->ReturnNode(returnNum);
    2360      597505 :             if (retNode > 0) {
    2361      597505 :                 if (numRetNodes == 1) {
    2362      597505 :                     returnNodeMassFlow = ExpTotalReturnMassFlow;
    2363             :                 } else { // multiple return nodes
    2364           0 :                     if (ExpTotalReturnMassFlow > 0.0) {
    2365           0 :                         Real64 returnAdjFactor = state.dataLoopNodes->Node(retNode).MassFlowRate / ExpTotalReturnMassFlow;
    2366           0 :                         returnNodeMassFlow = returnAdjFactor * ExpTotalReturnMassFlow;
    2367             :                     } else {
    2368           0 :                         returnNodeMassFlow = 0.0;
    2369             :                     }
    2370             :                 }
    2371             :             }
    2372      597505 :             zoneTotReturnFlow += returnNodeMassFlow;
    2373             :         }
    2374             :         // Adjust return node flows if zone total return flow is > 0
    2375      597505 :         if (zoneTotReturnFlow > 0.0) {
    2376      986042 :             for (int returnNum = 1; returnNum <= numRetNodes; ++returnNum) {
    2377      493021 :                 int retNode = this->ReturnNode(returnNum);
    2378      493021 :                 if (retNode > 0) {
    2379      493021 :                     if (numRetNodes == 1) {
    2380             :                         // set it to expected return flows
    2381      493021 :                         state.dataLoopNodes->Node(retNode).MassFlowRate = ExpTotalReturnMassFlow;
    2382      493021 :                         FinalTotalReturnMassFlow = ExpTotalReturnMassFlow;
    2383             :                     } else { // multiple return nodes, adjust nodes flow
    2384           0 :                         Real64 newReturnFlow = 0.0;
    2385           0 :                         Real64 returnAdjFactor = ExpTotalReturnMassFlow / zoneTotReturnFlow;
    2386           0 :                         Real64 curReturnFlow = state.dataLoopNodes->Node(retNode).MassFlowRate;
    2387           0 :                         newReturnFlow = curReturnFlow * returnAdjFactor;
    2388           0 :                         state.dataLoopNodes->Node(retNode).MassFlowRate = newReturnFlow;
    2389           0 :                         FinalTotalReturnMassFlow += newReturnFlow;
    2390             :                     }
    2391             :                 }
    2392             :             }
    2393             :         } else {
    2394      104484 :             FinalTotalReturnMassFlow = ExpTotalReturnMassFlow;
    2395             :         }
    2396             :     } else {
    2397             :         // Adjust return flows if greater than expected (i.e. there is exhaust or mixing flow reducing the total available for return)
    2398    50576556 :         if ((totReturnFlow > ExpTotalReturnMassFlow) && (totVarReturnFlow > 0.0)) {
    2399           0 :             Real64 newReturnFlow = 0.0;
    2400           0 :             Real64 returnAdjFactor = (1 - ((totReturnFlow - ExpTotalReturnMassFlow) / totVarReturnFlow)); // Return flow adjustment factor
    2401           0 :             for (int returnNum = 1; returnNum <= numRetNodes; ++returnNum) {
    2402           0 :                 int retNode = this->ReturnNode(returnNum);
    2403           0 :                 Real64 curReturnFlow = state.dataLoopNodes->Node(retNode).MassFlowRate;
    2404           0 :                 if (retNode > 0) {
    2405           0 :                     if (!this->FixedReturnFlow(returnNum)) {
    2406           0 :                         newReturnFlow = curReturnFlow * returnAdjFactor;
    2407           0 :                         FinalTotalReturnMassFlow += newReturnFlow;
    2408           0 :                         state.dataLoopNodes->Node(retNode).MassFlowRate = newReturnFlow;
    2409             :                     } else {
    2410           0 :                         FinalTotalReturnMassFlow += curReturnFlow;
    2411             :                     }
    2412             :                 }
    2413             :             }
    2414           0 :         } else {
    2415    50576556 :             FinalTotalReturnMassFlow = totReturnFlow;
    2416             :         }
    2417             :     }
    2418    51174061 : }
    2419             : 
    2420             : } // namespace EnergyPlus::DataZoneEquipment

Generated by: LCOV version 1.14