LCOV - code coverage report
Current view: top level - EnergyPlus - DataZoneEquipment.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 57.4 % 1354 777
Test Date: 2025-05-22 16:09:37 Functions: 77.4 % 31 24

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

Generated by: LCOV version 2.0-1