LCOV - code coverage report
Current view: top level - EnergyPlus - OutdoorAirUnit.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 70.6 % 1197 845
Test Date: 2025-06-02 07:23:51 Functions: 92.9 % 14 13

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

Generated by: LCOV version 2.0-1