LCOV - code coverage report
Current view: top level - EnergyPlus - OutdoorAirUnit.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 851 1217 69.9 %
Date: 2024-08-24 18:31:18 Functions: 13 14 92.9 %

          Line data    Source code
       1             : // EnergyPlus, Copyright (c) 1996-2024, The Board of Trustees of the University of Illinois,
       2             : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
       3             : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
       4             : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
       5             : // contributors. All rights reserved.
       6             : //
       7             : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
       8             : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
       9             : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
      10             : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
      11             : // derivative works, and perform publicly and display publicly, and to permit others to do so.
      12             : //
      13             : // Redistribution and use in source and binary forms, with or without modification, are permitted
      14             : // provided that the following conditions are met:
      15             : //
      16             : // (1) Redistributions of source code must retain the above copyright notice, this list of
      17             : //     conditions and the following disclaimer.
      18             : //
      19             : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
      20             : //     conditions and the following disclaimer in the documentation and/or other materials
      21             : //     provided with the distribution.
      22             : //
      23             : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
      24             : //     the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
      25             : //     used to endorse or promote products derived from this software without specific prior
      26             : //     written permission.
      27             : //
      28             : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
      29             : //     without changes from the version obtained under this License, or (ii) Licensee makes a
      30             : //     reference solely to the software portion of its product, Licensee must refer to the
      31             : //     software as "EnergyPlus version X" software, where "X" is the version number Licensee
      32             : //     obtained under this License and may not use a different name for the software. Except as
      33             : //     specifically required in this Section (4), Licensee shall not use in a company name, a
      34             : //     product name, in advertising, publicity, or other promotional activities any name, trade
      35             : //     name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
      36             : //     similar designation, without the U.S. Department of Energy's prior written consent.
      37             : //
      38             : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
      39             : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
      40             : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
      41             : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      42             : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      43             : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      44             : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      45             : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      46             : // POSSIBILITY OF SUCH DAMAGE.
      47             : 
      48             : // C++ Headers
      49             : #include <cmath>
      50             : 
      51             : // ObjexxFCL Headers
      52             : #include <ObjexxFCL/Array.functions.hh>
      53             : #include <ObjexxFCL/Fmath.hh>
      54             : 
      55             : // EnergyPlus Headers
      56             : #include <EnergyPlus/Autosizing/Base.hh>
      57             : #include <EnergyPlus/BranchNodeConnections.hh>
      58             : #include <EnergyPlus/Data/EnergyPlusData.hh>
      59             : #include <EnergyPlus/DataAirSystems.hh>
      60             : #include <EnergyPlus/DataEnvironment.hh>
      61             : #include <EnergyPlus/DataHVACGlobals.hh>
      62             : #include <EnergyPlus/DataIPShortCuts.hh>
      63             : #include <EnergyPlus/DataLoopNode.hh>
      64             : #include <EnergyPlus/DataSizing.hh>
      65             : #include <EnergyPlus/DataZoneEquipment.hh>
      66             : #include <EnergyPlus/DesiccantDehumidifiers.hh>
      67             : #include <EnergyPlus/Fans.hh>
      68             : #include <EnergyPlus/FluidProperties.hh>
      69             : #include <EnergyPlus/General.hh>
      70             : #include <EnergyPlus/GeneralRoutines.hh>
      71             : #include <EnergyPlus/GlobalNames.hh>
      72             : #include <EnergyPlus/HVACDXHeatPumpSystem.hh>
      73             : #include <EnergyPlus/HVACHXAssistedCoolingCoil.hh>
      74             : #include <EnergyPlus/HeatRecovery.hh>
      75             : #include <EnergyPlus/HeatingCoils.hh>
      76             : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      77             : #include <EnergyPlus/NodeInputManager.hh>
      78             : #include <EnergyPlus/OutAirNodeManager.hh>
      79             : #include <EnergyPlus/OutdoorAirUnit.hh>
      80             : #include <EnergyPlus/OutputProcessor.hh>
      81             : #include <EnergyPlus/PlantUtilities.hh>
      82             : #include <EnergyPlus/Psychrometrics.hh>
      83             : #include <EnergyPlus/ScheduleManager.hh>
      84             : #include <EnergyPlus/SteamCoils.hh>
      85             : #include <EnergyPlus/UnitarySystem.hh>
      86             : #include <EnergyPlus/UtilityRoutines.hh>
      87             : #include <EnergyPlus/WaterCoils.hh>
      88             : #include <EnergyPlus/ZoneTempPredictorCorrector.hh>
      89             : 
      90             : namespace EnergyPlus {
      91             : 
      92             : namespace OutdoorAirUnit {
      93             :     // Module containing the routines dealing with the outdoor air unit
      94             : 
      95             :     // MODULE INFORMATION:
      96             :     //       AUTHOR         Young Tae Chae, Rick Strand
      97             :     //       DATE WRITTEN   AUG. 2009
      98             :     //       MODIFIED
      99             :     //                      Feb 2013 Bereket Nigusse, FSEC
     100             :     //                        Added DX Coil Model For 100% OA systems
     101             :     //       RE-ENGINEERED  na
     102             : 
     103             :     // PURPOSE OF THIS MODULE:
     104             :     // Simulate zone outdoor air unit.
     105             : 
     106             :     // METHODOLOGY EMPLOYED:
     107             :     // Systems are modeled as a collection of components:
     108             :     // fan, heat recovery, dehumidifier, heating coil and/or cooling coil plus an integrated control
     109             :     // algorithm that adjusts the hot or cold water flow to meet the setpoint
     110             :     // condition.
     111             : 
     112             :     // Using/Aliasing
     113             :     using namespace DataLoopNode;
     114             :     using HVAC::SmallAirVolFlow;
     115             :     using HVAC::SmallLoad;
     116             :     using HVAC::SmallMassFlow;
     117             :     using namespace ScheduleManager;
     118             :     using namespace Psychrometrics;
     119             : 
     120             :     // component types addressed by this module
     121             :     constexpr static std::string_view ZoneHVACOAUnit = {"ZoneHVAC:OutdoorAirUnit"};
     122             :     constexpr static std::string_view ZoneHVACEqList = {"ZoneHVAC:OutdoorAirUnit:EquipmentList"};
     123             : 
     124       64818 :     void SimOutdoorAirUnit(EnergyPlusData &state,
     125             :                            std::string_view CompName,     // name of the outdoor air unit
     126             :                            int const ZoneNum,             // number of zone being served
     127             :                            bool const FirstHVACIteration, // TRUE if 1st HVAC simulation of system timestep
     128             :                            Real64 &PowerMet,              // Sensible power supplied (W)
     129             :                            Real64 &LatOutputProvided,     // Latent add/removal supplied by window AC (kg/s), dehumid = negative
     130             :                            int &CompIndex)
     131             :     {
     132             : 
     133             :         // SUBROUTINE INFORMATION:
     134             :         //       AUTHOR         Rick Strand
     135             :         //       DATE WRITTEN   May 2000
     136             :         //       MODIFIED       na
     137             :         //       RE-ENGINEERED
     138             :         // This is re-engineered by Rick Strand and Young T. Chae for OutdoorAirUnit (July, 2009)
     139             : 
     140             :         // PURPOSE OF THIS SUBROUTINE:
     141             :         // This is the main driver subroutine for the outdoor air control unit simulation.
     142             : 
     143             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     144       64818 :         int OAUnitNum = 0; // index of outdoor air unit being simulated
     145             : 
     146       64818 :         if (state.dataOutdoorAirUnit->GetOutdoorAirUnitInputFlag) {
     147           2 :             GetOutdoorAirUnitInputs(state);
     148           2 :             state.dataOutdoorAirUnit->GetOutdoorAirUnitInputFlag = false;
     149             :         }
     150             : 
     151             :         // Find the correct Outdoor Air Unit
     152             : 
     153       64818 :         if (CompIndex == 0) {
     154          12 :             OAUnitNum = Util::FindItemInList(CompName, state.dataOutdoorAirUnit->OutAirUnit);
     155          12 :             if (OAUnitNum == 0) {
     156           0 :                 ShowFatalError(state, format("ZoneHVAC:OutdoorAirUnit not found={}", CompName));
     157             :             }
     158          12 :             CompIndex = OAUnitNum;
     159             :         } else {
     160       64806 :             OAUnitNum = CompIndex;
     161       64806 :             if (OAUnitNum > state.dataOutdoorAirUnit->NumOfOAUnits || OAUnitNum < 1) {
     162           0 :                 ShowFatalError(state,
     163           0 :                                format("SimOutdoorAirUnit:  Invalid CompIndex passed={}, Number of Units={}, Entered Unit name={}",
     164             :                                       OAUnitNum,
     165           0 :                                       state.dataOutdoorAirUnit->NumOfOAUnits,
     166             :                                       CompName));
     167             :             }
     168       64806 :             if (state.dataOutdoorAirUnit->CheckEquipName(OAUnitNum)) {
     169          12 :                 if (CompName != state.dataOutdoorAirUnit->OutAirUnit(OAUnitNum).Name) {
     170           0 :                     ShowFatalError(state,
     171           0 :                                    format("SimOutdoorAirUnit: Invalid CompIndex passed={}, Unit name={}, stored Unit Name for that index={}",
     172             :                                           OAUnitNum,
     173             :                                           CompName,
     174           0 :                                           state.dataOutdoorAirUnit->OutAirUnit(OAUnitNum).Name));
     175             :                 }
     176          12 :                 state.dataOutdoorAirUnit->CheckEquipName(OAUnitNum) = false;
     177             :             }
     178             :         }
     179             : 
     180       64818 :         state.dataSize->ZoneEqOutdoorAirUnit = true;
     181             : 
     182       64818 :         if (state.dataGlobal->ZoneSizingCalc || state.dataGlobal->SysSizingCalc) {
     183          12 :             return;
     184             :         }
     185             : 
     186       64806 :         InitOutdoorAirUnit(state, OAUnitNum, ZoneNum, FirstHVACIteration);
     187             : 
     188       64806 :         CalcOutdoorAirUnit(state, OAUnitNum, ZoneNum, FirstHVACIteration, PowerMet, LatOutputProvided);
     189             : 
     190       64806 :         ReportOutdoorAirUnit(state, OAUnitNum);
     191             : 
     192       64806 :         state.dataSize->ZoneEqOutdoorAirUnit = false;
     193             :     }
     194             : 
     195           2 :     void GetOutdoorAirUnitInputs(EnergyPlusData &state)
     196             :     {
     197             : 
     198             :         // SUBROUTINE INFORMATION:
     199             :         //       AUTHOR         Young Tae Chae, Rick Strand
     200             :         //       DATE WRITTEN   July 2009
     201             :         //       MODIFIED       July 2012, Chandan Sharma - FSEC: Added zone sys avail managers
     202             :         //       RE-ENGINEERED  na
     203             : 
     204             :         // PURPOSE OF THIS SUBROUTINE:
     205             :         // This subroutine obtains the input for the outdoor air control unit and sets
     206             :         // up the appropriate derived type.
     207             : 
     208             :         // METHODOLOGY EMPLOYED:
     209             :         // Standard EnergyPlus methodology.
     210             : 
     211             :         // REFERENCES:
     212             :         // Fred Buhl's fan coil module (FanCoilUnits.cc)
     213             :         // Kwang Ho Lee's Unit Ventilator Module (UnitVentilator.cc)
     214             :         // Young Tae Chae's Ventilated Slab System (VentilatedSlab.cc)
     215             :         // Mixed Air.cc
     216             : 
     217             :         // Using/Aliasing
     218             :         using BranchNodeConnections::SetUpCompSets;
     219             :         using BranchNodeConnections::TestCompSet;
     220             :         using NodeInputManager::GetOnlySingleNode;
     221             :         using ScheduleManager::GetScheduleIndex;
     222             :         using SteamCoils::GetCoilAirInletNode;
     223             :         using SteamCoils::GetCoilAirOutletNode;
     224             :         using SteamCoils::GetCoilMaxSteamFlowRate;
     225             :         using SteamCoils::GetCoilSteamInletNode;
     226             :         using SteamCoils::GetCoilSteamOutletNode;
     227             :         using SteamCoils::GetSteamCoilIndex;
     228             :         using namespace DataLoopNode;
     229             :         using HeatingCoils::GetCoilInletNode;
     230             :         using HeatingCoils::GetCoilOutletNode;
     231             :         using OutAirNodeManager::CheckAndAddAirNodeNumber;
     232             :         using WaterCoils::GetCoilWaterInletNode;
     233             :         using WaterCoils::GetCoilWaterOutletNode;
     234             :         using WaterCoils::GetWaterCoilIndex;
     235             : 
     236             :         // SUBROUTINE PARAMETER DEFINITIONS:
     237             :         static constexpr std::string_view RoutineName("GetOutdoorAirUnitInputs: "); // include trailing blank space
     238             :         static constexpr std::string_view routineName = "GetOutdoorAirUnitInputs";  // include trailing blank space
     239             : 
     240             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     241             : 
     242           2 :         if (!state.dataOutdoorAirUnit->GetOutdoorAirUnitInputFlag) {
     243           0 :             return;
     244             :         }
     245             : 
     246           2 :         int NumAlphas = 0;        // Number of elements in the alpha array
     247           2 :         int NumNums = 0;          // Number of elements in the numeric array
     248           2 :         Array1D_string AlphArray; // character string data
     249           2 :         Array1D<Real64> NumArray; // numeric data
     250           2 :         int IOStat = -1;          // IO Status when calling get input subroutine
     251           2 :         bool ErrorsFound = false;
     252             : 
     253           2 :         int MaxNums = 0;                 // Maximum number of numeric input fields
     254           2 :         int MaxAlphas = 0;               // Maximum number of alpha input fields
     255           2 :         int TotalArgs = 0;               // Total number of alpha and numeric arguments (max) for a
     256             :         bool IsValid;                    // Set for outside air node check
     257           2 :         Array1D_string cAlphaArgs;       // Alpha input items for object
     258           2 :         std::string CurrentModuleObject; // Object type for getting and messages
     259           2 :         Array1D_string cAlphaFields;     // Alpha field names
     260           2 :         Array1D_string cNumericFields;   // Numeric field names
     261           2 :         Array1D_bool lAlphaBlanks;       // Logical array, alpha field input BLANK = .TRUE.
     262           2 :         Array1D_bool lNumericBlanks;     // Logical array, numeric field input BLANK = .TRUE.
     263             : 
     264             :         // Figure out how many outdoor air units there are in the input file
     265             : 
     266           2 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, ZoneHVACOAUnit, TotalArgs, NumAlphas, NumNums);
     267           2 :         MaxNums = max(MaxNums, NumNums);
     268           2 :         MaxAlphas = max(MaxAlphas, NumAlphas);
     269           2 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, ZoneHVACEqList, TotalArgs, NumAlphas, NumNums);
     270           2 :         MaxNums = max(MaxNums, NumNums);
     271           2 :         MaxAlphas = max(MaxAlphas, NumAlphas);
     272             : 
     273           2 :         AlphArray.allocate(MaxAlphas);
     274           2 :         cAlphaFields.allocate(MaxAlphas);
     275           2 :         NumArray.dimension(MaxNums, 0.0);
     276           2 :         cNumericFields.allocate(MaxNums);
     277           2 :         lAlphaBlanks.dimension(MaxAlphas, true);
     278           2 :         lNumericBlanks.dimension(MaxNums, true);
     279           2 :         cAlphaArgs.allocate(NumAlphas);
     280             : 
     281           2 :         CurrentModuleObject = ZoneHVACOAUnit;
     282           2 :         state.dataOutdoorAirUnit->NumOfOAUnits = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
     283             : 
     284           2 :         state.dataOutdoorAirUnit->OutAirUnit.allocate(state.dataOutdoorAirUnit->NumOfOAUnits);
     285           2 :         state.dataOutdoorAirUnit->SupplyFanUniqueNames.reserve(static_cast<unsigned>(state.dataOutdoorAirUnit->NumOfOAUnits));
     286           2 :         state.dataOutdoorAirUnit->ExhaustFanUniqueNames.reserve(static_cast<unsigned>(state.dataOutdoorAirUnit->NumOfOAUnits));
     287           2 :         state.dataOutdoorAirUnit->ComponentListUniqueNames.reserve(static_cast<unsigned>(state.dataOutdoorAirUnit->NumOfOAUnits));
     288           2 :         state.dataOutdoorAirUnit->MyOneTimeErrorFlag.dimension(state.dataOutdoorAirUnit->NumOfOAUnits, true);
     289           2 :         state.dataOutdoorAirUnit->CheckEquipName.dimension(state.dataOutdoorAirUnit->NumOfOAUnits, true);
     290             : 
     291          14 :         for (int OAUnitNum = 1; OAUnitNum <= state.dataOutdoorAirUnit->NumOfOAUnits; ++OAUnitNum) {
     292             : 
     293          12 :             auto &thisOutAirUnit = state.dataOutdoorAirUnit->OutAirUnit(OAUnitNum);
     294             : 
     295          24 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     296             :                                                                      CurrentModuleObject,
     297             :                                                                      OAUnitNum,
     298          12 :                                                                      state.dataIPShortCut->cAlphaArgs,
     299             :                                                                      NumAlphas,
     300             :                                                                      NumArray,
     301             :                                                                      NumNums,
     302             :                                                                      IOStat,
     303             :                                                                      lNumericBlanks,
     304             :                                                                      lAlphaBlanks,
     305             :                                                                      cAlphaFields,
     306             :                                                                      cNumericFields);
     307             : 
     308          12 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)};
     309          12 :             Util::IsNameEmpty(state, state.dataIPShortCut->cAlphaArgs(1), CurrentModuleObject, ErrorsFound);
     310             : 
     311             :             // A1
     312          12 :             thisOutAirUnit.Name = state.dataIPShortCut->cAlphaArgs(1);
     313             : 
     314             :             // A2
     315          12 :             thisOutAirUnit.SchedName = state.dataIPShortCut->cAlphaArgs(2);
     316          12 :             if (lAlphaBlanks(2)) {
     317           0 :                 thisOutAirUnit.SchedPtr = ScheduleManager::ScheduleAlwaysOn;
     318             :             } else {
     319          12 :                 thisOutAirUnit.SchedPtr = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(2)); // convert schedule name to pointer
     320          12 :                 if (thisOutAirUnit.SchedPtr == 0) {
     321           0 :                     ShowSevereError(state,
     322           0 :                                     format("{}=\"{}\" invalid {}=\"{}\" not found.",
     323             :                                            CurrentModuleObject,
     324           0 :                                            state.dataIPShortCut->cAlphaArgs(1),
     325           0 :                                            state.dataIPShortCut->cAlphaArgs(2),
     326           0 :                                            state.dataIPShortCut->cAlphaArgs(2)));
     327           0 :                     ErrorsFound = true;
     328             :                 }
     329             :             }
     330             : 
     331             :             // A3
     332          12 :             thisOutAirUnit.ZoneName = state.dataIPShortCut->cAlphaArgs(3);
     333          12 :             thisOutAirUnit.ZonePtr = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(3), state.dataHeatBal->Zone);
     334             : 
     335          12 :             if (thisOutAirUnit.ZonePtr == 0) {
     336           0 :                 if (lAlphaBlanks(3)) {
     337           0 :                     ShowSevereError(state,
     338           0 :                                     format("{}=\"{}\" invalid {} is required but input is blank.",
     339             :                                            CurrentModuleObject,
     340           0 :                                            state.dataIPShortCut->cAlphaArgs(1),
     341           0 :                                            state.dataIPShortCut->cAlphaArgs(3)));
     342             :                 } else {
     343           0 :                     ShowSevereError(state,
     344           0 :                                     format("{}=\"{}\" invalid {}=\"{}\" not found.",
     345             :                                            CurrentModuleObject,
     346           0 :                                            state.dataIPShortCut->cAlphaArgs(1),
     347           0 :                                            state.dataIPShortCut->cAlphaArgs(3),
     348           0 :                                            state.dataIPShortCut->cAlphaArgs(3)));
     349             :                 }
     350           0 :                 ErrorsFound = true;
     351             :             }
     352          12 :             thisOutAirUnit.ZoneNodeNum = state.dataHeatBal->Zone(thisOutAirUnit.ZonePtr).SystemZoneNodeNumber;
     353             :             // Outside air information:
     354             :             // N1
     355          12 :             thisOutAirUnit.OutAirVolFlow = NumArray(1);
     356             :             // A4
     357          12 :             thisOutAirUnit.OutAirSchedName = state.dataIPShortCut->cAlphaArgs(4);
     358             :             // convert schedule name to pointer
     359          12 :             thisOutAirUnit.OutAirSchedPtr = GetScheduleIndex(state, thisOutAirUnit.OutAirSchedName);
     360          12 :             if (thisOutAirUnit.OutAirSchedPtr == 0) {
     361           0 :                 ShowSevereError(state,
     362           0 :                                 format("{}=\"{}\" invalid {}=\"{}\" not found.",
     363             :                                        CurrentModuleObject,
     364           0 :                                        state.dataIPShortCut->cAlphaArgs(1),
     365             :                                        cAlphaFields(4),
     366           0 :                                        state.dataIPShortCut->cAlphaArgs(4)));
     367           0 :                 ErrorsFound = true;
     368             :             }
     369             : 
     370             :             // A5
     371          12 :             thisOutAirUnit.SFanName = state.dataIPShortCut->cAlphaArgs(5);
     372          12 :             GlobalNames::IntraObjUniquenessCheck(state,
     373          12 :                                                  state.dataIPShortCut->cAlphaArgs(5),
     374             :                                                  CurrentModuleObject,
     375          12 :                                                  cAlphaFields(5),
     376          12 :                                                  state.dataOutdoorAirUnit->SupplyFanUniqueNames,
     377             :                                                  ErrorsFound);
     378             : 
     379          12 :             if ((thisOutAirUnit.SFan_Index = Fans::GetFanIndex(state, thisOutAirUnit.SFanName)) == 0) {
     380           0 :                 ShowSevereItemNotFound(state, eoh, state.dataIPShortCut->cAlphaFieldNames(5), thisOutAirUnit.SFanName);
     381           0 :                 ErrorsFound = true;
     382             :             } else {
     383          12 :                 auto *fan = state.dataFans->fans(thisOutAirUnit.SFan_Index);
     384          12 :                 thisOutAirUnit.supFanType = fan->type;
     385          12 :                 thisOutAirUnit.SFanMaxAirVolFlow = fan->maxAirFlowRate;
     386          12 :                 thisOutAirUnit.SFanAvailSchedPtr = fan->availSchedNum;
     387             :             }
     388             :             // A6 :Fan Place
     389          12 :             thisOutAirUnit.supFanPlace = static_cast<HVAC::FanPlace>(getEnumValue(HVAC::fanPlaceNamesUC, state.dataIPShortCut->cAlphaArgs(6)));
     390             : 
     391             :             // A7
     392             : 
     393          12 :             if (lAlphaBlanks(7)) {
     394           0 :                 thisOutAirUnit.ExtFan = false;
     395           0 :                 if (!state.dataHeatBal->ZoneAirMassFlow.EnforceZoneMassBalance) {
     396           0 :                     ShowWarningError(state,
     397           0 :                                      format("{}=\"{}\", {} is blank.", CurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1), cAlphaFields(7)));
     398           0 :                     ShowContinueError(state,
     399             :                                       "Unbalanced mass flow rates between supply from outdoor air and exhaust from zone air will be introduced.");
     400             :                 }
     401          12 :             } else if (!lAlphaBlanks(7)) {
     402          12 :                 thisOutAirUnit.ExtFanName = state.dataIPShortCut->cAlphaArgs(7);
     403          12 :                 GlobalNames::IntraObjUniquenessCheck(state,
     404          12 :                                                      state.dataIPShortCut->cAlphaArgs(7),
     405             :                                                      CurrentModuleObject,
     406          12 :                                                      cAlphaFields(7),
     407          12 :                                                      state.dataOutdoorAirUnit->ExhaustFanUniqueNames,
     408             :                                                      ErrorsFound);
     409             : 
     410          12 :                 if ((thisOutAirUnit.ExtFan_Index = Fans::GetFanIndex(state, thisOutAirUnit.ExtFanName)) == 0) {
     411           0 :                     ShowSevereItemNotFound(state, eoh, state.dataIPShortCut->cAlphaFieldNames(7), thisOutAirUnit.ExtFanName);
     412           0 :                     ErrorsFound = true;
     413             :                 } else {
     414          12 :                     auto *fan = state.dataFans->fans(thisOutAirUnit.ExtFan_Index);
     415          12 :                     thisOutAirUnit.extFanType = fan->type;
     416          12 :                     thisOutAirUnit.EFanMaxAirVolFlow = fan->maxAirFlowRate;
     417          12 :                     thisOutAirUnit.ExtFanAvailSchedPtr = fan->availSchedNum;
     418             :                 }
     419          12 :                 thisOutAirUnit.ExtFan = true;
     420             :             }
     421             : 
     422             :             // N2
     423          12 :             thisOutAirUnit.ExtAirVolFlow = NumArray(2);
     424          12 :             if ((thisOutAirUnit.ExtFan) && (!state.dataHeatBal->ZoneAirMassFlow.EnforceZoneMassBalance)) {
     425          12 :                 if (NumArray(2) != NumArray(1)) {
     426           0 :                     ShowWarningError(state,
     427           0 :                                      format("{}=\"{}\", {} and {} are not equal. This may cause unbalanced flow.",
     428             :                                             CurrentModuleObject,
     429           0 :                                             state.dataIPShortCut->cAlphaArgs(1),
     430             :                                             cNumericFields(1),
     431             :                                             cNumericFields(2)));
     432           0 :                     ShowContinueError(state, format("{}={:.3R}= and {}{:.3R}", cNumericFields(1), NumArray(1), cNumericFields(2), NumArray(2)));
     433             :                 }
     434             :             }
     435             :             // A8
     436          12 :             thisOutAirUnit.ExtAirSchedName = state.dataIPShortCut->cAlphaArgs(8);
     437             :             // convert schedule name to pointer
     438          12 :             thisOutAirUnit.ExtOutAirSchedPtr = GetScheduleIndex(state, thisOutAirUnit.ExtAirSchedName);
     439          12 :             if (thisOutAirUnit.ExtFan) {
     440          12 :                 if ((thisOutAirUnit.ExtOutAirSchedPtr == 0) || (lNumericBlanks(2))) {
     441           0 :                     ShowSevereError(state,
     442           0 :                                     format("{}=\"{}\" invalid {}=\"{}\" not found.",
     443             :                                            CurrentModuleObject,
     444           0 :                                            state.dataIPShortCut->cAlphaArgs(1),
     445             :                                            cAlphaFields(8),
     446           0 :                                            state.dataIPShortCut->cAlphaArgs(8)));
     447           0 :                     ErrorsFound = true;
     448             :                 } else {
     449          12 :                     if ((thisOutAirUnit.ExtOutAirSchedPtr != thisOutAirUnit.OutAirSchedPtr) &&
     450           0 :                         (!state.dataHeatBal->ZoneAirMassFlow.EnforceZoneMassBalance)) {
     451           0 :                         ShowWarningError(
     452             :                             state,
     453           0 :                             format("{}=\"{}\", different schedule inputs for outdoor air and exhaust air schedules may cause unbalanced mass flow.",
     454             :                                    CurrentModuleObject,
     455           0 :                                    state.dataIPShortCut->cAlphaArgs(1)));
     456           0 :                         ShowContinueError(state,
     457           0 :                                           format("{}={} and {}={}",
     458             :                                                  cAlphaFields(4),
     459           0 :                                                  state.dataIPShortCut->cAlphaArgs(4),
     460             :                                                  cAlphaFields(8),
     461           0 :                                                  state.dataIPShortCut->cAlphaArgs(8)));
     462             :                     }
     463             :                 }
     464             : 
     465          24 :                 SetUpCompSets(
     466          12 :                     state, CurrentModuleObject, thisOutAirUnit.Name, "UNDEFINED", state.dataIPShortCut->cAlphaArgs(7), "UNDEFINED", "UNDEFINED");
     467             :             }
     468             : 
     469             :             // Process the unit control type
     470          12 :             if (!lAlphaBlanks(9)) {
     471          12 :                 constexpr std::array<std::string_view, static_cast<int>(OAUnitCtrlType::Num)> ctrlTypeNamesUC = {
     472             :                     "NEUTRALCONTROL", "INVALID-UNCONDITIONED", "TEMPERATURECONTROL"};
     473          12 :                 OAUnitCtrlType const tmpCtrlType = static_cast<OAUnitCtrlType>(getEnumValue(ctrlTypeNamesUC, state.dataIPShortCut->cAlphaArgs(9)));
     474          12 :                 switch (tmpCtrlType) {
     475          12 :                 case OAUnitCtrlType::Neutral:
     476             :                 case OAUnitCtrlType::Temperature:
     477          12 :                     thisOutAirUnit.controlType = tmpCtrlType;
     478          12 :                     break;
     479           0 :                 default:
     480           0 :                     break; // just leave it alone, nothing was done here
     481             :                 }
     482             :             } else {
     483           0 :                 ShowSevereError(state,
     484           0 :                                 format(R"({}="{}" invalid {}="{}".)",
     485             :                                        CurrentModuleObject,
     486           0 :                                        state.dataIPShortCut->cAlphaArgs(1),
     487             :                                        cAlphaFields(9),
     488           0 :                                        state.dataIPShortCut->cAlphaArgs(9)));
     489           0 :                 ShowContinueError(state, "Control reset to Unconditioned Control.");
     490           0 :                 thisOutAirUnit.controlType = OAUnitCtrlType::Neutral;
     491             :             }
     492             : 
     493             :             // A10:High Control Temp :
     494          12 :             thisOutAirUnit.HiCtrlTempSched = state.dataIPShortCut->cAlphaArgs(10);
     495          12 :             thisOutAirUnit.HiCtrlTempSchedPtr = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(10));
     496          12 :             if ((thisOutAirUnit.HiCtrlTempSchedPtr == 0) && (!lAlphaBlanks(10))) {
     497           0 :                 ShowSevereError(state,
     498           0 :                                 format(R"({}="{}" invalid {}="{}" not found.)",
     499             :                                        CurrentModuleObject,
     500           0 :                                        state.dataIPShortCut->cAlphaArgs(1),
     501             :                                        cAlphaFields(10),
     502           0 :                                        state.dataIPShortCut->cAlphaArgs(9)));
     503           0 :                 ErrorsFound = true;
     504             :             }
     505             : 
     506             :             // A11:Low Control Temp :
     507          12 :             thisOutAirUnit.LoCtrlTempSched = state.dataIPShortCut->cAlphaArgs(11);
     508          12 :             thisOutAirUnit.LoCtrlTempSchedPtr = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(11));
     509          12 :             if ((thisOutAirUnit.LoCtrlTempSchedPtr == 0) && (!lAlphaBlanks(11))) {
     510           0 :                 ShowSevereError(state,
     511           0 :                                 format(R"({}="{}" invalid {}="{}" not found.)",
     512             :                                        CurrentModuleObject,
     513           0 :                                        state.dataIPShortCut->cAlphaArgs(1),
     514             :                                        cAlphaFields(11),
     515           0 :                                        state.dataIPShortCut->cAlphaArgs(10)));
     516           0 :                 ErrorsFound = true;
     517             :             }
     518             : 
     519          12 :             thisOutAirUnit.CompOutSetTemp = 0.0;
     520             : 
     521             :             // A12~A15 : Node Condition
     522             : 
     523             :             // Main air nodes (except outside air node):
     524             : 
     525          12 :             thisOutAirUnit.AirOutletNode = GetOnlySingleNode(state,
     526          12 :                                                              state.dataIPShortCut->cAlphaArgs(13),
     527             :                                                              ErrorsFound,
     528             :                                                              DataLoopNode::ConnectionObjectType::ZoneHVACOutdoorAirUnit,
     529          12 :                                                              state.dataIPShortCut->cAlphaArgs(1),
     530             :                                                              DataLoopNode::NodeFluidType::Air,
     531             :                                                              DataLoopNode::ConnectionType::Outlet,
     532             :                                                              NodeInputManager::CompFluidStream::Primary,
     533             :                                                              ObjectIsParent);
     534          12 :             if (!lAlphaBlanks(14)) {
     535          24 :                 thisOutAirUnit.AirInletNode = GetOnlySingleNode(state,
     536          12 :                                                                 state.dataIPShortCut->cAlphaArgs(14),
     537             :                                                                 ErrorsFound,
     538             :                                                                 DataLoopNode::ConnectionObjectType::ZoneHVACOutdoorAirUnit,
     539          12 :                                                                 state.dataIPShortCut->cAlphaArgs(1),
     540             :                                                                 DataLoopNode::NodeFluidType::Air,
     541             :                                                                 DataLoopNode::ConnectionType::Inlet,
     542             :                                                                 NodeInputManager::CompFluidStream::Primary,
     543             :                                                                 ObjectIsParent);
     544             :             } else {
     545           0 :                 if (thisOutAirUnit.ExtFan) {
     546           0 :                     ShowSevereError(state,
     547           0 :                                     format("{}=\"{}\" invalid {} cannot be blank when there is an exhaust fan.",
     548             :                                            CurrentModuleObject,
     549           0 :                                            state.dataIPShortCut->cAlphaArgs(1),
     550             :                                            cAlphaFields(14)));
     551           0 :                     ErrorsFound = true;
     552             :                 }
     553             :             }
     554             : 
     555          12 :             thisOutAirUnit.SFanOutletNode = GetOnlySingleNode(state,
     556          12 :                                                               state.dataIPShortCut->cAlphaArgs(15),
     557             :                                                               ErrorsFound,
     558             :                                                               DataLoopNode::ConnectionObjectType::ZoneHVACOutdoorAirUnit,
     559          12 :                                                               state.dataIPShortCut->cAlphaArgs(1),
     560             :                                                               DataLoopNode::NodeFluidType::Air,
     561             :                                                               DataLoopNode::ConnectionType::Internal,
     562             :                                                               NodeInputManager::CompFluidStream::Primary,
     563             :                                                               ObjectIsNotParent);
     564             : 
     565             :             //  Set connection type to 'OutdoorAir', because this is hardwired to OA conditions
     566          12 :             thisOutAirUnit.OutsideAirNode = GetOnlySingleNode(state,
     567          12 :                                                               state.dataIPShortCut->cAlphaArgs(12),
     568             :                                                               ErrorsFound,
     569             :                                                               DataLoopNode::ConnectionObjectType::ZoneHVACOutdoorAirUnit,
     570          12 :                                                               state.dataIPShortCut->cAlphaArgs(1),
     571             :                                                               DataLoopNode::NodeFluidType::Air,
     572             :                                                               DataLoopNode::ConnectionType::OutsideAirReference,
     573             :                                                               NodeInputManager::CompFluidStream::Primary,
     574             :                                                               ObjectIsNotParent);
     575             : 
     576          12 :             if (!lAlphaBlanks(12)) {
     577          12 :                 CheckAndAddAirNodeNumber(state, thisOutAirUnit.OutsideAirNode, IsValid);
     578          12 :                 if (!IsValid) {
     579           0 :                     ShowWarningError(state,
     580           0 :                                      format("{}=\"{}\", Adding OutdoorAir:Node={}",
     581             :                                             CurrentModuleObject,
     582           0 :                                             state.dataIPShortCut->cAlphaArgs(1),
     583           0 :                                             state.dataIPShortCut->cAlphaArgs(12)));
     584             :                 }
     585             :             }
     586             : 
     587             :             // When the fan position is "BlowThru", Each node is set up
     588             : 
     589          12 :             if (thisOutAirUnit.supFanPlace == HVAC::FanPlace::BlowThru) {
     590          12 :                 SetUpCompSets(state,
     591             :                               CurrentModuleObject,
     592             :                               thisOutAirUnit.Name,
     593             :                               "UNDEFINED",
     594           6 :                               state.dataIPShortCut->cAlphaArgs(5),
     595           6 :                               state.dataIPShortCut->cAlphaArgs(12),
     596           6 :                               state.dataIPShortCut->cAlphaArgs(15));
     597             :             }
     598             : 
     599             :             // A16 : component list
     600             : 
     601          12 :             GlobalNames::IntraObjUniquenessCheck(state,
     602          12 :                                                  state.dataIPShortCut->cAlphaArgs(16),
     603             :                                                  CurrentModuleObject,
     604          12 :                                                  cAlphaFields(16),
     605          12 :                                                  state.dataOutdoorAirUnit->ComponentListUniqueNames,
     606             :                                                  ErrorsFound);
     607          24 :             std::string const ComponentListName = state.dataIPShortCut->cAlphaArgs(16);
     608          12 :             thisOutAirUnit.ComponentListName = ComponentListName;
     609          12 :             if (!lAlphaBlanks(16)) {
     610          12 :                 int const ListNum = state.dataInputProcessing->inputProcessor->getObjectItemNum(state, ZoneHVACEqList, ComponentListName);
     611          12 :                 if (ListNum > 0) {
     612          12 :                     state.dataInputProcessing->inputProcessor->getObjectItem(
     613             :                         state, ZoneHVACEqList, ListNum, AlphArray, NumAlphas, NumArray, NumNums, IOStat);
     614          12 :                     int NumInList = (NumAlphas - 1) / 2; // potential problem if puts in type but not name
     615          12 :                     if (mod(NumAlphas - 1, 2) != 0) {
     616           0 :                         ++NumInList;
     617             :                     }
     618          12 :                     thisOutAirUnit.NumComponents = NumInList;
     619          12 :                     thisOutAirUnit.OAEquip.allocate(NumInList);
     620             : 
     621             :                     // Get information of component
     622          51 :                     for (int InListNum = 1; InListNum <= NumInList; ++InListNum) {
     623          39 :                         thisOutAirUnit.OAEquip(InListNum).ComponentName = AlphArray(InListNum * 2 + 1);
     624             : 
     625          78 :                         thisOutAirUnit.OAEquip(InListNum).Type =
     626          39 :                             static_cast<CompType>(getEnumValue(CompTypeNamesUC, Util::makeUPPER(AlphArray(InListNum * 2))));
     627             : 
     628          39 :                         int const CompNum = InListNum;
     629             : 
     630             :                         // Coil Types
     631          39 :                         switch (thisOutAirUnit.OAEquip(InListNum).Type) {
     632           6 :                         case CompType::WaterCoil_Cooling: {
     633           6 :                             thisOutAirUnit.OAEquip(CompNum).CoilType = DataPlant::PlantEquipmentType::CoilWaterCooling;
     634          12 :                             thisOutAirUnit.OAEquip(CompNum).ComponentIndex =
     635           6 :                                 GetWaterCoilIndex(state,
     636           6 :                                                   CompTypeNamesUC[static_cast<int>(thisOutAirUnit.OAEquip(CompNum).Type)],
     637           6 :                                                   thisOutAirUnit.OAEquip(CompNum).ComponentName,
     638             :                                                   ErrorsFound);
     639          12 :                             thisOutAirUnit.OAEquip(CompNum).CoilAirInletNode =
     640           6 :                                 WaterCoils::GetCoilInletNode(state,
     641           6 :                                                              CompTypeNames[static_cast<int>(thisOutAirUnit.OAEquip(CompNum).Type)],
     642           6 :                                                              thisOutAirUnit.OAEquip(CompNum).ComponentName,
     643             :                                                              ErrorsFound);
     644          12 :                             thisOutAirUnit.OAEquip(CompNum).CoilAirOutletNode =
     645           6 :                                 WaterCoils::GetCoilOutletNode(state,
     646           6 :                                                               CompTypeNames[static_cast<int>(thisOutAirUnit.OAEquip(CompNum).Type)],
     647           6 :                                                               thisOutAirUnit.OAEquip(CompNum).ComponentName,
     648             :                                                               ErrorsFound);
     649          12 :                             thisOutAirUnit.OAEquip(CompNum).CoilWaterInletNode =
     650           6 :                                 GetCoilWaterInletNode(state,
     651           6 :                                                       CompTypeNames[static_cast<int>(thisOutAirUnit.OAEquip(CompNum).Type)],
     652           6 :                                                       thisOutAirUnit.OAEquip(CompNum).ComponentName,
     653             :                                                       ErrorsFound);
     654          12 :                             thisOutAirUnit.OAEquip(CompNum).CoilWaterOutletNode =
     655           6 :                                 GetCoilWaterOutletNode(state,
     656           6 :                                                        CompTypeNames[static_cast<int>(thisOutAirUnit.OAEquip(CompNum).Type)],
     657           6 :                                                        thisOutAirUnit.OAEquip(CompNum).ComponentName,
     658             :                                                        ErrorsFound);
     659          12 :                             thisOutAirUnit.OAEquip(CompNum).MaxVolWaterFlow =
     660           6 :                                 WaterCoils::GetCoilMaxWaterFlowRate(state,
     661           6 :                                                                     CompTypeNames[static_cast<int>(thisOutAirUnit.OAEquip(CompNum).Type)],
     662           6 :                                                                     thisOutAirUnit.OAEquip(CompNum).ComponentName,
     663             :                                                                     ErrorsFound);
     664           6 :                             thisOutAirUnit.OAEquip(CompNum).MinVolWaterFlow = 0.0;
     665           6 :                             break;
     666             :                         }
     667           6 :                         case CompType::WaterCoil_SimpleHeat: {
     668           6 :                             thisOutAirUnit.OAEquip(CompNum).CoilType = DataPlant::PlantEquipmentType::CoilWaterSimpleHeating;
     669          12 :                             thisOutAirUnit.OAEquip(CompNum).ComponentIndex =
     670           6 :                                 GetWaterCoilIndex(state,
     671           6 :                                                   CompTypeNamesUC[static_cast<int>(thisOutAirUnit.OAEquip(CompNum).Type)],
     672           6 :                                                   thisOutAirUnit.OAEquip(CompNum).ComponentName,
     673             :                                                   ErrorsFound);
     674          12 :                             thisOutAirUnit.OAEquip(CompNum).CoilAirInletNode =
     675           6 :                                 WaterCoils::GetCoilInletNode(state,
     676           6 :                                                              CompTypeNames[static_cast<int>(thisOutAirUnit.OAEquip(CompNum).Type)],
     677           6 :                                                              thisOutAirUnit.OAEquip(CompNum).ComponentName,
     678             :                                                              ErrorsFound);
     679           6 :                             thisOutAirUnit.OAEquip(CompNum).CoilAirOutletNode = WaterCoils::GetCoilOutletNode(
     680           6 :                                 state, "Coil:Heating:Water", thisOutAirUnit.OAEquip(CompNum).ComponentName, ErrorsFound);
     681          12 :                             thisOutAirUnit.OAEquip(CompNum).CoilWaterInletNode =
     682           6 :                                 GetCoilWaterInletNode(state,
     683           6 :                                                       CompTypeNames[static_cast<int>(thisOutAirUnit.OAEquip(CompNum).Type)],
     684           6 :                                                       thisOutAirUnit.OAEquip(CompNum).ComponentName,
     685             :                                                       ErrorsFound);
     686          12 :                             thisOutAirUnit.OAEquip(CompNum).CoilWaterOutletNode =
     687           6 :                                 GetCoilWaterOutletNode(state,
     688           6 :                                                        CompTypeNames[static_cast<int>(thisOutAirUnit.OAEquip(CompNum).Type)],
     689           6 :                                                        thisOutAirUnit.OAEquip(CompNum).ComponentName,
     690             :                                                        ErrorsFound);
     691           6 :                             thisOutAirUnit.OAEquip(CompNum).MaxVolWaterFlow = WaterCoils::GetCoilMaxWaterFlowRate(
     692           6 :                                 state, "Coil:Heating:Water", thisOutAirUnit.OAEquip(CompNum).ComponentName, ErrorsFound);
     693           6 :                             thisOutAirUnit.OAEquip(CompNum).MinVolWaterFlow = 0.0;
     694           6 :                             break;
     695             :                         }
     696           0 :                         case CompType::SteamCoil_AirHeat: {
     697           0 :                             thisOutAirUnit.OAEquip(CompNum).CoilType = DataPlant::PlantEquipmentType::CoilSteamAirHeating;
     698           0 :                             thisOutAirUnit.OAEquip(CompNum).ComponentIndex =
     699           0 :                                 GetSteamCoilIndex(state,
     700           0 :                                                   CompTypeNamesUC[static_cast<int>(thisOutAirUnit.OAEquip(CompNum).Type)],
     701           0 :                                                   thisOutAirUnit.OAEquip(CompNum).ComponentName,
     702             :                                                   ErrorsFound);
     703           0 :                             thisOutAirUnit.OAEquip(CompNum).CoilAirInletNode = GetCoilAirInletNode(
     704           0 :                                 state, thisOutAirUnit.OAEquip(CompNum).ComponentIndex, thisOutAirUnit.OAEquip(CompNum).ComponentName, ErrorsFound);
     705           0 :                             thisOutAirUnit.OAEquip(CompNum).CoilAirOutletNode = GetCoilAirOutletNode(
     706           0 :                                 state, thisOutAirUnit.OAEquip(CompNum).ComponentIndex, thisOutAirUnit.OAEquip(CompNum).ComponentName, ErrorsFound);
     707           0 :                             thisOutAirUnit.OAEquip(CompNum).CoilWaterInletNode = GetCoilSteamInletNode(
     708           0 :                                 state, thisOutAirUnit.OAEquip(CompNum).ComponentIndex, thisOutAirUnit.OAEquip(CompNum).ComponentName, ErrorsFound);
     709           0 :                             thisOutAirUnit.OAEquip(CompNum).CoilWaterOutletNode =
     710           0 :                                 GetCoilSteamOutletNode(state,
     711           0 :                                                        CompTypeNames[static_cast<int>(thisOutAirUnit.OAEquip(CompNum).Type)],
     712           0 :                                                        thisOutAirUnit.OAEquip(CompNum).ComponentName,
     713             :                                                        ErrorsFound);
     714             : 
     715           0 :                             thisOutAirUnit.OAEquip(CompNum).MaxVolWaterFlow =
     716           0 :                                 GetCoilMaxSteamFlowRate(state, thisOutAirUnit.OAEquip(CompNum).ComponentIndex, ErrorsFound);
     717           0 :                             thisOutAirUnit.OAEquip(CompNum).MinVolWaterFlow = 0.0;
     718             :                             // below: no extra error needed if steam properties not in input
     719             :                             // file because getting the steam coil will have done that.
     720           0 :                             thisOutAirUnit.OAEquip(CompNum).FluidIndex = FluidProperties::GetRefrigNum(state, "STEAM");
     721           0 :                             break;
     722             :                         }
     723           0 :                         case CompType::WaterCoil_DetailedCool: {
     724           0 :                             thisOutAirUnit.OAEquip(CompNum).ComponentIndex =
     725           0 :                                 GetWaterCoilIndex(state,
     726           0 :                                                   CompTypeNamesUC[static_cast<int>(thisOutAirUnit.OAEquip(CompNum).Type)],
     727           0 :                                                   thisOutAirUnit.OAEquip(CompNum).ComponentName,
     728             :                                                   ErrorsFound);
     729           0 :                             thisOutAirUnit.OAEquip(CompNum).CoilType = DataPlant::PlantEquipmentType::CoilWaterDetailedFlatCooling;
     730           0 :                             thisOutAirUnit.OAEquip(CompNum).CoilAirInletNode =
     731           0 :                                 WaterCoils::GetCoilInletNode(state,
     732           0 :                                                              CompTypeNames[static_cast<int>(thisOutAirUnit.OAEquip(CompNum).Type)],
     733           0 :                                                              thisOutAirUnit.OAEquip(CompNum).ComponentName,
     734             :                                                              ErrorsFound);
     735           0 :                             thisOutAirUnit.OAEquip(CompNum).CoilAirOutletNode =
     736           0 :                                 WaterCoils::GetCoilOutletNode(state,
     737           0 :                                                               CompTypeNames[static_cast<int>(thisOutAirUnit.OAEquip(CompNum).Type)],
     738           0 :                                                               thisOutAirUnit.OAEquip(CompNum).ComponentName,
     739             :                                                               ErrorsFound);
     740           0 :                             thisOutAirUnit.OAEquip(CompNum).CoilWaterInletNode =
     741           0 :                                 GetCoilWaterInletNode(state,
     742           0 :                                                       CompTypeNames[static_cast<int>(thisOutAirUnit.OAEquip(CompNum).Type)],
     743           0 :                                                       thisOutAirUnit.OAEquip(CompNum).ComponentName,
     744             :                                                       ErrorsFound);
     745           0 :                             thisOutAirUnit.OAEquip(CompNum).CoilWaterOutletNode =
     746           0 :                                 GetCoilWaterOutletNode(state,
     747           0 :                                                        CompTypeNames[static_cast<int>(thisOutAirUnit.OAEquip(CompNum).Type)],
     748           0 :                                                        thisOutAirUnit.OAEquip(CompNum).ComponentName,
     749             :                                                        ErrorsFound);
     750           0 :                             thisOutAirUnit.OAEquip(CompNum).MaxVolWaterFlow =
     751           0 :                                 WaterCoils::GetCoilMaxWaterFlowRate(state,
     752           0 :                                                                     CompTypeNames[static_cast<int>(thisOutAirUnit.OAEquip(CompNum).Type)],
     753           0 :                                                                     thisOutAirUnit.OAEquip(CompNum).ComponentName,
     754             :                                                                     ErrorsFound);
     755           0 :                             thisOutAirUnit.OAEquip(CompNum).MinVolWaterFlow = 0.0;
     756           0 :                             break;
     757             :                         }
     758           0 :                         case CompType::WaterCoil_CoolingHXAsst: {
     759           0 :                             thisOutAirUnit.OAEquip(CompNum).CoilAirInletNode =
     760           0 :                                 HVACHXAssistedCoolingCoil::GetCoilInletNode(state,
     761           0 :                                                                             CompTypeNames[static_cast<int>(thisOutAirUnit.OAEquip(CompNum).Type)],
     762           0 :                                                                             thisOutAirUnit.OAEquip(CompNum).ComponentName,
     763             :                                                                             ErrorsFound);
     764           0 :                             thisOutAirUnit.OAEquip(CompNum).CoilAirOutletNode =
     765           0 :                                 HVACHXAssistedCoolingCoil::GetCoilOutletNode(state,
     766           0 :                                                                              CompTypeNames[static_cast<int>(thisOutAirUnit.OAEquip(CompNum).Type)],
     767           0 :                                                                              thisOutAirUnit.OAEquip(CompNum).ComponentName,
     768             :                                                                              ErrorsFound);
     769           0 :                             thisOutAirUnit.OAEquip(CompNum).CoilWaterInletNode =
     770           0 :                                 GetCoilWaterInletNode(state,
     771           0 :                                                       CompTypeNames[static_cast<int>(thisOutAirUnit.OAEquip(CompNum).Type)],
     772           0 :                                                       thisOutAirUnit.OAEquip(CompNum).ComponentName,
     773             :                                                       ErrorsFound);
     774           0 :                             thisOutAirUnit.OAEquip(CompNum).CoilWaterOutletNode =
     775           0 :                                 GetCoilWaterOutletNode(state,
     776           0 :                                                        CompTypeNames[static_cast<int>(thisOutAirUnit.OAEquip(CompNum).Type)],
     777           0 :                                                        thisOutAirUnit.OAEquip(CompNum).ComponentName,
     778             :                                                        ErrorsFound);
     779           0 :                             thisOutAirUnit.OAEquip(CompNum).MaxVolWaterFlow = HVACHXAssistedCoolingCoil::GetCoilMaxWaterFlowRate(
     780             :                                 state,
     781           0 :                                 CompTypeNames[static_cast<int>(thisOutAirUnit.OAEquip(CompNum).Type)],
     782           0 :                                 thisOutAirUnit.OAEquip(CompNum).ComponentName,
     783             :                                 ErrorsFound);
     784           0 :                             thisOutAirUnit.OAEquip(CompNum).MinVolWaterFlow = 0.0;
     785           0 :                             break;
     786             :                         }
     787           4 :                         case CompType::Coil_ElectricHeat: {
     788             :                             // Get OutAirUnit( OAUnitNum ).OAEquip( CompNum ).ComponentIndex, 2 types of mining functions to choose from
     789           4 :                             HeatingCoils::GetCoilIndex(
     790           4 :                                 state, thisOutAirUnit.OAEquip(CompNum).ComponentName, thisOutAirUnit.OAEquip(CompNum).ComponentIndex, ErrorsFound);
     791           8 :                             thisOutAirUnit.OAEquip(CompNum).CoilAirInletNode =
     792           4 :                                 HeatingCoils::GetCoilInletNode(state,
     793           4 :                                                                CompTypeNames[static_cast<int>(thisOutAirUnit.OAEquip(CompNum).Type)],
     794           4 :                                                                thisOutAirUnit.OAEquip(CompNum).ComponentName,
     795             :                                                                ErrorsFound);
     796           8 :                             thisOutAirUnit.OAEquip(CompNum).CoilAirOutletNode =
     797           4 :                                 HeatingCoils::GetCoilOutletNode(state,
     798           4 :                                                                 CompTypeNames[static_cast<int>(thisOutAirUnit.OAEquip(CompNum).Type)],
     799           4 :                                                                 thisOutAirUnit.OAEquip(CompNum).ComponentName,
     800             :                                                                 ErrorsFound);
     801           4 :                             break;
     802             :                         }
     803           2 :                         case CompType::Coil_GasHeat: {
     804             :                             // Get OutAirUnit( OAUnitNum ).OAEquip( CompNum ).ComponentIndex, 2 types of mining functions to choose from
     805           2 :                             HeatingCoils::GetCoilIndex(
     806           2 :                                 state, thisOutAirUnit.OAEquip(CompNum).ComponentName, thisOutAirUnit.OAEquip(CompNum).ComponentIndex, ErrorsFound);
     807           4 :                             thisOutAirUnit.OAEquip(CompNum).CoilAirInletNode =
     808           2 :                                 GetCoilInletNode(state,
     809           2 :                                                  CompTypeNames[static_cast<int>(thisOutAirUnit.OAEquip(CompNum).Type)],
     810           2 :                                                  thisOutAirUnit.OAEquip(CompNum).ComponentName,
     811             :                                                  ErrorsFound);
     812           4 :                             thisOutAirUnit.OAEquip(CompNum).CoilAirOutletNode =
     813           2 :                                 GetCoilOutletNode(state,
     814           2 :                                                   CompTypeNames[static_cast<int>(thisOutAirUnit.OAEquip(CompNum).Type)],
     815           2 :                                                   thisOutAirUnit.OAEquip(CompNum).ComponentName,
     816             :                                                   ErrorsFound);
     817           2 :                             break;
     818             :                         }
     819           8 :                         case CompType::DXSystem: {
     820             :                             // set the data for 100% DOAS DX cooling coil
     821             :                             // is a different function call needed here? similar to one in HVACDXSystem
     822             :                             // CheckDXCoolingCoilInOASysExists(state, thisOutAirUnit.OAEquip(CompNum).ComponentName);
     823           8 :                             break;
     824             :                         }
     825           1 :                         case CompType::DXHeatPumpSystem: {
     826           1 :                             break;
     827             :                         }
     828           0 :                         case CompType::UnitarySystemModel: {
     829           0 :                             UnitarySystems::UnitarySys thisSys;
     830           0 :                             thisOutAirUnit.OAEquip(CompNum).compPointer = thisSys.factory(
     831           0 :                                 state, HVAC::UnitarySysType::Unitary_AnyCoilType, thisOutAirUnit.OAEquip(CompNum).ComponentName, false, OAUnitNum);
     832           0 :                             UnitarySystems::UnitarySys::checkUnitarySysCoilInOASysExists(
     833           0 :                                 state, thisOutAirUnit.OAEquip(CompNum).ComponentName, OAUnitNum);
     834             : 
     835             :                             // Heat recovery
     836           0 :                             break;
     837           0 :                         }
     838          10 :                         case CompType::HeatXchngrFP:
     839             :                         case CompType::HeatXchngrSL: {
     840             :                             //        CASE('HEATEXCHANGER:DESICCANT:BALANCEDFLOW')
     841             :                             //          thisOutAirUnit%OAEquip(CompNum)%Type= CompType::HeatXchngr
     842             : 
     843             :                             // Desiccant Dehumidifier
     844          10 :                             break;
     845             :                         }
     846           2 :                         case CompType::Desiccant: {
     847             :                             // Futher Enhancement
     848             :                             //        CASE('DEHUMIDIFIER:DESICCANT:SYSTEM')
     849             :                             //          thisOutAirUnit%OAEquip(CompNum)%Type= CompType::Desiccant
     850           2 :                             break;
     851             :                         }
     852           0 :                         default: {
     853           0 :                             ShowSevereError(state,
     854           0 :                                             format("{}= \"{}\" invalid Outside Air Component=\"{}\".",
     855             :                                                    CurrentModuleObject,
     856             :                                                    AlphArray(1),
     857           0 :                                                    CompTypeNames[static_cast<int>(thisOutAirUnit.OAEquip(CompNum).Type)]));
     858           0 :                             ErrorsFound = true;
     859             :                         }
     860             :                         }
     861             : 
     862             :                         // Add equipment to component sets array
     863             :                         // Node set up
     864          39 :                         if (thisOutAirUnit.supFanPlace == HVAC::FanPlace::BlowThru) {
     865          22 :                             if (InListNum == 1) { // the component is the first one
     866          12 :                                 SetUpCompSets(state,
     867             :                                               "ZoneHVAC:OutdoorAirUnit",
     868             :                                               thisOutAirUnit.Name,
     869           6 :                                               CompTypeNames[static_cast<int>(thisOutAirUnit.OAEquip(InListNum).Type)],
     870           6 :                                               thisOutAirUnit.OAEquip(InListNum).ComponentName,
     871           6 :                                               state.dataIPShortCut->cAlphaArgs(15),
     872             :                                               "UNDEFINED");
     873          16 :                             } else if (InListNum != NumInList) { // the component is placed in b/w components
     874          20 :                                 SetUpCompSets(state,
     875             :                                               "ZoneHVAC:OutdoorAirUnit",
     876             :                                               thisOutAirUnit.Name,
     877          10 :                                               CompTypeNames[static_cast<int>(thisOutAirUnit.OAEquip(InListNum).Type)],
     878          10 :                                               thisOutAirUnit.OAEquip(InListNum).ComponentName,
     879             :                                               "UNDEFINED",
     880             :                                               "UNDEFINED");
     881             :                             } else { // (InListNum == NumInList) => the component is the last one
     882          18 :                                 SetUpCompSets(state,
     883             :                                               "ZoneHVAC:OutdoorAirUnit",
     884             :                                               thisOutAirUnit.Name,
     885           6 :                                               CompTypeNames[static_cast<int>(thisOutAirUnit.OAEquip(InListNum).Type)],
     886           6 :                                               thisOutAirUnit.OAEquip(InListNum).ComponentName,
     887             :                                               "UNDEFINED",
     888           6 :                                               state.dataIPShortCut->cAlphaArgs(13));
     889             :                             }
     890             :                             // If fan is on the end of equipment.
     891          17 :                         } else if (thisOutAirUnit.supFanPlace == HVAC::FanPlace::DrawThru) {
     892          17 :                             if (InListNum == 1) {
     893          12 :                                 SetUpCompSets(state,
     894             :                                               "ZoneHVAC:OutdoorAirUnit",
     895             :                                               thisOutAirUnit.Name,
     896           6 :                                               CompTypeNames[static_cast<int>(thisOutAirUnit.OAEquip(InListNum).Type)],
     897           6 :                                               thisOutAirUnit.OAEquip(InListNum).ComponentName,
     898           6 :                                               state.dataIPShortCut->cAlphaArgs(12),
     899             :                                               "UNDEFINED");
     900          11 :                             } else if (InListNum != NumInList) {
     901          10 :                                 SetUpCompSets(state,
     902             :                                               "ZoneHVAC:OutdoorAirUnit",
     903             :                                               thisOutAirUnit.Name,
     904           5 :                                               CompTypeNames[static_cast<int>(thisOutAirUnit.OAEquip(InListNum).Type)],
     905           5 :                                               thisOutAirUnit.OAEquip(InListNum).ComponentName,
     906             :                                               "UNDEFINED",
     907             :                                               "UNDEFINED");
     908             :                             } else { // (InListNum == NumInList) => the component is the last one
     909          12 :                                 SetUpCompSets(state,
     910             :                                               "ZoneHVAC:OutdoorAirUnit",
     911             :                                               thisOutAirUnit.Name,
     912           6 :                                               CompTypeNames[static_cast<int>(thisOutAirUnit.OAEquip(InListNum).Type)],
     913           6 :                                               thisOutAirUnit.OAEquip(InListNum).ComponentName,
     914             :                                               "UNDEFINED",
     915             :                                               "UNDEFINED");
     916             :                             }
     917             :                         }
     918             :                         // Must call after SetUpCompSets since this will add another CoilSystem:Cooling:DX object in CompSets
     919          39 :                         if (CompTypeNamesUC[static_cast<int>(thisOutAirUnit.OAEquip(InListNum).Type)] == "COILSYSTEM:COOLING:DX") {
     920           8 :                             UnitarySystems::UnitarySys::checkUnitarySysCoilInOASysExists(
     921           8 :                                 state, thisOutAirUnit.OAEquip(CompNum).ComponentName, OAUnitNum);
     922             :                         }
     923             :                     } // End Inlist
     924             : 
     925             :                     // In case of draw through, the last component is linked with the zone air supply node
     926          12 :                     if (thisOutAirUnit.supFanPlace == HVAC::FanPlace::DrawThru) {
     927          18 :                         SetUpCompSets(state,
     928             :                                       CurrentModuleObject,
     929             :                                       thisOutAirUnit.Name,
     930             :                                       "UNDEFINED",
     931           6 :                                       state.dataIPShortCut->cAlphaArgs(5),
     932             :                                       "UNDEFINED",
     933           6 :                                       state.dataIPShortCut->cAlphaArgs(13));
     934             :                     }
     935             : 
     936             :                 } else { // when ListNum<0
     937           0 :                     ShowSevereError(state,
     938           0 :                                     format("{} = \"{}\" invalid {}=\"{}\" not found.",
     939             :                                            CurrentModuleObject,
     940           0 :                                            state.dataIPShortCut->cAlphaArgs(1),
     941             :                                            cAlphaFields(16),
     942           0 :                                            state.dataIPShortCut->cAlphaArgs(16)));
     943           0 :                     ErrorsFound = true;
     944             :                 }
     945             :             } else { // when Equipment list is left blanked
     946           0 :                 ShowSevereError(state,
     947           0 :                                 format("{} = \"{}\" invalid {} is blank and must be entered.",
     948             :                                        CurrentModuleObject,
     949           0 :                                        state.dataIPShortCut->cAlphaArgs(1),
     950             :                                        cAlphaFields(16)));
     951           0 :                 ErrorsFound = true;
     952             :             }
     953          12 :             if (!lAlphaBlanks(17)) {
     954           0 :                 thisOutAirUnit.AvailManagerListName = state.dataIPShortCut->cAlphaArgs(17);
     955             :             }
     956             :         }
     957             : 
     958           2 :         if (ErrorsFound) {
     959           0 :             ShowFatalError(state, format("{}Errors found in getting {}.", RoutineName, CurrentModuleObject));
     960             :         }
     961             : 
     962           2 :         AlphArray.deallocate();
     963           2 :         cAlphaFields.deallocate();
     964           2 :         NumArray.deallocate();
     965           2 :         cNumericFields.deallocate();
     966           2 :         lAlphaBlanks.deallocate();
     967           2 :         lNumericBlanks.deallocate();
     968             : 
     969           2 :         state.dataOutdoorAirUnit->GetOutdoorAirUnitInputFlag = false;
     970             : 
     971             :         // Setup Report variables for the zone outdoor air unit CurrentModuleObject='ZoneHVAC:OutdoorAirUnit'
     972          14 :         for (int OAUnitNum = 1; OAUnitNum <= state.dataOutdoorAirUnit->NumOfOAUnits; ++OAUnitNum) {
     973             : 
     974          12 :             auto &thisOutAirUnit = state.dataOutdoorAirUnit->OutAirUnit(OAUnitNum);
     975             : 
     976          24 :             SetupOutputVariable(state,
     977             :                                 "Zone Outdoor Air Unit Total Heating Rate",
     978             :                                 Constant::Units::W,
     979          12 :                                 thisOutAirUnit.TotHeatingRate,
     980             :                                 OutputProcessor::TimeStepType::System,
     981             :                                 OutputProcessor::StoreType::Average,
     982          12 :                                 thisOutAirUnit.Name);
     983          24 :             SetupOutputVariable(state,
     984             :                                 "Zone Outdoor Air Unit Total Heating Energy",
     985             :                                 Constant::Units::J,
     986          12 :                                 thisOutAirUnit.TotHeatingEnergy,
     987             :                                 OutputProcessor::TimeStepType::System,
     988             :                                 OutputProcessor::StoreType::Sum,
     989          12 :                                 thisOutAirUnit.Name);
     990          24 :             SetupOutputVariable(state,
     991             :                                 "Zone Outdoor Air Unit Sensible Heating Rate",
     992             :                                 Constant::Units::W,
     993          12 :                                 thisOutAirUnit.SensHeatingRate,
     994             :                                 OutputProcessor::TimeStepType::System,
     995             :                                 OutputProcessor::StoreType::Average,
     996          12 :                                 thisOutAirUnit.Name);
     997          24 :             SetupOutputVariable(state,
     998             :                                 "Zone Outdoor Air Unit Sensible Heating Energy",
     999             :                                 Constant::Units::J,
    1000          12 :                                 thisOutAirUnit.SensHeatingEnergy,
    1001             :                                 OutputProcessor::TimeStepType::System,
    1002             :                                 OutputProcessor::StoreType::Sum,
    1003          12 :                                 thisOutAirUnit.Name);
    1004          24 :             SetupOutputVariable(state,
    1005             :                                 "Zone Outdoor Air Unit Latent Heating Rate",
    1006             :                                 Constant::Units::W,
    1007          12 :                                 thisOutAirUnit.LatHeatingRate,
    1008             :                                 OutputProcessor::TimeStepType::System,
    1009             :                                 OutputProcessor::StoreType::Average,
    1010          12 :                                 thisOutAirUnit.Name);
    1011          24 :             SetupOutputVariable(state,
    1012             :                                 "Zone Outdoor Air Unit Latent Heating Energy",
    1013             :                                 Constant::Units::J,
    1014          12 :                                 thisOutAirUnit.LatHeatingEnergy,
    1015             :                                 OutputProcessor::TimeStepType::System,
    1016             :                                 OutputProcessor::StoreType::Sum,
    1017          12 :                                 thisOutAirUnit.Name);
    1018          24 :             SetupOutputVariable(state,
    1019             :                                 "Zone Outdoor Air Unit Total Cooling Rate",
    1020             :                                 Constant::Units::W,
    1021          12 :                                 thisOutAirUnit.TotCoolingRate,
    1022             :                                 OutputProcessor::TimeStepType::System,
    1023             :                                 OutputProcessor::StoreType::Average,
    1024          12 :                                 thisOutAirUnit.Name);
    1025          24 :             SetupOutputVariable(state,
    1026             :                                 "Zone Outdoor Air Unit Total Cooling Energy",
    1027             :                                 Constant::Units::J,
    1028          12 :                                 thisOutAirUnit.TotCoolingEnergy,
    1029             :                                 OutputProcessor::TimeStepType::System,
    1030             :                                 OutputProcessor::StoreType::Sum,
    1031          12 :                                 thisOutAirUnit.Name);
    1032          24 :             SetupOutputVariable(state,
    1033             :                                 "Zone Outdoor Air Unit Sensible Cooling Rate",
    1034             :                                 Constant::Units::W,
    1035          12 :                                 thisOutAirUnit.SensCoolingRate,
    1036             :                                 OutputProcessor::TimeStepType::System,
    1037             :                                 OutputProcessor::StoreType::Average,
    1038          12 :                                 thisOutAirUnit.Name);
    1039          24 :             SetupOutputVariable(state,
    1040             :                                 "Zone Outdoor Air Unit Sensible Cooling Energy",
    1041             :                                 Constant::Units::J,
    1042          12 :                                 thisOutAirUnit.SensCoolingEnergy,
    1043             :                                 OutputProcessor::TimeStepType::System,
    1044             :                                 OutputProcessor::StoreType::Sum,
    1045          12 :                                 thisOutAirUnit.Name);
    1046          24 :             SetupOutputVariable(state,
    1047             :                                 "Zone Outdoor Air Unit Latent Cooling Rate",
    1048             :                                 Constant::Units::W,
    1049          12 :                                 thisOutAirUnit.LatCoolingRate,
    1050             :                                 OutputProcessor::TimeStepType::System,
    1051             :                                 OutputProcessor::StoreType::Average,
    1052          12 :                                 thisOutAirUnit.Name);
    1053          24 :             SetupOutputVariable(state,
    1054             :                                 "Zone Outdoor Air Unit Latent Cooling Energy",
    1055             :                                 Constant::Units::J,
    1056          12 :                                 thisOutAirUnit.LatCoolingEnergy,
    1057             :                                 OutputProcessor::TimeStepType::System,
    1058             :                                 OutputProcessor::StoreType::Sum,
    1059          12 :                                 thisOutAirUnit.Name);
    1060          24 :             SetupOutputVariable(state,
    1061             :                                 "Zone Outdoor Air Unit Air Mass Flow Rate",
    1062             :                                 Constant::Units::kg_s,
    1063          12 :                                 thisOutAirUnit.AirMassFlow,
    1064             :                                 OutputProcessor::TimeStepType::System,
    1065             :                                 OutputProcessor::StoreType::Average,
    1066          12 :                                 thisOutAirUnit.Name);
    1067          24 :             SetupOutputVariable(state,
    1068             :                                 "Zone Outdoor Air Unit Fan Electricity Rate",
    1069             :                                 Constant::Units::W,
    1070          12 :                                 thisOutAirUnit.ElecFanRate,
    1071             :                                 OutputProcessor::TimeStepType::System,
    1072             :                                 OutputProcessor::StoreType::Average,
    1073          12 :                                 thisOutAirUnit.Name);
    1074          24 :             SetupOutputVariable(state,
    1075             :                                 "Zone Outdoor Air Unit Fan Electricity Energy",
    1076             :                                 Constant::Units::J,
    1077          12 :                                 thisOutAirUnit.ElecFanEnergy,
    1078             :                                 OutputProcessor::TimeStepType::System,
    1079             :                                 OutputProcessor::StoreType::Sum,
    1080          12 :                                 thisOutAirUnit.Name);
    1081          12 :             SetupOutputVariable(state,
    1082             :                                 "Zone Outdoor Air Unit Fan Availability Status",
    1083             :                                 Constant::Units::None,
    1084          12 :                                 (int &)thisOutAirUnit.availStatus,
    1085             :                                 OutputProcessor::TimeStepType::System,
    1086             :                                 OutputProcessor::StoreType::Average,
    1087          12 :                                 thisOutAirUnit.Name);
    1088             :             //! Note that the outdoor air unit fan electric is NOT metered because this value is already metered through the fan component
    1089             :         }
    1090           2 :     }
    1091             : 
    1092       64806 :     void InitOutdoorAirUnit(EnergyPlusData &state,
    1093             :                             int const OAUnitNum,          // index for the current outdoor air unit
    1094             :                             int const ZoneNum,            // number of zone being served
    1095             :                             bool const FirstHVACIteration // TRUE if 1st HVAC simulation of system timestep
    1096             :     )
    1097             :     {
    1098             : 
    1099             :         // SUBROUTINE INFORMATION:
    1100             :         //       AUTHOR         Young Tae Chae, Rick Strand
    1101             :         //       DATE WRITTEN   July 2009
    1102             :         //       MODIFIED       July 2012, Chandan Sharma - FSEC: Added zone sys avail managers
    1103             :         //       RE-ENGINEERED  na
    1104             : 
    1105             :         // PURPOSE OF THIS SUBROUTINE:
    1106             :         // This subroutine initializes all of the data elements which are necessary
    1107             :         // to simulate a zone outdoor air control unit.
    1108             : 
    1109             :         // METHODOLOGY EMPLOYED:
    1110             :         // Uses the status flags to trigger initializations.
    1111             : 
    1112             :         // REFERENCES:
    1113             :         // na
    1114             : 
    1115             :         // Using/Aliasing
    1116             :         using DataZoneEquipment::CheckZoneEquipmentList;
    1117             :         using FluidProperties::GetDensityGlycol;
    1118             :         using HVACHXAssistedCoolingCoil::SimHXAssistedCoolingCoil;
    1119             :         using PlantUtilities::InitComponentNodes;
    1120             :         using PlantUtilities::ScanPlantLoopsForObject;
    1121             :         using ScheduleManager::GetCurrentScheduleValue;
    1122             :         using SteamCoils::GetCoilMaxSteamFlowRate;
    1123             :         using WaterCoils::SimulateWaterCoilComponents;
    1124             : 
    1125             :         // SUBROUTINE PARAMETER DEFINITIONS:
    1126             :         static constexpr std::string_view CurrentModuleObject("ZoneHVAC:OutdoorAirUnit");
    1127             :         static constexpr std::string_view RoutineName("SizeOutdoorAirUnit");
    1128             : 
    1129             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1130             :         // Do the one time initializations
    1131             : 
    1132       64806 :         auto &thisOutAirUnit = state.dataOutdoorAirUnit->OutAirUnit(OAUnitNum);
    1133             : 
    1134       64806 :         Real64 const RhoAir = state.dataEnvrn->StdRhoAir;
    1135       64806 :         int const InNode = thisOutAirUnit.AirInletNode;
    1136       64806 :         int const OutNode = thisOutAirUnit.AirOutletNode;
    1137       64806 :         int const OutsideAirNode = thisOutAirUnit.OutsideAirNode;
    1138       64806 :         Real64 const OAFrac = GetCurrentScheduleValue(state, thisOutAirUnit.OutAirSchedPtr);
    1139             : 
    1140       64806 :         if (state.dataOutdoorAirUnit->MyOneTimeFlag) {
    1141             : 
    1142           2 :             state.dataOutdoorAirUnit->MyEnvrnFlag.dimension(state.dataOutdoorAirUnit->NumOfOAUnits, true);
    1143           2 :             state.dataOutdoorAirUnit->MySizeFlag.dimension(state.dataOutdoorAirUnit->NumOfOAUnits, true);
    1144           2 :             state.dataOutdoorAirUnit->MyPlantScanFlag.dimension(state.dataOutdoorAirUnit->NumOfOAUnits, true);
    1145           2 :             state.dataOutdoorAirUnit->MyZoneEqFlag.dimension(state.dataOutdoorAirUnit->NumOfOAUnits, true);
    1146           2 :             state.dataOutdoorAirUnit->MyOneTimeFlag = false;
    1147             :         }
    1148             : 
    1149       64806 :         if (allocated(state.dataAvail->ZoneComp)) {
    1150       64806 :             auto &availMgr = state.dataAvail->ZoneComp(DataZoneEquipment::ZoneEquipType::OutdoorAirUnit).ZoneCompAvailMgrs(OAUnitNum);
    1151       64806 :             if (state.dataOutdoorAirUnit->MyZoneEqFlag(OAUnitNum)) { // initialize the name of each availability manager list and zone number
    1152          12 :                 availMgr.AvailManagerListName = thisOutAirUnit.AvailManagerListName;
    1153          12 :                 availMgr.ZoneNum = ZoneNum;
    1154          12 :                 state.dataOutdoorAirUnit->MyZoneEqFlag(OAUnitNum) = false;
    1155             :             }
    1156       64806 :             thisOutAirUnit.availStatus = availMgr.availStatus;
    1157             :         }
    1158             : 
    1159       64806 :         if (state.dataOutdoorAirUnit->MyPlantScanFlag(OAUnitNum) && allocated(state.dataPlnt->PlantLoop)) {
    1160          51 :             for (int compLoop = 1; compLoop <= thisOutAirUnit.NumComponents; ++compLoop) {
    1161             : 
    1162          39 :                 CompType const Type = thisOutAirUnit.OAEquip(compLoop).Type;
    1163             : 
    1164          39 :                 switch (Type) {
    1165          12 :                 case CompType::WaterCoil_Cooling:
    1166             :                 case CompType::WaterCoil_DetailedCool:
    1167             :                 case CompType::WaterCoil_SimpleHeat:
    1168             :                 case CompType::SteamCoil_AirHeat:
    1169             : 
    1170             :                 {
    1171          12 :                     bool errFlag = false;
    1172          24 :                     ScanPlantLoopsForObject(state,
    1173          12 :                                             thisOutAirUnit.OAEquip(compLoop).ComponentName,
    1174          12 :                                             thisOutAirUnit.OAEquip(compLoop).CoilType,
    1175          12 :                                             thisOutAirUnit.OAEquip(compLoop).plantLoc,
    1176             :                                             errFlag,
    1177             :                                             _,
    1178             :                                             _,
    1179             :                                             _,
    1180             :                                             _,
    1181             :                                             _);
    1182          12 :                     if (errFlag) {
    1183           0 :                         ShowFatalError(state, "InitOutdoorAirUnit: Program terminated for previous conditions.");
    1184             :                     }
    1185          12 :                     break;
    1186             :                 }
    1187          27 :                 default:
    1188          27 :                     break;
    1189             :                 }
    1190             :             }
    1191             : 
    1192          12 :             state.dataOutdoorAirUnit->MyPlantScanFlag(OAUnitNum) = false;
    1193       64794 :         } else if (state.dataOutdoorAirUnit->MyPlantScanFlag(OAUnitNum) && !state.dataGlobal->AnyPlantInModel) {
    1194           0 :             state.dataOutdoorAirUnit->MyPlantScanFlag(OAUnitNum) = false;
    1195             :         }
    1196             : 
    1197             :         // need to check all zone outdoor air control units to see if they are on Zone Equipment List or issue warning
    1198       64806 :         if (!state.dataOutdoorAirUnit->ZoneEquipmentListChecked && state.dataZoneEquip->ZoneEquipInputsFilled) {
    1199           2 :             state.dataOutdoorAirUnit->ZoneEquipmentListChecked = true;
    1200          14 :             for (int Loop = 1; Loop <= state.dataOutdoorAirUnit->NumOfOAUnits; ++Loop) {
    1201          12 :                 if (CheckZoneEquipmentList(state, CurrentModuleObject, state.dataOutdoorAirUnit->OutAirUnit(Loop).Name)) {
    1202          12 :                     continue;
    1203             :                 }
    1204           0 :                 ShowSevereError(
    1205             :                     state,
    1206           0 :                     format("InitOutdoorAirUnit: Zone Outdoor Air Unit=[{},{}] is not on any ZoneHVAC:EquipmentList.  It will not be simulated.",
    1207             :                            CurrentModuleObject,
    1208           0 :                            state.dataOutdoorAirUnit->OutAirUnit(Loop).Name));
    1209             :             }
    1210             :         }
    1211             : 
    1212       64818 :         if (!state.dataGlobal->SysSizingCalc && state.dataOutdoorAirUnit->MySizeFlag(OAUnitNum) &&
    1213          12 :             !state.dataOutdoorAirUnit->MyPlantScanFlag(OAUnitNum)) {
    1214             : 
    1215          12 :             SizeOutdoorAirUnit(state, OAUnitNum);
    1216             : 
    1217          12 :             state.dataOutdoorAirUnit->MySizeFlag(OAUnitNum) = false;
    1218             :         }
    1219             : 
    1220             :         // Do the one time initializations
    1221       64806 :         if (state.dataGlobal->BeginEnvrnFlag && state.dataOutdoorAirUnit->MyEnvrnFlag(OAUnitNum)) {
    1222             :             // Node Conditions
    1223          72 :             thisOutAirUnit.OutAirMassFlow = RhoAir * OAFrac * thisOutAirUnit.OutAirVolFlow;
    1224          72 :             thisOutAirUnit.SMaxAirMassFlow = RhoAir * OAFrac * thisOutAirUnit.SFanMaxAirVolFlow;
    1225             : 
    1226          72 :             if (thisOutAirUnit.ExtFan) {
    1227             :                 // set the exhaust air mass flow rate from input
    1228          72 :                 Real64 const EAFrac = GetCurrentScheduleValue(state, thisOutAirUnit.ExtOutAirSchedPtr);
    1229          72 :                 thisOutAirUnit.ExtAirMassFlow = RhoAir * EAFrac * thisOutAirUnit.ExtAirVolFlow;
    1230          72 :                 thisOutAirUnit.EMaxAirMassFlow = RhoAir * EAFrac * thisOutAirUnit.EFanMaxAirVolFlow;
    1231             : 
    1232          72 :                 state.dataLoopNodes->Node(InNode).MassFlowRateMax = thisOutAirUnit.EMaxAirMassFlow;
    1233          72 :                 state.dataLoopNodes->Node(InNode).MassFlowRateMin = 0.0;
    1234             :             }
    1235             :             // set the node max and min mass flow rates
    1236          72 :             state.dataLoopNodes->Node(OutsideAirNode).MassFlowRateMax = thisOutAirUnit.SMaxAirMassFlow;
    1237          72 :             state.dataLoopNodes->Node(OutsideAirNode).MassFlowRateMin = 0.0;
    1238          72 :             state.dataLoopNodes->Node(OutNode).MassFlowRate = thisOutAirUnit.EMaxAirMassFlow;
    1239             : 
    1240          72 :             if (!state.dataOutdoorAirUnit->MyPlantScanFlag(OAUnitNum)) {
    1241          72 :                 bool errFlag = false;
    1242         306 :                 for (int compLoop = 1; compLoop <= thisOutAirUnit.NumComponents; ++compLoop) {
    1243         432 :                     if ((thisOutAirUnit.OAEquip(compLoop).Type == CompType::WaterCoil_Cooling) ||
    1244         198 :                         (thisOutAirUnit.OAEquip(compLoop).Type == CompType::WaterCoil_DetailedCool)) {
    1245          72 :                         thisOutAirUnit.OAEquip(compLoop).MaxVolWaterFlow =
    1246          36 :                             WaterCoils::GetCoilMaxWaterFlowRate(state,
    1247          36 :                                                                 CompTypeNames[static_cast<int>(thisOutAirUnit.OAEquip(compLoop).Type)],
    1248          36 :                                                                 thisOutAirUnit.OAEquip(compLoop).ComponentName,
    1249             :                                                                 errFlag);
    1250          36 :                         Real64 const rho = GetDensityGlycol(state,
    1251          36 :                                                             state.dataPlnt->PlantLoop(thisOutAirUnit.OAEquip(compLoop).plantLoc.loopNum).FluidName,
    1252             :                                                             Constant::CWInitConvTemp,
    1253          36 :                                                             state.dataPlnt->PlantLoop(thisOutAirUnit.OAEquip(compLoop).plantLoc.loopNum).FluidIndex,
    1254             :                                                             RoutineName);
    1255          36 :                         thisOutAirUnit.OAEquip(compLoop).MaxWaterMassFlow = rho * thisOutAirUnit.OAEquip(compLoop).MaxVolWaterFlow;
    1256          36 :                         thisOutAirUnit.OAEquip(compLoop).MinWaterMassFlow = rho * thisOutAirUnit.OAEquip(compLoop).MinVolWaterFlow;
    1257         144 :                         InitComponentNodes(state,
    1258          36 :                                            thisOutAirUnit.OAEquip(compLoop).MinWaterMassFlow,
    1259          36 :                                            thisOutAirUnit.OAEquip(compLoop).MaxWaterMassFlow,
    1260          36 :                                            thisOutAirUnit.OAEquip(compLoop).CoilWaterInletNode,
    1261          36 :                                            thisOutAirUnit.OAEquip(compLoop).CoilWaterOutletNode);
    1262             :                     }
    1263             : 
    1264         234 :                     if (thisOutAirUnit.OAEquip(compLoop).Type == CompType::WaterCoil_SimpleHeat) {
    1265          72 :                         thisOutAirUnit.OAEquip(compLoop).MaxVolWaterFlow =
    1266          36 :                             WaterCoils::GetCoilMaxWaterFlowRate(state,
    1267          36 :                                                                 CompTypeNames[static_cast<int>(thisOutAirUnit.OAEquip(compLoop).Type)],
    1268          36 :                                                                 thisOutAirUnit.OAEquip(compLoop).ComponentName,
    1269             :                                                                 errFlag);
    1270          36 :                         Real64 const rho = GetDensityGlycol(state,
    1271          36 :                                                             state.dataPlnt->PlantLoop(thisOutAirUnit.OAEquip(compLoop).plantLoc.loopNum).FluidName,
    1272             :                                                             Constant::HWInitConvTemp,
    1273          36 :                                                             state.dataPlnt->PlantLoop(thisOutAirUnit.OAEquip(compLoop).plantLoc.loopNum).FluidIndex,
    1274             :                                                             RoutineName);
    1275          36 :                         thisOutAirUnit.OAEquip(compLoop).MaxWaterMassFlow = rho * thisOutAirUnit.OAEquip(compLoop).MaxVolWaterFlow;
    1276          36 :                         thisOutAirUnit.OAEquip(compLoop).MinWaterMassFlow = rho * thisOutAirUnit.OAEquip(compLoop).MinVolWaterFlow;
    1277         144 :                         InitComponentNodes(state,
    1278          36 :                                            thisOutAirUnit.OAEquip(compLoop).MinWaterMassFlow,
    1279          36 :                                            thisOutAirUnit.OAEquip(compLoop).MaxWaterMassFlow,
    1280          36 :                                            thisOutAirUnit.OAEquip(compLoop).CoilWaterInletNode,
    1281          36 :                                            thisOutAirUnit.OAEquip(compLoop).CoilWaterOutletNode);
    1282             :                     }
    1283         234 :                     if (thisOutAirUnit.OAEquip(compLoop).Type == CompType::SteamCoil_AirHeat) {
    1284           0 :                         thisOutAirUnit.OAEquip(compLoop).MaxVolWaterFlow =
    1285           0 :                             GetCoilMaxSteamFlowRate(state, thisOutAirUnit.OAEquip(compLoop).ComponentIndex, errFlag);
    1286           0 :                         Real64 const rho = FluidProperties::GetSatDensityRefrig(
    1287             :                             state,
    1288           0 :                             state.dataPlnt->PlantLoop(thisOutAirUnit.OAEquip(compLoop).plantLoc.loopNum).FluidName,
    1289             :                             Constant::SteamInitConvTemp,
    1290             :                             1.0,
    1291           0 :                             state.dataPlnt->PlantLoop(thisOutAirUnit.OAEquip(compLoop).plantLoc.loopNum).FluidIndex,
    1292             :                             RoutineName);
    1293           0 :                         thisOutAirUnit.OAEquip(compLoop).MaxWaterMassFlow = rho * thisOutAirUnit.OAEquip(compLoop).MaxVolWaterFlow;
    1294           0 :                         thisOutAirUnit.OAEquip(compLoop).MinWaterMassFlow = rho * thisOutAirUnit.OAEquip(compLoop).MinVolWaterFlow;
    1295           0 :                         InitComponentNodes(state,
    1296           0 :                                            thisOutAirUnit.OAEquip(compLoop).MinWaterMassFlow,
    1297           0 :                                            thisOutAirUnit.OAEquip(compLoop).MaxWaterMassFlow,
    1298           0 :                                            thisOutAirUnit.OAEquip(compLoop).CoilWaterInletNode,
    1299           0 :                                            thisOutAirUnit.OAEquip(compLoop).CoilWaterOutletNode);
    1300             :                     }
    1301         234 :                     if (thisOutAirUnit.OAEquip(compLoop).Type == CompType::WaterCoil_CoolingHXAsst) {
    1302           0 :                         thisOutAirUnit.OAEquip(compLoop).MaxVolWaterFlow =
    1303           0 :                             WaterCoils::GetCoilMaxWaterFlowRate(state,
    1304           0 :                                                                 CompTypeNames[static_cast<int>(thisOutAirUnit.OAEquip(compLoop).Type)],
    1305           0 :                                                                 thisOutAirUnit.OAEquip(compLoop).ComponentName,
    1306             :                                                                 errFlag);
    1307           0 :                         Real64 const rho = GetDensityGlycol(state,
    1308           0 :                                                             state.dataPlnt->PlantLoop(thisOutAirUnit.OAEquip(compLoop).plantLoc.loopNum).FluidName,
    1309             :                                                             Constant::CWInitConvTemp,
    1310           0 :                                                             state.dataPlnt->PlantLoop(thisOutAirUnit.OAEquip(compLoop).plantLoc.loopNum).FluidIndex,
    1311             :                                                             RoutineName);
    1312           0 :                         thisOutAirUnit.OAEquip(compLoop).MaxWaterMassFlow = rho * thisOutAirUnit.OAEquip(compLoop).MaxVolWaterFlow;
    1313           0 :                         thisOutAirUnit.OAEquip(compLoop).MinWaterMassFlow = rho * thisOutAirUnit.OAEquip(compLoop).MinVolWaterFlow;
    1314           0 :                         InitComponentNodes(state,
    1315           0 :                                            thisOutAirUnit.OAEquip(compLoop).MinWaterMassFlow,
    1316           0 :                                            thisOutAirUnit.OAEquip(compLoop).MaxWaterMassFlow,
    1317           0 :                                            thisOutAirUnit.OAEquip(compLoop).CoilWaterInletNode,
    1318           0 :                                            thisOutAirUnit.OAEquip(compLoop).CoilWaterOutletNode);
    1319             :                     }
    1320             :                 }
    1321             :             }
    1322          72 :             state.dataOutdoorAirUnit->MyEnvrnFlag(OAUnitNum) = false;
    1323             : 
    1324             :         } // ...end start of environment inits
    1325             : 
    1326       64806 :         if (!state.dataGlobal->BeginEnvrnFlag) {
    1327       63816 :             state.dataOutdoorAirUnit->MyEnvrnFlag(OAUnitNum) = true;
    1328             :         }
    1329             : 
    1330             :         // These initializations are done every iteration...
    1331             :         // Set all the output variable
    1332       64806 :         thisOutAirUnit.TotHeatingRate = 0.0;
    1333       64806 :         thisOutAirUnit.SensHeatingRate = 0.0;
    1334       64806 :         thisOutAirUnit.LatHeatingRate = 0.0;
    1335       64806 :         thisOutAirUnit.TotCoolingRate = 0.0;
    1336       64806 :         thisOutAirUnit.SensCoolingRate = 0.0;
    1337       64806 :         thisOutAirUnit.LatCoolingRate = 0.0;
    1338       64806 :         thisOutAirUnit.AirMassFlow = 0.0;
    1339       64806 :         thisOutAirUnit.ElecFanRate = 0.0;
    1340             :         // Node Set
    1341             : 
    1342             :         // set the mass flow rates from the input volume flow rates
    1343       64806 :         if (OAFrac > 0.0 || (state.dataHVACGlobal->TurnFansOn && !state.dataHVACGlobal->TurnFansOff)) { // fan is available
    1344       63524 :             thisOutAirUnit.OutAirMassFlow = RhoAir * OAFrac * thisOutAirUnit.OutAirVolFlow;
    1345             :         } else {
    1346        1282 :             thisOutAirUnit.OutAirMassFlow = 0.0;
    1347             :         }
    1348             : 
    1349             :         // set the exhaust air mass flow rate from input
    1350       64806 :         if (thisOutAirUnit.ExtFan) {
    1351       64806 :             Real64 const EAFrac = GetCurrentScheduleValue(state, thisOutAirUnit.ExtOutAirSchedPtr);
    1352       64806 :             if (thisOutAirUnit.ExtFanAvailSchedPtr > 0.0) {
    1353       64806 :                 thisOutAirUnit.ExtAirMassFlow = RhoAir * EAFrac * thisOutAirUnit.ExtAirVolFlow;
    1354             :             } else {
    1355           0 :                 thisOutAirUnit.ExtAirMassFlow = 0.0;
    1356             :             }
    1357       64806 :             state.dataLoopNodes->Node(InNode).MassFlowRate = thisOutAirUnit.ExtAirMassFlow;
    1358       64806 :             state.dataLoopNodes->Node(InNode).MassFlowRateMaxAvail = thisOutAirUnit.ExtAirMassFlow;
    1359       64806 :             state.dataLoopNodes->Node(InNode).MassFlowRateMinAvail = 0.0;
    1360           0 :         } else if (!thisOutAirUnit.ExtFan) {
    1361           0 :             thisOutAirUnit.ExtAirMassFlow = 0.0;
    1362             :         }
    1363             : 
    1364             :         // First, set the flow conditions up so that there is flow through the unit
    1365             : 
    1366       64806 :         state.dataLoopNodes->Node(OutNode).MassFlowRate = thisOutAirUnit.OutAirMassFlow;
    1367       64806 :         state.dataLoopNodes->Node(OutNode).MassFlowRateMaxAvail = thisOutAirUnit.OutAirMassFlow;
    1368       64806 :         state.dataLoopNodes->Node(OutNode).MassFlowRateMinAvail = 0.0;
    1369       64806 :         state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate = thisOutAirUnit.OutAirMassFlow;
    1370       64806 :         state.dataLoopNodes->Node(OutsideAirNode).MassFlowRateMaxAvail = thisOutAirUnit.OutAirMassFlow;
    1371       64806 :         state.dataLoopNodes->Node(OutsideAirNode).MassFlowRateMinAvail = 0.0;
    1372             : 
    1373             :         // Just in case the system is off and conditions do not get sent through
    1374             :         // the system for some reason, set the outlet conditions equal to the inlet
    1375             :         // conditions of the zone outdoor air control unit
    1376       64806 :         if (thisOutAirUnit.ExtFan) {
    1377       64806 :             state.dataLoopNodes->Node(OutNode).Temp = state.dataLoopNodes->Node(InNode).Temp;
    1378       64806 :             state.dataLoopNodes->Node(OutNode).Press = state.dataLoopNodes->Node(InNode).Press;
    1379       64806 :             state.dataLoopNodes->Node(OutNode).HumRat = state.dataLoopNodes->Node(InNode).HumRat;
    1380       64806 :             state.dataLoopNodes->Node(OutNode).Enthalpy = state.dataLoopNodes->Node(InNode).Enthalpy;
    1381             :         } else {
    1382           0 :             state.dataLoopNodes->Node(OutNode).Temp = state.dataLoopNodes->Node(OutsideAirNode).Temp;
    1383           0 :             state.dataLoopNodes->Node(OutNode).Press = state.dataLoopNodes->Node(OutsideAirNode).Press;
    1384           0 :             state.dataLoopNodes->Node(OutNode).HumRat = state.dataLoopNodes->Node(OutsideAirNode).HumRat;
    1385           0 :             state.dataLoopNodes->Node(OutNode).Enthalpy = state.dataLoopNodes->Node(OutsideAirNode).Enthalpy;
    1386             :         }
    1387             :         // These initializations only need to be done once at the start of the iterations...
    1388       64806 :         if (FirstHVACIteration || state.dataHVACGlobal->ShortenTimeStepSys) {
    1389             :             // Initialize the outside air conditions...
    1390       37602 :             state.dataLoopNodes->Node(OutsideAirNode).Temp = state.dataLoopNodes->Node(OutsideAirNode).OutAirDryBulb;
    1391       37602 :             state.dataLoopNodes->Node(OutsideAirNode).HumRat = state.dataEnvrn->OutHumRat;
    1392       37602 :             state.dataLoopNodes->Node(OutsideAirNode).Press = state.dataEnvrn->OutBaroPress;
    1393             :         }
    1394       64806 :     }
    1395             : 
    1396          12 :     void SizeOutdoorAirUnit(EnergyPlusData &state, int const OAUnitNum)
    1397             :     {
    1398             : 
    1399             :         // SUBROUTINE INFORMATION:
    1400             :         //       AUTHOR         Young Tae Chae, Rick Strand
    1401             :         //       DATE WRITTEN   July 2009
    1402             :         //       MODIFIED       Brent Griffith, March 2010, autosize OA flow rate
    1403             :         //                      August 2013 Daeho Kang, add component sizing table entries
    1404             :         //       RE-ENGINEERED  na
    1405             : 
    1406             :         // PURPOSE OF THIS SUBROUTINE:
    1407             :         // This subroutine is for sizing zoen outdoor air control unit components for which flow rates have not been
    1408             :         // specified in the input.
    1409             : 
    1410             :         // METHODOLOGY EMPLOYED:
    1411             :         // Obtains flow rates from the zone sizing arrays and plant sizing data.
    1412             : 
    1413             :         // Using/Aliasing
    1414             :         using namespace DataSizing;
    1415             : 
    1416             :         using HVACHXAssistedCoolingCoil::SimHXAssistedCoolingCoil;
    1417             :         using PlantUtilities::MyPlantSizingIndex;
    1418             :         using SteamCoils::SimulateSteamCoilComponents;
    1419             :         using WaterCoils::SimulateWaterCoilComponents;
    1420             : 
    1421             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1422          12 :         bool IsAutoSize = false;        // Indicator to autosize
    1423          12 :         Real64 OutAirVolFlowDes = 0.0;  // Autosized outdoor air flow for reporting
    1424          12 :         Real64 OutAirVolFlowUser = 0.0; // Hardsized outdoor air flow for reporting
    1425          12 :         Real64 ExtAirVolFlowDes = 0.0;  // Autosized exhaust air flow for reporting
    1426          12 :         Real64 ExtAirVolFlowUser = 0.0; // Hardsized exhaust air flow for reporting
    1427             : 
    1428          12 :         bool ErrorsFound = false;
    1429             : 
    1430          12 :         auto &thisOutAirUnit = state.dataOutdoorAirUnit->OutAirUnit(OAUnitNum);
    1431             : 
    1432          12 :         state.dataSize->DataFanType = thisOutAirUnit.supFanType;
    1433          12 :         state.dataSize->DataFanIndex = thisOutAirUnit.SFan_Index;
    1434          12 :         state.dataSize->DataFanPlacement = thisOutAirUnit.supFanPlace;
    1435             : 
    1436          12 :         if (thisOutAirUnit.OutAirVolFlow == AutoSize) {
    1437           5 :             IsAutoSize = true;
    1438             :         }
    1439             : 
    1440          12 :         if (state.dataSize->CurZoneEqNum > 0) {
    1441          12 :             if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // Simulation continue
    1442           0 :                 if (thisOutAirUnit.OutAirVolFlow > 0.0) {
    1443           0 :                     BaseSizer::reportSizerOutput(
    1444             :                         state, ZoneHVACOAUnit, thisOutAirUnit.Name, "User-Specified Outdoor Air Flow Rate [m3/s]", thisOutAirUnit.OutAirVolFlow);
    1445             :                 }
    1446             :             } else {
    1447          12 :                 CheckZoneSizing(state, std::string(ZoneHVACOAUnit), thisOutAirUnit.Name);
    1448          12 :                 OutAirVolFlowDes = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).MinOA;
    1449          12 :                 if (OutAirVolFlowDes < SmallAirVolFlow) {
    1450           0 :                     OutAirVolFlowDes = 0.0;
    1451             :                 }
    1452          12 :                 if (IsAutoSize) {
    1453           5 :                     thisOutAirUnit.OutAirVolFlow = OutAirVolFlowDes;
    1454           5 :                     BaseSizer::reportSizerOutput(
    1455             :                         state, ZoneHVACOAUnit, thisOutAirUnit.Name, "Design Size Outdoor Air Flow Rate [m3/s]", OutAirVolFlowDes);
    1456             :                 } else {
    1457           7 :                     if (thisOutAirUnit.OutAirVolFlow > 0.0 && OutAirVolFlowDes > 0.0) {
    1458           7 :                         OutAirVolFlowUser = thisOutAirUnit.OutAirVolFlow;
    1459           7 :                         BaseSizer::reportSizerOutput(
    1460             :                             state, ZoneHVACOAUnit, thisOutAirUnit.Name, "User-Specified Outdoor Air Flow Rate [m3/s]", OutAirVolFlowUser);
    1461           7 :                         if (state.dataGlobal->DisplayExtraWarnings) {
    1462           0 :                             if ((std::abs(OutAirVolFlowDes - OutAirVolFlowUser) / OutAirVolFlowUser) > state.dataSize->AutoVsHardSizingThreshold) {
    1463           0 :                                 BaseSizer::reportSizerOutput(
    1464             :                                     state, ZoneHVACOAUnit, thisOutAirUnit.Name, "Design Size Outdoor Air Flow Rate [m3/s]", OutAirVolFlowDes);
    1465           0 :                                 ShowMessage(state,
    1466           0 :                                             format("SizeOutdoorAirUnit: Potential issue with equipment sizing for ZoneHVAC:OutdoorAirUnit {}",
    1467           0 :                                                    thisOutAirUnit.Name));
    1468           0 :                                 ShowContinueError(state, format("User-Specified Outdoor Air Flow Rate of {:.5R} [m3/s]", OutAirVolFlowUser));
    1469           0 :                                 ShowContinueError(state, format("differs from Design Size Outdoor Air Flow Rate of {:.5R} [m3/s]", OutAirVolFlowDes));
    1470           0 :                                 ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
    1471           0 :                                 ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
    1472             :                             }
    1473             :                         }
    1474             :                     }
    1475             :                 }
    1476             :             }
    1477             :         }
    1478             : 
    1479          12 :         IsAutoSize = false;
    1480          12 :         if (thisOutAirUnit.ExtAirVolFlow == AutoSize) {
    1481           5 :             IsAutoSize = true;
    1482             :         }
    1483          12 :         if (state.dataSize->CurZoneEqNum > 0) {
    1484          12 :             if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // Simulation continue
    1485           0 :                 if (thisOutAirUnit.ExtAirVolFlow > 0.0) {
    1486           0 :                     BaseSizer::reportSizerOutput(
    1487             :                         state, ZoneHVACOAUnit, thisOutAirUnit.Name, "User-Specified Exhaust Air Flow Rate [m3/s]", thisOutAirUnit.ExtAirVolFlow);
    1488             :                 }
    1489             :             } else {
    1490             :                 // set exhaust flow equal to the oa inlet flow
    1491          12 :                 ExtAirVolFlowDes = thisOutAirUnit.OutAirVolFlow;
    1492          12 :                 if (IsAutoSize) {
    1493           5 :                     thisOutAirUnit.ExtAirVolFlow = ExtAirVolFlowDes;
    1494           5 :                     BaseSizer::reportSizerOutput(
    1495             :                         state, ZoneHVACOAUnit, thisOutAirUnit.Name, "Design Size Exhaust Air Flow Rate [m3/s]", ExtAirVolFlowDes);
    1496             :                 } else {
    1497           7 :                     if (thisOutAirUnit.ExtAirVolFlow > 0.0 && ExtAirVolFlowDes > 0.0) {
    1498           7 :                         ExtAirVolFlowUser = thisOutAirUnit.ExtAirVolFlow;
    1499           7 :                         BaseSizer::reportSizerOutput(
    1500             :                             state, ZoneHVACOAUnit, thisOutAirUnit.Name, "User-Specified Exhaust Air Flow Rate [m3/s]", ExtAirVolFlowUser);
    1501           7 :                         if (state.dataGlobal->DisplayExtraWarnings) {
    1502           0 :                             if ((std::abs(ExtAirVolFlowDes - ExtAirVolFlowUser) / ExtAirVolFlowUser) > state.dataSize->AutoVsHardSizingThreshold) {
    1503           0 :                                 BaseSizer::reportSizerOutput(
    1504             :                                     state, ZoneHVACOAUnit, thisOutAirUnit.Name, "Design Size Exhaust Air Flow Rate [m3/s]", ExtAirVolFlowDes);
    1505           0 :                                 ShowMessage(state,
    1506           0 :                                             format("SizeOutdoorAirUnit: Potential issue with equipment sizing for ZoneHVAC:OutdoorAirUnit {}",
    1507           0 :                                                    thisOutAirUnit.Name));
    1508           0 :                                 ShowContinueError(state, format("User-Specified Exhaust Air Flow Rate of {:.5R} [m3/s]", ExtAirVolFlowUser));
    1509           0 :                                 ShowContinueError(state, format("differs from Design Size Exhaust Air Flow Rate of {:.5R} [m3/s]", ExtAirVolFlowDes));
    1510           0 :                                 ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
    1511           0 :                                 ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
    1512             :                             }
    1513             :                         }
    1514             :                     }
    1515             :                 }
    1516             :             }
    1517             :         }
    1518             : 
    1519          12 :         state.dataSize->ZoneEqSizing(state.dataSize->CurZoneEqNum).CoolingAirFlow = true;
    1520          12 :         state.dataSize->ZoneEqSizing(state.dataSize->CurZoneEqNum).HeatingAirFlow = true;
    1521          12 :         state.dataSize->ZoneEqSizing(state.dataSize->CurZoneEqNum).CoolingAirVolFlow = thisOutAirUnit.OutAirVolFlow;
    1522          12 :         state.dataSize->ZoneEqSizing(state.dataSize->CurZoneEqNum).HeatingAirVolFlow = thisOutAirUnit.OutAirVolFlow;
    1523          12 :         state.dataSize->ZoneEqSizing(state.dataSize->CurZoneEqNum).OAVolFlow = thisOutAirUnit.OutAirVolFlow;
    1524             : 
    1525          12 :         if (thisOutAirUnit.SFanMaxAirVolFlow == AutoSize) {
    1526           5 :             state.dataFans->fans(thisOutAirUnit.SFan_Index)->simulate(state, true, _, _);
    1527           5 :             thisOutAirUnit.SFanMaxAirVolFlow = state.dataFans->fans(thisOutAirUnit.SFan_Index)->maxAirFlowRate;
    1528             :         }
    1529          12 :         if (thisOutAirUnit.ExtFan) {
    1530          12 :             if (thisOutAirUnit.EFanMaxAirVolFlow == AutoSize) {
    1531           6 :                 state.dataFans->fans(thisOutAirUnit.ExtFan_Index)->simulate(state, true, _, _);
    1532           6 :                 thisOutAirUnit.EFanMaxAirVolFlow = state.dataFans->fans(thisOutAirUnit.ExtFan_Index)->maxAirFlowRate;
    1533             :             }
    1534             :         }
    1535             : 
    1536          51 :         for (int CompNum = 1; CompNum <= thisOutAirUnit.NumComponents; ++CompNum) {
    1537          39 :             auto &thisOAEquip = thisOutAirUnit.OAEquip(CompNum);
    1538          39 :             if ((thisOAEquip.Type == CompType::WaterCoil_Cooling) || (thisOAEquip.Type == CompType::WaterCoil_DetailedCool)) {
    1539           6 :                 if (thisOAEquip.MaxVolWaterFlow == AutoSize) {
    1540           1 :                     SimulateWaterCoilComponents(state, thisOAEquip.ComponentName, true, thisOAEquip.ComponentIndex, _, HVAC::FanOp::Cycling, 0.0);
    1541             :                 }
    1542             :             }
    1543          39 :             if (thisOAEquip.Type == CompType::WaterCoil_SimpleHeat) {
    1544           6 :                 if (thisOAEquip.MaxVolWaterFlow == AutoSize) {
    1545           3 :                     SimulateWaterCoilComponents(state, thisOAEquip.ComponentName, true, thisOAEquip.ComponentIndex, _, HVAC::FanOp::Cycling, 0.0);
    1546             :                 }
    1547             :             }
    1548          39 :             if (thisOAEquip.Type == CompType::SteamCoil_AirHeat) {
    1549           0 :                 if (thisOAEquip.MaxVolWaterFlow == AutoSize) {
    1550           0 :                     SimulateSteamCoilComponents(state, thisOAEquip.ComponentName, true, thisOAEquip.ComponentIndex);
    1551             :                 }
    1552             :             }
    1553          39 :             if (thisOAEquip.Type == CompType::WaterCoil_CoolingHXAsst) {
    1554           0 :                 if (thisOAEquip.MaxVolWaterFlow == AutoSize) {
    1555           0 :                     SimHXAssistedCoolingCoil(
    1556           0 :                         state, thisOAEquip.ComponentName, true, HVAC::CompressorOp::On, 0.0, thisOAEquip.ComponentIndex, HVAC::FanOp::Continuous);
    1557             :                 }
    1558             :             }
    1559             :         }
    1560             : 
    1561          12 :         if (ErrorsFound) {
    1562           0 :             ShowFatalError(state, "Preceding sizing errors cause program termination");
    1563             :         }
    1564          12 :     }
    1565             : 
    1566       64806 :     void CalcOutdoorAirUnit(EnergyPlusData &state,
    1567             :                             int &OAUnitNum,                // number of the current unit being simulated
    1568             :                             int const ZoneNum,             // number of zone being served
    1569             :                             bool const FirstHVACIteration, // TRUE if 1st HVAC simulation of system timestep
    1570             :                             Real64 &PowerMet,              // power supplied
    1571             :                             Real64 &LatOutputProvided      // Latent power supplied (kg/s), negative = dehumidification
    1572             :     )
    1573             :     {
    1574             : 
    1575             :         // SUBROUTINE INFORMATION:
    1576             :         //       AUTHOR         Young Tae Chae, Rick Strand
    1577             :         //       DATE WRITTEN   June 2008
    1578             :         //       MODIFIED       July 2012, Chandan Sharma - FSEC: Added zone sys avail managers
    1579             :         //       RE-ENGINEERED  na
    1580             : 
    1581             :         // PURPOSE OF THIS SUBROUTINE:
    1582             :         // This subroutine mainly controls the action of the outdoor air unit
    1583             :         // (or more exactly, it controls the coil outlet temperature of the unit)
    1584             :         // based on the user input for controls and the defined controls
    1585             :         // algorithms.
    1586             : 
    1587             :         // METHODOLOGY EMPLOYED:
    1588             :         // Outdoor air unit is controlled based on user input and what is happening in the
    1589             :         // simulation.
    1590             :         // Note: controls are strictly temperature based and do not factor
    1591             :         // humidity into the equation (not an enthalpy economy cycle but rather
    1592             :         // a simple return air cycle).
    1593             : 
    1594             :         // REFERENCES:
    1595             :         // ASHRAE Systems and Equipment Handbook (SI), 1996. page 31.3
    1596             : 
    1597             :         // USE STATEMENTS:
    1598             : 
    1599             :         // Using/Aliasing
    1600       64806 :         auto &thisOutAirUnit = state.dataOutdoorAirUnit->OutAirUnit(OAUnitNum);
    1601             : 
    1602       64806 :         auto &TurnFansOff = state.dataHVACGlobal->TurnFansOff;
    1603       64806 :         auto &TurnFansOn = state.dataHVACGlobal->TurnFansOn;
    1604             :         using HeatingCoils::CheckHeatingCoilSchedule;
    1605             :         using HVACHXAssistedCoolingCoil::CheckHXAssistedCoolingCoilSchedule;
    1606             :         using ScheduleManager::GetCurrentScheduleValue;
    1607             : 
    1608             :         // Locals
    1609             : 
    1610             :         // SUBROUTINE ARGUMENT DEFINITIONS:
    1611             : 
    1612             :         // SUBROUTINE PARAMETER DEFINITIONS:
    1613             :         // INTERFACE BLOCK SPECIFICATIONS
    1614             : 
    1615             :         // DERIVED TYPE DEFINITIONS
    1616             :         // na
    1617             : 
    1618             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1619             :         Real64 DesOATemp;      // Design OA Temp degree C
    1620             :         Real64 AirMassFlow;    // air mass flow rate [kg/s]
    1621             :         Real64 QTotUnitOut;    // total unit output [watts]
    1622       64806 :         Real64 QUnitOut = 0.0; // heating or sens. cooling provided by fan coil unit [watts]
    1623             :         Real64 LatLoadMet;     // heating or sens. cooling provided by fan coil unit [watts]
    1624             :         Real64 MinHumRat;      // desired temperature after mixing inlet and outdoor air [degrees C]
    1625             :         Real64 SetPointTemp;   // temperature that will be used to control the radiant system [Celsius]
    1626             :         Real64 HiCtrlTemp;     // Current high point in setpoint temperature range
    1627             :         Real64 LoCtrlTemp;     // Current low point in setpoint temperature range
    1628             :         Real64 AirInEnt;       // RE-calcualte the Enthalpy of supply air
    1629       64806 :         Real64 AirOutletTemp = 0.0;
    1630             :         Real64 ZoneSupAirEnt; // Specific humidity ratio of inlet air (kg moisture / kg moist air)
    1631             :         // Latent output
    1632             :         Real64 LatentOutput; // Latent (moisture) add/removal rate, negative is dehumidification [kg/s]
    1633             :         Real64 SpecHumOut;   // Specific humidity ratio of outlet air (kg moisture / kg moist air)
    1634             :         Real64 SpecHumIn;    // Specific humidity ratio of inlet air (kg moisture / kg moist air)
    1635             :         Real64 ZoneAirEnt;   // zone air enthalphy J/kg
    1636             : 
    1637             :         // initialize local variables
    1638       64806 :         int const InletNode = thisOutAirUnit.AirInletNode;        // Unit air inlet node, only used if ExtFan
    1639       64806 :         int const SFanOutletNode = thisOutAirUnit.SFanOutletNode; // Unit supply fan outlet node
    1640       64806 :         int const OutletNode = thisOutAirUnit.AirOutletNode;      // air outlet node
    1641       64806 :         int const OutsideAirNode = thisOutAirUnit.OutsideAirNode; // outside air node
    1642       64806 :         OAUnitCtrlType const UnitControlType = thisOutAirUnit.controlType;
    1643             : 
    1644       64806 :         thisOutAirUnit.CompOutSetTemp = 0.0;
    1645       64806 :         thisOutAirUnit.FanEffect = false;
    1646             : 
    1647      129612 :         if ((GetCurrentScheduleValue(state, thisOutAirUnit.SchedPtr) <= 0) || (GetCurrentScheduleValue(state, thisOutAirUnit.OutAirSchedPtr) <= 0) ||
    1648      129612 :             ((GetCurrentScheduleValue(state, thisOutAirUnit.SFanAvailSchedPtr) <= 0) && !TurnFansOn) || TurnFansOff) {
    1649             :             // System is off or has no load upon the unit; set the flow rates to zero and then
    1650             :             // simulate the components with the no flow conditions
    1651        1282 :             if (thisOutAirUnit.ExtFan) {
    1652        1282 :                 state.dataLoopNodes->Node(InletNode).MassFlowRate = 0.0;
    1653        1282 :                 state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail = 0.0;
    1654        1282 :                 state.dataLoopNodes->Node(InletNode).MassFlowRateMinAvail = 0.0;
    1655             :             }
    1656        1282 :             state.dataLoopNodes->Node(SFanOutletNode).MassFlowRate = 0.0;
    1657        1282 :             state.dataLoopNodes->Node(SFanOutletNode).MassFlowRateMaxAvail = 0.0;
    1658        1282 :             state.dataLoopNodes->Node(SFanOutletNode).MassFlowRateMinAvail = 0.0;
    1659        1282 :             state.dataLoopNodes->Node(OutletNode).MassFlowRate = 0.0;
    1660        1282 :             state.dataLoopNodes->Node(OutletNode).MassFlowRateMaxAvail = 0.0;
    1661        1282 :             state.dataLoopNodes->Node(OutletNode).MassFlowRateMinAvail = 0.0;
    1662        1282 :             state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate = 0.0;
    1663        1282 :             state.dataLoopNodes->Node(OutsideAirNode).MassFlowRateMaxAvail = 0.0;
    1664        1282 :             state.dataLoopNodes->Node(OutsideAirNode).MassFlowRateMinAvail = 0.0;
    1665             : 
    1666             :             // Node condition
    1667        1282 :             if (thisOutAirUnit.ExtFan) {
    1668        1282 :                 state.dataLoopNodes->Node(InletNode).Temp = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).MAT;
    1669        1282 :                 state.dataLoopNodes->Node(SFanOutletNode).Temp = state.dataLoopNodes->Node(InletNode).Temp;
    1670             :             } else {
    1671           0 :                 state.dataLoopNodes->Node(SFanOutletNode).Temp = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).MAT;
    1672             :             }
    1673        1282 :             state.dataLoopNodes->Node(OutletNode).Temp = state.dataLoopNodes->Node(SFanOutletNode).Temp;
    1674             : 
    1675        1282 :             if (thisOutAirUnit.supFanPlace == HVAC::FanPlace::BlowThru) {
    1676           0 :                 state.dataFans->fans(thisOutAirUnit.SFan_Index)->simulate(state, FirstHVACIteration, _);
    1677             : 
    1678           0 :                 SimZoneOutAirUnitComps(state, OAUnitNum, FirstHVACIteration);
    1679           0 :                 if (thisOutAirUnit.ExtFan) {
    1680           0 :                     state.dataFans->fans(thisOutAirUnit.ExtFan_Index)->simulate(state, FirstHVACIteration, _, _);
    1681             :                 }
    1682             : 
    1683        1282 :             } else if (thisOutAirUnit.supFanPlace == HVAC::FanPlace::DrawThru) {
    1684        1282 :                 SimZoneOutAirUnitComps(state, OAUnitNum, FirstHVACIteration);
    1685        1282 :                 state.dataFans->fans(thisOutAirUnit.SFan_Index)->simulate(state, FirstHVACIteration, _, _);
    1686             : 
    1687        1282 :                 if (thisOutAirUnit.ExtFan) {
    1688        1282 :                     state.dataFans->fans(thisOutAirUnit.ExtFan_Index)->simulate(state, FirstHVACIteration, _, _);
    1689             :                 }
    1690             :             }
    1691             : 
    1692             :         } else { // System On
    1693             : 
    1694             :             // Flowrate Check
    1695       63524 :             if (state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate > 0.0) {
    1696       63524 :                 state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate = thisOutAirUnit.OutAirMassFlow;
    1697             :             }
    1698             : 
    1699             :             // Fan Positioning Check
    1700             : 
    1701       63524 :             if (thisOutAirUnit.ExtFan) {
    1702       63524 :                 state.dataLoopNodes->Node(InletNode).MassFlowRate = thisOutAirUnit.ExtAirMassFlow;
    1703             :             }
    1704             : 
    1705             :             // Air mass balance check
    1706       63524 :             if ((std::abs(thisOutAirUnit.ExtAirMassFlow - thisOutAirUnit.OutAirMassFlow) > 0.001) &&
    1707           0 :                 (!state.dataHeatBal->ZoneAirMassFlow.EnforceZoneMassBalance)) {
    1708           0 :                 if (!thisOutAirUnit.FlowError) {
    1709           0 :                     ShowWarningError(state, "Air mass flow between zone supply and exhaust is not balanced. Only the first occurrence is reported.");
    1710           0 :                     ShowContinueError(state, format("Occurs in ZoneHVAC:OutdoorAirUnit Object= {}", thisOutAirUnit.Name));
    1711           0 :                     ShowContinueError(state,
    1712             :                                       "Air mass balance is required by other outdoor air units: Fan:ZoneExhaust, ZoneMixing, ZoneCrossMixing, or "
    1713             :                                       "other air flow control inputs.");
    1714           0 :                     ShowContinueErrorTimeStamp(state,
    1715           0 :                                                format("The outdoor mass flow rate = {:.3R} and the exhaust mass flow rate = {:.3R}.",
    1716           0 :                                                       thisOutAirUnit.OutAirMassFlow,
    1717           0 :                                                       thisOutAirUnit.ExtAirMassFlow));
    1718           0 :                     thisOutAirUnit.FlowError = true;
    1719             :                 }
    1720             :             }
    1721             : 
    1722       63524 :             if (thisOutAirUnit.supFanPlace == HVAC::FanPlace::BlowThru) {
    1723       32403 :                 state.dataFans->fans(thisOutAirUnit.SFan_Index)->simulate(state, FirstHVACIteration, _, _);
    1724       32403 :                 DesOATemp = state.dataLoopNodes->Node(SFanOutletNode).Temp;
    1725       31121 :             } else if (thisOutAirUnit.supFanPlace == HVAC::FanPlace::DrawThru) {
    1726       31121 :                 DesOATemp = state.dataLoopNodes->Node(OutsideAirNode).Temp;
    1727             :             }
    1728             : 
    1729             :             // Control type check
    1730       63524 :             switch (UnitControlType) {
    1731       31121 :             case OAUnitCtrlType::Neutral: {
    1732       31121 :                 SetPointTemp = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).MAT;
    1733             :                 // Neutral Control Condition
    1734       31121 :                 if (DesOATemp == SetPointTemp) {
    1735           0 :                     thisOutAirUnit.OperatingMode = Operation::NeutralMode;
    1736           0 :                     AirOutletTemp = DesOATemp;
    1737           0 :                     thisOutAirUnit.CompOutSetTemp = DesOATemp;
    1738           0 :                     SimZoneOutAirUnitComps(state, OAUnitNum, FirstHVACIteration);
    1739             :                 } else {
    1740       31121 :                     if (DesOATemp < SetPointTemp) { // Heating MODE
    1741       16710 :                         thisOutAirUnit.OperatingMode = Operation::HeatingMode;
    1742       16710 :                         AirOutletTemp = SetPointTemp;
    1743       16710 :                         thisOutAirUnit.CompOutSetTemp = AirOutletTemp;
    1744       16710 :                         SimZoneOutAirUnitComps(state, OAUnitNum, FirstHVACIteration);
    1745             :                     } else { // Cooling Mode
    1746       14411 :                         thisOutAirUnit.OperatingMode = Operation::CoolingMode;
    1747       14411 :                         AirOutletTemp = SetPointTemp;
    1748       14411 :                         thisOutAirUnit.CompOutSetTemp = AirOutletTemp;
    1749       14411 :                         SimZoneOutAirUnitComps(state, OAUnitNum, FirstHVACIteration);
    1750             :                     }
    1751             :                 }
    1752             :                 // SetPoint Temperature Condition
    1753       31121 :             } break;
    1754       32403 :             case OAUnitCtrlType::Temperature: {
    1755       32403 :                 SetPointTemp = DesOATemp;
    1756       32403 :                 HiCtrlTemp = GetCurrentScheduleValue(state, thisOutAirUnit.HiCtrlTempSchedPtr);
    1757       32403 :                 LoCtrlTemp = GetCurrentScheduleValue(state, thisOutAirUnit.LoCtrlTempSchedPtr);
    1758       32403 :                 if ((DesOATemp <= HiCtrlTemp) && (DesOATemp >= LoCtrlTemp)) {
    1759           0 :                     thisOutAirUnit.OperatingMode = Operation::NeutralMode;
    1760           0 :                     AirOutletTemp = DesOATemp;
    1761           0 :                     thisOutAirUnit.CompOutSetTemp = DesOATemp;
    1762           0 :                     SimZoneOutAirUnitComps(state, OAUnitNum, FirstHVACIteration);
    1763             :                 } else {
    1764       32403 :                     if (SetPointTemp < LoCtrlTemp) {
    1765       13095 :                         thisOutAirUnit.OperatingMode = Operation::HeatingMode;
    1766       13095 :                         AirOutletTemp = LoCtrlTemp;
    1767       13095 :                         thisOutAirUnit.CompOutSetTemp = AirOutletTemp;
    1768       13095 :                         SimZoneOutAirUnitComps(state, OAUnitNum, FirstHVACIteration);
    1769       19308 :                     } else if (SetPointTemp > HiCtrlTemp) {
    1770       19308 :                         thisOutAirUnit.OperatingMode = Operation::CoolingMode;
    1771       19308 :                         AirOutletTemp = HiCtrlTemp;
    1772       19308 :                         thisOutAirUnit.CompOutSetTemp = AirOutletTemp;
    1773       19308 :                         SimZoneOutAirUnitComps(state, OAUnitNum, FirstHVACIteration);
    1774             :                     }
    1775             :                 }
    1776       32403 :             } break;
    1777           0 :             default:
    1778           0 :                 break;
    1779             :             }
    1780             : 
    1781             :             // Fan positioning
    1782       63524 :             if (thisOutAirUnit.supFanPlace == HVAC::FanPlace::DrawThru) {
    1783       31121 :                 state.dataFans->fans(thisOutAirUnit.SFan_Index)->simulate(state, FirstHVACIteration, _, _);
    1784             : 
    1785       31121 :                 thisOutAirUnit.FanEffect = true; // RE-Simulation to take over the supply fan effect
    1786       31121 :                 thisOutAirUnit.FanCorTemp = (state.dataLoopNodes->Node(OutletNode).Temp - thisOutAirUnit.CompOutSetTemp);
    1787       31121 :                 SimZoneOutAirUnitComps(state, OAUnitNum, FirstHVACIteration);
    1788       31121 :                 state.dataFans->fans(thisOutAirUnit.SFan_Index)->simulate(state, FirstHVACIteration, _, _);
    1789       31121 :                 thisOutAirUnit.FanEffect = false;
    1790             :             }
    1791       63524 :             if (thisOutAirUnit.ExtFan) {
    1792       63524 :                 state.dataFans->fans(thisOutAirUnit.ExtFan_Index)->simulate(state, FirstHVACIteration, _, _);
    1793             :             }
    1794             :         } // ...end of system ON/OFF IF-THEN block
    1795             : 
    1796       64806 :         AirMassFlow = state.dataLoopNodes->Node(OutletNode).MassFlowRate;
    1797       64806 :         MinHumRat = min(state.dataLoopNodes->Node(OutletNode).HumRat, state.dataLoopNodes->Node(thisOutAirUnit.ZoneNodeNum).HumRat);
    1798             : 
    1799       64806 :         AirInEnt = PsyHFnTdbW(state.dataLoopNodes->Node(OutletNode).Temp, MinHumRat);                   // zone supply air node enthalpy
    1800       64806 :         ZoneAirEnt = PsyHFnTdbW(state.dataLoopNodes->Node(thisOutAirUnit.ZoneNodeNum).Temp, MinHumRat); // zone air enthalpy
    1801       64806 :         QUnitOut = AirMassFlow * (AirInEnt - ZoneAirEnt);                                               // Senscooling
    1802             : 
    1803             :         // CR9155 Remove specific humidity calculations
    1804       64806 :         SpecHumOut = state.dataLoopNodes->Node(OutletNode).HumRat;
    1805       64806 :         SpecHumIn = state.dataLoopNodes->Node(thisOutAirUnit.ZoneNodeNum).HumRat;
    1806       64806 :         LatentOutput = AirMassFlow * (SpecHumOut - SpecHumIn); // Latent rate (kg/s), dehumid = negative
    1807             : 
    1808             :         ZoneAirEnt =
    1809       64806 :             PsyHFnTdbW(state.dataLoopNodes->Node(thisOutAirUnit.ZoneNodeNum).Temp, state.dataLoopNodes->Node(thisOutAirUnit.ZoneNodeNum).HumRat);
    1810             : 
    1811       64806 :         ZoneSupAirEnt = PsyHFnTdbW(state.dataLoopNodes->Node(OutletNode).Temp, state.dataLoopNodes->Node(OutletNode).HumRat);
    1812       64806 :         QTotUnitOut = AirMassFlow * (ZoneSupAirEnt - ZoneAirEnt);
    1813       64806 :         LatLoadMet = QTotUnitOut - QUnitOut; // watts
    1814             : 
    1815             :         // Report variables...
    1816             : 
    1817       64806 :         if (QUnitOut < 0.0) {
    1818       43892 :             thisOutAirUnit.SensCoolingRate = std::abs(QUnitOut);
    1819       43892 :             thisOutAirUnit.SensHeatingRate = 0.0;
    1820             :         } else {
    1821       20914 :             thisOutAirUnit.SensCoolingRate = 0.0;
    1822       20914 :             thisOutAirUnit.SensHeatingRate = QUnitOut;
    1823             :         }
    1824             : 
    1825       64806 :         if (QTotUnitOut < 0.0) {
    1826       50319 :             thisOutAirUnit.TotCoolingRate = std::abs(QTotUnitOut);
    1827       50319 :             thisOutAirUnit.TotHeatingRate = 0.0;
    1828             :         } else {
    1829       14487 :             thisOutAirUnit.TotCoolingRate = 0.0;
    1830       14487 :             thisOutAirUnit.TotHeatingRate = QTotUnitOut;
    1831             :         }
    1832             : 
    1833       64806 :         if (LatLoadMet < 0.0) {
    1834       45025 :             thisOutAirUnit.LatCoolingRate = std::abs(LatLoadMet);
    1835       45025 :             thisOutAirUnit.LatHeatingRate = 0.0;
    1836             :         } else {
    1837       19781 :             thisOutAirUnit.LatCoolingRate = 0.0;
    1838       19781 :             thisOutAirUnit.LatHeatingRate = LatLoadMet;
    1839             :         }
    1840             : 
    1841             :         // OutAirUnit( OAUnitNum ).ElecFanRate = FanElecPower;  //Issue #5524 this would only get the last fan called, not both if there are two
    1842       64806 :         thisOutAirUnit.ElecFanRate = 0.0;
    1843       64806 :         thisOutAirUnit.ElecFanRate += state.dataFans->fans(thisOutAirUnit.SFan_Index)->totalPower;
    1844             : 
    1845       64806 :         if (thisOutAirUnit.ExtFan) {
    1846       64806 :             thisOutAirUnit.ElecFanRate += state.dataFans->fans(thisOutAirUnit.ExtFan_Index)->totalPower;
    1847             :         }
    1848             : 
    1849       64806 :         PowerMet = QUnitOut;
    1850       64806 :         LatOutputProvided = LatentOutput;
    1851       64806 :     }
    1852             : 
    1853       95927 :     void SimZoneOutAirUnitComps(EnergyPlusData &state, int const OAUnitNum, bool const FirstHVACIteration)
    1854             :     {
    1855             : 
    1856             :         // SUBROUTINE INFORMATION:
    1857             :         //       AUTHOR         Fred Buhl
    1858             :         //       DATE WRITTEN   Oct 1998
    1859             :         //       MODIFIED       na
    1860             :         //       RE-ENGINEERED  na
    1861             : 
    1862             :         // PURPOSE OF THIS SUBROUTINE
    1863             :         // Simulate the controllers and components in the outside air system.
    1864             : 
    1865             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1866       95927 :         bool const Sim = true;
    1867             : 
    1868       95927 :         auto &thisOutAirUnit = state.dataOutdoorAirUnit->OutAirUnit(OAUnitNum);
    1869      394574 :         for (int EquipNum = 1; EquipNum <= thisOutAirUnit.NumComponents; ++EquipNum) {
    1870      298647 :             auto &thisOAEquip = thisOutAirUnit.OAEquip(EquipNum);
    1871      298647 :             SimOutdoorAirEquipComps(state,
    1872             :                                     OAUnitNum,
    1873      298647 :                                     CompTypeNames[static_cast<int>(thisOAEquip.Type)],
    1874      298647 :                                     thisOAEquip.ComponentName,
    1875             :                                     EquipNum,
    1876             :                                     thisOAEquip.Type,
    1877             :                                     FirstHVACIteration,
    1878      298647 :                                     thisOAEquip.ComponentIndex,
    1879             :                                     Sim);
    1880             :         }
    1881       95927 :     }
    1882             : 
    1883      298647 :     void SimOutdoorAirEquipComps(EnergyPlusData &state,
    1884             :                                  int const OAUnitNum,          // actual outdoor air unit num
    1885             :                                  std::string_view EquipType,   // the component type
    1886             :                                  std::string const &EquipName, // the component Name
    1887             :                                  int const EquipNum,
    1888             :                                  [[maybe_unused]] CompType const CompTypeNum, // Component Type -- Integerized for this module
    1889             :                                  bool const FirstHVACIteration,
    1890             :                                  int &CompIndex,
    1891             :                                  bool const Sim // if TRUE, simulate component
    1892             :     )
    1893             :     {
    1894             : 
    1895             :         // SUBROUTINE INFORMATION:
    1896             :         //       AUTHOR         Young Tae Chae, Rick Strand
    1897             :         //       DATE WRITTEN   June 2008
    1898             :         //       MODIFIED
    1899             :         //       RE-ENGINEERED  na
    1900             : 
    1901             :         // PURPOSE OF THIS SUBROUTINE:
    1902             :         // Outdoor air unit has various coil options. This subroutine defines the coil loads and execute
    1903             :         // to simulate each components
    1904             :         // METHODOLOGY EMPLOYED:
    1905             : 
    1906             :         // REFERENCES:
    1907             : 
    1908             :         // USE STATEMENTS:
    1909             : 
    1910             :         // Using/Aliasing
    1911             :         using DesiccantDehumidifiers::SimDesiccantDehumidifier;
    1912             :         using HeatRecovery::SimHeatRecovery;
    1913             :         using HVAC::SmallLoad;
    1914             :         using HVACDXHeatPumpSystem::SimDXHeatPumpSystem;
    1915             :         using HVACHXAssistedCoolingCoil::SimHXAssistedCoolingCoil;
    1916             :         using ScheduleManager::GetCurrentScheduleValue;
    1917             :         using WaterCoils::SimulateWaterCoilComponents;
    1918             : 
    1919             :         // SUBROUTINE LOCAL VARIABLE DEFINITIONS
    1920             :         Real64 QCompReq;
    1921             :         Real64 MaxWaterFlow;
    1922             :         Real64 MinWaterFlow;
    1923             :         Real64 QUnitOut;
    1924             :         Real64 Dxsystemouttemp;
    1925             : 
    1926      298647 :         auto &thisOutAirUnit = state.dataOutdoorAirUnit->OutAirUnit(OAUnitNum);
    1927      298647 :         auto &thisOAEquip = thisOutAirUnit.OAEquip(EquipNum);
    1928      298647 :         int const InletNodeNum = thisOAEquip.CoilAirInletNode;
    1929      298647 :         int const OutletNodeNum = thisOAEquip.CoilAirOutletNode;
    1930             : 
    1931      298647 :         int UnitNum = OAUnitNum;
    1932      298647 :         int SimCompNum = EquipNum;
    1933             : 
    1934      298647 :         Real64 const CompAirOutTemp = thisOutAirUnit.CompOutSetTemp;
    1935      298647 :         Operation const OpMode = thisOutAirUnit.OperatingMode;
    1936      298647 :         CompType const EquipTypeNum = thisOAEquip.Type;
    1937      298647 :         Real64 const OAMassFlow = thisOutAirUnit.OutAirMassFlow;
    1938             : 
    1939             :         // check the fan positioning
    1940      298647 :         bool const DrawFan = thisOutAirUnit.FanEffect;
    1941      298647 :         Real64 const FanEffect = DrawFan ? thisOutAirUnit.FanCorTemp : 0.0;
    1942             : 
    1943             :         // checking equipment index
    1944             : 
    1945             :         {
    1946      298647 :             switch (EquipTypeNum) {
    1947             :             // Heat recovery
    1948       74325 :             case CompType::HeatXchngrFP: // 'HeatExchanger:AirToAir:FlatPlate',
    1949             :             case CompType::HeatXchngrSL: // 'HeatExchanger:AirToAir:SensibleAndLatent',
    1950             :                                          // 'HeatExchanger:Desiccant:BalancedFlow' - unused
    1951             :             {
    1952             : 
    1953       74325 :                 if (Sim) {
    1954       74325 :                     SimHeatRecovery(state, EquipName, FirstHVACIteration, CompIndex, HVAC::FanOp::Continuous, _, _, _, _, false, false);
    1955             :                 }
    1956       74325 :             } break;
    1957             :             // Desiccant Dehumidifier
    1958       10801 :             case CompType::Desiccant: { // 'Dehumidifier:Desiccant:NoFans'
    1959       10801 :                 if (Sim) {
    1960       10801 :                     SimDesiccantDehumidifier(state, EquipName, FirstHVACIteration, CompIndex);
    1961             :                 }
    1962             : 
    1963       10801 :             } break;
    1964       52723 :             case CompType::WaterCoil_SimpleHeat: { // ('Coil:Heating:Water')
    1965             : 
    1966       52723 :                 if (Sim) {
    1967       52723 :                     int const ControlNode = thisOAEquip.CoilWaterInletNode;
    1968       52723 :                     MaxWaterFlow = thisOAEquip.MaxWaterMassFlow;
    1969       52723 :                     MinWaterFlow = thisOAEquip.MinWaterMassFlow;
    1970             :                     // On the first HVAC iteration the system values are given to the controller, but after that
    1971             :                     // the demand limits are in place and there needs to be feedback to the Zone Equipment
    1972       52723 :                     if ((!FirstHVACIteration) && (ControlNode > 0)) {
    1973       27414 :                         MaxWaterFlow = state.dataLoopNodes->Node(ControlNode).MassFlowRateMaxAvail;
    1974       27414 :                         MinWaterFlow = state.dataLoopNodes->Node(ControlNode).MassFlowRateMinAvail;
    1975             :                     }
    1976       52723 :                     auto const &whCoilInletNode = state.dataLoopNodes->Node(InletNodeNum);
    1977             :                     // auto &whCoilOutletNode = state.dataLoopNodes->Node(OutletNodeNum);
    1978             : 
    1979       52723 :                     Real64 const CpAirZn = PsyCpAirFnW(whCoilInletNode.HumRat);
    1980             : 
    1981       52723 :                     if ((OpMode == Operation::NeutralMode) || (OpMode == Operation::CoolingMode) || (whCoilInletNode.Temp > CompAirOutTemp)) {
    1982       25296 :                         QCompReq = 0.0;
    1983             :                     } else {
    1984       27427 :                         QCompReq = CpAirZn * OAMassFlow * ((CompAirOutTemp - whCoilInletNode.Temp) - FanEffect);
    1985       27427 :                         if (std::abs(QCompReq) < SmallLoad) QCompReq = 0.0;
    1986       27427 :                         if (QCompReq < 0.0) QCompReq = 0.0; // coil can heat only
    1987             :                     }
    1988             : 
    1989      210892 :                     ControlCompOutput(state,
    1990       52723 :                                       thisOutAirUnit.Name,
    1991      105446 :                                       std::string(ZoneHVACOAUnit),
    1992             :                                       UnitNum,
    1993             :                                       FirstHVACIteration,
    1994             :                                       QCompReq,
    1995             :                                       ControlNode,
    1996             :                                       MaxWaterFlow,
    1997             :                                       MinWaterFlow,
    1998             :                                       0.0001,
    1999       52723 :                                       thisOutAirUnit.ControlCompTypeNum,
    2000       52723 :                                       thisOutAirUnit.CompErrIndex,
    2001             :                                       _,
    2002             :                                       _,
    2003             :                                       _,
    2004      105446 :                                       2,
    2005             :                                       SimCompNum,
    2006       52723 :                                       thisOAEquip.plantLoc);
    2007             :                 }
    2008       52723 :             } break;
    2009           0 :             case CompType::SteamCoil_AirHeat: { // 'Coil:Heating:Steam'
    2010           0 :                 if (Sim) {
    2011           0 :                     CalcOAUnitCoilComps(state, UnitNum, FirstHVACIteration, SimCompNum, QUnitOut);
    2012             :                 }
    2013           0 :             } break;
    2014       43204 :             case CompType::Coil_ElectricHeat: // 'Coil:Heating:Electric'
    2015             :             case CompType::Coil_GasHeat: {    // 'Coil:Heating:Fuel'
    2016       43204 :                 if (Sim) {
    2017             :                     //     stand-alone coils are temperature controlled (do not pass QCoilReq in argument list, QCoilReq overrides temp SP)
    2018       43204 :                     CalcOAUnitCoilComps(state, UnitNum, FirstHVACIteration, SimCompNum, QUnitOut);
    2019             :                 }
    2020       43204 :             } break;
    2021             :                 // water cooling coil Types
    2022       32403 :             case CompType::WaterCoil_Cooling: { // 'Coil:Cooling:Water'
    2023       32403 :                 if (Sim) {
    2024       32403 :                     int const ControlNode = thisOAEquip.CoilWaterInletNode;
    2025       32403 :                     MaxWaterFlow = thisOAEquip.MaxWaterMassFlow;
    2026       32403 :                     MinWaterFlow = thisOAEquip.MinWaterMassFlow;
    2027             :                     // On the first HVAC iteration the system values are given to the controller, but after that
    2028             :                     // the demand limits are in place and there needs to be feedback to the Zone Equipment
    2029       32403 :                     if ((!FirstHVACIteration) && (ControlNode > 0)) {
    2030       16833 :                         MaxWaterFlow = state.dataLoopNodes->Node(ControlNode).MassFlowRateMaxAvail;
    2031       16833 :                         MinWaterFlow = state.dataLoopNodes->Node(ControlNode).MassFlowRateMinAvail;
    2032             :                     }
    2033             : 
    2034       32403 :                     auto const &wcCoilInletNode = state.dataLoopNodes->Node(InletNodeNum);
    2035       32403 :                     auto &wcCoilOutletNode = state.dataLoopNodes->Node(OutletNodeNum);
    2036             : 
    2037       32403 :                     Real64 const CpAirZn = PsyCpAirFnW(wcCoilInletNode.HumRat);
    2038       32403 :                     if ((OpMode == Operation::NeutralMode) || (OpMode == Operation::HeatingMode) || (wcCoilInletNode.Temp < CompAirOutTemp)) {
    2039       18433 :                         QCompReq = 0.0;
    2040       18433 :                         wcCoilOutletNode.Temp = wcCoilInletNode.Temp;
    2041       18433 :                         wcCoilOutletNode.HumRat = wcCoilInletNode.HumRat;
    2042       18433 :                         wcCoilOutletNode.MassFlowRate = wcCoilInletNode.MassFlowRate;
    2043             : 
    2044             :                     } else {
    2045             : 
    2046       13970 :                         QCompReq = CpAirZn * OAMassFlow * ((CompAirOutTemp - wcCoilInletNode.Temp) - FanEffect);
    2047       13970 :                         if (std::abs(QCompReq) < SmallLoad) QCompReq = 0.0;
    2048       13970 :                         if (QCompReq > 0.0) QCompReq = 0.0; // coil can cool only
    2049             :                     }
    2050             : 
    2051      129612 :                     ControlCompOutput(state,
    2052       32403 :                                       thisOutAirUnit.Name,
    2053       64806 :                                       std::string(ZoneHVACOAUnit),
    2054             :                                       UnitNum,
    2055             :                                       FirstHVACIteration,
    2056             :                                       QCompReq,
    2057             :                                       ControlNode,
    2058             :                                       MaxWaterFlow,
    2059             :                                       MinWaterFlow,
    2060             :                                       0.001,
    2061       32403 :                                       thisOutAirUnit.ControlCompTypeNum,
    2062       32403 :                                       thisOutAirUnit.CompErrIndex,
    2063             :                                       _,
    2064             :                                       _,
    2065             :                                       _,
    2066       64806 :                                       1,
    2067             :                                       SimCompNum,
    2068       32403 :                                       thisOAEquip.plantLoc);
    2069             :                 }
    2070       32403 :             } break;
    2071           0 :             case CompType::WaterCoil_DetailedCool: { // 'Coil:Cooling:Water:DetailedGeometry'
    2072           0 :                 if (Sim) {
    2073           0 :                     int const ControlNode = thisOAEquip.CoilWaterInletNode;
    2074           0 :                     MaxWaterFlow = thisOAEquip.MaxWaterMassFlow;
    2075           0 :                     MinWaterFlow = thisOAEquip.MinWaterMassFlow;
    2076             :                     // On the first HVAC iteration the system values are given to the controller, but after that
    2077             :                     // the demand limits are in place and there needs to be feedback to the Zone Equipment
    2078           0 :                     if ((!FirstHVACIteration) && (ControlNode > 0)) {
    2079           0 :                         MaxWaterFlow = state.dataLoopNodes->Node(ControlNode).MassFlowRateMaxAvail;
    2080           0 :                         MinWaterFlow = state.dataLoopNodes->Node(ControlNode).MassFlowRateMinAvail;
    2081             :                     }
    2082           0 :                     auto const &wcCoilInletNode = state.dataLoopNodes->Node(InletNodeNum);
    2083             :                     // auto &wcCoilOutletNode = state.dataLoopNodes->Node(OutletNodeNum);
    2084             : 
    2085           0 :                     Real64 const CpAirZn = PsyCpAirFnW(wcCoilInletNode.HumRat);
    2086             : 
    2087           0 :                     if ((OpMode == Operation::NeutralMode) || (OpMode == Operation::HeatingMode) || (wcCoilInletNode.Temp < CompAirOutTemp)) {
    2088           0 :                         QCompReq = 0.0;
    2089             :                     } else {
    2090             : 
    2091           0 :                         QCompReq = CpAirZn * OAMassFlow * ((CompAirOutTemp - wcCoilInletNode.Temp) - FanEffect);
    2092           0 :                         if (std::abs(QCompReq) < SmallLoad) QCompReq = 0.0;
    2093           0 :                         if (QCompReq > 0.0) QCompReq = 0.0; // coil can cool only
    2094             :                     }
    2095             : 
    2096           0 :                     ControlCompOutput(state,
    2097           0 :                                       thisOutAirUnit.Name,
    2098             :                                       "ZONEHVAC:OUTDOORAIRUNIT",
    2099             :                                       UnitNum,
    2100             :                                       FirstHVACIteration,
    2101             :                                       QCompReq,
    2102             :                                       ControlNode,
    2103             :                                       MaxWaterFlow,
    2104             :                                       MinWaterFlow,
    2105             :                                       0.001,
    2106           0 :                                       thisOutAirUnit.ControlCompTypeNum,
    2107           0 :                                       thisOutAirUnit.CompErrIndex,
    2108             :                                       _,
    2109             :                                       _,
    2110             :                                       _,
    2111           0 :                                       1,
    2112             :                                       SimCompNum,
    2113           0 :                                       thisOAEquip.plantLoc);
    2114             :                 }
    2115           0 :             } break;
    2116           0 :             case CompType::WaterCoil_CoolingHXAsst: { // 'CoilSystem:Cooling:Water:HeatExchangerAssisted'
    2117           0 :                 if (Sim) {
    2118           0 :                     int const ControlNode = thisOAEquip.CoilWaterInletNode;
    2119           0 :                     MaxWaterFlow = thisOAEquip.MaxWaterMassFlow;
    2120           0 :                     MinWaterFlow = 0.0;
    2121             :                     // On the first HVAC iteration the system values are given to the controller, but after that
    2122             :                     // the demand limits are in place and there needs to be feedback to the Zone Equipment
    2123           0 :                     if ((!FirstHVACIteration) && (ControlNode > 0)) {
    2124           0 :                         MaxWaterFlow = state.dataLoopNodes->Node(ControlNode).MassFlowRateMaxAvail;
    2125           0 :                         MinWaterFlow = state.dataLoopNodes->Node(ControlNode).MassFlowRateMinAvail;
    2126             :                     }
    2127           0 :                     auto const &wcCoilInletNode = state.dataLoopNodes->Node(InletNodeNum);
    2128             :                     // auto &wcCoilOutletNode = state.dataLoopNodes->Node(OutletNodeNum);
    2129             : 
    2130           0 :                     Real64 const CpAirZn = PsyCpAirFnW(wcCoilInletNode.HumRat);
    2131           0 :                     if ((OpMode == Operation::NeutralMode) || (OpMode == Operation::HeatingMode) || (wcCoilInletNode.Temp < CompAirOutTemp)) {
    2132           0 :                         QCompReq = 0.0;
    2133             :                     } else {
    2134           0 :                         QCompReq = CpAirZn * OAMassFlow * ((CompAirOutTemp - wcCoilInletNode.Temp) - FanEffect);
    2135           0 :                         if (std::abs(QCompReq) < SmallLoad) QCompReq = 0.0;
    2136           0 :                         if (QCompReq > 0.0) QCompReq = 0.0; // coil can cool only
    2137             :                     }
    2138           0 :                     ControlCompOutput(state,
    2139           0 :                                       thisOutAirUnit.Name,
    2140             :                                       "ZONEHVAC:OUTDOORAIRUNIT",
    2141             :                                       UnitNum,
    2142             :                                       FirstHVACIteration,
    2143             :                                       QCompReq,
    2144             :                                       ControlNode,
    2145             :                                       MaxWaterFlow,
    2146             :                                       MinWaterFlow,
    2147             :                                       0.001,
    2148           0 :                                       thisOutAirUnit.ControlCompTypeNum,
    2149           0 :                                       thisOutAirUnit.CompErrIndex,
    2150             :                                       _,
    2151             :                                       _,
    2152             :                                       _,
    2153           0 :                                       1,
    2154             :                                       SimCompNum,
    2155           0 :                                       thisOAEquip.plantLoc);
    2156             :                 }
    2157           0 :             } break;
    2158       74325 :             case CompType::DXSystem: { // CoilSystem:Cooling:DX  old 'CompType:UnitaryCoolOnly'
    2159       74325 :                 if (Sim) {
    2160       74325 :                     if (thisOAEquip.compPointer == nullptr) {
    2161           8 :                         UnitarySystems::UnitarySys thisSys;
    2162           8 :                         thisOAEquip.compPointer =
    2163           8 :                             thisSys.factory(state, HVAC::UnitarySysType::Unitary_AnyCoilType, thisOAEquip.ComponentName, false, OAUnitNum);
    2164           8 :                         UnitarySystems::UnitarySys::checkUnitarySysCoilInOASysExists(state, thisOAEquip.ComponentName, OAUnitNum);
    2165           8 :                     }
    2166       74325 :                     if (((OpMode == Operation::NeutralMode) && (thisOutAirUnit.controlType == OAUnitCtrlType::Temperature)) ||
    2167             :                         (OpMode == Operation::HeatingMode)) {
    2168       34177 :                         Dxsystemouttemp = 100.0; // There is no cooling demand for the DX system.
    2169             :                     } else {
    2170       40148 :                         Dxsystemouttemp = CompAirOutTemp - FanEffect;
    2171             :                     }
    2172       74325 :                     Real64 sensOut = 0.0;
    2173       74325 :                     Real64 latOut = 0.0;
    2174       74325 :                     int DXSystemIndex = 0;
    2175       74325 :                     thisOAEquip.compPointer->simulate(state,
    2176             :                                                       EquipName,
    2177             :                                                       FirstHVACIteration,
    2178             :                                                       -1,
    2179             :                                                       DXSystemIndex,
    2180       74325 :                                                       state.dataOutdoorAirUnit->HeatActive,
    2181       74325 :                                                       state.dataOutdoorAirUnit->CoolActive,
    2182             :                                                       UnitNum,
    2183             :                                                       Dxsystemouttemp,
    2184             :                                                       false,
    2185             :                                                       sensOut,
    2186             :                                                       latOut);
    2187             :                 }
    2188       74325 :             } break;
    2189       10866 :             case CompType::DXHeatPumpSystem: {
    2190       10866 :                 if (Sim) {
    2191       10866 :                     if (((OpMode == Operation::NeutralMode) && (thisOutAirUnit.controlType == OAUnitCtrlType::Temperature)) ||
    2192             :                         (OpMode == Operation::CoolingMode)) {
    2193        6374 :                         Dxsystemouttemp = -20.0; // There is no heating demand for the DX system.
    2194             :                     } else {
    2195        4492 :                         Dxsystemouttemp = CompAirOutTemp - FanEffect;
    2196             :                     }
    2197       10866 :                     int DXSystemIndex = 0;
    2198       10866 :                     SimDXHeatPumpSystem(state, EquipName, FirstHVACIteration, -1, DXSystemIndex, UnitNum, Dxsystemouttemp);
    2199             :                 }
    2200       10866 :             } break;
    2201             :                 // RAR need new CompType:UnitarySystem object here
    2202           0 :             case CompType::UnitarySystemModel: { // 'CompType:UnitarySystem'
    2203           0 :                 if (Sim) {
    2204             :                     // This may have to be done in the unitary system object since there can be both cooling and heating
    2205           0 :                     if (((OpMode == Operation::NeutralMode) && (thisOutAirUnit.controlType == OAUnitCtrlType::Temperature)) ||
    2206             :                         (OpMode == Operation::HeatingMode)) {
    2207           0 :                         Dxsystemouttemp = 100.0; // There is no cooling demand.
    2208           0 :                     } else if (((OpMode == Operation::NeutralMode) && (thisOutAirUnit.controlType == OAUnitCtrlType::Temperature)) ||
    2209             :                                (OpMode == Operation::CoolingMode)) {
    2210           0 :                         Dxsystemouttemp = -20.0; // There is no heating demand.
    2211             :                     } else {
    2212           0 :                         Dxsystemouttemp = CompAirOutTemp - FanEffect;
    2213             :                     }
    2214           0 :                     Real64 sensOut = 0.0;
    2215           0 :                     Real64 latOut = 0.0;
    2216           0 :                     int DXSystemIndex = 0;
    2217           0 :                     thisOAEquip.compPointer->simulate(state,
    2218             :                                                       EquipName,
    2219             :                                                       FirstHVACIteration,
    2220             :                                                       -1,
    2221             :                                                       DXSystemIndex,
    2222           0 :                                                       state.dataOutdoorAirUnit->HeatActive,
    2223           0 :                                                       state.dataOutdoorAirUnit->CoolActive,
    2224             :                                                       UnitNum,
    2225             :                                                       Dxsystemouttemp,
    2226             :                                                       false,
    2227             :                                                       sensOut,
    2228             :                                                       latOut);
    2229             :                 }
    2230           0 :             } break;
    2231           0 :             default: {
    2232           0 :                 ShowFatalError(state, format("Invalid Outdoor Air Unit Component={}", EquipType)); // validate
    2233           0 :             } break;
    2234             :             }
    2235             :         }
    2236      298647 :     }
    2237             : 
    2238      796352 :     void CalcOAUnitCoilComps(EnergyPlusData &state,
    2239             :                              int const CompNum, // actual outdoor air unit num
    2240             :                              bool const FirstHVACIteration,
    2241             :                              int const EquipIndex, // Component Type -- Integerized for this module
    2242             :                              Real64 &LoadMet)
    2243             :     {
    2244             : 
    2245             :         // SUBROUTINE INFORMATION:
    2246             :         //       AUTHOR         Young Tae Chae, Rick Strand
    2247             :         //       DATE WRITTEN   June 2009
    2248             :         //       MODIFIED
    2249             :         //       RE-ENGINEERED  na
    2250             : 
    2251             :         // PURPOSE OF THIS SUBROUTINE:
    2252             :         // This subroutine mainly controls the action of water components in the unit
    2253             : 
    2254             :         // METHODOLOGY EMPLOYED:
    2255             : 
    2256             :         // REFERENCES:
    2257             : 
    2258             :         // USE STATEMENTS:
    2259             : 
    2260             :         // Using/Aliasing
    2261             :         using HVAC::SmallLoad;
    2262             :         using HVACHXAssistedCoolingCoil::SimHXAssistedCoolingCoil;
    2263             :         using SteamCoils::SimulateSteamCoilComponents;
    2264             :         using WaterCoils::SimulateWaterCoilComponents;
    2265             : 
    2266             :         // SUBROUTINE ARGUMENT DEFINITIONS:
    2267             : 
    2268             :         // Locals
    2269             :         // SUBROUTINE LOCAL VARIABLE DEFINITIONS
    2270      796352 :         int CoilIndex = 0;
    2271             : 
    2272      796352 :         auto &thisOutAirUnit = state.dataOutdoorAirUnit->OutAirUnit(CompNum);
    2273      796352 :         auto &thisOAEquip = thisOutAirUnit.OAEquip(EquipIndex);
    2274      796352 :         int const InletNodeNum = thisOAEquip.CoilAirInletNode;
    2275      796352 :         int const OutletNodeNum = thisOAEquip.CoilAirOutletNode;
    2276      796352 :         auto const &oaInletNode = state.dataLoopNodes->Node(InletNodeNum);
    2277      796352 :         auto &oaOutletNode = state.dataLoopNodes->Node(OutletNodeNum);
    2278             : 
    2279      796352 :         CompType const CoilTypeNum = thisOAEquip.Type;
    2280      796352 :         Operation const OpMode = thisOutAirUnit.OperatingMode;
    2281      796352 :         Real64 const CoilAirOutTemp = thisOutAirUnit.CompOutSetTemp;
    2282      796352 :         bool const DrawFan = thisOutAirUnit.FanEffect;
    2283      796352 :         Real64 const FanEffect = DrawFan ? thisOutAirUnit.FanCorTemp : 0.0;
    2284             : 
    2285             :         // Actual equipment load
    2286      164355 :         auto setupQCompReq = [&OpMode, &oaInletNode, &oaOutletNode, &CoilAirOutTemp, &FanEffect]() -> Real64 {
    2287       43204 :             Real64 QCompReq = 0.0;
    2288       43204 :             if ((OpMode == Operation::NeutralMode) || (OpMode == Operation::CoolingMode) || (oaInletNode.Temp > CoilAirOutTemp)) {
    2289       25921 :                 QCompReq = 0.0;
    2290             :             } else {
    2291       17283 :                 oaOutletNode.MassFlowRate = oaInletNode.MassFlowRate;
    2292       17283 :                 Real64 const CpAirZn = PsyCpAirFnW(oaInletNode.HumRat);
    2293       17283 :                 QCompReq = oaInletNode.MassFlowRate * CpAirZn * ((CoilAirOutTemp - oaInletNode.Temp) - FanEffect);
    2294       17283 :                 if (std::abs(QCompReq) < SmallLoad) {
    2295           0 :                     QCompReq = 0.0;
    2296             :                 }
    2297             :             }
    2298       43204 :             if (QCompReq <= 0.0) {
    2299       25921 :                 QCompReq = 0.0; // a heating coil can only heat, not cool
    2300       25921 :                 oaOutletNode.Temp = oaInletNode.Temp;
    2301       25921 :                 oaOutletNode.HumRat = oaInletNode.HumRat;
    2302       25921 :                 oaOutletNode.MassFlowRate = oaInletNode.MassFlowRate;
    2303             :             }
    2304       43204 :             return QCompReq;
    2305      796352 :         };
    2306             : 
    2307      796352 :         switch (CoilTypeNum) {
    2308       32403 :         case CompType::Coil_ElectricHeat: {
    2309       32403 :             Real64 const QCompReq = setupQCompReq();
    2310       32403 :             HeatingCoils::SimulateHeatingCoilComponents(state, thisOAEquip.ComponentName, FirstHVACIteration, QCompReq, CoilIndex);
    2311       32403 :             Real64 const AirMassFlow = oaInletNode.MassFlowRate;
    2312       32403 :             LoadMet = AirMassFlow * (PsyHFnTdbW(oaOutletNode.Temp, oaInletNode.HumRat) - PsyHFnTdbW(oaInletNode.Temp, oaInletNode.HumRat));
    2313             : 
    2314       32403 :         } break;
    2315       10801 :         case CompType::Coil_GasHeat: { // 'Coil:Heating:Steam'
    2316       10801 :             Real64 const QCompReq = setupQCompReq();
    2317       10801 :             HeatingCoils::SimulateHeatingCoilComponents(state, thisOAEquip.ComponentName, FirstHVACIteration, QCompReq, CoilIndex);
    2318       10801 :             Real64 const AirMassFlow = oaInletNode.MassFlowRate;
    2319       10801 :             LoadMet = AirMassFlow * (PsyHFnTdbW(oaOutletNode.Temp, oaInletNode.HumRat) - PsyHFnTdbW(oaInletNode.Temp, oaInletNode.HumRat));
    2320             : 
    2321       10801 :         } break;
    2322           0 :         case CompType::SteamCoil_AirHeat: { // 'Coil:Heating:Steam'
    2323           0 :             Real64 const QCompReq = setupQCompReq();
    2324           0 :             SimulateSteamCoilComponents(state, thisOAEquip.ComponentName, FirstHVACIteration, CoilIndex, QCompReq);
    2325           0 :             Real64 const AirMassFlow = oaInletNode.MassFlowRate;
    2326           0 :             LoadMet = AirMassFlow * (PsyHFnTdbW(oaOutletNode.Temp, oaInletNode.HumRat) - PsyHFnTdbW(oaInletNode.Temp, oaInletNode.HumRat));
    2327             : 
    2328           0 :         } break;
    2329      753148 :         case CompType::WaterCoil_SimpleHeat: // 'Coil:Heating:Water')
    2330             :         case CompType::WaterCoil_Cooling:    // 'Coil:Cooling:Water'
    2331             :         case CompType::WaterCoil_DetailedCool: {
    2332      753148 :             SimulateWaterCoilComponents(state, thisOAEquip.ComponentName, FirstHVACIteration, CoilIndex);
    2333      753148 :             Real64 const AirMassFlow = oaInletNode.MassFlowRate;
    2334      753148 :             LoadMet = AirMassFlow * (PsyHFnTdbW(oaOutletNode.Temp, oaInletNode.HumRat) - PsyHFnTdbW(oaInletNode.Temp, oaInletNode.HumRat));
    2335             : 
    2336      753148 :         } break;
    2337           0 :         case CompType::WaterCoil_CoolingHXAsst: {
    2338           0 :             SimHXAssistedCoolingCoil(
    2339             :                 state, thisOAEquip.ComponentName, FirstHVACIteration, HVAC::CompressorOp::On, 0.0, CoilIndex, HVAC::FanOp::Continuous);
    2340           0 :             Real64 const AirMassFlow = oaInletNode.MassFlowRate;
    2341           0 :             LoadMet = AirMassFlow * (PsyHFnTdbW(oaOutletNode.Temp, oaInletNode.HumRat) - PsyHFnTdbW(oaInletNode.Temp, oaInletNode.HumRat));
    2342           0 :         } break;
    2343           0 :         default:
    2344           0 :             ShowFatalError(state, format("Invalid Coil Type = {}", CoilTypeNum)); // validate
    2345           0 :             break;
    2346             :         }
    2347      796352 :     }
    2348             : 
    2349             :     // SUBROUTINE UpdateOutdoorAirUnit
    2350             : 
    2351             :     // No update routine needed in this module since all of the updates happen on
    2352             :     // the Node derived type directly and these updates are done by other routines.
    2353             : 
    2354             :     // END SUBROUTINE UpdateOutdoorAirUnit
    2355             : 
    2356       64806 :     void ReportOutdoorAirUnit(EnergyPlusData &state,
    2357             :                               int const OAUnitNum) // Index for the outdoor air unit under consideration within the derived types
    2358             :     {
    2359             : 
    2360             :         // SUBROUTINE INFORMATION:
    2361             :         //       AUTHOR         Young T. Chae
    2362             :         //       DATE WRITTEN   Oct. 2009
    2363             :         //       MODIFIED       na
    2364             :         //       RE-ENGINEERED  na
    2365             : 
    2366             :         // PURPOSE OF THIS SUBROUTINE:
    2367             :         // This subroutine simply produces output for the outdoor air unit.
    2368             :         // METHODOLOGY EMPLOYED:
    2369             :         // Standard EnergyPlus methodology.
    2370             : 
    2371             :         // Using/Aliasing
    2372       64806 :         Real64 const TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
    2373             : 
    2374       64806 :         auto &thisOutAirUnit = state.dataOutdoorAirUnit->OutAirUnit(OAUnitNum);
    2375       64806 :         thisOutAirUnit.TotHeatingEnergy = thisOutAirUnit.TotHeatingRate * TimeStepSysSec;
    2376       64806 :         thisOutAirUnit.SensHeatingEnergy = thisOutAirUnit.SensHeatingRate * TimeStepSysSec;
    2377       64806 :         thisOutAirUnit.LatHeatingEnergy = thisOutAirUnit.LatHeatingRate * TimeStepSysSec;
    2378       64806 :         thisOutAirUnit.SensCoolingEnergy = thisOutAirUnit.SensCoolingRate * TimeStepSysSec;
    2379       64806 :         thisOutAirUnit.LatCoolingEnergy = thisOutAirUnit.LatCoolingRate * TimeStepSysSec;
    2380       64806 :         thisOutAirUnit.TotCoolingEnergy = thisOutAirUnit.TotCoolingRate * TimeStepSysSec;
    2381       64806 :         thisOutAirUnit.AirMassFlow = thisOutAirUnit.OutAirMassFlow;
    2382       64806 :         thisOutAirUnit.ElecFanEnergy = thisOutAirUnit.ElecFanRate * TimeStepSysSec;
    2383             : 
    2384       64806 :         if (thisOutAirUnit.FirstPass) { // reset sizing flags so other zone equipment can size normally
    2385          12 :             if (!state.dataGlobal->SysSizingCalc) {
    2386          12 :                 DataSizing::resetHVACSizingGlobals(state, state.dataSize->CurZoneEqNum, 0, thisOutAirUnit.FirstPass);
    2387             :             }
    2388             :         }
    2389       64806 :     }
    2390             : 
    2391        3474 :     int GetOutdoorAirUnitOutAirNode(EnergyPlusData &state, int const OAUnitNum)
    2392             :     {
    2393             : 
    2394             :         // FUNCTION INFORMATION:
    2395             :         //       AUTHOR         B Griffith
    2396             :         //       DATE WRITTEN   Dec  2006
    2397             :         //       MODIFIED       na
    2398             :         //       RE-ENGINEERED  na
    2399             : 
    2400             :         // PURPOSE OF THIS FUNCTION:
    2401             :         // lookup function for OA inlet node
    2402             : 
    2403             :         // Return value
    2404        3474 :         int GetOutdoorAirUnitOutAirNode = 0;
    2405             : 
    2406        3474 :         if (state.dataOutdoorAirUnit->GetOutdoorAirUnitInputFlag) {
    2407           0 :             OutdoorAirUnit::GetOutdoorAirUnitInputs(state);
    2408           0 :             state.dataOutdoorAirUnit->GetOutdoorAirUnitInputFlag = false;
    2409             :         }
    2410             : 
    2411        3474 :         if (OAUnitNum > 0 && OAUnitNum <= state.dataOutdoorAirUnit->NumOfOAUnits) {
    2412        3474 :             GetOutdoorAirUnitOutAirNode = state.dataOutdoorAirUnit->OutAirUnit(OAUnitNum).OutsideAirNode;
    2413             :         }
    2414             : 
    2415        3474 :         return GetOutdoorAirUnitOutAirNode;
    2416             :     }
    2417             : 
    2418        3474 :     int GetOutdoorAirUnitZoneInletNode(EnergyPlusData &state, int const OAUnitNum)
    2419             :     {
    2420             : 
    2421             :         // FUNCTION INFORMATION:
    2422             :         //       AUTHOR         B Griffith
    2423             :         //       DATE WRITTEN   Dec  2006
    2424             :         //       MODIFIED       na
    2425             :         //       RE-ENGINEERED  na
    2426             : 
    2427             :         // PURPOSE OF THIS FUNCTION:
    2428             :         // lookup function for OA inlet node
    2429             : 
    2430             :         // Return value
    2431        3474 :         int GetOutdoorAirUnitZoneInletNode = 0;
    2432             : 
    2433        3474 :         if (state.dataOutdoorAirUnit->GetOutdoorAirUnitInputFlag) {
    2434           0 :             OutdoorAirUnit::GetOutdoorAirUnitInputs(state);
    2435           0 :             state.dataOutdoorAirUnit->GetOutdoorAirUnitInputFlag = false;
    2436             :         }
    2437             : 
    2438        3474 :         if (OAUnitNum > 0 && OAUnitNum <= state.dataOutdoorAirUnit->NumOfOAUnits) {
    2439        3474 :             GetOutdoorAirUnitZoneInletNode = state.dataOutdoorAirUnit->OutAirUnit(OAUnitNum).AirOutletNode;
    2440             :         }
    2441             : 
    2442        3474 :         return GetOutdoorAirUnitZoneInletNode;
    2443             :     }
    2444             : 
    2445        3474 :     int GetOutdoorAirUnitReturnAirNode(EnergyPlusData &state, int const OAUnitNum)
    2446             :     {
    2447             : 
    2448             :         // FUNCTION INFORMATION:
    2449             :         //       AUTHOR         B Griffith
    2450             :         //       DATE WRITTEN   Dec  2006
    2451             :         //       MODIFIED       na
    2452             :         //       RE-ENGINEERED  na
    2453             : 
    2454             :         // PURPOSE OF THIS FUNCTION:
    2455             :         // lookup function for OA inlet node
    2456             : 
    2457             :         // Return value
    2458        3474 :         int GetOutdoorAirUnitReturnAirNode = 0;
    2459             : 
    2460        3474 :         if (state.dataOutdoorAirUnit->GetOutdoorAirUnitInputFlag) {
    2461           0 :             OutdoorAirUnit::GetOutdoorAirUnitInputs(state);
    2462           0 :             state.dataOutdoorAirUnit->GetOutdoorAirUnitInputFlag = false;
    2463             :         }
    2464             : 
    2465        3474 :         if (OAUnitNum > 0 && OAUnitNum <= state.dataOutdoorAirUnit->NumOfOAUnits) {
    2466        3474 :             GetOutdoorAirUnitReturnAirNode = state.dataOutdoorAirUnit->OutAirUnit(OAUnitNum).AirInletNode;
    2467             :         }
    2468             : 
    2469        3474 :         return GetOutdoorAirUnitReturnAirNode;
    2470             :     }
    2471             : 
    2472           0 :     int getOutdoorAirUnitEqIndex(EnergyPlusData &state, std::string_view EquipName)
    2473             :     {
    2474           0 :         if (state.dataOutdoorAirUnit->GetOutdoorAirUnitInputFlag) {
    2475           0 :             OutdoorAirUnit::GetOutdoorAirUnitInputs(state);
    2476           0 :             state.dataOutdoorAirUnit->GetOutdoorAirUnitInputFlag = false;
    2477             :         }
    2478             : 
    2479           0 :         for (int OAUnitNum = 1; OAUnitNum <= state.dataOutdoorAirUnit->NumOfOAUnits; ++OAUnitNum) {
    2480           0 :             if (Util::SameString(state.dataOutdoorAirUnit->OutAirUnit(OAUnitNum).Name, EquipName)) {
    2481           0 :                 return OAUnitNum;
    2482             :             }
    2483             :         }
    2484             : 
    2485           0 :         return 0;
    2486             :     }
    2487             : 
    2488             : } // namespace OutdoorAirUnit
    2489             : 
    2490             : } // namespace EnergyPlus

Generated by: LCOV version 1.14