LCOV - code coverage report
Current view: top level - EnergyPlus - BranchInputManager.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 67.5 % 1327 896
Test Date: 2025-05-22 16:09:37 Functions: 96.2 % 26 25

            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              : // C++ Headers
      49              : #include <string>
      50              : 
      51              : // ObjexxFCL Headers
      52              : #include <ObjexxFCL/Array.functions.hh>
      53              : #include <ObjexxFCL/Fmath.hh>
      54              : #include <ObjexxFCL/string.functions.hh>
      55              : 
      56              : // EnergyPlus Headers
      57              : #include <EnergyPlus/BranchInputManager.hh>
      58              : #include <EnergyPlus/BranchNodeConnections.hh>
      59              : #include <EnergyPlus/CurveManager.hh>
      60              : #include <EnergyPlus/Data/EnergyPlusData.hh>
      61              : #include <EnergyPlus/DataBranchAirLoopPlant.hh>
      62              : #include <EnergyPlus/DataErrorTracking.hh>
      63              : #include <EnergyPlus/GeneralRoutines.hh>
      64              : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      65              : #include <EnergyPlus/NodeInputManager.hh>
      66              : #include <EnergyPlus/UtilityRoutines.hh>
      67              : 
      68              : namespace EnergyPlus {
      69              : 
      70              : namespace BranchInputManager {
      71              : 
      72              :     // Module containing the routines dealing with the BRANCH and CONNECTOR
      73              :     // lists input.
      74              : 
      75              :     // MODULE INFORMATION:
      76              :     //       AUTHOR         Linda Lawrie
      77              :     //       DATE WRITTEN   October 1999
      78              :     //       MODIFIED       na
      79              :     //       RE-ENGINEERED  na
      80              : 
      81              :     // PURPOSE OF THIS MODULE:
      82              :     // To Get the IDD objects "BranchList", "Branch", "ConnectorList",
      83              :     // "Connector:Splitter", and "Connector:Mixer".  Also, to supply other modules/routines with
      84              :     // information about these objects.
      85              : 
      86              :     // Using/Aliasing
      87              :     using namespace DataLoopNode;
      88              :     using namespace DataBranchAirLoopPlant;
      89              :     using namespace NodeInputManager;
      90              :     using namespace BranchNodeConnections;
      91              : 
      92              :     // MODULE PARAMETER DEFINITIONS
      93              :     const char *cMIXER("Connector:Mixer");
      94              :     const char *cSPLITTER("Connector:Splitter");
      95              : 
      96          105 :     void ManageBranchInput(EnergyPlusData &state)
      97              :     {
      98              : 
      99              :         // SUBROUTINE INFORMATION:
     100              :         //       AUTHOR         Linda Lawrie
     101              :         //       DATE WRITTEN   Nov 2004
     102              :         //       MODIFIED       na
     103              :         //       RE-ENGINEERED  na
     104              : 
     105              :         // PURPOSE OF THIS SUBROUTINE:
     106              :         // This subroutine is called from HVACManager to make sure that branch input is
     107              :         // gathered prior to need.
     108              : 
     109          105 :         if (state.dataBranchInputManager->GetBranchInputFlag) {
     110          105 :             GetBranchInput(state);
     111          105 :             if (state.dataBranchInputManager->GetBranchListInputFlag) {
     112          105 :                 state.dataBranchInputManager->GetBranchListInputFlag = false;
     113          105 :                 GetBranchListInput(state);
     114              :             }
     115          105 :             AuditBranches(state, false);
     116          105 :             state.dataBranchInputManager->GetBranchInputFlag = false;
     117              :         }
     118          105 :     }
     119              : 
     120              :     //==================================================================================
     121              :     //   Routines that "get" data from internal branch management structure
     122              :     //==================================================================================
     123              : 
     124          184 :     void GetBranchList(EnergyPlusData &state,
     125              :                        std::string const &LoopName,       // Name of Loop Branch List is on
     126              :                        std::string const &BranchListName, // Branch List Name from Input
     127              :                        int &NumBranchNames,               // Number of Branches for this Branch List
     128              :                        Array1D_string &BranchNames,       // Names of Branches on this Branch List
     129              :                        std::string const &LoopType        // Type of Loop Branch list is on
     130              :     )
     131              :     {
     132              : 
     133              :         // SUBROUTINE INFORMATION:
     134              :         //       AUTHOR         Linda K. Lawrie
     135              :         //       DATE WRITTEN   October 1999
     136              :         //       MODIFIED       October 2001, Automatic Extensibility
     137              :         //       RE-ENGINEERED  na
     138              : 
     139              :         // PURPOSE OF THIS SUBROUTINE:
     140              :         // This subroutine "gets" the branch list specified in a Plant or Condenser loop and
     141              :         // returns number and names to the outside calling routine.
     142              : 
     143              :         // Using/Aliasing
     144              : 
     145              :         int Found;     // Points to correct Branch List/Branch
     146              :         bool ErrFound; // True when error has occurred (cannot find Branch List)
     147              : 
     148          184 :         ErrFound = false;
     149              : 
     150          184 :         if (state.dataBranchInputManager->GetBranchListInputFlag) {
     151            0 :             state.dataBranchInputManager->GetBranchListInputFlag = false;
     152            0 :             GetBranchListInput(state);
     153              :         }
     154              : 
     155              :         //  Find this BranchList in the master BranchList Names
     156          184 :         Found = Util::FindItemInList(BranchListName, state.dataBranchInputManager->BranchList);
     157          184 :         if (Found == 0) {
     158            0 :             ShowFatalError(state, format("GetBranchList: BranchList Name not found={}", BranchListName));
     159              :         }
     160              : 
     161              :         // Set data
     162          184 :         if (state.dataBranchInputManager->BranchList(Found).LoopName.empty()) {
     163          184 :             state.dataBranchInputManager->BranchList(Found).LoopName = LoopName;
     164          184 :             state.dataBranchInputManager->BranchList(Found).LoopType = LoopType;
     165            0 :         } else if (state.dataBranchInputManager->BranchList(Found).LoopName != LoopName) {
     166            0 :             ShowSevereError(state, "GetBranchList: BranchList Loop Name already assigned");
     167            0 :             ShowContinueError(state,
     168            0 :                               format("BranchList={}, already assigned to loop={}",
     169            0 :                                      state.dataBranchInputManager->BranchList(Found).Name,
     170            0 :                                      state.dataBranchInputManager->BranchList(Found).LoopName));
     171            0 :             ShowContinueError(state, format("Now requesting assignment to Loop={}", LoopName));
     172            0 :             ErrFound = true;
     173              :         }
     174              : 
     175              :         // Return data
     176          184 :         NumBranchNames = state.dataBranchInputManager->BranchList(Found).NumOfBranchNames;
     177          184 :         if (isize(BranchNames) < NumBranchNames) {
     178            0 :             ShowSevereError(state, "GetBranchList: Branch Names array not big enough to hold Branch Names");
     179            0 :             ShowContinueError(state, format("Input BranchListName={}, in Loop={}", BranchListName, LoopName));
     180            0 :             ShowContinueError(state, fmt::format("BranchName Array size={}, but input size={}", size(BranchNames), (NumBranchNames)));
     181            0 :             ErrFound = true;
     182              :         } else {
     183          184 :             BranchNames = "";
     184          184 :             BranchNames({1, NumBranchNames}) = state.dataBranchInputManager->BranchList(Found).BranchNames({1, NumBranchNames});
     185              :         }
     186              : 
     187          184 :         if (ErrFound) {
     188            0 :             ShowFatalError(state, "GetBranchList: preceding condition(s) causes program termination.");
     189              :         }
     190          184 :     }
     191              : 
     192          184 :     int NumBranchesInBranchList(EnergyPlusData &state, std::string const &BranchListName)
     193              :     {
     194              : 
     195              :         // FUNCTION INFORMATION:
     196              :         //       AUTHOR         Linda K. Lawrie
     197              :         //       DATE WRITTEN   July 2003
     198              :         //       MODIFIED       na
     199              :         //       RE-ENGINEERED  na
     200              : 
     201              :         // PURPOSE OF THIS FUNCTION:
     202              :         // This function returns the number of branches in a branch list so that the calling
     203              :         // routine can allocate arrays before calling GetBranchList.
     204              : 
     205              :         // Return value
     206              :         int NumBranchesInBranchList;
     207              : 
     208              :         // FUNCTION LOCAL VARIABLE DECLARATIONS:
     209              :         int Found;
     210              : 
     211          184 :         if (state.dataBranchInputManager->GetBranchListInputFlag) {
     212           16 :             state.dataBranchInputManager->GetBranchListInputFlag = false;
     213           16 :             GetBranchListInput(state);
     214              :         }
     215              : 
     216              :         //  Find this BranchList in the master BranchList Names
     217          184 :         Found = Util::FindItemInList(BranchListName, state.dataBranchInputManager->BranchList);
     218          184 :         if (Found == 0) {
     219            0 :             ShowFatalError(state, format("NumBranchesInBranchList: BranchList Name not found={}", BranchListName));
     220              :         }
     221              : 
     222          184 :         NumBranchesInBranchList = state.dataBranchInputManager->BranchList(Found).NumOfBranchNames;
     223              : 
     224          184 :         return NumBranchesInBranchList;
     225              :     }
     226              : 
     227          549 :     void GetBranchData(EnergyPlusData &state,
     228              :                        std::string const &LoopName,                               // Loop Name of this Branch
     229              :                        std::string const &BranchName,                             // Requested Branch Name
     230              :                        DataBranchAirLoopPlant::PressureCurveType &PressCurveType, // Index of a pressure curve object
     231              :                        int &PressCurveIndex,                                      // Index of a pressure curve object
     232              :                        int &NumComps,                                             // Number of Components on Branch
     233              :                        Array1D_string &CompType,                                  // Component Type for each item on Branch
     234              :                        Array1D_string &CompName,                                  // Component Name for each item on Branch
     235              :                        Array1D_string &CompInletNodeNames,                        // Component Inlet Node IDs for each item on Branch
     236              :                        Array1D_int &CompInletNodeNums,                            // Component Inlet Node Numbers for each item on Branch
     237              :                        Array1D_string &CompOutletNodeNames,                       // Component Outlet Node IDs for each item on Branch
     238              :                        Array1D_int &CompOutletNodeNums,                           // Component Outlet Node Numbers for each item on Branch
     239              :                        bool &ErrorsFound)
     240              :     {
     241              : 
     242              :         // SUBROUTINE INFORMATION:
     243              :         //       AUTHOR         Linda K. Lawrie
     244              :         //       DATE WRITTEN   October 1999
     245              :         //       MODIFIED       October 2001, Automatic Extensibility
     246              :         //                      September 2012, B. Griffith, removed component control types
     247              :         //       RE-ENGINEERED  na
     248              : 
     249              :         // PURPOSE OF THIS SUBROUTINE:
     250              :         // This routine gets the Branch Data (internal structure) for the requested
     251              :         // Branch Name and returns it in "list structure" to the calling routine.
     252              : 
     253              :         // Using/Aliasing
     254              : 
     255              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     256              :         int Count; // Loop Counter
     257              :         int MinCompsAllowed;
     258              : 
     259              :         // NumComps now defined on input
     260              : 
     261          549 :         state.dataBranchInputManager->BComponents.allocate(NumComps);
     262              : 
     263          549 :         GetInternalBranchData(
     264          549 :             state, LoopName, BranchName, PressCurveType, PressCurveIndex, NumComps, state.dataBranchInputManager->BComponents, ErrorsFound);
     265              : 
     266         3843 :         MinCompsAllowed = min(
     267         1098 :             size(CompType), size(CompName), size(CompInletNodeNames), size(CompInletNodeNums), size(CompOutletNodeNames), size(CompOutletNodeNums));
     268          549 :         if (MinCompsAllowed < NumComps) {
     269            0 :             ShowSevereError(state, "GetBranchData: Component List arrays not big enough to hold Number of Components");
     270            0 :             ShowContinueError(state, format("Input BranchName={}, in Loop={}", BranchName, LoopName));
     271            0 :             ShowContinueError(state, fmt::format("Max Component Array size={}, but input size={}", MinCompsAllowed, NumComps));
     272            0 :             ShowFatalError(state, "Program terminates due to preceding conditions.");
     273              :         }
     274              : 
     275         1226 :         for (Count = 1; Count <= NumComps; ++Count) {
     276          677 :             CompType(Count) = state.dataBranchInputManager->BComponents(Count).CType;
     277          677 :             CompName(Count) = state.dataBranchInputManager->BComponents(Count).Name;
     278          677 :             CompInletNodeNames(Count) = state.dataBranchInputManager->BComponents(Count).InletNodeName;
     279          677 :             CompInletNodeNums(Count) = state.dataBranchInputManager->BComponents(Count).InletNode;
     280          677 :             CompOutletNodeNames(Count) = state.dataBranchInputManager->BComponents(Count).OutletNodeName;
     281          677 :             CompOutletNodeNums(Count) = state.dataBranchInputManager->BComponents(Count).OutletNode;
     282              :         }
     283          549 :         state.dataBranchInputManager->BComponents.deallocate();
     284          549 :     }
     285              : 
     286          549 :     int NumCompsInBranch(EnergyPlusData &state, std::string const &BranchName)
     287              :     {
     288              : 
     289              :         // FUNCTION INFORMATION:
     290              :         //       AUTHOR         Linda K. Lawrie
     291              :         //       DATE WRITTEN   July 2003
     292              :         //       MODIFIED       na
     293              :         //       RE-ENGINEERED  na
     294              : 
     295              :         // PURPOSE OF THIS FUNCTION:
     296              :         // This function returns the number of components in a branch so that the calling
     297              :         // routine can allocate arrays before calling GetBranchData.
     298              : 
     299              :         // Return value
     300              :         int NumCompsInBranch;
     301              : 
     302              :         // FUNCTION LOCAL VARIABLE DECLARATIONS:
     303              :         int Found;
     304              : 
     305          549 :         if (state.dataBranchInputManager->GetBranchInputFlag) {
     306           30 :             state.dataBranchInputManager->GetBranchInputFlag = false;
     307           30 :             GetBranchInput(state);
     308              :         }
     309              : 
     310          549 :         Found = Util::FindItemInList(BranchName, state.dataBranchInputManager->Branch);
     311          549 :         if (Found == 0) {
     312            0 :             ShowSevereError(state, format("NumCompsInBranch:  Branch not found={}", BranchName));
     313            0 :             NumCompsInBranch = 0;
     314              :         } else {
     315          549 :             NumCompsInBranch = state.dataBranchInputManager->Branch(Found).NumOfComponents;
     316              :         }
     317              : 
     318          549 :         return NumCompsInBranch;
     319              :     }
     320              : 
     321            3 :     int GetAirBranchIndex(EnergyPlusData &state, std::string const &CompType, std::string_view CompName)
     322              :     {
     323              : 
     324              :         // FUNCTION INFORMATION:
     325              :         //       AUTHOR         Richard Raustad, FSEC
     326              :         //       DATE WRITTEN   April 2013
     327              :         //       MODIFIED       na
     328              :         //       RE-ENGINEERED  na
     329              : 
     330              :         // PURPOSE OF THIS FUNCTION:
     331              :         // This function returns the branch index so that the calling
     332              :         // routine can search for a fan on this branch or use branch flow for sizing.
     333              : 
     334              :         // Return value
     335            3 :         int GetAirBranchIndex(0);
     336              : 
     337              :         // FUNCTION LOCAL VARIABLE DECLARATIONS:
     338              :         int BranchNum;
     339              :         int CompNum;
     340              :         int NumBranches;
     341              : 
     342            3 :         if (state.dataBranchInputManager->GetBranchInputFlag) {
     343            1 :             state.dataBranchInputManager->GetBranchInputFlag = false;
     344            1 :             GetBranchInput(state);
     345              :         }
     346              : 
     347            3 :         NumBranches = size(state.dataBranchInputManager->Branch);
     348              : 
     349            3 :         if (NumBranches == 0) {
     350            0 :             ShowSevereError(state, format("GetAirBranchIndex:  Branch not found with component = {} \"{}\"", CompType, CompName));
     351              :         } else {
     352            6 :             for (BranchNum = 1; BranchNum <= NumBranches; ++BranchNum) {
     353           14 :                 for (CompNum = 1; CompNum <= state.dataBranchInputManager->Branch(BranchNum).NumOfComponents; ++CompNum) {
     354           14 :                     if (Util::SameString(CompType, state.dataBranchInputManager->Branch(BranchNum).Component(CompNum).CType) &&
     355            3 :                         Util::SameString(CompName, state.dataBranchInputManager->Branch(BranchNum).Component(CompNum).Name)) {
     356            2 :                         GetAirBranchIndex = BranchNum;
     357            2 :                         goto BranchLoop_exit;
     358              :                     }
     359              :                 }
     360              :             }
     361            3 :         BranchLoop_exit:;
     362              :         }
     363              : 
     364            3 :         return GetAirBranchIndex;
     365              :     }
     366              : 
     367            0 :     void GetBranchFanTypeName(EnergyPlusData &state,
     368              :                               int const BranchNum,
     369              :                               std::string &FanType,
     370              :                               std::string &FanName,
     371              :                               bool &ErrFound // Set to true if error found, false otherwise
     372              :     )
     373              :     {
     374              : 
     375              :         // FUNCTION INFORMATION:
     376              :         //       AUTHOR         Richard Raustad, FSEC
     377              :         //       DATE WRITTEN   April 2013
     378              :         //       MODIFIED       na
     379              :         //       RE-ENGINEERED  na
     380              : 
     381              :         // PURPOSE OF THIS FUNCTION:
     382              :         // This function returns the branch fan flow rate so that the calling
     383              :         // routine can either use this flow or use then branch flow for sizing.
     384              : 
     385              :         // Using/Aliasing
     386              : 
     387              :         // FUNCTION LOCAL VARIABLE DECLARATIONS:
     388              :         int CompNum;
     389              :         int NumBranches;
     390              : 
     391            0 :         if (state.dataBranchInputManager->GetBranchInputFlag) {
     392            0 :             state.dataBranchInputManager->GetBranchInputFlag = false;
     393            0 :             GetBranchInput(state);
     394              :         }
     395              : 
     396            0 :         ErrFound = false;
     397            0 :         NumBranches = size(state.dataBranchInputManager->Branch);
     398              : 
     399            0 :         FanType = std::string();
     400            0 :         FanName = std::string();
     401              : 
     402            0 :         if (NumBranches == 0) {
     403            0 :             ShowSevereError(state, fmt::format("GetBranchFanTypeName:  Branch index not found = {}", BranchNum));
     404            0 :             ErrFound = true;
     405              :         } else {
     406            0 :             if (BranchNum > 0 && BranchNum <= NumBranches) {
     407            0 :                 for (CompNum = 1; CompNum <= state.dataBranchInputManager->Branch(BranchNum).NumOfComponents; ++CompNum) {
     408            0 :                     if (Util::SameString("Fan:OnOff", state.dataBranchInputManager->Branch(BranchNum).Component(CompNum).CType) ||
     409            0 :                         Util::SameString("Fan:ConstantVolume", state.dataBranchInputManager->Branch(BranchNum).Component(CompNum).CType) ||
     410            0 :                         Util::SameString("Fan:VariableVolume", state.dataBranchInputManager->Branch(BranchNum).Component(CompNum).CType) ||
     411            0 :                         Util::SameString("Fan:SystemModel", state.dataBranchInputManager->Branch(BranchNum).Component(CompNum).CType)) {
     412            0 :                         FanType = state.dataBranchInputManager->Branch(BranchNum).Component(CompNum).CType;
     413            0 :                         FanName = state.dataBranchInputManager->Branch(BranchNum).Component(CompNum).Name;
     414            0 :                         break;
     415              :                     }
     416              :                 }
     417            0 :                 if (FanType.empty()) ErrFound = true;
     418              :             } else {
     419            0 :                 ShowSevereError(state, fmt::format("GetBranchFanTypeName:  Branch index not found = {}", BranchNum));
     420            0 :                 ErrFound = true;
     421              :             }
     422              :         }
     423            0 :     }
     424              : 
     425         1277 :     void GetInternalBranchData(EnergyPlusData &state,
     426              :                                std::string const &LoopName,                               // Loop Name for Branch
     427              :                                std::string const &BranchName,                             // Requested Branch Name
     428              :                                DataBranchAirLoopPlant::PressureCurveType &PressCurveType, // Index of pressure curve object
     429              :                                int &PressCurveIndex,                                      // Index of pressure curve object
     430              :                                int &NumComps,                                             // Number of Components on Branch
     431              :                                Array1D<ComponentData> const &BComponents,                 // Component data returned
     432              :                                bool &ErrorsFound // True when Loop Name is already assigned and this not same loop
     433              :     )
     434              :     {
     435              : 
     436              :         // SUBROUTINE INFORMATION:
     437              :         //       AUTHOR         Linda K. Lawrie
     438              :         //       DATE WRITTEN   October 1999
     439              :         //       MODIFIED       na
     440              :         //       RE-ENGINEERED  na
     441              : 
     442              :         // PURPOSE OF THIS SUBROUTINE:
     443              :         // This routine gets the Branch Data (internal structure) for the requested
     444              :         // Branch Name and returns it to the calling routine.  This is used internally
     445              :         // in the module.
     446              : 
     447              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     448              :         int Found; // Pointer to requested Branch Name
     449              : 
     450         1277 :         if (state.dataBranchInputManager->GetBranchInputFlag) {
     451            0 :             GetBranchInput(state);
     452            0 :             state.dataBranchInputManager->GetBranchInputFlag = false;
     453              :         }
     454              : 
     455         1277 :         Found = Util::FindItemInList(BranchName, state.dataBranchInputManager->Branch);
     456         1277 :         if (Found == 0) {
     457            0 :             ShowSevereError(state, format("GetInternalBranchData:  Branch not found={}", BranchName));
     458            0 :             ErrorsFound = true;
     459            0 :             NumComps = 0;
     460              :         } else {
     461         1277 :             if (state.dataBranchInputManager->Branch(Found).AssignedLoopName.empty()) {
     462          549 :                 state.dataBranchInputManager->Branch(Found).AssignedLoopName = LoopName;
     463          549 :                 PressCurveType = state.dataBranchInputManager->Branch(Found).PressureCurveType;
     464          549 :                 PressCurveIndex = state.dataBranchInputManager->Branch(Found).PressureCurveIndex;
     465          549 :                 NumComps = state.dataBranchInputManager->Branch(Found).NumOfComponents;
     466          549 :                 BComponents({1, NumComps}) = state.dataBranchInputManager->Branch(Found).Component({1, NumComps});
     467          728 :             } else if (state.dataBranchInputManager->Branch(Found).AssignedLoopName != LoopName) {
     468            0 :                 ShowSevereError(state, format("Attempt to assign branch to two different loops, Branch={}", BranchName));
     469            0 :                 ShowContinueError(state, format("Branch already assigned to loop={}", state.dataBranchInputManager->Branch(Found).AssignedLoopName));
     470            0 :                 ShowContinueError(state, format("New attempt to assign to loop={}", LoopName));
     471            0 :                 ErrorsFound = true;
     472            0 :                 NumComps = 0;
     473              :             } else {
     474          728 :                 PressCurveType = state.dataBranchInputManager->Branch(Found).PressureCurveType;
     475          728 :                 PressCurveIndex = state.dataBranchInputManager->Branch(Found).PressureCurveIndex;
     476          728 :                 NumComps = state.dataBranchInputManager->Branch(Found).NumOfComponents;
     477          728 :                 BComponents({1, NumComps}) = state.dataBranchInputManager->Branch(Found).Component({1, NumComps});
     478              :             }
     479              :         }
     480         1277 :     }
     481              : 
     482          122 :     void GetNumSplitterMixerInConntrList(EnergyPlusData &state,
     483              :                                          std::string const &LoopName,          // Loop Name for this Splitter (used in error message)
     484              :                                          std::string const &ConnectorListName, // Requested Connector List Name
     485              :                                          int &numSplitters,                    // Number of splitters in the loop
     486              :                                          int &numMixers,                       // Number of mixers in the loop
     487              :                                          bool &ErrorsFound                     // if no connector list
     488              :     )
     489              :     {
     490              : 
     491              :         // SUBROUTINE INFORMATION:
     492              :         //       AUTHOR         Sankaranarayanan K P
     493              :         //       DATE WRITTEN   April 2005
     494              :         //       MODIFIED       Linda Lawrie - September 2005
     495              :         //       RE-ENGINEERED  na
     496              : 
     497              :         // PURPOSE OF THIS SUBROUTINE:
     498              :         // This subroutine returns the number of splitter and mixers in a connector list item
     499              :         // The data is filled from the idd object 'ConnectorList'
     500              : 
     501              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     502              :         int ConnNum;
     503              : 
     504          122 :         if (state.dataBranchInputManager->GetConnectorListInputFlag) {
     505           43 :             GetConnectorListInput(state);
     506           43 :             state.dataBranchInputManager->GetConnectorListInputFlag = false;
     507              :         }
     508              : 
     509          122 :         numSplitters = 0;
     510          122 :         numMixers = 0;
     511          122 :         ConnNum = Util::FindItemInList(ConnectorListName, state.dataBranchInputManager->ConnectorLists);
     512              : 
     513          122 :         if (ConnNum > 0) {
     514          122 :             numSplitters = state.dataBranchInputManager->ConnectorLists(ConnNum).NumOfSplitters;
     515          122 :             numMixers = state.dataBranchInputManager->ConnectorLists(ConnNum).NumOfMixers;
     516              :         } else {
     517            0 :             ShowSevereError(state, format("Ref: Loop={}, Connector List not found={}", LoopName, ConnectorListName));
     518            0 :             ErrorsFound = true;
     519              :         }
     520          122 :     }
     521              : 
     522          366 :     void GetConnectorList(EnergyPlusData &state,
     523              :                           std::string const &ConnectorListName,   // Requested Connector List
     524              :                           ConnectorData &Connectoid,              // Returned Connector Data
     525              :                           ObjexxFCL::Optional_int_const NumInList // Number of the current connector in the list of connectors
     526              :     )
     527              :     {
     528              : 
     529              :         // SUBROUTINE INFORMATION:
     530              :         //       AUTHOR         Linda K. Lawrie
     531              :         //       DATE WRITTEN   October 1999
     532              : 
     533              :         // PURPOSE OF THIS SUBROUTINE:
     534              :         // Obtains connector data for requested connector list.  Also,
     535              :         // this subroutine gets the input for the following IDD structure:
     536              :         // ConnectorList,
     537              :         //         \memo only two connectors allowed per loop
     538              :         //         \memo if two entered, one must be Connector:Splitter and one must be Connector:Mixer
     539              :         //     A1, \field Name
     540              :         //         \required-field
     541              :         //         \reference ConnectorLists
     542              :         //     A2, \field Connector 1 Object Type
     543              :         //         \required-field
     544              :         //         \key Connector:Splitter
     545              :         //         \key Connector:Mixer
     546              :         //     A3, \field Connector 1 Name
     547              :         //         \required-field
     548              :         //     A4, \field Connector 2 Object Type
     549              :         //         \key Connector:Splitter
     550              :         //         \key Connector:Mixer
     551              :         //     A5; \field Connector 2 Name
     552              : 
     553          366 :         if (state.dataBranchInputManager->GetConnectorListInputFlag) {
     554            0 :             GetConnectorListInput(state);
     555            0 :             state.dataBranchInputManager->GetConnectorListInputFlag = false;
     556              :         }
     557              : 
     558          366 :         if (not_blank(ConnectorListName)) {
     559          366 :             int Count = Util::FindItemInList(ConnectorListName, state.dataBranchInputManager->ConnectorLists);
     560          366 :             if (Count == 0) {
     561            0 :                 ShowFatalError(state, format("GetConnectorList: Connector List not found={}", ConnectorListName));
     562              :             }
     563          366 :             Connectoid = state.dataBranchInputManager->ConnectorLists(Count);
     564          366 :             if (present(NumInList)) {
     565          366 :                 Connectoid.ConnectorType(1) = state.dataBranchInputManager->ConnectorLists(Count).ConnectorType(NumInList);
     566          366 :                 Connectoid.ConnectorName(1) = state.dataBranchInputManager->ConnectorLists(Count).ConnectorName(NumInList);
     567          366 :                 Connectoid.ConnectorType(2) = "";
     568          366 :                 Connectoid.ConnectorName(2) = "";
     569              :             }
     570              :         } else {
     571            0 :             Connectoid.Name = "";
     572            0 :             Connectoid.NumOfConnectors = 0;
     573            0 :             Connectoid.ConnectorType(1) = "";
     574            0 :             Connectoid.ConnectorType(2) = "";
     575            0 :             Connectoid.ConnectorName(1) = "";
     576            0 :             Connectoid.ConnectorName(2) = "";
     577              :         }
     578          366 :     }
     579              : 
     580          244 :     void GetLoopMixer(EnergyPlusData &state,
     581              :                       std::string const &LoopName,          // Loop Name for Mixer
     582              :                       std::string const &ConnectorListName, // Requested Connector List Name
     583              :                       std::string &MixerName,               // Name of Mixer
     584              :                       bool &IsMixer,                        // True when Mixer is on this connector, false otherwise
     585              :                       std::string &OutletNodeName,          // Outlet Node ID
     586              :                       int &OutletNodeNum,                   // Outlet Node Number
     587              :                       int &NumInletNodes,                   // Number of Inlet Nodes
     588              :                       Array1D_string &InletNodeNames,       // Inlet Node IDs
     589              :                       Array1D_int &InletNodeNums,           // Inlet Node Numbers
     590              :                       bool &ErrorsFound,
     591              :                       ObjexxFCL::Optional_int_const ConnectorNumber, // number of the current item in connector list
     592              :                       ObjexxFCL::Optional_int MixerNumber            // Mixer number for this specific splitter
     593              :     )
     594              :     {
     595              : 
     596              :         // SUBROUTINE INFORMATION:
     597              :         //       AUTHOR         Linda K. Lawrie
     598              :         //       DATE WRITTEN   October 1999
     599              :         //       MODIFIED       October 2001, Automatic Extensibility
     600              : 
     601              :         // PURPOSE OF THIS SUBROUTINE:
     602              :         // This routine gets the data for the requested Connector List and returns values indicating
     603              :         // if this connector list name is a mixer or not.
     604              : 
     605              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     606              :         int Count; // Loop Counter
     607              :         DataBranchAirLoopPlant::PressureCurveType PressCurveType;
     608              : 
     609              :         // Object Data
     610          244 :         ConnectorData Connectoid;           // Connector Data
     611          244 :         Array1D<ComponentData> BComponents; // Branch Component Data
     612              : 
     613          244 :         if (state.dataBranchInputManager->GetMixerInputFlag) {
     614            0 :             GetMixerInput(state);
     615            0 :             state.dataBranchInputManager->GetMixerInputFlag = false;
     616              :         }
     617              : 
     618          244 :         GetConnectorList(state, ConnectorListName, Connectoid, ConnectorNumber);
     619          244 :         if (Util::SameString(Connectoid.ConnectorType(1), cMIXER)) {
     620          122 :             Count = Util::FindItemInList(Connectoid.ConnectorName(1), state.dataBranchInputManager->Mixers);
     621          122 :             if (present(MixerNumber)) ++MixerNumber;
     622          122 :             if (Count == 0) {
     623            0 :                 ShowFatalError(state, format("GetLoopMixer: No Mixer Found={}", Connectoid.ConnectorName(1)));
     624              :             }
     625          122 :         } else if (Util::SameString(Connectoid.ConnectorType(2), cMIXER)) {
     626            0 :             Count = Util::FindItemInList(Connectoid.ConnectorName(2), state.dataBranchInputManager->Mixers);
     627            0 :             if (Count == 0) {
     628            0 :                 ShowFatalError(state, format("GetLoopMixer: No Mixer Found={}", Connectoid.ConnectorName(2)));
     629              :             }
     630              :         } else {
     631          122 :             Count = 0;
     632              :         }
     633              : 
     634              :         // Set defaults for later error potential
     635          244 :         IsMixer = false;
     636          244 :         MixerName = std::string();
     637          244 :         OutletNodeName = std::string();
     638          244 :         OutletNodeNum = 0;
     639          244 :         NumInletNodes = 0;
     640          244 :         InletNodeNames = "";
     641          244 :         InletNodeNums = 0;
     642              : 
     643          244 :         if (Count != 0) { // Build up Output list(s). For each component(?)
     644              : 
     645              :             int NumParams;
     646              :             int NumAlphas;
     647              :             int NumNumbers;
     648              :             // The inlet nodes for the mixer will be the last "outlet" node of
     649              :             // each corresponding inlet branch.  The outlet node for the mixer
     650              :             // will be the first "inlet" node of the outlet branch since that
     651              :             // would be the first node on the branch.
     652          122 :             MixerName = state.dataBranchInputManager->Mixers(Count).Name;
     653          122 :             IsMixer = true;
     654              :             // The number of "components" on a Mixer is the number of branches.  This is the number of alpha arguments -1.
     655          122 :             state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, "Branch", NumParams, NumAlphas, NumNumbers);
     656          122 :             BComponents.allocate(NumAlphas - 1);
     657          122 :             bool errFlag = false;
     658              :             int PressCurveIndex;
     659              :             int NumComps; // Number of Components on this Branch
     660          122 :             GetInternalBranchData(state,
     661              :                                   LoopName,
     662          122 :                                   state.dataBranchInputManager->Mixers(Count).OutletBranchName,
     663              :                                   PressCurveType,
     664              :                                   PressCurveIndex,
     665              :                                   NumComps,
     666              :                                   BComponents,
     667              :                                   errFlag);
     668          122 :             if (errFlag) {
     669            0 :                 ShowContinueError(state, format("..occurs for Connector:Mixer Name={}", state.dataBranchInputManager->Mixers(Count).Name));
     670            0 :                 ErrorsFound = true;
     671              :             }
     672          122 :             if (NumComps > 0) {
     673          122 :                 OutletNodeName = BComponents(1).InletNodeName;
     674          122 :                 OutletNodeNum = BComponents(1).InletNode;
     675          122 :                 NumInletNodes = state.dataBranchInputManager->Mixers(Count).NumInletBranches;
     676              :                 // Register this node connection because the mixer gets node information indirectly from the branch
     677          122 :                 errFlag = false;
     678          244 :                 RegisterNodeConnection(state,
     679              :                                        OutletNodeNum,
     680          122 :                                        state.dataLoopNodes->NodeID(OutletNodeNum),
     681              :                                        DataLoopNode::ConnectionObjectType::ConnectorMixer,
     682              :                                        MixerName,
     683              :                                        DataLoopNode::ConnectionType::Outlet,
     684              :                                        NodeInputManager::CompFluidStream::Primary,
     685              :                                        ObjectIsNotParent,
     686              :                                        errFlag);
     687              : 
     688          122 :                 if (NumInletNodes > isize(InletNodeNames) || NumInletNodes > isize(InletNodeNums)) {
     689            0 :                     ShowSevereError(state, format("GetLoopMixer: Connector:Mixer={} contains too many inlets for size of Inlet Array.", MixerName));
     690            0 :                     ShowContinueError(state, fmt::format("Max array size={}, Mixer statement inlets={}", size(InletNodeNames), NumInletNodes));
     691            0 :                     ShowFatalError(state, "Program terminates due to preceding condition.");
     692              :                 }
     693          122 :                 InletNodeNums = 0;
     694          122 :                 InletNodeNames = "";
     695              : 
     696          364 :                 for (int Loop = 1; Loop <= state.dataBranchInputManager->Mixers(Count).NumInletBranches; ++Loop) {
     697          242 :                     GetInternalBranchData(state,
     698              :                                           LoopName,
     699          242 :                                           state.dataBranchInputManager->Mixers(Count).InletBranchNames(Loop),
     700              :                                           PressCurveType,
     701              :                                           PressCurveIndex,
     702              :                                           NumComps,
     703              :                                           BComponents,
     704              :                                           ErrorsFound);
     705          242 :                     if (NumComps > 0) {
     706          242 :                         InletNodeNames(Loop) = BComponents(NumComps).OutletNodeName;
     707          242 :                         InletNodeNums(Loop) = BComponents(NumComps).OutletNode;
     708              :                         // Register this node connection because the mixer gets node information indirectly from the branch
     709          242 :                         errFlag = false;
     710          484 :                         RegisterNodeConnection(state,
     711          242 :                                                InletNodeNums(Loop),
     712          242 :                                                state.dataLoopNodes->NodeID(InletNodeNums(Loop)),
     713              :                                                DataLoopNode::ConnectionObjectType::ConnectorMixer,
     714              :                                                MixerName,
     715              :                                                DataLoopNode::ConnectionType::Inlet,
     716              :                                                NodeInputManager::CompFluidStream::Primary,
     717              :                                                ObjectIsNotParent,
     718              :                                                errFlag);
     719              :                     }
     720              :                 }
     721              :             } else {
     722              :                 // Set so cascading errors don't happen?
     723            0 :                 IsMixer = false;
     724              :             }
     725          122 :             BComponents.deallocate();
     726              :         }
     727          244 :     }
     728              : 
     729          122 :     void GetLoopSplitter(EnergyPlusData &state,
     730              :                          std::string const &LoopName,          // Loop Name for this Splitter
     731              :                          std::string const &ConnectorListName, // Requested Connector List Name
     732              :                          std::string &SplitterName,            // Name of Splitter
     733              :                          bool &IsSplitter,                     // True if splitter on this connector list, false otherwise
     734              :                          std::string &InletNodeName,           // Inlet Node ID
     735              :                          int &InletNodeNum,                    // Inlet Node Number
     736              :                          int &NumOutletNodes,                  // Number of Outlet Nodes
     737              :                          Array1D_string &OutletNodeNames,      // Outlet Node IDs
     738              :                          Array1D_int &OutletNodeNums,          // Outlet Node Numbers
     739              :                          bool &ErrorsFound,
     740              :                          ObjexxFCL::Optional_int_const ConnectorNumber, // number of the current item in connector list
     741              :                          ObjexxFCL::Optional_int SplitterNumber         // splitter number for this specific splitter
     742              :     )
     743              :     {
     744              : 
     745              :         // SUBROUTINE INFORMATION:
     746              :         //       AUTHOR         Linda K. Lawrie
     747              :         //       DATE WRITTEN   October 1999
     748              :         //       MODIFIED       October 2001, Automatic Extensibility
     749              : 
     750              :         // PURPOSE OF THIS SUBROUTINE:
     751              :         // This routine gets the data for the requested Connector List and returns values indicating
     752              :         // if this connector list name is a splitter or not.
     753              : 
     754              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     755              :         int Count; // Loop Counter
     756              :         DataBranchAirLoopPlant::PressureCurveType PressCurveType;
     757              : 
     758              :         // Object Data
     759          122 :         ConnectorData Connectoid;           // Connector Data
     760          122 :         Array1D<ComponentData> BComponents; // Branch Component Data
     761              : 
     762          122 :         if (state.dataBranchInputManager->GetSplitterInputFlag) {
     763            0 :             GetSplitterInput(state);
     764            0 :             state.dataBranchInputManager->GetSplitterInputFlag = false;
     765              :         }
     766              : 
     767          122 :         if (ConnectorListName.empty()) {
     768            0 :             ShowSevereError(state, format("GetLoopSplitter: ConnectorListName is blank.  LoopName={}", LoopName));
     769            0 :             ShowFatalError(state, "Program terminates due to previous condition.");
     770              :         }
     771          122 :         GetConnectorList(state, ConnectorListName, Connectoid, ConnectorNumber);
     772          122 :         if (Util::SameString(Connectoid.ConnectorType(1), cSPLITTER)) {
     773          122 :             Count = Util::FindItemInList(Connectoid.ConnectorName(1), state.dataBranchInputManager->Splitters);
     774          122 :             if (present(SplitterNumber)) ++SplitterNumber;
     775          122 :             if (Count == 0) {
     776            0 :                 ShowFatalError(state, format("GetLoopSplitter: No Splitter Found={}", Connectoid.ConnectorName(1)));
     777              :             }
     778            0 :         } else if (Util::SameString(Connectoid.ConnectorType(2), cSPLITTER)) {
     779            0 :             Count = Util::FindItemInList(Connectoid.ConnectorName(2), state.dataBranchInputManager->Splitters);
     780            0 :             if (Count == 0) {
     781            0 :                 ShowFatalError(state, format("GetLoopSplitter: No Splitter Found={}", Connectoid.ConnectorName(2)));
     782              :             }
     783              :         } else {
     784            0 :             Count = 0;
     785              :         }
     786              : 
     787              :         // Default for any errors
     788          122 :         SplitterName = std::string();
     789          122 :         IsSplitter = false;
     790          122 :         InletNodeName = std::string();
     791          122 :         InletNodeNum = 0;
     792          122 :         NumOutletNodes = 0;
     793          122 :         OutletNodeNames = "";
     794          122 :         OutletNodeNums = 0;
     795              : 
     796          122 :         if (Count != 0) { // Build up Output list(s). For each component(?)
     797              : 
     798              :             int NumComps; // Number of Components on this Branch
     799              :             int NumParams;
     800              :             int NumAlphas;
     801              :             int NumNumbers;
     802              :             int PressCurveIndex;
     803              : 
     804              :             // The inlet node for the splitter will be the last "outlet" node of the inlet
     805              :             // branch. The outlet nodes for the splitter will be the first "inlet" node of
     806              :             // each corresponding outlet branch since that would be the first node on the branch.
     807              : 
     808          122 :             SplitterName = state.dataBranchInputManager->Splitters(Count).Name;
     809          122 :             IsSplitter = true;
     810              :             // The number of "components" on a Splitter is the number of branches.  This is the number of alpha arguments -1.
     811          122 :             state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, "Branch", NumParams, NumAlphas, NumNumbers);
     812          122 :             BComponents.allocate(NumAlphas - 1);
     813          122 :             bool errFlag = false;
     814          122 :             GetInternalBranchData(state,
     815              :                                   LoopName,
     816          122 :                                   state.dataBranchInputManager->Splitters(Count).InletBranchName,
     817              :                                   PressCurveType,
     818              :                                   PressCurveIndex,
     819              :                                   NumComps,
     820              :                                   BComponents,
     821              :                                   errFlag);
     822          122 :             if (errFlag) {
     823            0 :                 ShowContinueError(state, format("..occurs for Splitter Name={}", state.dataBranchInputManager->Splitters(Count).Name));
     824            0 :                 ErrorsFound = true;
     825              :             }
     826          122 :             if (NumComps > 0) {
     827          122 :                 InletNodeName = BComponents(NumComps).OutletNodeName;
     828          122 :                 InletNodeNum = BComponents(NumComps).OutletNode;
     829          122 :                 NumOutletNodes = state.dataBranchInputManager->Splitters(Count).NumOutletBranches;
     830              :                 // Register this node connection because the splitter gets node information indirectly from the branch
     831          122 :                 errFlag = false;
     832          244 :                 RegisterNodeConnection(state,
     833              :                                        InletNodeNum,
     834          122 :                                        state.dataLoopNodes->NodeID(InletNodeNum),
     835              :                                        DataLoopNode::ConnectionObjectType::ConnectorSplitter,
     836              :                                        SplitterName,
     837              :                                        DataLoopNode::ConnectionType::Inlet,
     838              :                                        NodeInputManager::CompFluidStream::Primary,
     839              :                                        ObjectIsNotParent,
     840              :                                        errFlag);
     841              : 
     842          122 :                 if (NumOutletNodes > isize(OutletNodeNames) || NumOutletNodes > isize(OutletNodeNums)) {
     843            0 :                     ShowSevereError(
     844            0 :                         state, format("GetLoopSplitter: Connector:Splitter={} contains too many outlets for size of Outlet Array.", SplitterName));
     845            0 :                     ShowContinueError(state, fmt::format("Max array size={}, Splitter statement outlets={}", size(OutletNodeNames), NumOutletNodes));
     846            0 :                     ShowFatalError(state, "Program terminates due to preceding condition.");
     847              :                 }
     848          122 :                 OutletNodeNums = 0;
     849          122 :                 OutletNodeNames = "";
     850              : 
     851          364 :                 for (int Loop = 1; Loop <= state.dataBranchInputManager->Splitters(Count).NumOutletBranches; ++Loop) {
     852          242 :                     GetInternalBranchData(state,
     853              :                                           LoopName,
     854          242 :                                           state.dataBranchInputManager->Splitters(Count).OutletBranchNames(Loop),
     855              :                                           PressCurveType,
     856              :                                           PressCurveIndex,
     857              :                                           NumComps,
     858              :                                           BComponents,
     859              :                                           ErrorsFound);
     860          242 :                     if (NumComps > 0) {
     861          242 :                         OutletNodeNames(Loop) = BComponents(1).InletNodeName;
     862          242 :                         OutletNodeNums(Loop) = BComponents(1).InletNode;
     863              :                         // Register this node connection because the splitter gets node information indirectly from the branch
     864          242 :                         errFlag = false;
     865          484 :                         RegisterNodeConnection(state,
     866          242 :                                                OutletNodeNums(Loop),
     867          242 :                                                state.dataLoopNodes->NodeID(OutletNodeNums(Loop)),
     868              :                                                DataLoopNode::ConnectionObjectType::ConnectorSplitter,
     869              :                                                SplitterName,
     870              :                                                DataLoopNode::ConnectionType::Outlet,
     871              :                                                NodeInputManager::CompFluidStream::Primary,
     872              :                                                ObjectIsNotParent,
     873              :                                                errFlag);
     874              :                     }
     875              :                 }
     876              :             } else {
     877              :                 //  Set so cascading errors don't happen
     878            0 :                 IsSplitter = false;
     879              :             }
     880          122 :             BComponents.deallocate();
     881              :         }
     882          122 :     }
     883              : 
     884          124 :     std::string GetFirstBranchInletNodeName(EnergyPlusData &state, std::string const &BranchListName) // Branch List name to search
     885              :     {
     886              : 
     887              :         // FUNCTION INFORMATION:
     888              :         //       AUTHOR         Linda K. Lawrie
     889              :         //       DATE WRITTEN   November 2004
     890              : 
     891              :         // PURPOSE OF THIS FUNCTION:
     892              :         // This function uses the branch structure to obtain the inlet node
     893              :         // of the first branch from referenced Branch List.
     894              : 
     895              :         // Return value
     896          124 :         std::string InletNodeName; // Inlet node name of first branch in branch list
     897              : 
     898          124 :         if (state.dataBranchInputManager->GetBranchListInputFlag) {
     899           15 :             state.dataBranchInputManager->GetBranchListInputFlag = false;
     900           15 :             GetBranchListInput(state);
     901              :         }
     902              : 
     903          124 :         int Found1 = Util::FindItemInList(BranchListName, state.dataBranchInputManager->BranchList);
     904          124 :         if (Found1 == 0) {
     905            0 :             ShowSevereError(state, format("GetFirstBranchInletNodeName: BranchList=\"{}\", not a valid BranchList Name", BranchListName));
     906            0 :             InletNodeName = "Invalid Node Name";
     907              :         } else {
     908          124 :             int Found2 = Util::FindItemInList(state.dataBranchInputManager->BranchList(Found1).BranchNames(1), state.dataBranchInputManager->Branch);
     909          124 :             if (Found2 == 0) {
     910            0 :                 ShowSevereError(state,
     911            0 :                                 format("GetFirstBranchInletNodeName: BranchList=\"{}\", Branch=\"{}\" not a valid Branch Name",
     912              :                                        BranchListName,
     913            0 :                                        state.dataBranchInputManager->BranchList(Found1).BranchNames(1)));
     914            0 :                 InletNodeName = "Invalid Node Name";
     915              :             } else {
     916          124 :                 InletNodeName = state.dataBranchInputManager->Branch(Found2).Component(1).InletNodeName;
     917              :             }
     918              :         }
     919              : 
     920          124 :         return InletNodeName;
     921            0 :     }
     922              : 
     923          124 :     std::string GetLastBranchOutletNodeName(EnergyPlusData &state, std::string const &BranchListName) // Branch List name to search
     924              :     {
     925              : 
     926              :         // FUNCTION INFORMATION:
     927              :         //       AUTHOR         Linda K. Lawrie
     928              :         //       DATE WRITTEN   August 2003
     929              : 
     930              :         // PURPOSE OF THIS FUNCTION:
     931              :         // This function uses the branch structure to obtain the outlet node
     932              :         // of the last branch from referenced Branch List.
     933              : 
     934              :         // Return value
     935          124 :         std::string OutletNodeName; // Outlet node name of last branch in branch list
     936              : 
     937          124 :         if (state.dataBranchInputManager->GetBranchListInputFlag) {
     938            0 :             state.dataBranchInputManager->GetBranchListInputFlag = false;
     939            0 :             GetBranchListInput(state);
     940              :         }
     941              : 
     942          124 :         int Found1 = Util::FindItemInList(BranchListName, state.dataBranchInputManager->BranchList);
     943          124 :         if (Found1 == 0) {
     944            0 :             ShowSevereError(state, format("GetLastBranchOutletNodeName: BranchList=\"{}\", not a valid BranchList Name", BranchListName));
     945            0 :             OutletNodeName = "Invalid Node Name";
     946              :         } else {
     947          124 :             int Found2 = Util::FindItemInList(
     948          124 :                 state.dataBranchInputManager->BranchList(Found1).BranchNames(state.dataBranchInputManager->BranchList(Found1).NumOfBranchNames),
     949          124 :                 state.dataBranchInputManager->Branch);
     950          124 :             if (Found2 == 0) {
     951            0 :                 ShowSevereError(state,
     952            0 :                                 format("GetLastBranchOutletNodeName: BranchList=\"{}\", Branch=\"{}\" not a valid Branch Name",
     953              :                                        BranchListName,
     954            0 :                                        state.dataBranchInputManager->BranchList(Found1).BranchNames(
     955            0 :                                            state.dataBranchInputManager->BranchList(Found1).NumOfBranchNames)));
     956            0 :                 OutletNodeName = "Invalid Node Name";
     957              :             } else {
     958          124 :                 OutletNodeName = state.dataBranchInputManager->Branch(Found2)
     959          124 :                                      .Component(state.dataBranchInputManager->Branch(Found2).NumOfComponents)
     960          124 :                                      .OutletNodeName;
     961              :             }
     962              :         }
     963              : 
     964          124 :         return OutletNodeName;
     965            0 :     }
     966              : 
     967              :     //==================================================================================
     968              :     //   Routines that get the input for the internal branch management structure
     969              :     //==================================================================================
     970              : 
     971          253 :     void GetBranchInput(EnergyPlusData &state)
     972              :     {
     973              : 
     974              :         // SUBROUTINE INFORMATION:
     975              :         //       AUTHOR         Linda K. Lawrie
     976              :         //       DATE WRITTEN   October 1999
     977              :         //       MODIFIED       October 2001, Automatic Extensibility
     978              : 
     979              :         // PURPOSE OF THIS SUBROUTINE:
     980              :         // This subroutine gets the input for the following IDD structure:
     981              :         // Branch,
     982              :         //         \extensible:4 Just duplicate last 4 fields and \ comments (changing numbering, please)
     983              :         //         \memo List components on the branch in simulation and connection order
     984              :         //         \memo Note: this should NOT include splitters or mixers which define
     985              :         //         \memo endpoints of branches
     986              :         //    A1,  \field Name
     987              :         //         \required-field
     988              :         //         \reference Branches
     989              :         //    N1, \field Maximum Flow Rate
     990              :         //         \default 0
     991              :         //         \units m3/s
     992              :         //         \minimum 0
     993              :         //         \autosizable
     994              :         //    A2, \field Pressure Curve Name
     995              :         //         \type object-list
     996              :         //         \reference AllCurves
     997              :         //    A3, \field Component 1 Object Type
     998              :         //         \required-field
     999              :         //    A4, \field Component 1 Name
    1000              :         //         \required-field
    1001              :         //    A5, \field Component 1 Inlet Node Name
    1002              :         //         \required-field
    1003              :         //    A6, \field Component 1 Outlet Node Name
    1004              :         //         \required-field
    1005              : 
    1006              :         // SUBROUTINE PARAMETER DEFINITIONS:
    1007              :         static constexpr std::string_view RoutineName("GetBranchInput: ");
    1008              : 
    1009              :         // INTERFACE BLOCK SPECIFICATIONS
    1010              :         // na
    1011              : 
    1012          253 :         Array1D_string Alphas;   // Used to retrieve names from IDF
    1013          253 :         Array1D_int NodeNums;    // Possible Array of Node Numbers (only 1 allowed)
    1014          253 :         Array1D<Real64> Numbers; // Used to retrieve numbers from IDF
    1015          253 :         Array1D_string cAlphaFields;
    1016          253 :         Array1D_string cNumericFields;
    1017          253 :         Array1D_bool lNumericBlanks;
    1018          253 :         Array1D_bool lAlphaBlanks;
    1019              : 
    1020          253 :         if (state.dataBranchInputManager->GetBranchInputOneTimeFlag) {
    1021          137 :             std::string CurrentModuleObject = "Branch";
    1022          137 :             int NumOfBranches = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
    1023              : 
    1024          137 :             if (NumOfBranches > 0) {
    1025           86 :                 state.dataBranchInputManager->Branch.allocate(NumOfBranches);
    1026              :                 int NumNumbers; // Used to retrieve numbers from IDF
    1027              :                 int NumAlphas;  // Used to retrieve names from IDF
    1028              :                 int NumParams;
    1029           86 :                 state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, "NodeList", NumParams, NumAlphas, NumNumbers);
    1030           86 :                 NodeNums.dimension(NumParams, 0);
    1031           86 :                 state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NumParams, NumAlphas, NumNumbers);
    1032           86 :                 Alphas.allocate(NumAlphas);
    1033           86 :                 Numbers.dimension(NumNumbers, 0.0);
    1034           86 :                 cAlphaFields.allocate(NumAlphas);
    1035           86 :                 cNumericFields.allocate(NumNumbers);
    1036           86 :                 lAlphaBlanks.dimension(NumAlphas, true);
    1037           86 :                 lNumericBlanks.dimension(NumNumbers, true);
    1038           86 :                 int BCount = 0; // Actual Num of Branches
    1039              :                 int IOStat;     // Could be used in the Get Routines, not currently checked
    1040          643 :                 for (int Count = 1; Count <= NumOfBranches; ++Count) {
    1041          557 :                     state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1042              :                                                                              CurrentModuleObject,
    1043              :                                                                              Count,
    1044              :                                                                              Alphas,
    1045              :                                                                              NumAlphas,
    1046              :                                                                              Numbers,
    1047              :                                                                              NumNumbers,
    1048              :                                                                              IOStat,
    1049              :                                                                              lNumericBlanks,
    1050              :                                                                              lAlphaBlanks,
    1051              :                                                                              cAlphaFields,
    1052              :                                                                              cNumericFields);
    1053          557 :                     ++BCount;
    1054          557 :                     GetSingleBranchInput(state, RoutineName, BCount, Alphas, cAlphaFields, NumAlphas, NodeNums, lAlphaBlanks);
    1055              :                 }
    1056              : 
    1057           86 :                 NumOfBranches = BCount;
    1058           86 :                 NodeNums.deallocate();
    1059           86 :                 Alphas.deallocate();
    1060           86 :                 Numbers.deallocate();
    1061           86 :                 cAlphaFields.deallocate();
    1062           86 :                 cNumericFields.deallocate();
    1063           86 :                 lAlphaBlanks.deallocate();
    1064           86 :                 lNumericBlanks.deallocate();
    1065           86 :                 TestInletOutletNodes(state);
    1066           86 :                 state.dataBranchInputManager->GetBranchInputOneTimeFlag = false;
    1067              :             }
    1068          137 :         }
    1069          253 :     }
    1070              : 
    1071          559 :     void GetSingleBranchInput(EnergyPlusData &state,
    1072              :                               std::string_view const RoutineName,
    1073              :                               int const BCount,
    1074              :                               Array1D_string const &Alphas,
    1075              :                               Array1D_string const &cAlphaFields,
    1076              :                               int const NumAlphas,
    1077              :                               Array1D_int &NodeNums,
    1078              :                               Array1D_bool const &lAlphaBlanks)
    1079              :     {
    1080              :         // Locals
    1081              :         PressureCurveType pressureCurveType;
    1082              :         int PressureCurveIndex;
    1083              :         bool ErrFound;                               // Flag for error detection
    1084              :         int Comp;                                    // Loop Counter
    1085              :         bool IsNotOK;                                // Flag to verify name
    1086              :         int NumInComps;                              // Number of components actually verified (no SPLITTER or MIXER allowed)
    1087              :         DataLoopNode::ConnectionType ConnectionType; // Used to pass variable node connection type to GetNodeNums
    1088              :         int NumNodes;                                // Number of Nodes from NodeInputManager
    1089              : 
    1090          559 :         std::string CurrentModuleObject = "Branch";
    1091              : 
    1092          559 :         state.dataBranchInputManager->Branch(BCount).Name = Alphas(1);
    1093          559 :         Curve::GetPressureCurveTypeAndIndex(state, Alphas(2), pressureCurveType, PressureCurveIndex);
    1094          559 :         if (pressureCurveType == DataBranchAirLoopPlant::PressureCurveType::Invalid) {
    1095            0 :             ShowSevereError(state, format("{}{}=\"{}\", invalid data.", RoutineName, CurrentModuleObject, Alphas(1)));
    1096            0 :             ShowContinueError(state, format("..Invalid {}=\"{}\".", cAlphaFields(2), Alphas(2)));
    1097            0 :             ShowContinueError(state, "This curve could not be found in the input deck.  Ensure that this curve has been entered");
    1098            0 :             ShowContinueError(state, " as either a Curve:Functional:PressureDrop or one of Curve:{Linear,Quadratic,Cubic,Exponent}");
    1099            0 :             ShowContinueError(state, "This error could be caused by a misspelled curve name");
    1100            0 :             ErrFound = true;
    1101              :         }
    1102          559 :         state.dataBranchInputManager->Branch(BCount).PressureCurveType = pressureCurveType;
    1103          559 :         state.dataBranchInputManager->Branch(BCount).PressureCurveIndex = PressureCurveIndex;
    1104          559 :         state.dataBranchInputManager->Branch(BCount).NumOfComponents = (NumAlphas - 2) / 4;
    1105          559 :         if (state.dataBranchInputManager->Branch(BCount).NumOfComponents * 4 != (NumAlphas - 2))
    1106            0 :             ++state.dataBranchInputManager->Branch(BCount).NumOfComponents;
    1107          559 :         NumInComps = state.dataBranchInputManager->Branch(BCount).NumOfComponents;
    1108          559 :         state.dataBranchInputManager->Branch(BCount).Component.allocate(state.dataBranchInputManager->Branch(BCount).NumOfComponents);
    1109          559 :         Comp = 1;
    1110         1255 :         for (int Loop = 3; Loop <= NumAlphas; Loop += 4) {
    1111          696 :             if (Util::SameString(Alphas(Loop), cSPLITTER) || Util::SameString(Alphas(Loop), cMIXER)) {
    1112            0 :                 ShowSevereError(state, format("{}{}=\"{}\", invalid data.", RoutineName, CurrentModuleObject, Alphas(1)));
    1113            0 :                 ShowContinueError(state, format("Connector:Splitter/Connector:Mixer not allowed in object {}", CurrentModuleObject));
    1114            0 :                 ErrFound = true;
    1115            0 :                 continue;
    1116              :             }
    1117          696 :             if (Comp > NumInComps) {
    1118            0 :                 ShowSevereError(state, format("{}{}=\"{}\", invalid data.", RoutineName, CurrentModuleObject, Alphas(1)));
    1119            0 :                 ShowContinueError(state, fmt::format("...Number of Arguments indicate [{}], but count of fields indicates [{}]", NumInComps, Comp));
    1120            0 :                 ShowContinueError(state, format("...examine {} carefully.", CurrentModuleObject));
    1121            0 :                 continue;
    1122              :             }
    1123          696 :             state.dataBranchInputManager->Branch(BCount).Component(Comp).CType = Alphas(Loop);
    1124          696 :             state.dataBranchInputManager->Branch(BCount).Component(Comp).Name = Alphas(Loop + 1);
    1125          696 :             ValidateComponent(state, Alphas(Loop), Alphas(Loop + 1), IsNotOK, CurrentModuleObject);
    1126          696 :             if (IsNotOK) {
    1127           27 :                 ShowContinueError(state, format("Occurs on {}={}", CurrentModuleObject, Alphas(1)));
    1128           27 :                 ErrFound = true;
    1129              :             }
    1130          696 :             state.dataBranchInputManager->Branch(BCount).Component(Comp).InletNodeName = Alphas(Loop + 2);
    1131              :             // If first component on branch, then inlet node is inlet to branch, otherwise node is internal
    1132          696 :             if (Loop == 3) {
    1133          559 :                 ConnectionType = DataLoopNode::ConnectionType::Inlet;
    1134              :             } else {
    1135          137 :                 ConnectionType = DataLoopNode::ConnectionType::Internal;
    1136              :             }
    1137          696 :             if (!lAlphaBlanks(Loop + 2)) {
    1138         1392 :                 GetNodeNums(state,
    1139          696 :                             state.dataBranchInputManager->Branch(BCount).Component(Comp).InletNodeName,
    1140              :                             NumNodes,
    1141              :                             NodeNums,
    1142              :                             ErrFound,
    1143              :                             DataLoopNode::NodeFluidType::Blank,
    1144              :                             DataLoopNode::ConnectionObjectType::Branch,
    1145          696 :                             state.dataBranchInputManager->Branch(BCount).Name,
    1146              :                             ConnectionType,
    1147              :                             NodeInputManager::CompFluidStream::Primary,
    1148              :                             ObjectIsParent,
    1149              :                             false,
    1150          696 :                             cAlphaFields(Loop + 2));
    1151          696 :                 if (NumNodes > 1) {
    1152            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid data.", RoutineName, CurrentModuleObject, Alphas(1)));
    1153            0 :                     ShowContinueError(state,
    1154            0 :                                       format("..invalid {}=\"{}\" must be a single node - appears to be a list.",
    1155              :                                              cAlphaFields(Loop + 2),
    1156            0 :                                              state.dataBranchInputManager->Branch(BCount).Component(Comp).InletNodeName));
    1157            0 :                     ShowContinueError(
    1158            0 :                         state, format("Occurs on {}=\"{}\", {}=\"{}\".", cAlphaFields(Loop), Alphas(Loop), cAlphaFields(Loop + 1), Alphas(Loop + 1)));
    1159            0 :                     ErrFound = true;
    1160              :                 } else {
    1161          696 :                     state.dataBranchInputManager->Branch(BCount).Component(Comp).InletNode = NodeNums(1);
    1162              :                 }
    1163              :             } else {
    1164            0 :                 ShowSevereError(state, format("{}{}=\"{}\", invalid data.", RoutineName, CurrentModuleObject, Alphas(1)));
    1165            0 :                 ShowContinueError(state, format("blank required field: {}", cAlphaFields(Loop + 2)));
    1166            0 :                 ShowContinueError(
    1167            0 :                     state, format("Occurs on {}=\"{}\", {}=\"{}\".", cAlphaFields(Loop), Alphas(Loop), cAlphaFields(Loop + 1), Alphas(Loop + 1)));
    1168            0 :                 ErrFound = true;
    1169              :             }
    1170          696 :             state.dataBranchInputManager->Branch(BCount).Component(Comp).OutletNodeName = Alphas(Loop + 3);
    1171              :             // If last component on branch, then outlet node is outlet from branch, otherwise node is internal
    1172          696 :             if (Loop == NumAlphas - 3) {
    1173          559 :                 ConnectionType = DataLoopNode::ConnectionType::Outlet;
    1174              :             } else {
    1175          137 :                 ConnectionType = DataLoopNode::ConnectionType::Internal;
    1176              :             }
    1177          696 :             if (!lAlphaBlanks(Loop + 3)) {
    1178         1392 :                 GetNodeNums(state,
    1179          696 :                             state.dataBranchInputManager->Branch(BCount).Component(Comp).OutletNodeName,
    1180              :                             NumNodes,
    1181              :                             NodeNums,
    1182              :                             ErrFound,
    1183              :                             DataLoopNode::NodeFluidType::Blank,
    1184              :                             DataLoopNode::ConnectionObjectType::Branch,
    1185          696 :                             state.dataBranchInputManager->Branch(BCount).Name,
    1186              :                             ConnectionType,
    1187              :                             NodeInputManager::CompFluidStream::Primary,
    1188              :                             ObjectIsParent,
    1189              :                             false,
    1190          696 :                             cAlphaFields(Loop + 3));
    1191          696 :                 if (NumNodes > 1) {
    1192            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid data.", RoutineName, CurrentModuleObject, Alphas(1)));
    1193            0 :                     ShowContinueError(state,
    1194            0 :                                       format("..invalid {}=\"{}\" must be a single node - appears to be a list.",
    1195              :                                              cAlphaFields(Loop + 2),
    1196            0 :                                              state.dataBranchInputManager->Branch(BCount).Component(Comp).InletNodeName));
    1197            0 :                     ShowContinueError(
    1198            0 :                         state, format("Occurs on {}=\"{}\", {}=\"{}\".", cAlphaFields(Loop), Alphas(Loop), cAlphaFields(Loop + 1), Alphas(Loop + 1)));
    1199            0 :                     ErrFound = true;
    1200              :                 } else {
    1201          696 :                     state.dataBranchInputManager->Branch(BCount).Component(Comp).OutletNode = NodeNums(1);
    1202              :                 }
    1203              :             } else {
    1204            0 :                 ShowSevereError(state, format("{}{}=\"{}\", invalid data.", RoutineName, CurrentModuleObject, Alphas(1)));
    1205            0 :                 ShowContinueError(state, format("blank required field: {}", cAlphaFields(Loop + 3)));
    1206            0 :                 ShowContinueError(
    1207            0 :                     state, format("Occurs on {}=\"{}\", {}=\"{}\".", cAlphaFields(Loop), Alphas(Loop), cAlphaFields(Loop + 1), Alphas(Loop + 1)));
    1208            0 :                 ErrFound = true;
    1209              :             }
    1210              : 
    1211          696 :             if (!lAlphaBlanks(Loop) && !lAlphaBlanks(Loop + 1) && !lAlphaBlanks(Loop + 2) && !lAlphaBlanks(Loop + 3))
    1212         1392 :                 SetUpCompSets(state,
    1213              :                               CurrentModuleObject,
    1214          696 :                               state.dataBranchInputManager->Branch(BCount).Name,
    1215          696 :                               Alphas(Loop),
    1216          696 :                               Alphas(Loop + 1),
    1217          696 :                               Alphas(Loop + 2),
    1218          696 :                               Alphas(Loop + 3)); // no blanks in required field set
    1219              : 
    1220          696 :             ++Comp;
    1221              :         }
    1222          559 :         state.dataBranchInputManager->Branch(BCount).NumOfComponents = NumInComps;
    1223          559 :     }
    1224              : 
    1225          136 :     void GetBranchListInput(EnergyPlusData &state)
    1226              :     {
    1227              : 
    1228              :         // SUBROUTINE INFORMATION:
    1229              :         //       AUTHOR         Linda K. Lawrie
    1230              :         //       DATE WRITTEN   July 2003
    1231              : 
    1232              :         // PURPOSE OF THIS SUBROUTINE:
    1233              :         // This subroutine gets the branch list input and fills up the structures for
    1234              :         // branch lists.
    1235              :         // This subroutine gets the input for the following IDD structure:
    1236              :         // BRANCH LIST,
    1237              :         //  \extensible:1 Just duplicate last field and \ comments (changing numbering, please)
    1238              :         //  \memo Branches MUST be listed in flow order: inlet branch, then parallel branches, then outlet branch.
    1239              :         //  \memo Branches are simulated in the order listed.  Branch names cannot be duplicated within a single branch list.
    1240              :         //    A1, \field Branch List Name
    1241              :         //        \required-field
    1242              :         //        \reference BranchLists
    1243              :         //    A2, \field Branch Name 1
    1244              :         //        \required-field
    1245              :         //        \type object-list
    1246              :         //        \object-list Branches
    1247              :         //    A3, \field Branch Name 2
    1248              :         //        \type object-list
    1249              :         //        \object-list Branches
    1250              : 
    1251              :         // Using/Aliasing
    1252              : 
    1253              :         // SUBROUTINE PARAMETER DEFINITIONS:
    1254              :         static constexpr std::string_view RoutineName("GetBranchListInput: ");
    1255              : 
    1256              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1257              :         int Count;     // Loop Counter
    1258              :         int BCount;    // Actual Branch List Count
    1259              :         int Loop;      // Loop Counter
    1260              :         int Found;     // Points to correct Branch List/Branch
    1261              :         bool ErrFound; // True when error has occurred (cannot find Branch List)
    1262              :         // Following are needed because routine calls GetBranchInput
    1263              :         // which would overwrite the module Alphas and NumAlphas
    1264              :         int NumAlphas;         // Used to retrieve Branch list from IDF
    1265          136 :         Array1D_string Alphas; // Used to retrieve names from IDF
    1266              :         int NumNumbers;
    1267          136 :         Array1D<Real64> Numbers; // Not used in this object
    1268          136 :         Array1D_string cAlphaFields;
    1269          136 :         Array1D_string cNumericFields;
    1270          136 :         Array1D_bool lNumericBlanks;
    1271          136 :         Array1D_bool lAlphaBlanks;
    1272              :         int IOStat; // Could be used in the Get Routines, not currently checked
    1273              :         int NumParams;
    1274          136 :         std::string TestName;
    1275              : 
    1276          136 :         ErrFound = false;
    1277          136 :         std::string CurrentModuleObject = "BranchList";
    1278          136 :         int NumOfBranchLists = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
    1279          136 :         state.dataBranchInputManager->BranchList.allocate(NumOfBranchLists);
    1280          136 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NumParams, NumAlphas, NumNumbers);
    1281          136 :         Alphas.allocate(NumAlphas);
    1282          136 :         Numbers.dimension(NumNumbers, 0.0);
    1283          136 :         cAlphaFields.allocate(NumAlphas);
    1284          136 :         cNumericFields.allocate(NumNumbers);
    1285          136 :         lAlphaBlanks.dimension(NumAlphas, true);
    1286          136 :         lNumericBlanks.dimension(NumNumbers, true);
    1287              : 
    1288          136 :         if (NumNumbers > 0) {
    1289            0 :             ShowSevereError(state,
    1290            0 :                             format("{}{} Object definition contains numbers, cannot be decoded by GetBranchListInput routine.",
    1291              :                                    RoutineName,
    1292              :                                    CurrentModuleObject));
    1293            0 :             ErrFound = true;
    1294              :         }
    1295          136 :         BCount = 0;
    1296          324 :         for (Count = 1; Count <= NumOfBranchLists; ++Count) {
    1297          188 :             CurrentModuleObject = "BranchList";
    1298          188 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1299              :                                                                      CurrentModuleObject,
    1300              :                                                                      Count,
    1301              :                                                                      Alphas,
    1302              :                                                                      NumAlphas,
    1303              :                                                                      Numbers,
    1304              :                                                                      NumNumbers,
    1305              :                                                                      IOStat,
    1306              :                                                                      lNumericBlanks,
    1307              :                                                                      lAlphaBlanks,
    1308              :                                                                      cAlphaFields,
    1309              :                                                                      cNumericFields);
    1310              : 
    1311          188 :             ++BCount;
    1312          188 :             state.dataBranchInputManager->BranchList(BCount).Name = Alphas(1);
    1313          188 :             state.dataBranchInputManager->BranchList(BCount).NumOfBranchNames = NumAlphas - 1;
    1314          188 :             state.dataBranchInputManager->BranchList(BCount).BranchNames.allocate(NumAlphas - 1);
    1315          188 :             if (state.dataBranchInputManager->BranchList(BCount).NumOfBranchNames == 0) {
    1316            0 :                 ShowSevereError(state,
    1317            0 :                                 format("{}{}=\"{}\", No branch names entered.",
    1318              :                                        RoutineName,
    1319              :                                        CurrentModuleObject,
    1320            0 :                                        state.dataBranchInputManager->BranchList(BCount).Name));
    1321            0 :                 ErrFound = true;
    1322              :             } else {
    1323          188 :                 state.dataBranchInputManager->BranchList(BCount).BranchNames({1, NumAlphas - 1}) = Alphas({2, NumAlphas});
    1324          747 :                 for (Loop = 1; Loop <= state.dataBranchInputManager->BranchList(BCount).NumOfBranchNames; ++Loop) {
    1325              :                     // If NumOfBranches = 0 then Branches haven't been read yet.
    1326          559 :                     if ((int)state.dataBranchInputManager->Branch.size() == 0) {
    1327           31 :                         GetBranchInput(state);
    1328              :                     }
    1329          559 :                     if (!state.dataBranchInputManager->BranchList(BCount).BranchNames(Loop).empty()) {
    1330          559 :                         Found = Util::FindItemInList(state.dataBranchInputManager->BranchList(BCount).BranchNames(Loop),
    1331          559 :                                                      state.dataBranchInputManager->Branch);
    1332          559 :                         if (Found == 0) {
    1333            8 :                             ShowSevereError(state,
    1334            8 :                                             format("{}{}=\"{}\", invalid data.",
    1335              :                                                    RoutineName,
    1336              :                                                    CurrentModuleObject,
    1337            4 :                                                    state.dataBranchInputManager->BranchList(BCount).Name));
    1338            8 :                             ShowContinueError(state,
    1339            8 :                                               format("..invalid Branch Name not found=\"{}\".",
    1340            4 :                                                      state.dataBranchInputManager->BranchList(BCount).BranchNames(Loop)));
    1341            4 :                             ErrFound = true;
    1342              :                         }
    1343              :                     }
    1344              :                 }
    1345              :             }
    1346              :         }
    1347              : 
    1348              :         // Check for duplicate names specified in Branch Lists
    1349          324 :         for (Count = 1; Count <= NumOfBranchLists; ++Count) {
    1350          188 :             if (state.dataBranchInputManager->BranchList(Count).NumOfBranchNames == 0) continue;
    1351          188 :             TestName = state.dataBranchInputManager->BranchList(Count).BranchNames(1);
    1352          559 :             for (Loop = 2; Loop <= state.dataBranchInputManager->BranchList(Count).NumOfBranchNames; ++Loop) {
    1353          371 :                 if (TestName != state.dataBranchInputManager->BranchList(Count).BranchNames(Loop)) continue;
    1354            0 :                 ShowSevereError(
    1355              :                     state,
    1356            0 :                     format("{}{}=\"{}\", invalid data.", RoutineName, CurrentModuleObject, state.dataBranchInputManager->BranchList(BCount).Name));
    1357            0 :                 ShowContinueError(state, "..invalid: duplicate branch name specified in the list.");
    1358            0 :                 ShowContinueError(state, format("..Branch Name={}", TestName));
    1359            0 :                 ShowContinueError(state, fmt::format("..Branch Name #{} is duplicate.", Loop));
    1360            0 :                 ErrFound = true;
    1361              :             }
    1362              :         }
    1363              : 
    1364          136 :         if (ErrFound) {
    1365            1 :             ShowSevereError(state, format("{} Invalid Input -- preceding condition(s) will likely cause termination.", RoutineName));
    1366              :         }
    1367          136 :         NumOfBranchLists = BCount;
    1368          136 :         Alphas.deallocate();
    1369          136 :         Numbers.deallocate();
    1370          136 :         cAlphaFields.deallocate();
    1371          136 :         cNumericFields.deallocate();
    1372          136 :         lAlphaBlanks.deallocate();
    1373          136 :         lNumericBlanks.deallocate();
    1374          136 :     }
    1375              : 
    1376           43 :     void GetConnectorListInput(EnergyPlusData &state)
    1377              :     {
    1378              : 
    1379              :         // SUBROUTINE INFORMATION:
    1380              :         //       AUTHOR         Linda K. Lawrie
    1381              :         //       DATE WRITTEN   October 1999
    1382              : 
    1383              :         // PURPOSE OF THIS SUBROUTINE:
    1384              :         // Obtains connector list input from IDF.
    1385              :         // ConnectorList,
    1386              :         //         \memo only two connectors allowed per loop
    1387              :         //         \memo if two entered, one must be Connector:Splitter and one must be Connector:Mixer
    1388              :         //     A1, \field Name
    1389              :         //         \required-field
    1390              :         //         \reference ConnectorLists
    1391              :         //     A2, \field Connector 1 Object Type
    1392              :         //         \required-field
    1393              :         //         \key Connector:Splitter
    1394              :         //         \key Connector:Mixer
    1395              :         //     A3, \field Connector 1 Name
    1396              :         //         \required-field
    1397              :         //     A4, \field Connector 2 Object Type
    1398              :         //         \key Connector:Splitter
    1399              :         //         \key Connector:Mixer
    1400              :         //     A5; \field Connector 2 Name
    1401              :         //  This is in the process of possibly being extended, thus the code herein.
    1402              : 
    1403              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1404              :         int Count;               // Loop Counter
    1405              :         int NumAlphas;           // Used to retrieve names from IDF
    1406           43 :         Array1D_string Alphas;   // Used to retrieve names from IDF
    1407              :         int NumNumbers;          // Used to retrieve numbers from IDF
    1408           43 :         Array1D<Real64> Numbers; // Used to retrieve numbers from IDF
    1409           43 :         Array1D_string cAlphaFields;
    1410           43 :         Array1D_string cNumericFields;
    1411           43 :         Array1D_bool lNumericBlanks;
    1412           43 :         Array1D_bool lAlphaBlanks;
    1413              :         int IOStat; // Could be used in the Get Routines, not currently checked
    1414              :         int NumParams;
    1415              :         int Arg;
    1416              :         int SplitNum;
    1417              :         int MixerNum;
    1418           43 :         Array1D_string BranchNames;
    1419              :         int NumBranchNames;
    1420              :         bool ErrorsFound;
    1421              :         int Loop;
    1422              :         int Loop1;
    1423              :         int Loop2;
    1424              :         bool CurMixer;
    1425              :         bool CurSplitter;
    1426              :         int TestNum;
    1427              :         bool MatchFound;
    1428              : 
    1429           43 :         if (!state.dataBranchInputManager->GetConnectorListInputFlag) return;
    1430           43 :         ErrorsFound = false;
    1431           43 :         std::string CurrentModuleObject = "ConnectorList";
    1432           43 :         int NumOfConnectorLists = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
    1433           43 :         state.dataBranchInputManager->ConnectorLists.allocate(NumOfConnectorLists);
    1434           43 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NumParams, NumAlphas, NumNumbers);
    1435           43 :         if (NumAlphas != 5 || NumNumbers != 0) {
    1436            0 :             ShowWarningError(state,
    1437            0 :                              format("GetConnectorList: Illegal \"extension\" to {} object. Internal code does not support > 2 connectors "
    1438              :                                     "(Connector:Splitter and Connector:Mixer)",
    1439              :                                     CurrentModuleObject));
    1440              :         }
    1441           43 :         Alphas.allocate(NumAlphas);
    1442           43 :         Numbers.dimension(NumNumbers, 0.0);
    1443           43 :         cAlphaFields.allocate(NumAlphas);
    1444           43 :         cNumericFields.allocate(NumNumbers);
    1445           43 :         lAlphaBlanks.dimension(NumAlphas, true);
    1446           43 :         lNumericBlanks.dimension(NumNumbers, true);
    1447          165 :         for (Count = 1; Count <= NumOfConnectorLists; ++Count) {
    1448          122 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1449              :                                                                      CurrentModuleObject,
    1450              :                                                                      Count,
    1451              :                                                                      Alphas,
    1452              :                                                                      NumAlphas,
    1453              :                                                                      Numbers,
    1454              :                                                                      NumNumbers,
    1455              :                                                                      IOStat,
    1456              :                                                                      lNumericBlanks,
    1457              :                                                                      lAlphaBlanks,
    1458              :                                                                      cAlphaFields,
    1459              :                                                                      cNumericFields);
    1460          122 :             state.dataBranchInputManager->ConnectorLists(Count).Name = Alphas(1);
    1461          122 :             int NumConnectors = (NumAlphas - 1) / 2; // potential problem if puts in type but not name
    1462          122 :             if (mod(NumAlphas - 1, 2) != 0) ++NumConnectors;
    1463          122 :             state.dataBranchInputManager->ConnectorLists(Count).NumOfConnectors = NumConnectors;
    1464          122 :             state.dataBranchInputManager->ConnectorLists(Count).ConnectorType.allocate(NumConnectors);
    1465          122 :             state.dataBranchInputManager->ConnectorLists(Count).ConnectorName.allocate(NumConnectors);
    1466          122 :             state.dataBranchInputManager->ConnectorLists(Count).ConnectorMatchNo.allocate(NumConnectors);
    1467          244 :             state.dataBranchInputManager->ConnectorLists(Count).ConnectorType = "UNKNOWN";
    1468          122 :             state.dataBranchInputManager->ConnectorLists(Count).ConnectorName = "UNKNOWN";
    1469          122 :             state.dataBranchInputManager->ConnectorLists(Count).ConnectorMatchNo = 0;
    1470          122 :             state.dataBranchInputManager->ConnectorLists(Count).NumOfSplitters = 0;
    1471          122 :             state.dataBranchInputManager->ConnectorLists(Count).NumOfMixers = 0;
    1472              : 
    1473          122 :             int CCount = 0;
    1474          366 :             for (Arg = 2; Arg <= NumAlphas; Arg += 2) {
    1475          244 :                 ++CCount;
    1476          244 :                 if (Util::SameString(Alphas(Arg), cSPLITTER)) {
    1477          122 :                     state.dataBranchInputManager->ConnectorLists(Count).ConnectorType(CCount) = Alphas(Arg).substr(0, 30);
    1478          122 :                     ++state.dataBranchInputManager->ConnectorLists(Count).NumOfSplitters;
    1479          122 :                 } else if (Util::SameString(Alphas(Arg), cMIXER)) {
    1480          122 :                     state.dataBranchInputManager->ConnectorLists(Count).ConnectorType(CCount) = Alphas(Arg).substr(0, 30);
    1481          122 :                     ++state.dataBranchInputManager->ConnectorLists(Count).NumOfMixers;
    1482              :                 } else {
    1483            0 :                     ShowWarningError(
    1484              :                         state,
    1485            0 :                         format("GetConnectorListInput: Invalid {}={} in {}={}", cAlphaFields(Arg), Alphas(Arg), CurrentModuleObject, Alphas(1)));
    1486              :                 }
    1487          244 :                 state.dataBranchInputManager->ConnectorLists(Count).ConnectorName(CCount) = Alphas(Arg + 1);
    1488              :             }
    1489              :         }
    1490           43 :         state.dataBranchInputManager->GetConnectorListInputFlag = false;
    1491           43 :         Alphas.deallocate();
    1492           43 :         Numbers.deallocate();
    1493           43 :         cAlphaFields.deallocate();
    1494           43 :         cNumericFields.deallocate();
    1495           43 :         lAlphaBlanks.deallocate();
    1496           43 :         lNumericBlanks.deallocate();
    1497              : 
    1498              :         // Validity checks on Connector Lists
    1499           43 :         if (state.dataBranchInputManager->GetSplitterInputFlag) {
    1500           43 :             GetSplitterInput(state);
    1501           43 :             state.dataBranchInputManager->GetSplitterInputFlag = false;
    1502              :         }
    1503           43 :         if (state.dataBranchInputManager->GetMixerInputFlag) {
    1504           43 :             GetMixerInput(state);
    1505           43 :             state.dataBranchInputManager->GetMixerInputFlag = false;
    1506              :         }
    1507              : 
    1508           43 :         SplitNum = 0;
    1509           43 :         MixerNum = 0;
    1510          165 :         for (Count = 1; Count <= NumOfConnectorLists; ++Count) {
    1511          122 :             if (state.dataBranchInputManager->ConnectorLists(Count).NumOfConnectors <= 1) continue; // Air Loop only has one.
    1512          122 :             if (state.dataBranchInputManager->ConnectorLists(Count).NumOfConnectors > 2) continue;  // Rules not clear for this case
    1513          366 :             for (Loop = 1; Loop <= state.dataBranchInputManager->ConnectorLists(Count).NumOfConnectors; ++Loop) {
    1514          244 :                 if (state.dataBranchInputManager->ConnectorLists(Count).ConnectorMatchNo(Loop) != 0) continue;
    1515          122 :                 if (Util::SameString(state.dataBranchInputManager->ConnectorLists(Count).ConnectorType(Loop), cSPLITTER)) {
    1516          122 :                     CurSplitter = true;
    1517          122 :                     CurMixer = false;
    1518          122 :                     SplitNum = Util::FindItemInList(state.dataBranchInputManager->ConnectorLists(Count).ConnectorName(Loop),
    1519          122 :                                                     state.dataBranchInputManager->Splitters);
    1520              :                     // Following code sets up branch names to be matched from Splitter/Mixer data structure
    1521          122 :                     if (SplitNum == 0) {
    1522            0 :                         ShowSevereError(state,
    1523            0 :                                         format("Invalid Connector:Splitter(none)={}, referenced by {}={}",
    1524            0 :                                                state.dataBranchInputManager->ConnectorLists(Count).ConnectorName(Loop),
    1525              :                                                CurrentModuleObject,
    1526            0 :                                                state.dataBranchInputManager->ConnectorLists(Count).Name));
    1527            0 :                         ErrorsFound = true;
    1528            0 :                         continue;
    1529              :                     }
    1530          122 :                     NumBranchNames = state.dataBranchInputManager->Splitters(SplitNum).NumOutletBranches;
    1531          122 :                     BranchNames = state.dataBranchInputManager->Splitters(SplitNum).OutletBranchNames;
    1532            0 :                 } else if (Util::SameString(state.dataBranchInputManager->ConnectorLists(Count).ConnectorType(Loop), cMIXER)) {
    1533            0 :                     CurSplitter = true;
    1534            0 :                     CurMixer = false;
    1535            0 :                     MixerNum = Util::FindItemInList(state.dataBranchInputManager->ConnectorLists(Count).ConnectorName(Loop),
    1536            0 :                                                     state.dataBranchInputManager->Mixers);
    1537            0 :                     if (MixerNum == 0) {
    1538            0 :                         ShowSevereError(state,
    1539            0 :                                         format("Invalid Connector:Mixer(none)={}, referenced by {}={}",
    1540            0 :                                                state.dataBranchInputManager->ConnectorLists(Count).ConnectorName(Loop),
    1541              :                                                CurrentModuleObject,
    1542            0 :                                                state.dataBranchInputManager->ConnectorLists(Count).Name));
    1543            0 :                         ErrorsFound = true;
    1544            0 :                         continue;
    1545              :                     }
    1546            0 :                     NumBranchNames = state.dataBranchInputManager->Mixers(MixerNum).NumInletBranches;
    1547            0 :                     BranchNames = state.dataBranchInputManager->Mixers(MixerNum).InletBranchNames;
    1548              :                 } else {
    1549            0 :                     continue;
    1550              :                 }
    1551              :                 // Try to match mixer to splitter
    1552          244 :                 for (Loop1 = Loop + 1; Loop1 <= state.dataBranchInputManager->ConnectorLists(Count).NumOfConnectors; ++Loop1) {
    1553          122 :                     if (CurMixer && !Util::SameString(state.dataBranchInputManager->ConnectorLists(Count).ConnectorType(Loop1), cSPLITTER)) continue;
    1554          122 :                     if (CurSplitter && !Util::SameString(state.dataBranchInputManager->ConnectorLists(Count).ConnectorType(Loop1), cMIXER)) continue;
    1555          122 :                     if (state.dataBranchInputManager->ConnectorLists(Count).ConnectorMatchNo(Loop1) != 0) continue;
    1556              :                     {
    1557          122 :                         if (CurSplitter) {
    1558              :                             // Current "item" is a splitter, candidate is a mixer.
    1559          122 :                             MixerNum = Util::FindItemInList(state.dataBranchInputManager->ConnectorLists(Count).ConnectorName(Loop1),
    1560          122 :                                                             state.dataBranchInputManager->Mixers);
    1561          122 :                             if (MixerNum == 0) continue;
    1562          122 :                             if (state.dataBranchInputManager->Mixers(MixerNum).NumInletBranches != NumBranchNames) continue;
    1563          122 :                             MatchFound = true;
    1564          364 :                             for (Loop2 = 1; Loop2 <= state.dataBranchInputManager->Mixers(MixerNum).NumInletBranches; ++Loop2) {
    1565          242 :                                 TestNum = Util::FindItemInList(
    1566          242 :                                     state.dataBranchInputManager->Mixers(MixerNum).InletBranchNames(Loop2), BranchNames, NumBranchNames);
    1567          242 :                                 if (TestNum == 0) {
    1568            0 :                                     MatchFound = false;
    1569            0 :                                     break;
    1570              :                                 }
    1571              :                             }
    1572          122 :                             if (MatchFound) {
    1573          122 :                                 state.dataBranchInputManager->ConnectorLists(Count).ConnectorMatchNo(Loop1) = MixerNum;
    1574          122 :                                 state.dataBranchInputManager->ConnectorLists(Count).ConnectorMatchNo(Loop) = SplitNum;
    1575              :                             }
    1576              :                         } else {
    1577              :                             // Current "item" is a splitter, candidate is a mixer.
    1578            0 :                             SplitNum = Util::FindItemInList(state.dataBranchInputManager->ConnectorLists(Count).ConnectorName(Loop1),
    1579            0 :                                                             state.dataBranchInputManager->Splitters);
    1580            0 :                             if (SplitNum == 0) continue;
    1581            0 :                             if (state.dataBranchInputManager->Splitters(SplitNum).NumOutletBranches != NumBranchNames) continue;
    1582            0 :                             MatchFound = true;
    1583            0 :                             for (Loop2 = 1; Loop2 <= state.dataBranchInputManager->Splitters(SplitNum).NumOutletBranches; ++Loop2) {
    1584            0 :                                 TestNum = Util::FindItemInList(
    1585            0 :                                     state.dataBranchInputManager->Splitters(SplitNum).OutletBranchNames(Loop2), BranchNames, NumBranchNames);
    1586            0 :                                 if (TestNum == 0) {
    1587            0 :                                     MatchFound = false;
    1588            0 :                                     break;
    1589              :                                 }
    1590              :                             }
    1591            0 :                             if (MatchFound) {
    1592            0 :                                 state.dataBranchInputManager->ConnectorLists(Count).ConnectorMatchNo(Loop1) = SplitNum;
    1593            0 :                                 state.dataBranchInputManager->ConnectorLists(Count).ConnectorMatchNo(Loop) = MixerNum;
    1594              :                             }
    1595              :                         }
    1596              :                     }
    1597              :                 }
    1598          122 :                 BranchNames.deallocate();
    1599              :             }
    1600              :         }
    1601              : 
    1602          165 :         for (Count = 1; Count <= NumOfConnectorLists; ++Count) {
    1603          122 :             if (state.dataBranchInputManager->ConnectorLists(Count).NumOfConnectors <= 1) continue; // Air Loop only has one.
    1604          122 :             if (state.dataBranchInputManager->ConnectorLists(Count).NumOfConnectors > 2) continue;  // Rules not clear
    1605          366 :             for (Loop = 1; Loop <= state.dataBranchInputManager->ConnectorLists(Count).NumOfConnectors; ++Loop) {
    1606          244 :                 if (state.dataBranchInputManager->ConnectorLists(Count).ConnectorMatchNo(Loop) != 0) continue;
    1607              :                 //  = 0, not matched.
    1608            0 :                 ShowSevereError(state, format("For {}={}", CurrentModuleObject, state.dataBranchInputManager->ConnectorLists(Count).Name));
    1609            0 :                 ShowContinueError(state,
    1610            0 :                                   format("...Item={}, Type={} was not matched.",
    1611            0 :                                          state.dataBranchInputManager->ConnectorLists(Count).ConnectorName(Loop),
    1612            0 :                                          state.dataBranchInputManager->ConnectorLists(Count).ConnectorType(Loop)));
    1613            0 :                 if (Util::SameString(state.dataBranchInputManager->ConnectorLists(Count).ConnectorType(Loop), "Connector:Splitter")) {
    1614            0 :                     ShowContinueError(
    1615              :                         state, "The BranchList for this Connector:Splitter does not match the BranchList for its corresponding Connector:Mixer.");
    1616              :                 } else {
    1617            0 :                     ShowContinueError(
    1618              :                         state, "The BranchList for this Connector:Mixer does not match the BranchList for its corresponding Connector:Splitter.");
    1619              :                 }
    1620            0 :                 ErrorsFound = true;
    1621              :             }
    1622              :         }
    1623              : 
    1624           43 :         if (ErrorsFound) {
    1625            0 :             ShowFatalError(state, "GetConnectorListInput: Program terminates for preceding conditions.");
    1626              :         }
    1627           43 :     }
    1628              : 
    1629           43 :     void GetSplitterInput(EnergyPlusData &state)
    1630              :     {
    1631              : 
    1632              :         // SUBROUTINE INFORMATION:
    1633              :         //       AUTHOR         Linda Lawrie
    1634              :         //       DATE WRITTEN   Sept 2005 (moved from GetLoopSplitter)
    1635              : 
    1636              :         // PURPOSE OF THIS SUBROUTINE:
    1637              :         // Gets the Splitter data that is used in Loops.
    1638              :         // IDD structure:
    1639              :         // Connector:Splitter,
    1640              :         //   \min-fields 3
    1641              :         //        \extensible:1 Just duplicate last field and \ comments (changing numbering, please)
    1642              :         //        \memo Split one air/water stream into N outlet streams.  Branch names cannot be duplicated
    1643              :         //        \memo within a single Splitter list.
    1644              :         //    A1, \field Name
    1645              :         //         \required-field
    1646              :         //    A2, \field Inlet Branch Name
    1647              :         //         \required-field
    1648              :         //         \type object-list
    1649              :         //         \object-list Branches
    1650              :         //    A3, \field Outlet Branch 1 Name
    1651              :         //         \required-field
    1652              :         //         \type object-list
    1653              :         //         \object-list Branches
    1654              :         //    A4, \field Outlet Branch 2 Name
    1655              :         //         \type object-list
    1656              :         //         \object-list Branches
    1657              : 
    1658              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1659              :         int NumAlphas;           // Used to retrieve names from IDF
    1660           43 :         Array1D_string Alphas;   // Used to retrieve names from IDF
    1661              :         int NumNumbers;          // Used to retrieve numbers from IDF
    1662           43 :         Array1D<Real64> Numbers; // Used to retrieve numbers from IDF
    1663           43 :         Array1D_string cAlphaFields;
    1664           43 :         Array1D_string cNumericFields;
    1665           43 :         Array1D_bool lNumericBlanks;
    1666           43 :         Array1D_bool lAlphaBlanks;
    1667              :         int IOStat; // Could be used in the Get Routines, not currently checked
    1668              :         int NumParams;
    1669              :         int Loop;
    1670              :         int Loop1;
    1671              :         int Count;
    1672           43 :         bool ErrorsFound(false);
    1673           43 :         std::string TestName;
    1674           43 :         std::string FoundSupplyDemandAir;
    1675           43 :         std::string SaveSupplyDemandAir;
    1676           43 :         std::string FoundLoop;
    1677           43 :         std::string SaveLoop;
    1678              :         bool MatchedLoop;
    1679              : 
    1680           43 :         if (!state.dataBranchInputManager->GetSplitterInputFlag) return;
    1681           43 :         std::string CurrentModuleObject = cSPLITTER;
    1682           43 :         int NumSplitters = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
    1683           43 :         state.dataBranchInputManager->Splitters.allocate(NumSplitters);
    1684           43 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NumParams, NumAlphas, NumNumbers);
    1685           43 :         Alphas.allocate(NumAlphas);
    1686           43 :         Numbers.dimension(NumNumbers, 0.0);
    1687           43 :         cAlphaFields.allocate(NumAlphas);
    1688           43 :         cNumericFields.allocate(NumNumbers);
    1689           43 :         lAlphaBlanks.dimension(NumAlphas, true);
    1690           43 :         lNumericBlanks.dimension(NumNumbers, true);
    1691          165 :         for (Count = 1; Count <= NumSplitters; ++Count) {
    1692          122 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1693              :                                                                      CurrentModuleObject,
    1694              :                                                                      Count,
    1695              :                                                                      Alphas,
    1696              :                                                                      NumAlphas,
    1697              :                                                                      Numbers,
    1698              :                                                                      NumNumbers,
    1699              :                                                                      IOStat,
    1700              :                                                                      lNumericBlanks,
    1701              :                                                                      lAlphaBlanks,
    1702              :                                                                      cAlphaFields,
    1703              :                                                                      cNumericFields);
    1704          122 :             state.dataBranchInputManager->Splitters(Count).Name = Alphas(1);
    1705          122 :             state.dataBranchInputManager->Splitters(Count).InletBranchName = Alphas(2);
    1706          122 :             state.dataBranchInputManager->Splitters(Count).NumOutletBranches = NumAlphas - 2;
    1707          244 :             state.dataBranchInputManager->Splitters(Count).OutletBranchNames.allocate(
    1708          122 :                 state.dataBranchInputManager->Splitters(Count).NumOutletBranches);
    1709          364 :             for (Loop = 1; Loop <= state.dataBranchInputManager->Splitters(Count).NumOutletBranches; ++Loop) {
    1710          242 :                 state.dataBranchInputManager->Splitters(Count).OutletBranchNames(Loop) = Alphas(2 + Loop);
    1711              :             }
    1712              :         }
    1713           43 :         state.dataBranchInputManager->GetSplitterInputFlag = false;
    1714           43 :         Alphas.deallocate();
    1715           43 :         Numbers.deallocate();
    1716           43 :         cAlphaFields.deallocate();
    1717           43 :         cNumericFields.deallocate();
    1718           43 :         lAlphaBlanks.deallocate();
    1719           43 :         lNumericBlanks.deallocate();
    1720              : 
    1721              :         // More validity -- check splitter "names" against branches.
    1722           43 :         if (!state.dataBranchInputManager->GetBranchInputFlag) {
    1723           43 :             GetBranchInput(state);
    1724           43 :             state.dataBranchInputManager->GetBranchInputFlag = false;
    1725              :         }
    1726          165 :         for (Count = 1; Count <= NumSplitters; ++Count) {
    1727          122 :             int Found = Util::FindItemInList(state.dataBranchInputManager->Splitters(Count).InletBranchName, state.dataBranchInputManager->Branch);
    1728          122 :             if (Found == 0) {
    1729            0 :                 ShowSevereError(state,
    1730            0 :                                 format("GetSplitterInput: Invalid Branch={}, referenced as Inlet Branch to {}={}",
    1731            0 :                                        state.dataBranchInputManager->Splitters(Count).InletBranchName,
    1732              :                                        CurrentModuleObject,
    1733            0 :                                        state.dataBranchInputManager->Splitters(Count).Name));
    1734            0 :                 ErrorsFound = true;
    1735              :             }
    1736          364 :             for (Loop = 1; Loop <= state.dataBranchInputManager->Splitters(Count).NumOutletBranches; ++Loop) {
    1737          242 :                 Found = Util::FindItemInList(state.dataBranchInputManager->Splitters(Count).OutletBranchNames(Loop),
    1738          242 :                                              state.dataBranchInputManager->Branch);
    1739          242 :                 if (Found == 0) {
    1740            0 :                     ShowSevereError(state,
    1741            0 :                                     fmt::format("GetSplitterInput: Invalid Branch={}, referenced as Outlet Branch # {} to {}={}",
    1742            0 :                                                 state.dataBranchInputManager->Splitters(Count).OutletBranchNames(Loop),
    1743              :                                                 Loop,
    1744              :                                                 CurrentModuleObject,
    1745            0 :                                                 state.dataBranchInputManager->Splitters(Count).Name));
    1746            0 :                     ErrorsFound = true;
    1747              :                 }
    1748              :             }
    1749              :         }
    1750              : 
    1751              :         // Check for duplicate names specified in Splitters
    1752          165 :         for (Count = 1; Count <= NumSplitters; ++Count) {
    1753          122 :             TestName = state.dataBranchInputManager->Splitters(Count).InletBranchName;
    1754          364 :             for (Loop = 1; Loop <= state.dataBranchInputManager->Splitters(Count).NumOutletBranches; ++Loop) {
    1755          242 :                 if (TestName != state.dataBranchInputManager->Splitters(Count).OutletBranchNames(Loop)) continue;
    1756            0 :                 ShowSevereError(state,
    1757            0 :                                 format("{}={} specifies an outlet node name the same as the inlet node.",
    1758              :                                        CurrentModuleObject,
    1759            0 :                                        state.dataBranchInputManager->Splitters(Count).Name));
    1760            0 :                 ShowContinueError(state, format("..Inlet Node={}", TestName));
    1761            0 :                 ShowContinueError(state, fmt::format("..Outlet Node #{} is duplicate.", Loop));
    1762            0 :                 ErrorsFound = true;
    1763              :             }
    1764          364 :             for (Loop = 1; Loop <= state.dataBranchInputManager->Splitters(Count).NumOutletBranches; ++Loop) {
    1765          417 :                 for (Loop1 = Loop + 1; Loop1 <= state.dataBranchInputManager->Splitters(Count).NumOutletBranches; ++Loop1) {
    1766          175 :                     if (state.dataBranchInputManager->Splitters(Count).OutletBranchNames(Loop) !=
    1767          175 :                         state.dataBranchInputManager->Splitters(Count).OutletBranchNames(Loop1))
    1768          175 :                         continue;
    1769            0 :                     ShowSevereError(state,
    1770            0 :                                     format("{}={} specifies duplicate outlet nodes in its outlet node list.",
    1771              :                                            CurrentModuleObject,
    1772            0 :                                            state.dataBranchInputManager->Splitters(Count).Name));
    1773            0 :                     ShowContinueError(
    1774              :                         state,
    1775            0 :                         fmt::format("..Outlet Node #{} Name={}", Loop, state.dataBranchInputManager->Splitters(Count).OutletBranchNames(Loop)));
    1776            0 :                     ShowContinueError(state, fmt::format("..Outlet Node #{} is duplicate.", Loop));
    1777            0 :                     ErrorsFound = true;
    1778              :                 }
    1779              :             }
    1780              :         }
    1781              : 
    1782           43 :         if (ErrorsFound) {
    1783            0 :             ShowFatalError(state, format("GetSplitterInput: Fatal Errors Found in {}, program terminates.", CurrentModuleObject));
    1784              :         }
    1785              : 
    1786              :         //  Everything supposed to be good.  Now make sure all branches in Splitter on same side of loop.
    1787           43 :         SaveSupplyDemandAir = std::string();
    1788          165 :         for (Count = 1; Count <= NumSplitters; ++Count) {
    1789              :             // 2.  Find the branch name in branchlist
    1790          122 :             TestName = state.dataBranchInputManager->Splitters(Count).InletBranchName;
    1791          122 :             std::string BranchListName = std::string();
    1792          327 :             for (Loop1 = 1; Loop1 <= (int)state.dataBranchInputManager->BranchList.size(); ++Loop1) {
    1793          327 :                 if (any_eq(state.dataBranchInputManager->BranchList(Loop1).BranchNames, TestName)) {
    1794          122 :                     BranchListName = state.dataBranchInputManager->BranchList(Loop1).Name;
    1795          122 :                     break;
    1796              :                 }
    1797              :             }
    1798              : 
    1799          122 :             if (!BranchListName.empty()) {
    1800          122 :                 FoundSupplyDemandAir = std::string();
    1801          122 :                 FoundLoop = std::string();
    1802          122 :                 MatchedLoop = false;
    1803              :                 // 3.  Find the loop and type
    1804          122 :                 FindAirPlantCondenserLoopFromBranchList(state, BranchListName, FoundLoop, FoundSupplyDemandAir, MatchedLoop);
    1805          122 :                 if (MatchedLoop) {
    1806          122 :                     SaveSupplyDemandAir = FoundSupplyDemandAir;
    1807          122 :                     SaveLoop = FoundLoop;
    1808              :                 } else {
    1809            0 :                     ShowSevereError(
    1810              :                         state,
    1811            0 :                         format("GetSplitterInput: Inlet Splitter Branch=\"{}\" and BranchList=\"{}\" not matched to a Air/Plant/Condenser Loop",
    1812              :                                TestName,
    1813              :                                BranchListName));
    1814            0 :                     ShowContinueError(state, "...and therefore, not a valid Loop Splitter.");
    1815            0 :                     ShowContinueError(state, format("...{}={}", CurrentModuleObject, state.dataBranchInputManager->Splitters(Count).Name));
    1816            0 :                     ErrorsFound = true;
    1817              :                 }
    1818              :             } else {
    1819            0 :                 ShowSevereError(state, format("GetSplitterInput: Inlet Splitter Branch=\"{}\" not on BranchList", TestName));
    1820            0 :                 ShowContinueError(state, "...and therefore, not a valid Loop Splitter.");
    1821            0 :                 ShowContinueError(state, format("...{}={}", CurrentModuleObject, state.dataBranchInputManager->Splitters(Count).Name));
    1822            0 :                 ErrorsFound = true;
    1823              :             }
    1824          364 :             for (Loop = 1; Loop <= state.dataBranchInputManager->Splitters(Count).NumOutletBranches; ++Loop) {
    1825          242 :                 TestName = state.dataBranchInputManager->Splitters(Count).OutletBranchNames(Loop);
    1826          242 :                 BranchListName = std::string();
    1827          659 :                 for (Loop1 = 1; Loop1 <= (int)state.dataBranchInputManager->BranchList.size(); ++Loop1) {
    1828          659 :                     if (any_eq(state.dataBranchInputManager->BranchList(Loop1).BranchNames, TestName)) {
    1829          242 :                         BranchListName = state.dataBranchInputManager->BranchList(Loop1).Name;
    1830          242 :                         break;
    1831              :                     }
    1832              :                 }
    1833              : 
    1834          242 :                 if (!BranchListName.empty()) {
    1835          242 :                     FoundSupplyDemandAir = std::string();
    1836          242 :                     FoundLoop = std::string();
    1837          242 :                     MatchedLoop = false;
    1838              :                     // 3.  Find the loop and type
    1839          242 :                     FindAirPlantCondenserLoopFromBranchList(state, BranchListName, FoundLoop, FoundSupplyDemandAir, MatchedLoop);
    1840          242 :                     if (MatchedLoop) {
    1841          242 :                         if (SaveSupplyDemandAir != FoundSupplyDemandAir || SaveLoop != FoundLoop) {
    1842            0 :                             ShowSevereError(
    1843            0 :                                 state, format("GetSplitterInput: Outlet Splitter Branch=\"{}\" does not match types of Inlet Branch.", TestName));
    1844            0 :                             ShowContinueError(state, format("...Inlet Branch is on \"{}\" on \"{}\" side.", SaveLoop, SaveSupplyDemandAir));
    1845            0 :                             ShowContinueError(state, format("...Outlet Branch is on \"{}\" on \"{}\" side.", FoundLoop, FoundSupplyDemandAir));
    1846            0 :                             ShowContinueError(state, "...All branches in Loop Splitter must be on same kind of loop and supply/demand side.");
    1847            0 :                             ShowContinueError(state, format("...{}={}", CurrentModuleObject, state.dataBranchInputManager->Splitters(Count).Name));
    1848            0 :                             ErrorsFound = true;
    1849              :                         }
    1850              :                     } else {
    1851            0 :                         ShowSevereError(
    1852              :                             state,
    1853            0 :                             format("GetSplitterInput: Outlet Splitter Branch=\"{}\" and BranchList=\"{}\" not matched to a Air/Plant/Condenser Loop",
    1854              :                                    TestName,
    1855              :                                    BranchListName));
    1856            0 :                         ShowContinueError(state, "...and therefore, not a valid Loop Splitter.");
    1857            0 :                         ShowContinueError(state, format("...{}={}", CurrentModuleObject, state.dataBranchInputManager->Splitters(Count).Name));
    1858            0 :                         ErrorsFound = true;
    1859              :                     }
    1860              :                 } else {
    1861            0 :                     ShowSevereError(state, format("GetSplitterInput: Outlet Splitter Branch=\"{}\" not on BranchList", TestName));
    1862            0 :                     ShowContinueError(state, "...and therefore, not a valid Loop Splitter");
    1863            0 :                     ShowContinueError(state, format("...{}={}", CurrentModuleObject, state.dataBranchInputManager->Splitters(Count).Name));
    1864            0 :                     ErrorsFound = true;
    1865              :                 }
    1866              :             }
    1867          122 :         }
    1868              : 
    1869           43 :         if (ErrorsFound) {
    1870            0 :             ShowFatalError(state, format("GetSplitterInput: Fatal Errors Found in {}, program terminates.", CurrentModuleObject));
    1871              :         }
    1872           43 :     }
    1873              : 
    1874           46 :     void GetMixerInput(EnergyPlusData &state)
    1875              :     {
    1876              : 
    1877              :         // SUBROUTINE INFORMATION:
    1878              :         //       AUTHOR         Linda Lawrie
    1879              :         //       DATE WRITTEN   Sept 2005 (moved from GetLoopMixer)
    1880              : 
    1881              :         // PURPOSE OF THIS SUBROUTINE:
    1882              :         // Gets the Mixer data that is used in Loops.
    1883              :         // IDD Structure:
    1884              :         // Connector:Mixer,
    1885              :         //   \min-fields 3
    1886              :         //        \extensible:1 Just duplicate last field and \ comments (changing numbering, please)
    1887              :         //        \memo Mix N inlet air/water streams into one.  Branch names cannot be duplicated within
    1888              :         //        \memo a single mixer list.
    1889              :         //    A1 , \field Name
    1890              :         //         \required-field
    1891              :         //    A2 , \field Outlet Branch Name
    1892              :         //         \required-field
    1893              :         //         \type object-list
    1894              :         //         \object-list Branches
    1895              :         //    A3 , \field Inlet Branch 1 Name
    1896              :         //         \required-field
    1897              :         //         \type object-list
    1898              :         //         \object-list Branches
    1899              :         //    A4 , \field Inlet Branch 2 Name
    1900              :         //         \type object-list
    1901              :         //         \object-list Branches
    1902              : 
    1903              :         // Using/Aliasing
    1904              : 
    1905              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1906              :         int NumAlphas;           // Used to retrieve names from IDF
    1907           46 :         Array1D_string Alphas;   // Used to retrieve names from IDF
    1908              :         int NumNumbers;          // Used to retrieve numbers from IDF
    1909           46 :         Array1D<Real64> Numbers; // Used to retrieve numbers from IDF
    1910           46 :         Array1D_string cAlphaFields;
    1911           46 :         Array1D_string cNumericFields;
    1912           46 :         Array1D_bool lNumericBlanks;
    1913           46 :         Array1D_bool lAlphaBlanks;
    1914              :         int IOStat; // Could be used in the Get Routines, not currently checked
    1915              :         int NumParams;
    1916              :         int Loop;
    1917              :         int Loop1;
    1918              :         int Count;
    1919           46 :         bool ErrorsFound(false);
    1920           46 :         std::string TestName;
    1921           46 :         std::string FoundSupplyDemandAir;
    1922           46 :         std::string SaveSupplyDemandAir;
    1923           46 :         std::string FoundLoop;
    1924           46 :         std::string SaveLoop;
    1925              :         bool MatchedLoop;
    1926              : 
    1927           46 :         if (!state.dataBranchInputManager->GetMixerInputFlag) return;
    1928              : 
    1929           46 :         std::string CurrentModuleObject = cMIXER;
    1930              : 
    1931           46 :         int NumMixers = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
    1932           46 :         state.dataBranchInputManager->Mixers.allocate(NumMixers);
    1933           46 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NumParams, NumAlphas, NumNumbers);
    1934           46 :         Alphas.allocate(NumAlphas);
    1935           46 :         Numbers.dimension(NumNumbers, 0.0);
    1936           46 :         cAlphaFields.allocate(NumAlphas);
    1937           46 :         cNumericFields.allocate(NumNumbers);
    1938           46 :         lAlphaBlanks.dimension(NumAlphas, true);
    1939           46 :         lNumericBlanks.dimension(NumNumbers, true);
    1940          168 :         for (Count = 1; Count <= NumMixers; ++Count) {
    1941          122 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1942              :                                                                      CurrentModuleObject,
    1943              :                                                                      Count,
    1944              :                                                                      Alphas,
    1945              :                                                                      NumAlphas,
    1946              :                                                                      Numbers,
    1947              :                                                                      NumNumbers,
    1948              :                                                                      IOStat,
    1949              :                                                                      lNumericBlanks,
    1950              :                                                                      lAlphaBlanks,
    1951              :                                                                      cAlphaFields,
    1952              :                                                                      cNumericFields);
    1953          122 :             state.dataBranchInputManager->Mixers(Count).Name = Alphas(1);
    1954          122 :             state.dataBranchInputManager->Mixers(Count).OutletBranchName = Alphas(2);
    1955          122 :             state.dataBranchInputManager->Mixers(Count).NumInletBranches = NumAlphas - 2;
    1956          122 :             state.dataBranchInputManager->Mixers(Count).InletBranchNames.allocate(state.dataBranchInputManager->Mixers(Count).NumInletBranches);
    1957          364 :             for (Loop = 1; Loop <= state.dataBranchInputManager->Mixers(Count).NumInletBranches; ++Loop) {
    1958          242 :                 state.dataBranchInputManager->Mixers(Count).InletBranchNames(Loop) = Alphas(2 + Loop);
    1959              :             }
    1960              :         }
    1961           46 :         state.dataBranchInputManager->GetMixerInputFlag = false;
    1962           46 :         Alphas.deallocate();
    1963           46 :         Numbers.deallocate();
    1964           46 :         cAlphaFields.deallocate();
    1965           46 :         cNumericFields.deallocate();
    1966           46 :         lAlphaBlanks.deallocate();
    1967           46 :         lNumericBlanks.deallocate();
    1968              : 
    1969              :         // More validity -- check mixer "names" against branches.
    1970           46 :         if (!state.dataBranchInputManager->GetBranchInputFlag) {
    1971           43 :             GetBranchInput(state);
    1972           43 :             state.dataBranchInputManager->GetBranchInputFlag = false;
    1973              :         }
    1974          168 :         for (Count = 1; Count <= NumMixers; ++Count) {
    1975          122 :             int Found = Util::FindItemInList(state.dataBranchInputManager->Mixers(Count).OutletBranchName, state.dataBranchInputManager->Branch);
    1976          122 :             if (Found == 0) {
    1977            0 :                 ShowSevereError(state,
    1978            0 :                                 format("GetMixerInput: Invalid Branch={}, referenced as Outlet Branch in {}={}",
    1979            0 :                                        state.dataBranchInputManager->Mixers(Count).OutletBranchName,
    1980              :                                        CurrentModuleObject,
    1981            0 :                                        state.dataBranchInputManager->Mixers(Count).Name));
    1982            0 :                 ErrorsFound = true;
    1983              :             }
    1984          364 :             for (Loop = 1; Loop <= state.dataBranchInputManager->Mixers(Count).NumInletBranches; ++Loop) {
    1985              :                 Found =
    1986          242 :                     Util::FindItemInList(state.dataBranchInputManager->Mixers(Count).InletBranchNames(Loop), state.dataBranchInputManager->Branch);
    1987          242 :                 if (Found == 0) {
    1988            0 :                     ShowSevereError(state,
    1989            0 :                                     format("GetMixerInput: Invalid Branch={}, referenced as Inlet Branch # {} in {}={}",
    1990            0 :                                            state.dataBranchInputManager->Mixers(Count).InletBranchNames(Loop),
    1991              :                                            Loop,
    1992              :                                            CurrentModuleObject,
    1993            0 :                                            state.dataBranchInputManager->Mixers(Count).Name));
    1994            0 :                     ErrorsFound = true;
    1995              :                 }
    1996              :             }
    1997              :         }
    1998              : 
    1999              :         // Check for duplicate names specified in Mixer
    2000          168 :         for (Count = 1; Count <= NumMixers; ++Count) {
    2001          122 :             TestName = state.dataBranchInputManager->Mixers(Count).OutletBranchName;
    2002          364 :             for (Loop = 1; Loop <= state.dataBranchInputManager->Mixers(Count).NumInletBranches; ++Loop) {
    2003          242 :                 if (TestName != state.dataBranchInputManager->Mixers(Count).InletBranchNames(Loop)) continue;
    2004            0 :                 ShowSevereError(state,
    2005            0 :                                 format("{}={} specifies an inlet node name the same as the outlet node.",
    2006              :                                        CurrentModuleObject,
    2007            0 :                                        state.dataBranchInputManager->Mixers(Count).Name));
    2008            0 :                 ShowContinueError(state, format("..Outlet Node={}", TestName));
    2009            0 :                 ShowContinueError(state, format("..Inlet Node #{} is duplicate.", Loop));
    2010            0 :                 ErrorsFound = true;
    2011              :             }
    2012          364 :             for (Loop = 1; Loop <= state.dataBranchInputManager->Mixers(Count).NumInletBranches; ++Loop) {
    2013          417 :                 for (Loop1 = Loop + 1; Loop1 <= state.dataBranchInputManager->Mixers(Count).NumInletBranches; ++Loop1) {
    2014          175 :                     if (state.dataBranchInputManager->Mixers(Count).InletBranchNames(Loop) !=
    2015          175 :                         state.dataBranchInputManager->Mixers(Count).InletBranchNames(Loop1))
    2016          175 :                         continue;
    2017            0 :                     ShowSevereError(state,
    2018            0 :                                     format("{}={} specifies duplicate inlet nodes in its inlet node list.",
    2019              :                                            CurrentModuleObject,
    2020            0 :                                            state.dataBranchInputManager->Mixers(Count).Name));
    2021            0 :                     ShowContinueError(
    2022            0 :                         state, fmt::format("..Inlet Node #{} Name={}", Loop, state.dataBranchInputManager->Mixers(Count).InletBranchNames(Loop)));
    2023            0 :                     ShowContinueError(state, fmt::format("..Inlet Node #{} is duplicate.", Loop));
    2024            0 :                     ErrorsFound = true;
    2025              :                 }
    2026              :             }
    2027              :         }
    2028              : 
    2029           46 :         if (ErrorsFound) {
    2030            0 :             ShowFatalError(state, format("GetMixerInput: Fatal Errors Found in {}, program terminates.", CurrentModuleObject));
    2031              :         }
    2032              : 
    2033              :         //  Everything supposed to be good.  Now make sure all branches in Splitter on same side of loop.
    2034           46 :         SaveSupplyDemandAir = std::string();
    2035          168 :         for (Count = 1; Count <= NumMixers; ++Count) {
    2036              :             // 2.  Find the branch name in branchlist
    2037          122 :             TestName = state.dataBranchInputManager->Mixers(Count).OutletBranchName;
    2038          122 :             std::string BranchListName = std::string();
    2039          327 :             for (Loop1 = 1; Loop1 <= (int)state.dataBranchInputManager->BranchList.size(); ++Loop1) {
    2040          327 :                 if (any_eq(state.dataBranchInputManager->BranchList(Loop1).BranchNames, TestName)) {
    2041          122 :                     BranchListName = state.dataBranchInputManager->BranchList(Loop1).Name;
    2042          122 :                     break;
    2043              :                 }
    2044              :             }
    2045              : 
    2046          122 :             if (!BranchListName.empty()) {
    2047          122 :                 FoundSupplyDemandAir = std::string();
    2048          122 :                 FoundLoop = std::string();
    2049          122 :                 MatchedLoop = false;
    2050              :                 // 3.  Find the loop and type
    2051          122 :                 FindAirPlantCondenserLoopFromBranchList(state, BranchListName, FoundLoop, FoundSupplyDemandAir, MatchedLoop);
    2052          122 :                 if (MatchedLoop) {
    2053          122 :                     SaveSupplyDemandAir = FoundSupplyDemandAir;
    2054          122 :                     SaveLoop = FoundLoop;
    2055              :                 } else {
    2056            0 :                     ShowSevereError(
    2057              :                         state,
    2058            0 :                         format("GetMixerInput: Outlet Mixer Branch=\"{}\" and BranchList=\"{}\" not matched to a Air/Plant/Condenser Loop",
    2059              :                                TestName,
    2060              :                                BranchListName));
    2061            0 :                     ShowContinueError(state, "...and therefore, not a valid Loop Mixer.");
    2062            0 :                     ShowContinueError(state, format("...{}={}", CurrentModuleObject, state.dataBranchInputManager->Mixers(Count).Name));
    2063            0 :                     ErrorsFound = true;
    2064              :                 }
    2065              :             } else {
    2066            0 :                 ShowSevereError(state, format("GetMixerInput: Outlet Mixer Branch=\"{}\" not on BranchList", TestName));
    2067            0 :                 ShowContinueError(state, "...and therefore, not a valid Loop Mixer.");
    2068            0 :                 ShowContinueError(state, format("...{}={}", CurrentModuleObject, state.dataBranchInputManager->Mixers(Count).Name));
    2069            0 :                 ErrorsFound = true;
    2070              :             }
    2071          364 :             for (Loop = 1; Loop <= state.dataBranchInputManager->Mixers(Count).NumInletBranches; ++Loop) {
    2072          242 :                 TestName = state.dataBranchInputManager->Mixers(Count).InletBranchNames(Loop);
    2073          242 :                 BranchListName = std::string();
    2074          659 :                 for (Loop1 = 1; Loop1 <= (int)state.dataBranchInputManager->BranchList.size(); ++Loop1) {
    2075          659 :                     if (any_eq(state.dataBranchInputManager->BranchList(Loop1).BranchNames, TestName)) {
    2076          242 :                         BranchListName = state.dataBranchInputManager->BranchList(Loop1).Name;
    2077          242 :                         break;
    2078              :                     }
    2079              :                 }
    2080              : 
    2081          242 :                 if (!BranchListName.empty()) {
    2082          242 :                     FoundSupplyDemandAir = std::string();
    2083          242 :                     FoundLoop = std::string();
    2084          242 :                     MatchedLoop = false;
    2085              :                     // 3.  Find the plant loop and type
    2086          242 :                     FindAirPlantCondenserLoopFromBranchList(state, BranchListName, FoundLoop, FoundSupplyDemandAir, MatchedLoop);
    2087          242 :                     if (MatchedLoop) {
    2088          242 :                         if (SaveSupplyDemandAir != FoundSupplyDemandAir || SaveLoop != FoundLoop) {
    2089            0 :                             ShowSevereError(state,
    2090            0 :                                             format("GetMixerInput: Outlet Mixer Branch=\"{}\" does not match types of Inlet Branch.", TestName));
    2091            0 :                             ShowContinueError(state, format("...Outlet Branch is on \"{}\" on \"{}\" side.", SaveLoop, SaveSupplyDemandAir));
    2092            0 :                             ShowContinueError(state, format("...Inlet Branch is on \"{}\" on \"{}\" side.", FoundLoop, FoundSupplyDemandAir));
    2093            0 :                             ShowContinueError(state, "...All branches in Loop Mixer must be on same kind of loop and supply/demand side.");
    2094            0 :                             ShowContinueError(state, format("...{}={}", CurrentModuleObject, state.dataBranchInputManager->Mixers(Count).Name));
    2095            0 :                             ErrorsFound = true;
    2096              :                         }
    2097              :                     } else {
    2098            0 :                         ShowSevereError(
    2099              :                             state,
    2100            0 :                             format("GetMixerInput: Inlet Mixer Branch=\"{}\" and BranchList=\"{}\" not matched to a Air/Plant/Condenser Loop",
    2101              :                                    TestName,
    2102              :                                    BranchListName));
    2103            0 :                         ShowContinueError(state, "...and therefore, not a valid Loop Mixer.");
    2104            0 :                         ShowContinueError(state, format("...{}={}", CurrentModuleObject, state.dataBranchInputManager->Mixers(Count).Name));
    2105            0 :                         ErrorsFound = true;
    2106              :                     }
    2107              :                 } else {
    2108            0 :                     ShowSevereError(state, format("GetMixerInput: Inlet Mixer Branch=\"{}\" not on BranchList", TestName));
    2109            0 :                     ShowContinueError(state, "...and therefore, not a valid Loop Mixer");
    2110            0 :                     ShowContinueError(state, format("...{}={}", CurrentModuleObject, state.dataBranchInputManager->Mixers(Count).Name));
    2111            0 :                     ErrorsFound = true;
    2112              :                 }
    2113              :             }
    2114          122 :         }
    2115              : 
    2116           46 :         if (ErrorsFound) {
    2117            0 :             ShowFatalError(state, format("GetMixerInput: Fatal Errors Found in {}, program terminates.", CurrentModuleObject));
    2118              :         }
    2119           46 :     }
    2120              : 
    2121          728 :     void FindPlantLoopBranchConnection(EnergyPlusData &state,
    2122              :                                        std::string const &BranchListName,
    2123              :                                        std::string &FoundPlantLoopName,
    2124              :                                        int &FoundPlantLoopNum,
    2125              :                                        std::string &FoundSupplyDemand,
    2126              :                                        Real64 &FoundVolFlowRate,
    2127              :                                        bool &MatchedPlantLoop)
    2128              :     {
    2129              : 
    2130              :         // SUBROUTINE INFORMATION:
    2131              :         //       AUTHOR         Linda Lawrie
    2132              :         //       DATE WRITTEN   October 2007
    2133              : 
    2134              :         // PURPOSE OF THIS SUBROUTINE:
    2135              :         // An auxiliary routine locate a plant loop and type from a BranchListName
    2136              : 
    2137              :         // METHODOLOGY EMPLOYED:
    2138              :         // Calls GetObject for PLANT LOOP
    2139              : 
    2140              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2141              :         int Num;
    2142              :         int NumPlantLoops;
    2143              :         int NumParams;
    2144          728 :         Array1D_string Alphas;
    2145              :         int NumAlphas;
    2146          728 :         Array1D<Real64> Numbers;
    2147              :         int NumNumbers;
    2148              :         int IOStat;
    2149              : 
    2150              :         // Get Inputs
    2151          728 :         std::string CurrentModuleObject = "PlantLoop";
    2152              : 
    2153          728 :         NumPlantLoops = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
    2154          728 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NumParams, NumAlphas, NumNumbers);
    2155          728 :         Alphas.allocate(NumAlphas);
    2156          728 :         Numbers.allocate(NumNumbers);
    2157              : 
    2158         1034 :         for (Num = 1; Num <= NumPlantLoops; ++Num) {
    2159          932 :             state.dataInputProcessing->inputProcessor->getObjectItem(state, CurrentModuleObject, Num, Alphas, NumAlphas, Numbers, NumNumbers, IOStat);
    2160              :             // Only looking for BranchList here.
    2161          932 :             if (Alphas(8) == BranchListName) {
    2162          270 :                 FoundPlantLoopName = Alphas(1);
    2163          270 :                 FoundSupplyDemand = "Supply";
    2164          270 :                 FoundVolFlowRate = Numbers(3);
    2165          270 :                 FoundPlantLoopNum = Num;
    2166          270 :                 MatchedPlantLoop = true;
    2167          270 :                 break;
    2168          662 :             } else if (Alphas(12) == BranchListName) {
    2169          356 :                 FoundPlantLoopName = Alphas(1);
    2170          356 :                 FoundSupplyDemand = "Demand";
    2171          356 :                 FoundVolFlowRate = Numbers(3);
    2172          356 :                 FoundPlantLoopNum = Num;
    2173          356 :                 MatchedPlantLoop = true;
    2174          356 :                 break;
    2175              :             }
    2176              :         }
    2177              : 
    2178          728 :         Alphas.deallocate();
    2179          728 :         Numbers.deallocate();
    2180          728 :     }
    2181              : 
    2182          102 :     void FindCondenserLoopBranchConnection(EnergyPlusData &state,
    2183              :                                            std::string const &BranchListName,
    2184              :                                            std::string &FoundCondLoopName,
    2185              :                                            int &FoundCondLoopNum,
    2186              :                                            std::string &FoundSupplyDemand,
    2187              :                                            Real64 &FoundVolFlowRate,
    2188              :                                            bool &MatchedCondLoop)
    2189              :     {
    2190              : 
    2191              :         // SUBROUTINE INFORMATION:
    2192              :         //       AUTHOR         Linda Lawrie
    2193              :         //       DATE WRITTEN   February 2008
    2194              : 
    2195              :         // PURPOSE OF THIS SUBROUTINE:
    2196              :         // An auxiliary routine locate a condenser loop and type from a BranchListName
    2197              : 
    2198              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2199              :         int Num;
    2200              :         int NumCondLoops;
    2201              :         int NumParams;
    2202          102 :         Array1D_string Alphas;
    2203              :         int NumAlphas;
    2204          102 :         Array1D<Real64> Numbers;
    2205              :         int NumNumbers;
    2206              :         int IOStat;
    2207              : 
    2208              :         // Get Inputs
    2209          102 :         std::string CurrentModuleObject = "CondenserLoop";
    2210              : 
    2211          102 :         NumCondLoops = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
    2212          102 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NumParams, NumAlphas, NumNumbers);
    2213          102 :         Alphas.allocate(NumAlphas);
    2214          102 :         Numbers.allocate(NumNumbers);
    2215              : 
    2216          102 :         for (Num = 1; Num <= NumCondLoops; ++Num) {
    2217          102 :             state.dataInputProcessing->inputProcessor->getObjectItem(state, CurrentModuleObject, Num, Alphas, NumAlphas, Numbers, NumNumbers, IOStat);
    2218              :             // Only looking for BranchList here.
    2219          102 :             if (Alphas(8) == BranchListName) {
    2220           48 :                 FoundCondLoopName = Alphas(1);
    2221           48 :                 FoundSupplyDemand = "Supply";
    2222           48 :                 FoundVolFlowRate = Numbers(3);
    2223           48 :                 FoundCondLoopNum = Num;
    2224           48 :                 MatchedCondLoop = true;
    2225           48 :                 break;
    2226           54 :             } else if (Alphas(12) == BranchListName) {
    2227           54 :                 FoundCondLoopName = Alphas(1);
    2228           54 :                 FoundSupplyDemand = "Demand";
    2229           54 :                 FoundVolFlowRate = Numbers(3);
    2230           54 :                 FoundCondLoopNum = Num;
    2231           54 :                 MatchedCondLoop = true;
    2232           54 :                 break;
    2233              :             }
    2234              :         }
    2235              : 
    2236          102 :         Alphas.deallocate();
    2237          102 :         Numbers.deallocate();
    2238          102 :     }
    2239              : 
    2240            3 :     void FindAirLoopBranchConnection(EnergyPlusData &state,
    2241              :                                      std::string const &BranchListName,
    2242              :                                      std::string &FoundAirLoopName,
    2243              :                                      int &FoundAirLoopNum,
    2244              :                                      std::string &FoundAir,
    2245              :                                      Real64 &FoundVolFlowRate,
    2246              :                                      bool &MatchedAirLoop)
    2247              :     {
    2248              : 
    2249              :         // SUBROUTINE INFORMATION:
    2250              :         //       AUTHOR         Linda Lawrie
    2251              :         //       DATE WRITTEN   February 2008
    2252              : 
    2253              :         // PURPOSE OF THIS SUBROUTINE:
    2254              :         // An auxiliary routine to locate a Air condenser loop and type from a BranchListName
    2255              : 
    2256              :         // METHODOLOGY EMPLOYED:
    2257              :         // calls GetObject for PRIMARY AIR LOOP
    2258              : 
    2259              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2260              :         int Num;
    2261              :         int NumAirLoops;
    2262              :         int NumParams;
    2263            3 :         Array1D_string Alphas;
    2264              :         int NumAlphas;
    2265            3 :         Array1D<Real64> Numbers;
    2266              :         int NumNumbers;
    2267              :         int IOStat;
    2268              : 
    2269              :         // Get Inputs
    2270            3 :         std::string CurrentModuleObject = "AirLoopHVAC";
    2271            3 :         NumAirLoops = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
    2272            3 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NumParams, NumAlphas, NumNumbers);
    2273            3 :         Alphas.allocate(NumAlphas);
    2274            3 :         Numbers.allocate(NumNumbers);
    2275              : 
    2276            6 :         for (Num = 1; Num <= NumAirLoops; ++Num) {
    2277            5 :             state.dataInputProcessing->inputProcessor->getObjectItem(state, CurrentModuleObject, Num, Alphas, NumAlphas, Numbers, NumNumbers, IOStat);
    2278              :             // Only looking for BranchList here.
    2279            5 :             if (Alphas(4) == BranchListName) {
    2280            2 :                 FoundAirLoopName = Alphas(1);
    2281            2 :                 FoundAir = "Air";
    2282            2 :                 FoundVolFlowRate = Numbers(1);
    2283            2 :                 FoundAirLoopNum = Num;
    2284            2 :                 MatchedAirLoop = true;
    2285            2 :                 break;
    2286              :             }
    2287              :         }
    2288              : 
    2289            3 :         Alphas.deallocate();
    2290            3 :         Numbers.deallocate();
    2291            3 :     }
    2292              : 
    2293          728 :     void FindAirPlantCondenserLoopFromBranchList(EnergyPlusData &state,
    2294              :                                                  std::string const &BranchListName, // Branch List Name
    2295              :                                                  std::string &LoopType,             // LoopType (if found, Plant,Condenser or Air)
    2296              :                                                  std::string &LoopSupplyDemandAir,  // Supply if "Supply" or Demand if "Demand" or Air if "Air"
    2297              :                                                  bool &MatchedLoop                  // true if found
    2298              :     )
    2299              :     {
    2300              : 
    2301              :         // SUBROUTINE INFORMATION:
    2302              :         //       AUTHOR         Linda Lawrie
    2303              :         //       DATE WRITTEN   February 2008
    2304              : 
    2305              :         // PURPOSE OF THIS SUBROUTINE:
    2306              :         // Assist in validating Loop Splitter/Mixer connections.
    2307              : 
    2308              :         // METHODOLOGY EMPLOYED:
    2309              :         // Call two previously written subroutines that match a Branch List Name to
    2310              :         // Plant or Condenser Loop
    2311              : 
    2312              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2313          728 :         std::string FoundLoopName;
    2314              :         int FoundLoopNum;
    2315              :         Real64 FoundLoopVolFlowRate;
    2316              : 
    2317          728 :         LoopSupplyDemandAir = std::string();
    2318          728 :         FoundLoopName = std::string();
    2319          728 :         FoundLoopNum = 0;
    2320          728 :         FoundLoopVolFlowRate = 0.0;
    2321          728 :         MatchedLoop = false;
    2322          728 :         LoopType = std::string();
    2323              : 
    2324              :         // Try Plant first
    2325          728 :         FindPlantLoopBranchConnection(state, BranchListName, FoundLoopName, FoundLoopNum, LoopSupplyDemandAir, FoundLoopVolFlowRate, MatchedLoop);
    2326              : 
    2327          728 :         if (MatchedLoop) LoopType = "Plant";
    2328          728 :         if (!MatchedLoop) { // Try Condenser Loop
    2329          102 :             LoopSupplyDemandAir = std::string();
    2330          102 :             FoundLoopName = std::string();
    2331          102 :             FoundLoopNum = 0;
    2332          102 :             FoundLoopVolFlowRate = 0.0;
    2333          102 :             MatchedLoop = false;
    2334              : 
    2335              :             // Try Condenser
    2336          102 :             FindCondenserLoopBranchConnection(
    2337              :                 state, BranchListName, FoundLoopName, FoundLoopNum, LoopSupplyDemandAir, FoundLoopVolFlowRate, MatchedLoop);
    2338          102 :             if (MatchedLoop) LoopType = "Condenser";
    2339              :         }
    2340              : 
    2341          728 :         if (!MatchedLoop) { // Try Air Loop
    2342            0 :             LoopSupplyDemandAir = std::string();
    2343            0 :             FoundLoopName = std::string();
    2344            0 :             FoundLoopNum = 0;
    2345            0 :             FoundLoopVolFlowRate = 0.0;
    2346            0 :             MatchedLoop = false;
    2347              : 
    2348              :             // Try Air
    2349            0 :             FindAirLoopBranchConnection(state, BranchListName, FoundLoopName, FoundLoopNum, LoopSupplyDemandAir, FoundLoopVolFlowRate, MatchedLoop);
    2350            0 :             if (MatchedLoop) LoopType = "Air";
    2351              :         }
    2352          728 :     }
    2353              : 
    2354              :     //==================================================================================
    2355              :     //   Routines that test branch integrity
    2356              :     //==================================================================================
    2357              : 
    2358          110 :     void AuditBranches(EnergyPlusData &state,
    2359              :                        bool const mustprint,                      // true if the warning should be printed.
    2360              :                        ObjexxFCL::Optional_string_const CompType, // when mustprint (ScanPlantLoop)  use CompType in error message and scan
    2361              :                        ObjexxFCL::Optional_string_const CompName  // when mustprint (ScanPlantLoop)  use CompName in error message and scan
    2362              :     )
    2363              :     {
    2364              : 
    2365              :         // SUBROUTINE INFORMATION:
    2366              :         //       AUTHOR         Linda Lawrie
    2367              :         //       DATE WRITTEN   November 2011
    2368              : 
    2369              :         // PURPOSE OF THIS SUBROUTINE:
    2370              :         // This routine will point out any "dangling branches" that are not included on a BranchList.
    2371              :         // Warnings are produced as the user might clutter up the input file with unused branches.
    2372              : 
    2373              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2374              :         int NumDanglingCount; // when mustprint not true, count and report
    2375              :         int BlNum;            // Branch List Counter
    2376              :         int BrN;              // Branch Counter
    2377              :         int CpN;              // Components on Branch
    2378              :         bool NeverFound;
    2379              : 
    2380          110 :         NumDanglingCount = 0;
    2381          110 :         NeverFound = true;
    2382          499 :         for (BrN = 1; BrN <= (int)state.dataBranchInputManager->Branch.size(); ++BrN) {
    2383          389 :             int Found = 0;
    2384          389 :             std::string FoundBranchName = "";
    2385          389 :             if (present(CompType) && present(CompName)) {
    2386            0 :                 for (CpN = 1; CpN <= state.dataBranchInputManager->Branch(BrN).NumOfComponents; ++CpN) {
    2387            0 :                     if (!Util::SameString(CompType(), state.dataBranchInputManager->Branch(BrN).Component(CpN).CType) ||
    2388            0 :                         !Util::SameString(CompName(), state.dataBranchInputManager->Branch(BrN).Component(CpN).Name))
    2389            0 :                         continue;
    2390            0 :                     FoundBranchName = state.dataBranchInputManager->Branch(BrN).Name;
    2391            0 :                     NeverFound = false;
    2392              :                 }
    2393              :             }
    2394         1094 :             for (BlNum = 1; BlNum <= (int)state.dataBranchInputManager->BranchList.size(); ++BlNum) {
    2395         1094 :                 Found = Util::FindItemInList(state.dataBranchInputManager->Branch(BrN).Name,
    2396         1094 :                                              state.dataBranchInputManager->BranchList(BlNum).BranchNames,
    2397         1094 :                                              state.dataBranchInputManager->BranchList(BlNum).NumOfBranchNames);
    2398         1094 :                 if (Found != 0) break;
    2399              :             }
    2400          389 :             if (Found != 0) continue;
    2401            0 :             ++NumDanglingCount;
    2402            0 :             if (state.dataGlobal->DisplayExtraWarnings || mustprint) {
    2403            0 :                 if (mustprint) {
    2404            0 :                     ShowContinueError(
    2405            0 :                         state, format("AuditBranches: Branch=\"{}\" not found on any BranchLists.", state.dataBranchInputManager->Branch(BrN).Name));
    2406            0 :                     if (!FoundBranchName.empty()) {
    2407            0 :                         ShowContinueError(state, format("Branch contains component, type=\"{}\", name=\"{}\"", CompType, CompName));
    2408              :                     }
    2409              :                 } else {
    2410            0 :                     ShowSevereMessage(
    2411            0 :                         state, format("AuditBranches: Branch=\"{}\" not found on any BranchLists.", state.dataBranchInputManager->Branch(BrN).Name));
    2412            0 :                     ++state.dataErrTracking->TotalSevereErrors;
    2413              :                 }
    2414              :             }
    2415          389 :         }
    2416          110 :         if (mustprint && NeverFound) { // this may be caught during branch input, not sure
    2417            5 :             ShowContinueError(state, format("Component, type=\"{}\", name=\"{}\" was not found on any Branch.", CompType, CompName));
    2418           15 :             ShowContinueError(state, "Look for mistyped branch or component names/types.");
    2419              :         }
    2420          110 :         if (!mustprint && NumDanglingCount > 0) {
    2421            0 :             ShowSevereMessage(state, fmt::format("AuditBranches: There are {} branch(es) that do not appear on any BranchList.", NumDanglingCount));
    2422            0 :             state.dataErrTracking->TotalSevereErrors += NumDanglingCount;
    2423            0 :             ShowContinueError(state, "Use Output:Diagnostics,DisplayExtraWarnings; for detail of each branch not on a branch list.");
    2424              :         }
    2425          110 :     }
    2426              : 
    2427           73 :     void TestBranchIntegrity(EnergyPlusData &state, bool &ErrFound)
    2428              :     {
    2429              : 
    2430              :         // SUBROUTINE INFORMATION:
    2431              :         //       AUTHOR         Linda Lawrie
    2432              :         //       DATE WRITTEN   November 2001
    2433              : 
    2434              :         // PURPOSE OF THIS SUBROUTINE:
    2435              :         // This subroutine tests branch integrity and displays the loop for each branch.
    2436              :         // Also, input and output nodes.
    2437              : 
    2438              :         // Using/Aliasing
    2439              : 
    2440              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2441              :         int Loop;
    2442              :         int Count;
    2443              :         int MatchNode;                    // Node Number for match
    2444           73 :         std::string MatchNodeName;        // Name for error message if not matched
    2445           73 :         std::string BranchInletNodeName;  // Branch Inlet Node Name
    2446           73 :         std::string BranchOutletNodeName; // Branch Outlet Node Name
    2447           73 :         std::string BranchLoopName;       // Loop Name which Branch is part of
    2448           73 :         std::string BranchLoopType;       // Loop Type which Branch is part of
    2449              :         int NumErr;                       // Error Counter
    2450           73 :         Array1D_bool BranchReported;
    2451              :         int BCount;
    2452              :         int Found;
    2453              :         //  LOGICAL UniqueNodeError
    2454              :         int Loop2;
    2455              :         NodeFluidType BranchFluidType;
    2456              :         int InitialBranchFluidNode;
    2457           73 :         Array1D_int BranchFluidNodes;
    2458           73 :         Array1D_int FoundBranches;
    2459           73 :         Array1D_int BranchPtrs;
    2460           73 :         std::string cBranchFluidType;
    2461              :         int Ptr;
    2462              :         int EndPtr;
    2463              : 
    2464              :         struct BranchUniqueNodes
    2465              :         {
    2466              :             int NumNodes{0};
    2467              :             Array1D_string UniqueNodeNames;
    2468              :         };
    2469              : 
    2470              :         // Object Data
    2471           73 :         Array1D<BranchUniqueNodes> BranchNodes;
    2472              : 
    2473              :         // Formats
    2474              : 
    2475           73 :         BranchReported.dimension((int)state.dataBranchInputManager->Branch.size(), false);
    2476              : 
    2477              :         // Do by Branch Lists
    2478          146 :         ShowMessage(state, "Testing Individual Branch Integrity");
    2479           73 :         ErrFound = false;
    2480              : 
    2481           73 :         BranchNodes.allocate((int)state.dataBranchInputManager->Branch.size());
    2482              : 
    2483           73 :         print(state.files.bnd, "{}\n", "! ===============================================================");
    2484              :         static constexpr std::string_view Format_700("! <#Branch Lists>,<Number of Branch Lists>");
    2485           73 :         print(state.files.bnd, "{}\n", Format_700);
    2486           73 :         print(state.files.bnd, " #Branch Lists,{}\n", (int)state.dataBranchInputManager->BranchList.size());
    2487              :         static constexpr std::string_view Format_702(
    2488              :             "! <Branch List>,<Branch List Count>,<Branch List Name>,<Loop Name>,<Loop Type>,<Number of Branches>");
    2489           73 :         print(state.files.bnd, "{}\n", Format_702);
    2490              :         static constexpr std::string_view Format_704(
    2491              :             "! <Branch>,<Branch Count>,<Branch Name>,<Loop Name>,<Loop Type>,<Branch Inlet Node Name>,<Branch Outlet Node Name>");
    2492           73 :         print(state.files.bnd, "{}\n", Format_704);
    2493              : 
    2494          121 :         for (BCount = 1; BCount <= (int)state.dataBranchInputManager->BranchList.size(); ++BCount) {
    2495           48 :             print(state.files.bnd,
    2496              :                   " Branch List,{},{},{},{},{}\n",
    2497              :                   BCount,
    2498           48 :                   state.dataBranchInputManager->BranchList(BCount).Name,
    2499           48 :                   state.dataBranchInputManager->BranchList(BCount).LoopName,
    2500           48 :                   state.dataBranchInputManager->BranchList(BCount).LoopType,
    2501           48 :                   state.dataBranchInputManager->BranchList(BCount).NumOfBranchNames);
    2502              : 
    2503           48 :             BranchFluidType = NodeFluidType::Blank;
    2504           48 :             bool MixedFluidTypesOnBranchList = false;
    2505           48 :             int NumNodesOnBranchList = 0;
    2506           48 :             FoundBranches.allocate(state.dataBranchInputManager->BranchList(BCount).NumOfBranchNames);
    2507           48 :             FoundBranches = 0;
    2508           48 :             BranchPtrs.allocate(state.dataBranchInputManager->BranchList(BCount).NumOfBranchNames + 2);
    2509           48 :             BranchPtrs = 0;
    2510          188 :             for (Count = 1; Count <= state.dataBranchInputManager->BranchList(BCount).NumOfBranchNames; ++Count) {
    2511              :                 Found =
    2512          140 :                     Util::FindItemInList(state.dataBranchInputManager->BranchList(BCount).BranchNames(Count), state.dataBranchInputManager->Branch);
    2513          140 :                 if (Found > 0) {
    2514          140 :                     NumNodesOnBranchList += state.dataBranchInputManager->Branch(Found).NumOfComponents * 2;
    2515          140 :                     FoundBranches(Count) = Found;
    2516          140 :                     BranchPtrs(Count) = NumNodesOnBranchList;
    2517              :                 } else {
    2518            0 :                     ShowSevereError(state, format("Branch not found={}", state.dataBranchInputManager->BranchList(BCount).BranchNames(Count)));
    2519            0 :                     ErrFound = true;
    2520              :                 }
    2521              :             }
    2522           48 :             BranchPtrs(state.dataBranchInputManager->BranchList(BCount).NumOfBranchNames + 1) =
    2523           48 :                 BranchPtrs(state.dataBranchInputManager->BranchList(BCount).NumOfBranchNames) + 1;
    2524           48 :             BranchFluidNodes.dimension(NumNodesOnBranchList, 0);
    2525           48 :             std::string OriginalBranchFluidType = std::string();
    2526           48 :             int NumFluidNodes = 0;
    2527          188 :             for (Count = 1; Count <= state.dataBranchInputManager->BranchList(BCount).NumOfBranchNames; ++Count) {
    2528          140 :                 Found = FoundBranches(Count);
    2529          140 :                 if (Found == 0) {
    2530            0 :                     print(state.files.bnd,
    2531              :                           "   Branch,{},{},(not found),**Unknown**,**Unknown**,**Unknown**,**Unknown**\n",
    2532              :                           Count,
    2533            0 :                           state.dataBranchInputManager->BranchList(BCount).BranchNames(Count));
    2534            0 :                     continue;
    2535              :                 }
    2536          140 :                 BranchReported(Found) = true;
    2537              :                 // Check Branch for connections
    2538              : 
    2539          140 :                 MatchNode = 0;
    2540          140 :                 InitialBranchFluidNode = 0;
    2541          140 :                 if (state.dataBranchInputManager->Branch(Found).NumOfComponents > 0) {
    2542          140 :                     MatchNode = state.dataBranchInputManager->Branch(Found).Component(1).InletNode;
    2543          140 :                     MatchNodeName = state.dataBranchInputManager->Branch(Found).Component(1).InletNodeName;
    2544          140 :                     BranchInletNodeName = state.dataBranchInputManager->Branch(Found).Component(1).InletNodeName;
    2545              :                 } else {
    2546            0 :                     ShowWarningError(state, format("Branch has no components={}", state.dataBranchInputManager->Branch(Found).Name));
    2547              :                 }
    2548          140 :                 NumErr = 0;
    2549          332 :                 for (Loop = 1; Loop <= state.dataBranchInputManager->Branch(Found).NumOfComponents; ++Loop) {
    2550          192 :                     if (BranchFluidType == DataLoopNode::NodeFluidType::Blank) {
    2551           48 :                         ++NumFluidNodes;
    2552           48 :                         BranchFluidNodes(NumFluidNodes) = state.dataBranchInputManager->Branch(Found).Component(Loop).InletNode;
    2553           48 :                         BranchFluidType = state.dataLoopNodes->Node(state.dataBranchInputManager->Branch(Found).Component(Loop).InletNode).FluidType;
    2554           48 :                         InitialBranchFluidNode = state.dataBranchInputManager->Branch(Found).Component(Loop).InletNode;
    2555           48 :                         OriginalBranchFluidType = DataLoopNode::NodeFluidTypeNames[static_cast<int>(DataLoopNode::NodeFluidType::Blank)];
    2556          144 :                     } else if (BranchFluidType !=
    2557          144 :                                    state.dataLoopNodes->Node(state.dataBranchInputManager->Branch(Found).Component(Loop).InletNode).FluidType &&
    2558            0 :                                state.dataLoopNodes->Node(state.dataBranchInputManager->Branch(Found).Component(Loop).InletNode).FluidType !=
    2559              :                                    DataLoopNode::NodeFluidType::Blank) {
    2560            0 :                         ++NumFluidNodes;
    2561            0 :                         BranchFluidNodes(NumFluidNodes) = state.dataBranchInputManager->Branch(Found).Component(Loop).InletNode;
    2562            0 :                         MixedFluidTypesOnBranchList = true;
    2563              :                     } else {
    2564          144 :                         ++NumFluidNodes;
    2565          144 :                         BranchFluidNodes(NumFluidNodes) = state.dataBranchInputManager->Branch(Found).Component(Loop).InletNode;
    2566              :                     }
    2567          192 :                     if (BranchFluidType == DataLoopNode::NodeFluidType::Blank) {
    2568            0 :                         ++NumFluidNodes;
    2569            0 :                         BranchFluidNodes(NumFluidNodes) = state.dataBranchInputManager->Branch(Found).Component(Loop).InletNode;
    2570            0 :                         BranchFluidType = state.dataLoopNodes->Node(state.dataBranchInputManager->Branch(Found).Component(Loop).OutletNode).FluidType;
    2571            0 :                         InitialBranchFluidNode = state.dataBranchInputManager->Branch(Found).Component(Loop).OutletNode;
    2572            0 :                         OriginalBranchFluidType = DataLoopNode::NodeFluidTypeNames[static_cast<int>(BranchFluidType)];
    2573          192 :                     } else if (BranchFluidType !=
    2574          192 :                                    state.dataLoopNodes->Node(state.dataBranchInputManager->Branch(Found).Component(Loop).OutletNode).FluidType &&
    2575            0 :                                state.dataLoopNodes->Node(state.dataBranchInputManager->Branch(Found).Component(Loop).OutletNode).FluidType !=
    2576              :                                    DataLoopNode::NodeFluidType::Blank) {
    2577            0 :                         ++NumFluidNodes;
    2578            0 :                         BranchFluidNodes(NumFluidNodes) = state.dataBranchInputManager->Branch(Found).Component(Loop).OutletNode;
    2579            0 :                         MixedFluidTypesOnBranchList = true;
    2580              :                     } else {
    2581          192 :                         ++NumFluidNodes;
    2582          192 :                         BranchFluidNodes(NumFluidNodes) = state.dataBranchInputManager->Branch(Found).Component(Loop).OutletNode;
    2583              :                     }
    2584          192 :                     if (state.dataBranchInputManager->Branch(Found).Component(Loop).InletNode != MatchNode) {
    2585            0 :                         ShowSevereError(state, format("Error Detected in BranchList={}", state.dataBranchInputManager->BranchList(BCount).Name));
    2586            0 :                         ShowContinueError(state, format("Actual Error occurs in Branch={}", state.dataBranchInputManager->Branch(Found).Name));
    2587            0 :                         ShowContinueError(state, format("Branch Outlet does not match Inlet, Outlet={}", MatchNodeName));
    2588            0 :                         ShowContinueError(state, format("Inlet Name={}", state.dataBranchInputManager->Branch(Found).Component(Loop).InletNodeName));
    2589            0 :                         ErrFound = true;
    2590            0 :                         ++NumErr;
    2591              :                     } else {
    2592          192 :                         MatchNode = state.dataBranchInputManager->Branch(Found).Component(Loop).OutletNode;
    2593          192 :                         MatchNodeName = state.dataBranchInputManager->Branch(Found).Component(Loop).OutletNodeName;
    2594              :                     }
    2595              :                 }
    2596          140 :                 state.dataBranchInputManager->Branch(Found).FluidType = BranchFluidType;
    2597          140 :                 BranchOutletNodeName = MatchNodeName;
    2598          140 :                 if (state.dataBranchInputManager->Branch(Found).AssignedLoopName.empty()) {
    2599            0 :                     BranchLoopName = "**Unknown**";
    2600            0 :                     BranchLoopType = "**Unknown**";
    2601          140 :                 } else if (state.dataBranchInputManager->Branch(Found).AssignedLoopName ==
    2602          140 :                            state.dataBranchInputManager->BranchList(BCount).LoopName) {
    2603          140 :                     BranchLoopName = state.dataBranchInputManager->BranchList(BCount).LoopName;
    2604          140 :                     BranchLoopType = state.dataBranchInputManager->BranchList(BCount).LoopType;
    2605              :                 } else {
    2606            0 :                     BranchLoopName = state.dataBranchInputManager->Branch(Found).AssignedLoopName;
    2607            0 :                     BranchLoopType = "**Unknown**";
    2608              :                 }
    2609          140 :                 print(state.files.bnd,
    2610              :                       "   Branch,{},{},{},{},{},{}\n",
    2611              :                       Count,
    2612          140 :                       state.dataBranchInputManager->Branch(Found).Name,
    2613              :                       BranchLoopName,
    2614              :                       BranchLoopType,
    2615              :                       BranchInletNodeName,
    2616              :                       BranchOutletNodeName);
    2617              :             }
    2618           48 :             if (MixedFluidTypesOnBranchList) {
    2619            0 :                 ShowSevereError(state,
    2620            0 :                                 format("BranchList={} has mixed fluid types in its nodes.", state.dataBranchInputManager->BranchList(BCount).Name));
    2621            0 :                 ErrFound = true;
    2622            0 :                 if (OriginalBranchFluidType.empty()) OriginalBranchFluidType = "**Unknown**";
    2623            0 :                 ShowContinueError(
    2624            0 :                     state, format("Initial Node={}, Fluid Type={}", state.dataLoopNodes->NodeID(InitialBranchFluidNode), OriginalBranchFluidType));
    2625            0 :                 ShowContinueError(state, "BranchList Topology - Note nodes which do not match that fluid type:");
    2626            0 :                 Ptr = 1;
    2627            0 :                 EndPtr = BranchPtrs(1);
    2628            0 :                 for (Loop = 1; Loop <= state.dataBranchInputManager->BranchList(BCount).NumOfBranchNames; ++Loop) {
    2629            0 :                     if (FoundBranches(Loop) != 0) {
    2630            0 :                         ShowContinueError(state, format("..Branch={}", state.dataBranchInputManager->Branch(FoundBranches(Loop)).Name));
    2631              :                     } else {
    2632            0 :                         ShowContinueError(state, format("..Illegal Branch={}", state.dataBranchInputManager->BranchList(BCount).BranchNames(Loop)));
    2633            0 :                         continue;
    2634              :                     }
    2635            0 :                     for (Loop2 = Ptr; Loop2 <= EndPtr; ++Loop2) {
    2636              :                         cBranchFluidType =
    2637            0 :                             DataLoopNode::NodeFluidTypeNames[static_cast<int>(state.dataLoopNodes->Node(BranchFluidNodes(Loop2)).FluidType)];
    2638            0 :                         if (cBranchFluidType.empty()) cBranchFluidType = "**Unknown**";
    2639            0 :                         ShowContinueError(
    2640            0 :                             state, format("....Node={}, Fluid Type={}", state.dataLoopNodes->NodeID(BranchFluidNodes(Loop2)), cBranchFluidType));
    2641              :                     }
    2642            0 :                     Ptr = EndPtr + 1;
    2643            0 :                     EndPtr = BranchPtrs(Loop + 1);
    2644              :                 }
    2645              :             }
    2646           48 :             BranchFluidNodes.deallocate();
    2647           48 :             BranchPtrs.deallocate();
    2648           48 :             FoundBranches.deallocate();
    2649           48 :         }
    2650              : 
    2651              :         // Build node names in branches
    2652          213 :         for (Count = 1; Count <= (int)state.dataBranchInputManager->Branch.size(); ++Count) {
    2653          140 :             BranchNodes(Count).UniqueNodeNames.allocate(state.dataBranchInputManager->Branch(Count).NumOfComponents * 2);
    2654          140 :             int NodeNum = 0;
    2655          332 :             for (Loop = 1; Loop <= state.dataBranchInputManager->Branch(Count).NumOfComponents; ++Loop) {
    2656          192 :                 Found = Util::FindItemInList(
    2657          192 :                     state.dataBranchInputManager->Branch(Count).Component(Loop).InletNodeName, BranchNodes(Count).UniqueNodeNames, NodeNum);
    2658          192 :                 if (Found == 0) {
    2659          140 :                     ++NodeNum;
    2660          140 :                     BranchNodes(Count).UniqueNodeNames(NodeNum) = state.dataBranchInputManager->Branch(Count).Component(Loop).InletNodeName;
    2661              :                 }
    2662          192 :                 Found = Util::FindItemInList(
    2663          192 :                     state.dataBranchInputManager->Branch(Count).Component(Loop).OutletNodeName, BranchNodes(Count).UniqueNodeNames, NodeNum);
    2664          192 :                 if (Found == 0) {
    2665          192 :                     ++NodeNum;
    2666          192 :                     BranchNodes(Count).UniqueNodeNames(NodeNum) = state.dataBranchInputManager->Branch(Count).Component(Loop).OutletNodeName;
    2667              :                 }
    2668              :             }
    2669          140 :             BranchNodes(Count).NumNodes = NodeNum;
    2670              :         }
    2671              :         // Check Uniqueness branch to branch
    2672          213 :         for (Count = 1; Count <= (int)state.dataBranchInputManager->Branch.size(); ++Count) {
    2673         1295 :             for (Loop = Count + 1; Loop <= (int)state.dataBranchInputManager->Branch.size(); ++Loop) {
    2674         3624 :                 for (Loop2 = 1; Loop2 <= BranchNodes(Count).NumNodes; ++Loop2) {
    2675         2469 :                     Found = Util::FindItemInList(
    2676         2469 :                         BranchNodes(Count).UniqueNodeNames(Loop2), BranchNodes(Loop).UniqueNodeNames, BranchNodes(Loop).NumNodes);
    2677         2469 :                     if (Found != 0) {
    2678            0 :                         ShowSevereError(state, format("Non-unique node name found, name={}", BranchNodes(Count).UniqueNodeNames(Loop2)));
    2679            0 :                         ShowContinueError(state, format("..1st occurrence in Branch={}", state.dataBranchInputManager->Branch(Count).Name));
    2680            0 :                         ShowContinueError(state, format("..duplicate occurrence in Branch={}", state.dataBranchInputManager->Branch(Loop).Name));
    2681            0 :                         ErrFound = true;
    2682              :                     }
    2683              :                 }
    2684              :             }
    2685              :         }
    2686          213 :         for (Count = 1; Count <= (int)state.dataBranchInputManager->Branch.size(); ++Count) {
    2687          140 :             BranchNodes(Count).UniqueNodeNames.deallocate();
    2688              :         }
    2689           73 :         BranchNodes.deallocate();
    2690              : 
    2691           73 :         BCount = 0;
    2692          213 :         for (Count = 1; Count <= (int)state.dataBranchInputManager->Branch.size(); ++Count) {
    2693          140 :             if (BranchReported(Count)) continue;
    2694            0 :             ++BCount;
    2695              :         }
    2696           73 :         if (BCount > 0) {
    2697              :             static constexpr std::string_view Format_706("! <# Orphaned Branches>,<Number of Branches not on Branch Lists>");
    2698            0 :             print(state.files.bnd, "{}\n", Format_706);
    2699            0 :             print(state.files.bnd, " #Orphaned Branches,{}\n", BCount);
    2700            0 :             ShowWarningError(state, "There are orphaned Branches in input. See .bnd file for details.");
    2701              : 
    2702            0 :             BCount = 0;
    2703              : 
    2704            0 :             for (Count = 1; Count <= (int)state.dataBranchInputManager->Branch.size(); ++Count) {
    2705            0 :                 if (BranchReported(Count)) continue;
    2706            0 :                 ++BCount;
    2707            0 :                 ShowWarningError(state, format("Orphan Branch=\"{}\".", state.dataBranchInputManager->Branch(Count).Name));
    2708              : 
    2709            0 :                 if (state.dataBranchInputManager->Branch(Count).NumOfComponents > 0) {
    2710            0 :                     MatchNode = state.dataBranchInputManager->Branch(Count).Component(1).InletNode;
    2711            0 :                     MatchNodeName = state.dataBranchInputManager->Branch(Count).Component(1).InletNodeName;
    2712            0 :                     BranchInletNodeName = state.dataBranchInputManager->Branch(Count).Component(1).InletNodeName;
    2713              :                 } else {
    2714            0 :                     ShowWarningError(state, format("Branch has no components={}", state.dataBranchInputManager->Branch(Count).Name));
    2715              :                 }
    2716            0 :                 NumErr = 0;
    2717            0 :                 for (Loop = 1; Loop <= state.dataBranchInputManager->Branch(Count).NumOfComponents; ++Loop) {
    2718            0 :                     if (state.dataBranchInputManager->Branch(Count).Component(Loop).InletNode != MatchNode) {
    2719            0 :                         ShowSevereError(state, format("Error Detected in Branch={}", state.dataBranchInputManager->Branch(Count).Name));
    2720            0 :                         ShowContinueError(state, format("Branch Outlet does not match Inlet, Outlet={}", MatchNodeName));
    2721            0 :                         ShowContinueError(state, format("Inlet Name={}", state.dataBranchInputManager->Branch(Count).Component(Loop).InletNodeName));
    2722            0 :                         ErrFound = true;
    2723            0 :                         ++NumErr;
    2724              :                     } else {
    2725            0 :                         MatchNode = state.dataBranchInputManager->Branch(Count).Component(Loop).OutletNode;
    2726            0 :                         MatchNodeName = state.dataBranchInputManager->Branch(Count).Component(Loop).OutletNodeName;
    2727              :                     }
    2728              :                 }
    2729            0 :                 BranchOutletNodeName = MatchNodeName;
    2730            0 :                 if (state.dataBranchInputManager->Branch(Count).AssignedLoopName.empty()) {
    2731            0 :                     BranchLoopName = "**Unknown**";
    2732            0 :                     BranchLoopType = "**Unknown**";
    2733              :                 } else {
    2734            0 :                     BranchLoopName = state.dataBranchInputManager->Branch(Count).AssignedLoopName;
    2735            0 :                     BranchLoopType = "**Unknown**";
    2736              :                 }
    2737            0 :                 print(state.files.bnd,
    2738              :                       " Branch,{},{},{},{},{},{}\n",
    2739              :                       BCount,
    2740            0 :                       state.dataBranchInputManager->Branch(Count).Name,
    2741              :                       BranchLoopName,
    2742              :                       BranchLoopType,
    2743              :                       BranchInletNodeName,
    2744              :                       BranchOutletNodeName);
    2745              :             }
    2746              :         }
    2747              : 
    2748           73 :         if (ErrFound) {
    2749            0 :             ShowSevereError(state, "Branch(es) did not pass integrity testing");
    2750              :         } else {
    2751          219 :             ShowMessage(state, "All Branches passed integrity testing");
    2752              :         }
    2753           73 :     }
    2754              : 
    2755              : } // namespace BranchInputManager
    2756              : 
    2757              : } // namespace EnergyPlus
        

Generated by: LCOV version 2.0-1