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

Generated by: LCOV version 2.0-1