LCOV - code coverage report
Current view: top level - EnergyPlus - UnitVentilator.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 30.2 % 1862 562
Test Date: 2025-05-22 16:09:37 Functions: 82.4 % 17 14

            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              : 
      54              : // EnergyPlus Headers
      55              : #include <EnergyPlus/Autosizing/CoolingAirFlowSizing.hh>
      56              : #include <EnergyPlus/Autosizing/CoolingCapacitySizing.hh>
      57              : #include <EnergyPlus/Autosizing/HeatingAirFlowSizing.hh>
      58              : #include <EnergyPlus/Autosizing/HeatingCapacitySizing.hh>
      59              : #include <EnergyPlus/Autosizing/SystemAirFlowSizing.hh>
      60              : #include <EnergyPlus/BranchNodeConnections.hh>
      61              : #include <EnergyPlus/Data/EnergyPlusData.hh>
      62              : #include <EnergyPlus/DataAirSystems.hh>
      63              : #include <EnergyPlus/DataContaminantBalance.hh>
      64              : #include <EnergyPlus/DataEnvironment.hh>
      65              : #include <EnergyPlus/DataHVACGlobals.hh>
      66              : #include <EnergyPlus/DataHeatBalance.hh>
      67              : #include <EnergyPlus/DataLoopNode.hh>
      68              : #include <EnergyPlus/DataSizing.hh>
      69              : #include <EnergyPlus/DataZoneEnergyDemands.hh>
      70              : #include <EnergyPlus/DataZoneEquipment.hh>
      71              : #include <EnergyPlus/Fans.hh>
      72              : #include <EnergyPlus/FluidProperties.hh>
      73              : #include <EnergyPlus/General.hh>
      74              : #include <EnergyPlus/GeneralRoutines.hh>
      75              : #include <EnergyPlus/HVACHXAssistedCoolingCoil.hh>
      76              : #include <EnergyPlus/HeatingCoils.hh>
      77              : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      78              : #include <EnergyPlus/NodeInputManager.hh>
      79              : #include <EnergyPlus/OutAirNodeManager.hh>
      80              : #include <EnergyPlus/OutputProcessor.hh>
      81              : #include <EnergyPlus/PlantUtilities.hh>
      82              : #include <EnergyPlus/Psychrometrics.hh>
      83              : #include <EnergyPlus/ScheduleManager.hh>
      84              : #include <EnergyPlus/SingleDuct.hh>
      85              : #include <EnergyPlus/SteamCoils.hh>
      86              : #include <EnergyPlus/UnitVentilator.hh>
      87              : #include <EnergyPlus/UtilityRoutines.hh>
      88              : #include <EnergyPlus/WaterCoils.hh>
      89              : #include <EnergyPlus/ZonePlenum.hh>
      90              : 
      91              : namespace EnergyPlus {
      92              : 
      93              : namespace UnitVentilator {
      94              : 
      95              :     // Module containing the routines dealing with the Unit Ventilator
      96              : 
      97              :     // MODULE INFORMATION:
      98              :     //       AUTHOR         Rick Strand
      99              :     //       DATE WRITTEN   May 2000
     100              :     //       MODIFIED       March 2001   (addition of gas and electric coils)
     101              :     //                      October 2003 (addition of cooling coil type)
     102              :     //       MODIFIED       Bereket Nigusse, FSEC, October 2013, Added cycling fan operating mode
     103              : 
     104              :     // PURPOSE OF THIS MODULE:
     105              :     // To simulate unit ventilators.
     106              : 
     107              :     // METHODOLOGY EMPLOYED:
     108              :     // Units are modeled as a collection of components: outside air mixer,
     109              :     // fan, heating coil and/or cooling coil plus an integrated control
     110              :     // algorithm that adjusts the hot or cold water flow to meet the zone
     111              :     // load.  Outside air mixing is handled locally as either fixed percent
     112              :     // or as attempting to meet a prescribed mixed air temperature.
     113              : 
     114              :     // REFERENCES:
     115              :     // ASHRAE Systems and Equipment Handbook (SI), 1996. pp. 31.1-31.3
     116              :     // Fred Buhl's fan coil module (FanCoilUnits.cc)
     117              : 
     118              :     static constexpr std::array<std::string_view, static_cast<int>(CoilsUsed::Num)> CoilsUsedNamesUC = {
     119              :         "NONE", "HEATINGANDCOOLING", "HEATING", "COOLING"};
     120              :     static constexpr std::array<std::string_view, static_cast<int>(OAControl::Num)> OAControlNamesUC = {
     121              :         "VARIABLEPERCENT", "FIXEDTEMPERATURE", "FIXEDAMOUNT"};
     122              :     static constexpr std::array<std::string_view, static_cast<int>(HeatCoilType::Num)> HeatCoilTypeNamesUC = {
     123              :         "COIL:HEATING:ELECTRIC", "COIL:HEATING:FUEL", "COIL:HEATING:WATER", "COIL:HEATING:STEAM"};
     124              :     static constexpr std::array<std::string_view, static_cast<int>(CoolCoilType::Num)> CoolCoilTypeNamesUC = {
     125              :         "COIL:COOLING:WATER", "COIL:COOLING:WATER:DETAILEDGEOMETRY", "COILSYSTEM:COOLING:WATER:HEATEXCHANGERASSISTED"};
     126              : 
     127            2 :     void SimUnitVentilator(EnergyPlusData &state,
     128              :                            std::string_view CompName,     // name of the fan coil unit
     129              :                            int const ZoneNum,             // number of zone being served
     130              :                            bool const FirstHVACIteration, // TRUE if 1st HVAC simulation of system timestep
     131              :                            Real64 &PowerMet,              // Sensible power supplied (W)
     132              :                            Real64 &LatOutputProvided,     // Latent add/removal supplied by window AC (kg/s), dehumid = negative
     133              :                            int &CompIndex)
     134              :     {
     135              : 
     136              :         // SUBROUTINE INFORMATION:
     137              :         //       AUTHOR         Rick Strand
     138              :         //       DATE WRITTEN   May 2000
     139              :         //       MODIFIED       Don Shirey, Aug 2009 (LatOutputProvided)
     140              : 
     141              :         // PURPOSE OF THIS SUBROUTINE:
     142              :         // This is the main driver subroutine for the Unit Ventilator simulation.
     143              : 
     144              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     145              :         int UnitVentNum; // index of unit ventilator being simulated
     146              : 
     147            2 :         if (state.dataUnitVentilators->GetUnitVentilatorInputFlag) {
     148            0 :             GetUnitVentilatorInput(state);
     149            0 :             state.dataUnitVentilators->GetUnitVentilatorInputFlag = false;
     150              :         }
     151              : 
     152              :         // Find the correct Unit Ventilator Equipment
     153            2 :         if (CompIndex == 0) {
     154            0 :             UnitVentNum = Util::FindItemInList(CompName, state.dataUnitVentilators->UnitVent);
     155            0 :             if (UnitVentNum == 0) {
     156            0 :                 ShowFatalError(state, format("SimUnitVentilator: Unit not found={}", CompName));
     157              :             }
     158            0 :             CompIndex = UnitVentNum;
     159              :         } else {
     160            2 :             UnitVentNum = CompIndex;
     161            2 :             if (UnitVentNum > state.dataUnitVentilators->NumOfUnitVents || UnitVentNum < 1) {
     162            0 :                 ShowFatalError(state,
     163            0 :                                format("SimUnitVentilator:  Invalid CompIndex passed={}, Number of Units={}, Entered Unit name={}",
     164              :                                       UnitVentNum,
     165            0 :                                       state.dataUnitVentilators->NumOfUnitVents,
     166              :                                       CompName));
     167              :             }
     168            2 :             if (state.dataUnitVentilators->CheckEquipName(UnitVentNum)) {
     169            2 :                 if (CompName != state.dataUnitVentilators->UnitVent(UnitVentNum).Name) {
     170            0 :                     ShowFatalError(state,
     171            0 :                                    format("SimUnitVentilator: Invalid CompIndex passed={}, Unit name={}, stored Unit Name for that index={}",
     172              :                                           UnitVentNum,
     173              :                                           CompName,
     174            0 :                                           state.dataUnitVentilators->UnitVent(UnitVentNum).Name));
     175              :                 }
     176            2 :                 state.dataUnitVentilators->CheckEquipName(UnitVentNum) = false;
     177              :             }
     178              :         }
     179              : 
     180            2 :         state.dataSize->ZoneEqUnitVent = true;
     181              : 
     182            2 :         InitUnitVentilator(state, UnitVentNum, FirstHVACIteration, ZoneNum);
     183              : 
     184            2 :         CalcUnitVentilator(state, UnitVentNum, ZoneNum, FirstHVACIteration, PowerMet, LatOutputProvided);
     185              : 
     186            2 :         ReportUnitVentilator(state, UnitVentNum);
     187              : 
     188            2 :         state.dataSize->ZoneEqUnitVent = false;
     189            2 :     }
     190              : 
     191            2 :     void GetUnitVentilatorInput(EnergyPlusData &state)
     192              :     {
     193              : 
     194              :         // SUBROUTINE INFORMATION:
     195              :         //       AUTHOR         Rick Strand
     196              :         //       DATE WRITTEN   May 2000
     197              :         //       MODIFIED       Chandan Sharma, FSEC, March 2011: Added zone sys avail manager
     198              :         //                      Bereket Nigusse, FSEC, April 2011: eliminated input node names
     199              :         //                                                         & added fan object type
     200              : 
     201              :         // PURPOSE OF THIS SUBROUTINE:
     202              :         // This subroutine obtains the input for unit ventilators and sets
     203              :         // up the appropriate derived type.
     204              : 
     205              :         // REFERENCES:
     206              :         // Fred Buhl's fan coil module (FanCoilUnits.cc)
     207              : 
     208              :         // SUBROUTINE PARAMETER DEFINITIONS:
     209              :         static constexpr std::string_view RoutineName("GetUnitVentilatorInput: "); // include trailing blank
     210              :         static constexpr std::string_view routineName = "GetUnitVentilatorInput";  // include trailing blank
     211              : 
     212              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     213            2 :         bool ErrorsFound(false);       // Set to true if errors in input, fatal at end of routine
     214              :         int IOStatus;                  // Used in GetObjectItem
     215              :         bool IsNotOK;                  // TRUE if there was a problem with a list name
     216              :         int NumFields;                 // Total number of fields in object
     217              :         int NumAlphas;                 // Number of Alphas for each GetObjectItem call
     218              :         int NumNumbers;                // Number of Numbers for each GetObjectItem call
     219              :         bool IsValid;                  // Set for outside air node check
     220            2 :         bool errFlag(false);           // interim error flag
     221            2 :         std::string cCoolingCoilType;  // Cooling coil object type
     222            2 :         std::string cHeatingCoilType;  // Heating coil object type
     223              :         Real64 FanVolFlow;             // volumetric flow rate of fan
     224            2 :         Array1D_string Alphas;         // Alpha items for object
     225            2 :         Array1D<Real64> Numbers;       // Numeric items for object
     226            2 :         Array1D_string cAlphaFields;   // Alpha field names
     227            2 :         Array1D_string cNumericFields; // Numeric field names
     228            2 :         Array1D_bool lAlphaBlanks;     // Logical array, alpha field input BLANK = .TRUE.
     229            2 :         Array1D_bool lNumericBlanks;   // Logical array, numeric field input BLANK = .TRUE.
     230              :         bool ZoneNodeNotFound;         // used in error checking
     231              : 
     232              :         // Figure out how many unit ventilators there are in the input file
     233              : 
     234            2 :         std::string CurrentModuleObject = state.dataUnitVentilators->cMO_UnitVentilator;
     235            2 :         state.dataUnitVentilators->NumOfUnitVents = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
     236            2 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NumFields, NumAlphas, NumNumbers);
     237              : 
     238            2 :         Alphas.allocate(NumAlphas);
     239            2 :         Numbers.dimension(NumNumbers, 0.0);
     240            2 :         cAlphaFields.allocate(NumAlphas);
     241            2 :         cNumericFields.allocate(NumNumbers);
     242            2 :         lAlphaBlanks.dimension(NumAlphas, true);
     243            2 :         lNumericBlanks.dimension(NumNumbers, true);
     244              : 
     245              :         // Allocate the local derived type and do one-time initializations for all parts of it
     246            2 :         if (state.dataUnitVentilators->NumOfUnitVents > 0) {
     247            2 :             state.dataUnitVentilators->UnitVent.allocate(state.dataUnitVentilators->NumOfUnitVents);
     248            2 :             state.dataUnitVentilators->CheckEquipName.allocate(state.dataUnitVentilators->NumOfUnitVents);
     249            2 :             state.dataUnitVentilators->UnitVentNumericFields.allocate(state.dataUnitVentilators->NumOfUnitVents);
     250              :         }
     251            2 :         state.dataUnitVentilators->CheckEquipName = true;
     252              : 
     253              :         // Loop over all of the unit ventilators found in the input file.
     254            4 :         for (int UnitVentNum = 1; UnitVentNum <= state.dataUnitVentilators->NumOfUnitVents; ++UnitVentNum) {
     255              : 
     256            2 :             auto &unitVent = state.dataUnitVentilators->UnitVent(UnitVentNum);
     257              : 
     258            2 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     259              :                                                                      CurrentModuleObject,
     260              :                                                                      UnitVentNum,
     261              :                                                                      Alphas,
     262              :                                                                      NumAlphas,
     263              :                                                                      Numbers,
     264              :                                                                      NumNumbers,
     265              :                                                                      IOStatus,
     266              :                                                                      lNumericBlanks,
     267              :                                                                      lAlphaBlanks,
     268              :                                                                      cAlphaFields,
     269              :                                                                      cNumericFields);
     270              : 
     271            2 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
     272              : 
     273            2 :             state.dataUnitVentilators->UnitVentNumericFields(UnitVentNum).FieldNames.allocate(NumNumbers);
     274            2 :             state.dataUnitVentilators->UnitVentNumericFields(UnitVentNum).FieldNames = "";
     275            2 :             state.dataUnitVentilators->UnitVentNumericFields(UnitVentNum).FieldNames = cNumericFields;
     276            2 :             Util::IsNameEmpty(state, Alphas(1), CurrentModuleObject, ErrorsFound);
     277              : 
     278            2 :             unitVent.Name = Alphas(1);
     279            2 :             if (lAlphaBlanks(2)) {
     280            0 :                 unitVent.availSched = Sched::GetScheduleAlwaysOn(state);
     281            2 :             } else if ((unitVent.availSched = Sched::GetSchedule(state, Alphas(2))) == nullptr) {
     282            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(2), Alphas(2));
     283            0 :                 ErrorsFound = true;
     284              :             }
     285              : 
     286            2 :             unitVent.MaxAirVolFlow = Numbers(1);
     287              : 
     288              :             // Outside air information:
     289            2 :             unitVent.MinOutAirVolFlow = Numbers(2);
     290              : 
     291            2 :             if (lAlphaBlanks(4)) {
     292            0 :                 ShowSevereEmptyField(state, eoh, cAlphaFields(4));
     293            0 :                 ErrorsFound = true;
     294            2 :             } else if ((unitVent.minOASched = Sched::GetSchedule(state, Alphas(4))) == nullptr) {
     295            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(4), Alphas(4));
     296            0 :                 ErrorsFound = true;
     297              :             }
     298              : 
     299            2 :             unitVent.OutAirVolFlow = Numbers(3);
     300            2 :             cCoolingCoilType = "";
     301            2 :             cHeatingCoilType = "";
     302              : 
     303            2 :             unitVent.OAControlType = static_cast<OAControl>(getEnumValue(OAControlNamesUC, Alphas(3)));
     304            2 :             switch (unitVent.OAControlType) {
     305            2 :             case OAControl::VariablePercent:
     306              :             case OAControl::FixedAmount: {
     307            2 :                 if (lAlphaBlanks(5)) {
     308            0 :                     ShowSevereEmptyField(state, eoh, cAlphaFields(5));
     309            0 :                     ErrorsFound = true;
     310            2 :                 } else if ((unitVent.maxOASched = Sched::GetSchedule(state, Alphas(5))) == nullptr) {
     311            0 :                     ShowSevereItemNotFound(state, eoh, cAlphaFields(5), Alphas(5));
     312            0 :                     ErrorsFound = true;
     313            2 :                 } else if (!unitVent.maxOASched->checkMinMaxVals(state, Clusive::In, 0.0, Clusive::In, 1.0)) {
     314            0 :                     Sched::ShowSevereBadMinMax(state, eoh, cAlphaFields(5), Alphas(5), Clusive::In, 0.0, Clusive::In, 1.0);
     315            0 :                     ErrorsFound = true;
     316              :                 }
     317            2 :             } break;
     318              : 
     319            0 :             case OAControl::FixedTemperature: {
     320            0 :                 if (lAlphaBlanks(5)) {
     321            0 :                     ShowSevereEmptyField(state, eoh, cAlphaFields(5));
     322            0 :                     ErrorsFound = true;
     323            0 :                 } else if ((unitVent.tempSched = Sched::GetSchedule(state, Alphas(5))) == nullptr) {
     324            0 :                     ShowSevereItemNotFound(state, eoh, cAlphaFields(5), Alphas(5));
     325            0 :                     ErrorsFound = true;
     326              :                 }
     327            0 :             } break;
     328              : 
     329            0 :             default: {
     330            0 :                 assert(false);
     331              :             } break;
     332              :             } // end (switch)
     333              : 
     334              :             // Main air nodes (except outside air node):
     335              :             // For node connections, this object is both a parent and a non-parent, because the
     336              :             // OA mixing box is not called out as a separate component, its nodes must be connected
     337              :             // as ObjectIsNotParent.  But for the fan and coils, the nodes are connected as ObjectIsParent
     338              :             // To support the diagramming tool, the unit ventilator inlet node must appear both as
     339              :             // an inlet to the unit ventilator parent object and as an inlet to the implied
     340              :             // non-parent OA mixing box within the unit ventilator.
     341              :             // Because there is overlap between the nodes that are parent and non-parent, use a different
     342              :             // object type for the non parent nodes
     343            2 :             unitVent.AirInNode = NodeInputManager::GetOnlySingleNode(state,
     344            2 :                                                                      Alphas(6),
     345              :                                                                      ErrorsFound,
     346              :                                                                      DataLoopNode::ConnectionObjectType::ZoneHVACUnitVentilator,
     347            2 :                                                                      Alphas(1),
     348              :                                                                      DataLoopNode::NodeFluidType::Air,
     349              :                                                                      DataLoopNode::ConnectionType::Inlet,
     350              :                                                                      NodeInputManager::CompFluidStream::Primary,
     351              :                                                                      DataLoopNode::ObjectIsParent);
     352            2 :             unitVent.AirOutNode = NodeInputManager::GetOnlySingleNode(state,
     353            2 :                                                                       Alphas(7),
     354              :                                                                       ErrorsFound,
     355              :                                                                       DataLoopNode::ConnectionObjectType::ZoneHVACUnitVentilator,
     356            2 :                                                                       Alphas(1),
     357              :                                                                       DataLoopNode::NodeFluidType::Air,
     358              :                                                                       DataLoopNode::ConnectionType::Outlet,
     359              :                                                                       NodeInputManager::CompFluidStream::Primary,
     360              :                                                                       DataLoopNode::ObjectIsParent);
     361              : 
     362              :             // Get AirTerminal mixer data
     363            2 :             SingleDuct::GetATMixer(state,
     364            2 :                                    unitVent.Name,
     365            2 :                                    unitVent.ATMixerName,
     366            2 :                                    unitVent.ATMixerIndex,
     367            2 :                                    unitVent.ATMixerType,
     368            2 :                                    unitVent.ATMixerPriNode,
     369            2 :                                    unitVent.ATMixerSecNode,
     370            2 :                                    unitVent.ATMixerOutNode,
     371              :                                    unitVent.AirOutNode);
     372            2 :             if (unitVent.ATMixerType == HVAC::MixerType::InletSide || unitVent.ATMixerType == HVAC::MixerType::SupplySide) {
     373            2 :                 unitVent.ATMixerExists = true;
     374              :             }
     375            2 :             unitVent.ZonePtr =
     376            2 :                 DataZoneEquipment::GetZoneEquipControlledZoneNum(state, DataZoneEquipment::ZoneEquipType::UnitVentilator, unitVent.Name);
     377            2 :             if (unitVent.ZonePtr == 0) {
     378            0 :                 ErrorsFound = true;
     379              :             }
     380              : 
     381            2 :             if (!unitVent.ATMixerExists) {
     382            0 :                 unitVent.AirInNode = NodeInputManager::GetOnlySingleNode(state,
     383            0 :                                                                          Alphas(6),
     384              :                                                                          ErrorsFound,
     385              :                                                                          DataLoopNode::ConnectionObjectType::ZoneHVACUnitVentilator,
     386            0 :                                                                          Alphas(1) + "-OA MIXER",
     387              :                                                                          DataLoopNode::NodeFluidType::Air,
     388              :                                                                          DataLoopNode::ConnectionType::Inlet,
     389              :                                                                          NodeInputManager::CompFluidStream::Primary,
     390              :                                                                          DataLoopNode::ObjectIsNotParent);
     391              :             }
     392              : 
     393            2 :             unitVent.FanName = Alphas(12);
     394            2 :             unitVent.fanType = static_cast<HVAC::FanType>(getEnumValue(HVAC::fanTypeNamesUC, Alphas(11)));
     395              : 
     396            2 :             if (unitVent.fanType != HVAC::FanType::Constant && unitVent.fanType != HVAC::FanType::VAV && unitVent.fanType != HVAC::FanType::OnOff &&
     397            0 :                 unitVent.fanType != HVAC::FanType::SystemModel) {
     398            0 :                 ShowSevereInvalidKey(state, eoh, cAlphaFields(11), Alphas(11));
     399            0 :                 ShowContinueError(state, "Fan Type must be Fan:OnOff, Fan:ConstantVolume, Fan:VariableVolume, or Fan:SystemModel");
     400            0 :                 ErrorsFound = true;
     401              : 
     402            2 :             } else if ((unitVent.Fan_Index = Fans::GetFanIndex(state, unitVent.FanName)) == 0) {
     403            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(12), unitVent.FanName);
     404            0 :                 ErrorsFound = true;
     405              : 
     406              :             } else {
     407            2 :                 auto *fan = state.dataFans->fans(unitVent.Fan_Index);
     408            2 :                 unitVent.FanOutletNode = fan->outletNodeNum;
     409            2 :                 unitVent.fanAvailSched = fan->availSched; // Get the fan's availability schedule
     410            2 :                 FanVolFlow = fan->maxAirFlowRate;
     411            2 :                 if (FanVolFlow != DataSizing::AutoSize && unitVent.MaxAirVolFlow != DataSizing::AutoSize && FanVolFlow < unitVent.MaxAirVolFlow) {
     412            0 :                     ShowSevereError(state, format("{}{}=\"{}\".", RoutineName, CurrentModuleObject, unitVent.Name));
     413            0 :                     ShowContinueError(state,
     414            0 :                                       format("...air flow rate [{:.7T}] in fan object {} is less than the unit ventilator maximum "
     415              :                                              "supply air flow rate [{:.7T}].",
     416              :                                              FanVolFlow,
     417            0 :                                              unitVent.FanName,
     418            0 :                                              unitVent.MaxAirVolFlow));
     419            0 :                     ShowContinueError(state,
     420              :                                       "...the fan flow rate must be greater than or equal to the unit ventilator maximum supply "
     421              :                                       "air flow rate.");
     422            0 :                     ErrorsFound = true;
     423            2 :                 } else if (FanVolFlow == DataSizing::AutoSize && unitVent.MaxAirVolFlow != DataSizing::AutoSize) {
     424            0 :                     ShowWarningError(state, format("{}{}=\"{}\".", RoutineName, CurrentModuleObject, unitVent.Name));
     425            0 :                     ShowContinueError(state, "...the fan flow rate is autosized while the unit ventilator flow rate is not.");
     426            0 :                     ShowContinueError(state, "...this can lead to unexpected results where the fan flow rate is less than required.");
     427            2 :                 } else if (FanVolFlow != DataSizing::AutoSize && unitVent.MaxAirVolFlow == DataSizing::AutoSize) {
     428            0 :                     ShowWarningError(state, format("{}{}=\"{}\".", RoutineName, CurrentModuleObject, unitVent.Name));
     429            0 :                     ShowContinueError(state, "...the unit ventilator flow rate is autosized while the fan flow rate is not.");
     430            0 :                     ShowContinueError(state, "...this can lead to unexpected results where the fan flow rate is less than required.");
     431              :                 }
     432              :             }
     433              : 
     434              :             // For node connections, this object is both a parent and a non-parent, because the
     435              :             // OA mixing box is not called out as a separate component, its nodes must be connected
     436              :             // as ObjectIsNotParent.  But for the fan and coils, the nodes are connected as ObjectIsParent
     437              :             // Because there is overlap between the nodes that are parent and non-parent, use a different
     438              :             // object type for the non parent nodes
     439              :             //  Set connection type to 'OutdoorAir', because this is hardwired to OA conditions
     440            2 :             if (!unitVent.ATMixerExists) {
     441            0 :                 unitVent.OutsideAirNode = NodeInputManager::GetOnlySingleNode(state,
     442            0 :                                                                               Alphas(8),
     443              :                                                                               ErrorsFound,
     444              :                                                                               DataLoopNode::ConnectionObjectType::ZoneHVACUnitVentilator,
     445            0 :                                                                               Alphas(1) + "-OA MIXER",
     446              :                                                                               DataLoopNode::NodeFluidType::Air,
     447              :                                                                               DataLoopNode::ConnectionType::OutsideAirReference,
     448              :                                                                               NodeInputManager::CompFluidStream::Primary,
     449              :                                                                               DataLoopNode::ObjectIsNotParent);
     450            0 :                 if (!lAlphaBlanks(8)) {
     451            0 :                     OutAirNodeManager::CheckAndAddAirNodeNumber(state, unitVent.OutsideAirNode, IsValid);
     452            0 :                     if (!IsValid) {
     453            0 :                         ShowWarningError(state, format("{}{} Adding {}={}", RoutineName, CurrentModuleObject, cAlphaFields(8), Alphas(8)));
     454              :                     }
     455              :                 }
     456              : 
     457            0 :                 unitVent.AirReliefNode = NodeInputManager::GetOnlySingleNode(state,
     458            0 :                                                                              Alphas(9),
     459              :                                                                              ErrorsFound,
     460              :                                                                              DataLoopNode::ConnectionObjectType::ZoneHVACUnitVentilator,
     461            0 :                                                                              Alphas(1) + "-OA MIXER",
     462              :                                                                              DataLoopNode::NodeFluidType::Air,
     463              :                                                                              DataLoopNode::ConnectionType::ReliefAir,
     464              :                                                                              NodeInputManager::CompFluidStream::Primary,
     465              :                                                                              DataLoopNode::ObjectIsNotParent);
     466              : 
     467            0 :                 unitVent.OAMixerOutNode = NodeInputManager::GetOnlySingleNode(state,
     468            0 :                                                                               Alphas(10),
     469              :                                                                               ErrorsFound,
     470              :                                                                               DataLoopNode::ConnectionObjectType::ZoneHVACUnitVentilator,
     471            0 :                                                                               Alphas(1) + "-OA MIXER",
     472              :                                                                               DataLoopNode::NodeFluidType::Air,
     473              :                                                                               DataLoopNode::ConnectionType::Outlet,
     474              :                                                                               NodeInputManager::CompFluidStream::Primary,
     475              :                                                                               DataLoopNode::ObjectIsNotParent);
     476              :             } else {
     477            2 :                 unitVent.OutsideAirNode = unitVent.ATMixerPriNode;
     478            2 :                 unitVent.OAMixerOutNode = unitVent.ATMixerOutNode;
     479            2 :                 if (!lAlphaBlanks(8) || !lAlphaBlanks(9) || !lAlphaBlanks(10)) {
     480            0 :                     ShowWarningError(state, format("{}{}=\"{}\" is connected to central DOA.", RoutineName, CurrentModuleObject, unitVent.Name));
     481            0 :                     if (!lAlphaBlanks(8)) {
     482            0 :                         ShowContinueError(state, format("... input field {} should have been blank. Specified = {}", cAlphaFields(8), Alphas(8)));
     483              :                     }
     484            0 :                     if (!lAlphaBlanks(9)) {
     485            0 :                         ShowContinueError(state, format("... input field {} should have been blank. Specified = {}", cAlphaFields(9), Alphas(9)));
     486              :                     }
     487            0 :                     if (!lAlphaBlanks(10)) {
     488            0 :                         ShowContinueError(state, format("... input field {} should have been blank. Specified = {}", cAlphaFields(10), Alphas(10)));
     489              :                     }
     490              :                 }
     491              :             }
     492              : 
     493            2 :             if (unitVent.OAControlType == OAControl::FixedAmount) {
     494            0 :                 unitVent.OutAirVolFlow = unitVent.MinOutAirVolFlow;
     495            0 :                 unitVent.maxOASched = unitVent.minOASched;
     496              :             }
     497              : 
     498            2 :             if (!unitVent.ATMixerExists) {
     499              :                 // Add fan to component sets array
     500            0 :                 BranchNodeConnections::SetUpCompSets(state,
     501              :                                                      CurrentModuleObject,
     502              :                                                      unitVent.Name,
     503            0 :                                                      Alphas(11),
     504              :                                                      unitVent.FanName,
     505            0 :                                                      state.dataLoopNodes->NodeID(unitVent.OAMixerOutNode),
     506            0 :                                                      state.dataLoopNodes->NodeID(unitVent.FanOutletNode));
     507              :             } else {
     508            2 :                 if (unitVent.ATMixerType == HVAC::MixerType::InletSide) {
     509              :                     // Add fan to component sets array
     510            3 :                     BranchNodeConnections::SetUpCompSets(state,
     511              :                                                          CurrentModuleObject,
     512              :                                                          unitVent.Name,
     513            1 :                                                          Alphas(11),
     514              :                                                          unitVent.FanName,
     515            1 :                                                          state.dataLoopNodes->NodeID(unitVent.ATMixerOutNode),
     516            1 :                                                          state.dataLoopNodes->NodeID(unitVent.FanOutletNode));
     517              :                 }
     518            2 :                 if (unitVent.ATMixerType == HVAC::MixerType::SupplySide) {
     519              :                     // Add fan to component sets array
     520            3 :                     BranchNodeConnections::SetUpCompSets(state,
     521              :                                                          CurrentModuleObject,
     522              :                                                          unitVent.Name,
     523            1 :                                                          Alphas(11),
     524              :                                                          unitVent.FanName,
     525            1 :                                                          state.dataLoopNodes->NodeID(unitVent.AirInNode),
     526            1 :                                                          state.dataLoopNodes->NodeID(unitVent.FanOutletNode));
     527              :                 }
     528              :             }
     529              : 
     530            2 :             if (!lAlphaBlanks(19)) {
     531            0 :                 unitVent.AvailManagerListName = Alphas(19);
     532              :             }
     533              : 
     534            2 :             unitVent.HVACSizingIndex = 0;
     535            2 :             if (!lAlphaBlanks(20)) {
     536            0 :                 unitVent.HVACSizingIndex = Util::FindItemInList(Alphas(20), state.dataSize->ZoneHVACSizing);
     537            0 :                 if (unitVent.HVACSizingIndex == 0) {
     538            0 :                     ShowSevereError(state, format("{} = {} not found.", cAlphaFields(20), Alphas(20)));
     539            0 :                     ShowContinueError(state, format("Occurs in {} = \"{}\".", CurrentModuleObject, unitVent.Name));
     540            0 :                     ErrorsFound = true;
     541              :                 }
     542              :             }
     543              : 
     544            2 :             unitVent.CoilOption = (CoilsUsed)getEnumValue(CoilsUsedNamesUC, Alphas(13));
     545              : 
     546            2 :             if (lAlphaBlanks(14)) {
     547            6 :                 unitVent.fanOp = (unitVent.fanType == HVAC::FanType::OnOff || unitVent.fanType == HVAC::FanType::SystemModel)
     548            2 :                                      ? HVAC::FanOp::Cycling
     549              :                                      : HVAC::FanOp::Continuous;
     550            0 :             } else if ((unitVent.fanOpModeSched = Sched::GetSchedule(state, Alphas(14))) == nullptr) {
     551            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(14), Alphas(14));
     552            0 :                 ErrorsFound = true;
     553            0 :             } else if ((unitVent.fanType == HVAC::FanType::Constant) &&
     554            0 :                        !unitVent.fanOpModeSched->checkMinMaxVals(state, Clusive::Ex, 0.0, Clusive::In, 1.0)) {
     555            0 :                 Sched::ShowSevereBadMinMax(state, eoh, cAlphaFields(14), Alphas(14), Clusive::Ex, 0.0, Clusive::In, 1.0);
     556            0 :                 ErrorsFound = true;
     557              :             }
     558              : 
     559              :             // Get Coil information
     560            2 :             if (unitVent.CoilOption == CoilsUsed::Both || unitVent.CoilOption == CoilsUsed::Heating) {
     561            2 :                 if ((!lAlphaBlanks(16))) {
     562            2 :                     unitVent.HCoilPresent = true;
     563            2 :                     cHeatingCoilType = Alphas(15);
     564            2 :                     unitVent.HCoilTypeCh = cHeatingCoilType;
     565            2 :                     unitVent.HCoilType = (HeatCoilType)getEnumValue(HeatCoilTypeNamesUC, cHeatingCoilType);
     566            2 :                     unitVent.HeatingCoilType = (DataPlant::PlantEquipmentType)getEnumValue(DataPlant::PlantEquipTypeNamesUC, cHeatingCoilType);
     567              : 
     568            2 :                     unitVent.HCoilName = Alphas(16);
     569            2 :                     ValidateComponent(state, cHeatingCoilType, unitVent.HCoilName, IsNotOK, CurrentModuleObject);
     570            2 :                     if (IsNotOK) {
     571            0 :                         ShowContinueError(state, format("...specified in {} = \"{}\".", CurrentModuleObject, unitVent.Name));
     572            0 :                         ErrorsFound = true;
     573              :                     } else {
     574              :                         // The heating coil control node is necessary for a hot water coil, but not necessary for electric or gas.
     575            2 :                         if (unitVent.HCoilType == HeatCoilType::Water || unitVent.HCoilType == HeatCoilType::Steam) {
     576              :                             // mine the hot water or steam node from the coil object
     577            0 :                             if (unitVent.HCoilType == HeatCoilType::Water) {
     578            0 :                                 unitVent.HCoil_Index = WaterCoils::GetCompIndex(state, WaterCoils::CoilModel::HeatingSimple, unitVent.HCoilName);
     579            0 :                                 unitVent.HotControlNode = state.dataWaterCoils->WaterCoil(unitVent.HCoil_Index).WaterInletNodeNum;
     580            0 :                                 unitVent.MaxVolHotWaterFlow = state.dataWaterCoils->WaterCoil(unitVent.HCoil_Index).MaxWaterVolFlowRate;
     581              :                                 // Could probably remove MaxVolHotSteamFlow here
     582            0 :                                 unitVent.MaxVolHotSteamFlow = unitVent.MaxVolHotWaterFlow;
     583              :                             } else {
     584            0 :                                 unitVent.HCoil_Index = SteamCoils::GetCompIndex(state, unitVent.HCoilName);
     585            0 :                                 unitVent.HotControlNode = state.dataSteamCoils->SteamCoil(unitVent.HCoil_Index).SteamInletNodeNum;
     586              :                                 // Could probably replace MaxVolHotWaterFlow here with MaxVolHotSteamFlow
     587            0 :                                 unitVent.MaxVolHotWaterFlow = state.dataSteamCoils->SteamCoil(unitVent.HCoil_Index).MaxSteamVolFlowRate;
     588              :                                 // unitVent.MaxVolHotWaterFlow =
     589              :                                 //    SteamCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Steam", unitVent.HCoilName, ErrorsFound);
     590            0 :                                 unitVent.MaxVolHotSteamFlow = unitVent.MaxVolHotWaterFlow;
     591              :                             }
     592              :                         }
     593              :                     }
     594              : 
     595            2 :                     unitVent.HotControlOffset = Numbers(4);
     596              :                     // Set default convergence tolerance
     597            2 :                     if (unitVent.HotControlOffset <= 0.0) {
     598            0 :                         unitVent.HotControlOffset = 0.001;
     599              :                     }
     600              :                 } else { // heating coil is required for these options
     601            0 :                     ShowSevereError(state, format("{}{}=\"{}\".", RoutineName, CurrentModuleObject, unitVent.Name));
     602            0 :                     ShowContinueError(state, format("a heating coil is required for {}=\"{}\".", cAlphaFields(13), Alphas(13)));
     603            0 :                     ErrorsFound = true;
     604              :                 } // IF (.NOT. lAlphaBlanks(15)) THEN - from the start of heating coil information
     605              :             }     // is option both or heating only
     606              : 
     607            2 :             if (unitVent.CoilOption == CoilsUsed::Both || unitVent.CoilOption == CoilsUsed::Cooling) {
     608            0 :                 if (!lAlphaBlanks(18)) {
     609            0 :                     unitVent.CCoilPresent = true;
     610            0 :                     errFlag = false;
     611              : 
     612            0 :                     cCoolingCoilType = Alphas(17);
     613            0 :                     unitVent.CCoilTypeCh = cCoolingCoilType;
     614            0 :                     unitVent.CCoilType = (CoolCoilType)getEnumValue(CoolCoilTypeNamesUC, cCoolingCoilType);
     615            0 :                     unitVent.CoolingCoilType = (DataPlant::PlantEquipmentType)getEnumValue(DataPlant::PlantEquipTypeNamesUC, cCoolingCoilType);
     616            0 :                     unitVent.CCoilPlantName = Alphas(18);
     617              : 
     618            0 :                     if (cCoolingCoilType == "COILSYSTEM:COOLING:WATER:HEATEXCHANGERASSISTED") {
     619            0 :                         unitVent.CCoilType = CoolCoilType::HXAssisted;
     620            0 :                         HVACHXAssistedCoolingCoil::GetHXCoilTypeAndName(
     621            0 :                             state, cCoolingCoilType, Alphas(18), ErrorsFound, unitVent.CCoilPlantType, unitVent.CCoilPlantName);
     622            0 :                         if (Util::SameString(unitVent.CCoilPlantType, "Coil:Cooling:Water")) {
     623            0 :                             unitVent.CoolingCoilType = DataPlant::PlantEquipmentType::CoilWaterCooling;
     624            0 :                         } else if (Util::SameString(unitVent.CCoilPlantType, "Coil:Cooling:Water:DetailedGeometry")) {
     625            0 :                             unitVent.CoolingCoilType = DataPlant::PlantEquipmentType::CoilWaterDetailedFlatCooling;
     626              :                         } else {
     627            0 :                             ShowSevereError(state, format("{}{}=\"{}\".", RoutineName, CurrentModuleObject, unitVent.Name));
     628            0 :                             ShowContinueError(state, format("For: {}=\"{}\".", cAlphaFields(17), Alphas(17)));
     629            0 :                             ShowContinueError(state, format("Invalid Coil Type={}, Name={}", unitVent.CCoilPlantType, unitVent.CCoilPlantName));
     630            0 :                             ShowContinueError(state,
     631              :                                               "must be \"Coil:Cooling:Water\", \"Coil:Cooling:Water:DetailedGeometry\" or, "
     632              :                                               "\"CoilSystem:Cooling:Water:HeatExchangerAssisted\".");
     633            0 :                             errFlag = true;
     634            0 :                             ErrorsFound = true;
     635              :                         }
     636              :                     }
     637              : 
     638            0 :                     if (!errFlag) {
     639            0 :                         unitVent.CCoilName = Alphas(18);
     640            0 :                         ValidateComponent(state, cCoolingCoilType, unitVent.CCoilName, IsNotOK, CurrentModuleObject);
     641            0 :                         if (IsNotOK) {
     642            0 :                             ShowContinueError(state, format("...specified in {} = \"{}\".", CurrentModuleObject, unitVent.Name));
     643            0 :                             ErrorsFound = true;
     644              :                         } else {
     645            0 :                             if (unitVent.CCoilType != CoolCoilType::HXAssisted) {
     646            0 :                                 WaterCoils::CoilModel coilModel = WaterCoils::CoilModel::CoolingSimple;
     647            0 :                                 if (unitVent.CCoilType == CoolCoilType::Detailed) coilModel = WaterCoils::CoilModel::CoolingDetailed;
     648            0 :                                 unitVent.CCoil_Index = WaterCoils::GetCompIndex(state, coilModel, unitVent.CCoilName);
     649            0 :                                 unitVent.ColdControlNode = state.dataWaterCoils->WaterCoil(unitVent.CCoil_Index).WaterInletNodeNum;
     650            0 :                                 unitVent.MaxVolColdWaterFlow = state.dataWaterCoils->WaterCoil(unitVent.CCoil_Index).MaxWaterVolFlowRate;
     651              :                             } else {
     652              :                                 // special case, call the parent and return the child water inlet node and water volume flow rate
     653            0 :                                 unitVent.ColdControlNode =
     654            0 :                                     HVACHXAssistedCoolingCoil::GetCoilWaterInletNode(state, unitVent.CCoilTypeCh, unitVent.CCoilName, errFlag);
     655            0 :                                 unitVent.MaxVolColdWaterFlow = HVACHXAssistedCoolingCoil::GetCoilMaxWaterFlowRate(
     656            0 :                                     state, "CoilSystem:Cooling:Water:HeatExchangerAssisted", unitVent.CCoilName, errFlag);
     657              :                             }
     658              :                             // Other error checks should trap before it gets to this point in the code, but including just in case.
     659            0 :                             if (errFlag) {
     660            0 :                                 ShowContinueError(state, format("...specified in {} = \"{}\".", CurrentModuleObject, unitVent.Name));
     661            0 :                                 ErrorsFound = true;
     662              :                             }
     663              :                         }
     664              :                     }
     665              : 
     666            0 :                     unitVent.MinVolColdWaterFlow = 0.0;
     667            0 :                     unitVent.ColdControlOffset = Numbers(5);
     668              :                     // Set default convergence tolerance
     669            0 :                     if (unitVent.ColdControlOffset <= 0.0) {
     670            0 :                         unitVent.ColdControlOffset = 0.001;
     671              :                     }
     672              :                 } else { // Cooling Coil is required for this/these options
     673            0 :                     ShowSevereError(state, format("{}{}=\"{}\".", RoutineName, CurrentModuleObject, unitVent.Name));
     674            0 :                     ShowContinueError(state, format("a cooling coil is required for {}=\"{}\".", cAlphaFields(13), Alphas(13)));
     675            0 :                     ErrorsFound = true;
     676              :                 } // IF (.NOT. lAlphaBlanks(17)) THEN - from the start of cooling coil information
     677              :             }
     678            2 :             if (!unitVent.ATMixerExists) {
     679              :                 // check that unit ventilator air inlet node is the same as a zone exhaust node
     680            0 :                 ZoneNodeNotFound = true;
     681            0 :                 for (int NodeNum = 1; NodeNum <= state.dataZoneEquip->ZoneEquipConfig(unitVent.ZonePtr).NumExhaustNodes; ++NodeNum) {
     682            0 :                     if (unitVent.AirInNode == state.dataZoneEquip->ZoneEquipConfig(unitVent.ZonePtr).ExhaustNode(NodeNum)) {
     683            0 :                         ZoneNodeNotFound = false;
     684            0 :                         break;
     685              :                     }
     686              :                 }
     687            0 :                 if (ZoneNodeNotFound) {
     688            0 :                     bool InletNodeFound = false;
     689            0 :                     if (unitVent.ZonePtr > 0) {
     690            0 :                         InletNodeFound = ZonePlenum::ValidateInducedNode(state,
     691              :                                                                          unitVent.AirInNode,
     692            0 :                                                                          state.dataZoneEquip->ZoneEquipConfig(unitVent.ZonePtr).NumReturnNodes,
     693            0 :                                                                          state.dataZoneEquip->ZoneEquipConfig(unitVent.ZonePtr).ReturnNode);
     694              :                     }
     695            0 :                     if (!InletNodeFound) {
     696            0 :                         ShowSevereError(state,
     697            0 :                                         format("{} = \"{}\". Unit ventilator air inlet node name must be the same either as a zone exhaust node name "
     698              :                                                "or an induce air node in ZoePlenum.",
     699              :                                                CurrentModuleObject,
     700            0 :                                                unitVent.Name));
     701            0 :                         ShowContinueError(state, "..Zone exhaust node name is specified in ZoneHVAC:EquipmentConnections object.");
     702            0 :                         ShowContinueError(state, "..Induced Air Outlet Node name is specified in AirLoopHVAC:ReturnPlenum object.");
     703            0 :                         ShowContinueError(state,
     704            0 :                                           format("..Unit ventilator unit air inlet node name = {}", state.dataLoopNodes->NodeID(unitVent.AirInNode)));
     705            0 :                         ErrorsFound = true;
     706              :                     }
     707              :                 }
     708              :                 // check that unit ventilator air outlet node is the same as a zone inlet node.
     709            0 :                 ZoneNodeNotFound = true;
     710            0 :                 for (int NodeNum = 1; NodeNum <= state.dataZoneEquip->ZoneEquipConfig(unitVent.ZonePtr).NumInletNodes; ++NodeNum) {
     711            0 :                     if (unitVent.AirOutNode == state.dataZoneEquip->ZoneEquipConfig(unitVent.ZonePtr).InletNode(NodeNum)) {
     712            0 :                         ZoneNodeNotFound = false;
     713            0 :                         break;
     714              :                     }
     715              :                 }
     716            0 :                 if (ZoneNodeNotFound) {
     717            0 :                     ShowSevereError(state,
     718            0 :                                     format("{} = \"{}\". Unit ventilator air outlet node name must be the same as a zone inlet node name.",
     719              :                                            CurrentModuleObject,
     720            0 :                                            unitVent.Name));
     721            0 :                     ShowContinueError(state, "..Zone inlet node name is specified in ZoneHVAC:EquipmentConnections object.");
     722            0 :                     ShowContinueError(state, format("..Unit ventilator air outlet node name = {}", state.dataLoopNodes->NodeID(unitVent.AirOutNode)));
     723            0 :                     ErrorsFound = true;
     724              :                 }
     725              :             } else {
     726            2 :                 if (unitVent.ATMixerType == HVAC::MixerType::InletSide) {
     727              :                     // check that unit ventilator air outlet node is the same as a zone inlet node.
     728            1 :                     ZoneNodeNotFound = true;
     729            1 :                     for (int NodeNum = 1; NodeNum <= state.dataZoneEquip->ZoneEquipConfig(unitVent.ZonePtr).NumInletNodes; ++NodeNum) {
     730            1 :                         if (unitVent.AirOutNode == state.dataZoneEquip->ZoneEquipConfig(unitVent.ZonePtr).InletNode(NodeNum)) {
     731            1 :                             ZoneNodeNotFound = false;
     732            1 :                             break;
     733              :                         }
     734              :                     }
     735            1 :                     if (ZoneNodeNotFound) {
     736            0 :                         ShowSevereError(state,
     737            0 :                                         format("{} = \"{}\". Unit ventilator air outlet node name must be the same as a zone inlet node name.",
     738              :                                                CurrentModuleObject,
     739            0 :                                                unitVent.Name));
     740            0 :                         ShowContinueError(state, "..Zone inlet node name is specified in ZoneHVAC:EquipmentConnections object.");
     741            0 :                         ShowContinueError(state,
     742            0 :                                           format("..Unit ventilator air outlet node name = {}", state.dataLoopNodes->NodeID(unitVent.AirOutNode)));
     743            0 :                         ErrorsFound = true;
     744              :                     }
     745              : 
     746              :                     // check that the air mixer out node is the unit ventilator air inlet node
     747            1 :                     if (unitVent.AirInNode != unitVent.ATMixerOutNode) {
     748            0 :                         ShowSevereError(state,
     749            0 :                                         format("{} = \"{}\". unit ventilator air inlet node name must be the same as the mixer outlet node name.",
     750              :                                                CurrentModuleObject,
     751            0 :                                                unitVent.Name));
     752            0 :                         ShowContinueError(state, "..Air terminal mixer outlet node name is specified in AirTerminal:SingleDuct:Mixer object.");
     753            0 :                         ShowContinueError(state,
     754            0 :                                           format("..Unit ventilator air inlet node name = {}", state.dataLoopNodes->NodeID(unitVent.AirInNode)));
     755            0 :                         ErrorsFound = true;
     756              :                     }
     757              :                 }
     758            2 :                 if (unitVent.ATMixerType == HVAC::MixerType::SupplySide) {
     759              :                     // check that the mixer secondary air node is the unit ventilator air outlet node
     760            1 :                     if (unitVent.AirOutNode != unitVent.ATMixerSecNode) {
     761            0 :                         ShowSevereError(
     762              :                             state,
     763            0 :                             format("{} = \"{}\". unit ventilator air outlet node name must be the same as the mixer secondary air inlet node name.",
     764              :                                    CurrentModuleObject,
     765            0 :                                    unitVent.Name));
     766            0 :                         ShowContinueError(state, "..Air terminal mixer secondary node name is specified in AirTerminal:SingleDuct:Mixer object.");
     767            0 :                         ShowContinueError(state,
     768            0 :                                           format("..Unit ventilator air outlet node name = {}", state.dataLoopNodes->NodeID(unitVent.AirOutNode)));
     769            0 :                         ErrorsFound = true;
     770              :                     }
     771              : 
     772              :                     // check that air teminal mixer outlet node is the same as a zone inlet node.
     773            1 :                     ZoneNodeNotFound = true;
     774            1 :                     for (int NodeNum = 1; NodeNum <= state.dataZoneEquip->ZoneEquipConfig(unitVent.ZonePtr).NumInletNodes; ++NodeNum) {
     775            1 :                         if (unitVent.ATMixerOutNode == state.dataZoneEquip->ZoneEquipConfig(unitVent.ZonePtr).InletNode(NodeNum)) {
     776            1 :                             ZoneNodeNotFound = false;
     777            1 :                             break;
     778              :                         }
     779              :                     }
     780            1 :                     if (ZoneNodeNotFound) {
     781            0 :                         ShowSevereError(state,
     782            0 :                                         format("{} = \"{}\". Air mixer outlet node name must be the same as a zone inlet node name.",
     783              :                                                CurrentModuleObject,
     784            0 :                                                unitVent.Name));
     785            0 :                         ShowContinueError(state, "..Zone inlet node name is specified in ZoneHVAC:EquipmentConnections object.");
     786            0 :                         ShowContinueError(state,
     787            0 :                                           format("..Air terminal mixer outlet node name = {}", state.dataLoopNodes->NodeID(unitVent.ATMixerOutNode)));
     788            0 :                         ErrorsFound = true;
     789              :                     } else {
     790            1 :                         bool ExhastNodeNotFound = true;
     791              :                         // check exhaust node
     792            1 :                         for (int NodeNum = 1; NodeNum <= state.dataZoneEquip->ZoneEquipConfig(unitVent.ZonePtr).NumExhaustNodes; ++NodeNum) {
     793            1 :                             if (unitVent.AirInNode == state.dataZoneEquip->ZoneEquipConfig(unitVent.ZonePtr).ExhaustNode(NodeNum)) {
     794            1 :                                 ExhastNodeNotFound = false;
     795            1 :                                 break;
     796              :                             }
     797              :                         }
     798              :                         // check induce node
     799            1 :                         if (ExhastNodeNotFound) {
     800            0 :                             bool InletNodeFound = false;
     801            0 :                             if (unitVent.ZonePtr > 0) {
     802              :                                 InletNodeFound =
     803            0 :                                     ZonePlenum::ValidateInducedNode(state,
     804              :                                                                     unitVent.AirInNode,
     805            0 :                                                                     state.dataZoneEquip->ZoneEquipConfig(unitVent.ZonePtr).NumReturnNodes,
     806            0 :                                                                     state.dataZoneEquip->ZoneEquipConfig(unitVent.ZonePtr).ReturnNode);
     807              :                             }
     808            0 :                             if (!InletNodeFound) {
     809            0 :                                 ShowSevereError(state, format("{}{}=\"{}\".", RoutineName, CurrentModuleObject, unitVent.Name));
     810            0 :                                 ShowContinueError(
     811              :                                     state,
     812              :                                     "..UnitVentilator inlet node name must be the same as either a zone exhaust node name or an induced "
     813              :                                     "air node in ZonePlenum.");
     814            0 :                                 ShowContinueError(state, "..Zone exhaust node name is specified in ZoneHVAC:EquipmentConnections object.");
     815            0 :                                 ShowContinueError(state, "..Induced Air Outlet Node name is specified in AirLoopHVAC:ReturnPlenum object.");
     816            0 :                                 ShowContinueError(state,
     817            0 :                                                   format("..UnitVentilator inlet node name = {}", state.dataLoopNodes->NodeID(unitVent.AirInNode)));
     818            0 :                                 ErrorsFound = true;
     819              :                             }
     820              :                         }
     821              :                     }
     822              :                 }
     823              :             }
     824              :             {
     825            2 :                 switch (unitVent.CoilOption) {
     826            0 :                 case CoilsUsed::Both: {
     827              :                     // Add cooling coil to component sets array when present
     828            0 :                     BranchNodeConnections::SetUpCompSets(state,
     829              :                                                          CurrentModuleObject,
     830              :                                                          unitVent.Name,
     831              :                                                          cCoolingCoilType,
     832              :                                                          unitVent.CCoilName,
     833            0 :                                                          state.dataLoopNodes->NodeID(unitVent.FanOutletNode),
     834              :                                                          "UNDEFINED");
     835              : 
     836              :                     // Add heating coil to component sets array when cooling coil present
     837            0 :                     BranchNodeConnections::SetUpCompSets(state,
     838              :                                                          CurrentModuleObject,
     839              :                                                          unitVent.Name,
     840              :                                                          cHeatingCoilType,
     841              :                                                          unitVent.HCoilName,
     842              :                                                          "UNDEFINED",
     843            0 :                                                          state.dataLoopNodes->NodeID(unitVent.AirOutNode));
     844            0 :                 } break;
     845            2 :                 case CoilsUsed::Heating: {
     846              :                     // Add heating coil to component sets array when no cooling coil present
     847            4 :                     BranchNodeConnections::SetUpCompSets(state,
     848              :                                                          CurrentModuleObject,
     849              :                                                          unitVent.Name,
     850              :                                                          cHeatingCoilType,
     851              :                                                          unitVent.HCoilName,
     852            2 :                                                          state.dataLoopNodes->NodeID(unitVent.FanOutletNode),
     853            2 :                                                          state.dataLoopNodes->NodeID(unitVent.AirOutNode));
     854            2 :                 } break;
     855            0 :                 case CoilsUsed::Cooling: {
     856              :                     // Add cooling coil to component sets array when no heating coil present
     857            0 :                     BranchNodeConnections::SetUpCompSets(state,
     858              :                                                          CurrentModuleObject,
     859              :                                                          unitVent.Name,
     860              :                                                          cCoolingCoilType,
     861              :                                                          unitVent.CCoilName,
     862            0 :                                                          state.dataLoopNodes->NodeID(unitVent.FanOutletNode),
     863            0 :                                                          state.dataLoopNodes->NodeID(unitVent.AirOutNode));
     864            0 :                 } break;
     865            0 :                 default: {
     866            0 :                 } break;
     867              :                 }
     868              :             }
     869              :         } // ...loop over all of the unit ventilators found in the input file
     870              : 
     871            2 :         Alphas.deallocate();
     872            2 :         Numbers.deallocate();
     873            2 :         cAlphaFields.deallocate();
     874            2 :         cNumericFields.deallocate();
     875            2 :         lAlphaBlanks.deallocate();
     876            2 :         lNumericBlanks.deallocate();
     877              : 
     878            2 :         if (ErrorsFound) ShowFatalError(state, format("{}Errors found in input.", RoutineName));
     879              : 
     880              :         // Setup Report variables for the Unit Ventilators, CurrentModuleObject='ZoneHVAC:UnitVentilator'
     881            4 :         for (int UnitVentNum = 1; UnitVentNum <= state.dataUnitVentilators->NumOfUnitVents; ++UnitVentNum) {
     882              : 
     883            2 :             auto &unitVent = state.dataUnitVentilators->UnitVent(UnitVentNum);
     884            2 :             auto &coilReportObj = state.dataRptCoilSelection->coilSelectionReportObj;
     885              : 
     886            4 :             SetupOutputVariable(state,
     887              :                                 "Zone Unit Ventilator Heating Rate",
     888              :                                 Constant::Units::W,
     889            2 :                                 unitVent.HeatPower,
     890              :                                 OutputProcessor::TimeStepType::System,
     891              :                                 OutputProcessor::StoreType::Average,
     892            2 :                                 unitVent.Name);
     893            4 :             SetupOutputVariable(state,
     894              :                                 "Zone Unit Ventilator Heating Energy",
     895              :                                 Constant::Units::J,
     896            2 :                                 unitVent.HeatEnergy,
     897              :                                 OutputProcessor::TimeStepType::System,
     898              :                                 OutputProcessor::StoreType::Sum,
     899            2 :                                 unitVent.Name);
     900            4 :             SetupOutputVariable(state,
     901              :                                 "Zone Unit Ventilator Total Cooling Rate",
     902              :                                 Constant::Units::W,
     903            2 :                                 unitVent.TotCoolPower,
     904              :                                 OutputProcessor::TimeStepType::System,
     905              :                                 OutputProcessor::StoreType::Average,
     906            2 :                                 unitVent.Name);
     907            4 :             SetupOutputVariable(state,
     908              :                                 "Zone Unit Ventilator Total Cooling Energy",
     909              :                                 Constant::Units::J,
     910            2 :                                 unitVent.TotCoolEnergy,
     911              :                                 OutputProcessor::TimeStepType::System,
     912              :                                 OutputProcessor::StoreType::Sum,
     913            2 :                                 unitVent.Name);
     914            4 :             SetupOutputVariable(state,
     915              :                                 "Zone Unit Ventilator Sensible Cooling Rate",
     916              :                                 Constant::Units::W,
     917            2 :                                 unitVent.SensCoolPower,
     918              :                                 OutputProcessor::TimeStepType::System,
     919              :                                 OutputProcessor::StoreType::Average,
     920            2 :                                 unitVent.Name);
     921            4 :             SetupOutputVariable(state,
     922              :                                 "Zone Unit Ventilator Sensible Cooling Energy",
     923              :                                 Constant::Units::J,
     924            2 :                                 unitVent.SensCoolEnergy,
     925              :                                 OutputProcessor::TimeStepType::System,
     926              :                                 OutputProcessor::StoreType::Sum,
     927            2 :                                 unitVent.Name);
     928            4 :             SetupOutputVariable(state,
     929              :                                 "Zone Unit Ventilator Fan Electricity Rate",
     930              :                                 Constant::Units::W,
     931            2 :                                 unitVent.ElecPower,
     932              :                                 OutputProcessor::TimeStepType::System,
     933              :                                 OutputProcessor::StoreType::Average,
     934            2 :                                 unitVent.Name);
     935              :             // Note that the unit vent fan electric is NOT metered because this value is already metered through the fan component
     936            4 :             SetupOutputVariable(state,
     937              :                                 "Zone Unit Ventilator Fan Electricity Energy",
     938              :                                 Constant::Units::J,
     939            2 :                                 unitVent.ElecEnergy,
     940              :                                 OutputProcessor::TimeStepType::System,
     941              :                                 OutputProcessor::StoreType::Sum,
     942            2 :                                 unitVent.Name);
     943            2 :             SetupOutputVariable(state,
     944              :                                 "Zone Unit Ventilator Fan Availability Status",
     945              :                                 Constant::Units::None,
     946            2 :                                 (int &)unitVent.availStatus,
     947              :                                 OutputProcessor::TimeStepType::System,
     948              :                                 OutputProcessor::StoreType::Average,
     949            2 :                                 unitVent.Name);
     950            2 :             if (unitVent.fanType == HVAC::FanType::OnOff) {
     951            0 :                 SetupOutputVariable(state,
     952              :                                     "Zone Unit Ventilator Fan Part Load Ratio",
     953              :                                     Constant::Units::None,
     954            0 :                                     unitVent.FanPartLoadRatio,
     955              :                                     OutputProcessor::TimeStepType::System,
     956              :                                     OutputProcessor::StoreType::Average,
     957            0 :                                     unitVent.Name);
     958              :             }
     959              : 
     960            2 :             if (unitVent.HCoilPresent) {
     961            2 :                 coilReportObj->setCoilSupplyFanInfo(
     962            2 :                     state, unitVent.HCoilName, unitVent.HCoilTypeCh, unitVent.FanName, unitVent.fanType, unitVent.Fan_Index);
     963              :             }
     964            2 :             if (unitVent.CCoilPresent) {
     965            0 :                 coilReportObj->setCoilSupplyFanInfo(
     966            0 :                     state, unitVent.CCoilName, unitVent.CCoilTypeCh, unitVent.FanName, unitVent.fanType, unitVent.Fan_Index);
     967              :             }
     968              :         }
     969            2 :     }
     970              : 
     971            2 :     void InitUnitVentilator(EnergyPlusData &state,
     972              :                             int const UnitVentNum,         // index for the current unit ventilator
     973              :                             bool const FirstHVACIteration, // TRUE if 1st HVAC simulation of system timestep
     974              :                             int const ZoneNum              // number of zone being served
     975              :     )
     976              :     {
     977              : 
     978              :         // SUBROUTINE INFORMATION:
     979              :         //       AUTHOR         Rick Strand
     980              :         //       DATE WRITTEN   May 2000
     981              :         //       MODIFIED       Chandan Sharma, FSEC, March 2011: Added zone sys avail manager
     982              : 
     983              :         // PURPOSE OF THIS SUBROUTINE:
     984              :         // This subroutine initializes all of the data elements which are necessary
     985              :         // to simulate a unit ventilator.
     986              : 
     987              :         // METHODOLOGY EMPLOYED:
     988              :         // Uses the status flags to trigger initializations.
     989              : 
     990            2 :         auto &unitVent = state.dataUnitVentilators->UnitVent(UnitVentNum);
     991              : 
     992              :         static constexpr std::string_view RoutineName("InitUnitVentilator");
     993              : 
     994            2 :         bool SetMassFlowRateToZero = false; // TRUE when mass flow rates need to be set to zero
     995              : 
     996              :         // Do the one time initializations
     997            2 :         if (state.dataUnitVentilators->MyOneTimeFlag) {
     998              : 
     999            2 :             state.dataUnitVentilators->MyEnvrnFlag.allocate(state.dataUnitVentilators->NumOfUnitVents);
    1000            2 :             state.dataUnitVentilators->MySizeFlag.allocate(state.dataUnitVentilators->NumOfUnitVents);
    1001            2 :             state.dataUnitVentilators->MyPlantScanFlag.allocate(state.dataUnitVentilators->NumOfUnitVents);
    1002            2 :             state.dataUnitVentilators->MyZoneEqFlag.allocate(state.dataUnitVentilators->NumOfUnitVents);
    1003            2 :             state.dataUnitVentilators->MyEnvrnFlag = true;
    1004            2 :             state.dataUnitVentilators->MySizeFlag = true;
    1005            2 :             state.dataUnitVentilators->MyPlantScanFlag = true;
    1006            2 :             state.dataUnitVentilators->MyZoneEqFlag = true;
    1007            2 :             state.dataUnitVentilators->MyOneTimeFlag = false;
    1008              :         }
    1009              : 
    1010            2 :         if (allocated(state.dataAvail->ZoneComp)) {
    1011            0 :             auto &availMgr = state.dataAvail->ZoneComp(DataZoneEquipment::ZoneEquipType::UnitVentilator).ZoneCompAvailMgrs(UnitVentNum);
    1012            0 :             if (state.dataUnitVentilators->MyZoneEqFlag(UnitVentNum)) { // initialize the name of each availability manager list and zone number
    1013            0 :                 availMgr.AvailManagerListName = unitVent.AvailManagerListName;
    1014            0 :                 availMgr.ZoneNum = ZoneNum;
    1015            0 :                 state.dataUnitVentilators->MyZoneEqFlag(UnitVentNum) = false;
    1016              :             }
    1017            0 :             unitVent.availStatus = availMgr.availStatus;
    1018              :         }
    1019              : 
    1020            2 :         if (state.dataUnitVentilators->MyPlantScanFlag(UnitVentNum) && allocated(state.dataPlnt->PlantLoop)) {
    1021            0 :             if ((unitVent.HeatingCoilType == DataPlant::PlantEquipmentType::CoilWaterSimpleHeating) ||
    1022            0 :                 (unitVent.HeatingCoilType == DataPlant::PlantEquipmentType::CoilSteamAirHeating)) {
    1023            0 :                 bool errFlag = false;
    1024            0 :                 PlantUtilities::ScanPlantLoopsForObject(
    1025            0 :                     state, unitVent.HCoilName, unitVent.HeatingCoilType, unitVent.HWplantLoc, errFlag, _, _, _, _, _);
    1026            0 :                 if (errFlag) {
    1027            0 :                     ShowContinueError(state, format("Reference Unit=\"{}\", type=ZoneHVAC:UnitVentilator", unitVent.Name));
    1028            0 :                     ShowFatalError(state, "InitUnitVentilator: Program terminated due to previous condition(s).");
    1029              :                 }
    1030              : 
    1031            0 :                 unitVent.HotCoilOutNodeNum = DataPlant::CompData::getPlantComponent(state, unitVent.HWplantLoc).NodeNumOut;
    1032              :             }
    1033            0 :             if ((unitVent.CoolingCoilType == DataPlant::PlantEquipmentType::CoilWaterCooling) ||
    1034            0 :                 (unitVent.CoolingCoilType == DataPlant::PlantEquipmentType::CoilWaterDetailedFlatCooling)) {
    1035            0 :                 bool errFlag = false;
    1036            0 :                 PlantUtilities::ScanPlantLoopsForObject(
    1037            0 :                     state, unitVent.CCoilPlantName, unitVent.CoolingCoilType, unitVent.CWPlantLoc, errFlag, _, _, _, _, _);
    1038            0 :                 if (errFlag) {
    1039            0 :                     ShowContinueError(state, format("Reference Unit=\"{}\", type=ZoneHVAC:UnitVentilator", unitVent.Name));
    1040            0 :                     ShowFatalError(state, "InitUnitVentilator: Program terminated due to previous condition(s).");
    1041              :                 }
    1042              : 
    1043            0 :                 unitVent.ColdCoilOutNodeNum = DataPlant::CompData::getPlantComponent(state, unitVent.CWPlantLoc).NodeNumOut;
    1044            0 :             } else {
    1045            0 :                 if (unitVent.CCoilPresent)
    1046            0 :                     ShowFatalError(state, format("InitUnitVentilator: Unit={}, invalid cooling coil type. Program terminated.", unitVent.Name));
    1047              :             }
    1048            0 :             state.dataUnitVentilators->MyPlantScanFlag(UnitVentNum) = false;
    1049            2 :         } else if (state.dataUnitVentilators->MyPlantScanFlag(UnitVentNum) && !state.dataGlobal->AnyPlantInModel) {
    1050            2 :             state.dataUnitVentilators->MyPlantScanFlag(UnitVentNum) = false;
    1051              :         }
    1052              : 
    1053            2 :         if (!state.dataUnitVentilators->ZoneEquipmentListChecked && state.dataZoneEquip->ZoneEquipInputsFilled) {
    1054            0 :             state.dataUnitVentilators->ZoneEquipmentListChecked = true;
    1055            0 :             for (int Loop = 1; Loop <= state.dataUnitVentilators->NumOfUnitVents; ++Loop) {
    1056            0 :                 if (DataZoneEquipment::CheckZoneEquipmentList(state, "ZoneHVAC:UnitVentilator", state.dataUnitVentilators->UnitVent(Loop).Name))
    1057            0 :                     continue;
    1058            0 :                 ShowSevereError(
    1059              :                     state,
    1060            0 :                     format("InitUnitVentilator: Unit=[UNIT VENTILATOR,{}] is not on any ZoneHVAC:EquipmentList.  It will not be simulated.",
    1061            0 :                            state.dataUnitVentilators->UnitVent(Loop).Name));
    1062              :             }
    1063              :         }
    1064              : 
    1065            2 :         if (!state.dataGlobal->SysSizingCalc && state.dataUnitVentilators->MySizeFlag(UnitVentNum) &&
    1066            0 :             !state.dataUnitVentilators->MyPlantScanFlag(UnitVentNum)) {
    1067              : 
    1068            0 :             SizeUnitVentilator(state, UnitVentNum);
    1069              : 
    1070            0 :             state.dataUnitVentilators->MySizeFlag(UnitVentNum) = false;
    1071              :         }
    1072              : 
    1073            2 :         int InNode = unitVent.AirInNode;
    1074            2 :         int OutNode = unitVent.AirOutNode;
    1075            2 :         int OutsideAirNode = unitVent.OutsideAirNode;
    1076            2 :         int AirRelNode = unitVent.AirReliefNode;
    1077              : 
    1078              :         // Do the one time initializations
    1079            2 :         if (state.dataGlobal->BeginEnvrnFlag && state.dataUnitVentilators->MyEnvrnFlag(UnitVentNum) &&
    1080            0 :             !state.dataUnitVentilators->MyPlantScanFlag(UnitVentNum)) {
    1081            0 :             Real64 RhoAir = state.dataEnvrn->StdRhoAir;
    1082              : 
    1083              :             // set the mass flow rates from the input volume flow rates
    1084            0 :             unitVent.MaxAirMassFlow = RhoAir * unitVent.MaxAirVolFlow;
    1085            0 :             unitVent.OutAirMassFlow = RhoAir * unitVent.OutAirVolFlow;
    1086            0 :             unitVent.MinOutAirMassFlow = RhoAir * unitVent.MinOutAirVolFlow;
    1087            0 :             if (unitVent.OutAirMassFlow > unitVent.MaxAirMassFlow) {
    1088            0 :                 unitVent.OutAirMassFlow = unitVent.MaxAirMassFlow;
    1089            0 :                 unitVent.MinOutAirMassFlow = unitVent.OutAirMassFlow * (unitVent.MinOutAirVolFlow / unitVent.OutAirVolFlow);
    1090            0 :                 ShowWarningError(state,
    1091            0 :                                  format("Outdoor air mass flow rate higher than unit flow rate, reset to unit flow rate for {}", unitVent.Name));
    1092              :             }
    1093              : 
    1094              :             // set the node max and min mass flow rates
    1095            0 :             state.dataLoopNodes->Node(OutsideAirNode).MassFlowRateMax = unitVent.OutAirMassFlow;
    1096            0 :             state.dataLoopNodes->Node(OutsideAirNode).MassFlowRateMin = 0.0;
    1097              : 
    1098            0 :             state.dataLoopNodes->Node(OutNode).MassFlowRateMax = unitVent.MaxAirMassFlow;
    1099            0 :             state.dataLoopNodes->Node(OutNode).MassFlowRateMin = 0.0;
    1100              : 
    1101            0 :             state.dataLoopNodes->Node(InNode).MassFlowRateMax = unitVent.MaxAirMassFlow;
    1102            0 :             state.dataLoopNodes->Node(InNode).MassFlowRateMin = 0.0;
    1103              : 
    1104            0 :             if (unitVent.HCoilPresent) { // Only initialize these if a heating coil is actually present
    1105              : 
    1106            0 :                 if (unitVent.HCoilType == HeatCoilType::Water) {
    1107              : 
    1108              :                     Real64 rho =
    1109            0 :                         state.dataPlnt->PlantLoop(unitVent.HWplantLoc.loopNum).glycol->getDensity(state, Constant::HWInitConvTemp, RoutineName);
    1110              : 
    1111            0 :                     unitVent.MaxHotWaterFlow = rho * unitVent.MaxVolHotWaterFlow;
    1112            0 :                     unitVent.MinHotWaterFlow = rho * unitVent.MinVolHotWaterFlow;
    1113              : 
    1114            0 :                     PlantUtilities::InitComponentNodes(
    1115              :                         state, unitVent.MinHotWaterFlow, unitVent.MaxHotWaterFlow, unitVent.HotControlNode, unitVent.HotCoilOutNodeNum);
    1116              :                 }
    1117            0 :                 if (unitVent.HCoilType == HeatCoilType::Steam) {
    1118            0 :                     Real64 TempSteamIn = 100.00;
    1119            0 :                     Real64 SteamDensity = unitVent.HCoil_fluid->getSatDensity(state, TempSteamIn, 1.0, RoutineName);
    1120            0 :                     unitVent.MaxHotSteamFlow = SteamDensity * unitVent.MaxVolHotSteamFlow;
    1121            0 :                     unitVent.MinHotSteamFlow = SteamDensity * unitVent.MinVolHotSteamFlow;
    1122              : 
    1123            0 :                     PlantUtilities::InitComponentNodes(
    1124              :                         state, unitVent.MinHotSteamFlow, unitVent.MaxHotSteamFlow, unitVent.HotControlNode, unitVent.HotCoilOutNodeNum);
    1125              :                 }
    1126              :             } //(UnitVent(UnitVentNum)%HCoilPresent)
    1127              : 
    1128            0 :             if (unitVent.CCoilPresent) { // Only initialize these if a cooling coil is actually present
    1129            0 :                 Real64 rho = state.dataPlnt->PlantLoop(unitVent.CWPlantLoc.loopNum).glycol->getDensity(state, 5.0, RoutineName);
    1130              : 
    1131            0 :                 unitVent.MaxColdWaterFlow = rho * unitVent.MaxVolColdWaterFlow;
    1132            0 :                 unitVent.MinColdWaterFlow = rho * unitVent.MinVolColdWaterFlow;
    1133            0 :                 PlantUtilities::InitComponentNodes(
    1134              :                     state, unitVent.MinColdWaterFlow, unitVent.MaxColdWaterFlow, unitVent.ColdControlNode, unitVent.ColdCoilOutNodeNum);
    1135              :             }
    1136            0 :             state.dataUnitVentilators->MyEnvrnFlag(UnitVentNum) = false;
    1137              :         } // ...end start of environment inits
    1138              : 
    1139            2 :         if (!state.dataGlobal->BeginEnvrnFlag) state.dataUnitVentilators->MyEnvrnFlag(UnitVentNum) = true;
    1140              : 
    1141              :         // These initializations are done every iteration...
    1142              : 
    1143            2 :         state.dataUnitVentilators->QZnReq = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).RemainingOutputRequired; // zone load needed
    1144            2 :         unitVent.FanPartLoadRatio = 0.0;
    1145              : 
    1146            2 :         if (unitVent.fanOpModeSched != nullptr) {
    1147            0 :             unitVent.fanOp = (unitVent.fanOpModeSched->getCurrentVal() == 0.0) ? HVAC::FanOp::Cycling : HVAC::FanOp::Continuous;
    1148              :         }
    1149              : 
    1150            2 :         if (unitVent.availSched->getCurrentVal() > 0) {
    1151            2 :             if ((unitVent.fanAvailSched->getCurrentVal() > 0 || state.dataHVACGlobal->TurnFansOn) && !state.dataHVACGlobal->TurnFansOff) {
    1152            4 :                 if ((std::abs(state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).RemainingOutputRequired) < HVAC::SmallLoad) ||
    1153            2 :                     (state.dataZoneEnergyDemand->CurDeadBandOrSetback(ZoneNum))) {
    1154            0 :                     SetMassFlowRateToZero = true;
    1155              :                 }
    1156              :             } else {
    1157            0 :                 SetMassFlowRateToZero = true;
    1158              :             }
    1159              :         } else {
    1160            0 :             SetMassFlowRateToZero = true;
    1161              :         }
    1162              : 
    1163            2 :         auto &inNode(state.dataLoopNodes->Node(InNode));
    1164            2 :         auto &outNode(state.dataLoopNodes->Node(OutNode));
    1165            2 :         auto &oaNode(state.dataLoopNodes->Node(OutsideAirNode));
    1166            2 :         if (SetMassFlowRateToZero) {
    1167            0 :             inNode.MassFlowRate = 0.0;
    1168            0 :             inNode.MassFlowRateMaxAvail = 0.0;
    1169            0 :             inNode.MassFlowRateMinAvail = 0.0;
    1170            0 :             outNode.MassFlowRate = 0.0;
    1171            0 :             outNode.MassFlowRateMaxAvail = 0.0;
    1172            0 :             outNode.MassFlowRateMinAvail = 0.0;
    1173            0 :             oaNode.MassFlowRate = 0.0;
    1174            0 :             oaNode.MassFlowRateMaxAvail = 0.0;
    1175            0 :             oaNode.MassFlowRateMinAvail = 0.0;
    1176            0 :             if (!unitVent.ATMixerExists) {
    1177            0 :                 auto &relNode(state.dataLoopNodes->Node(AirRelNode));
    1178            0 :                 relNode.MassFlowRate = 0.0;
    1179            0 :                 relNode.MassFlowRateMaxAvail = 0.0;
    1180            0 :                 relNode.MassFlowRateMinAvail = 0.0;
    1181              :             }
    1182              :         } else {
    1183            2 :             inNode.MassFlowRate = unitVent.MaxAirMassFlow;
    1184            2 :             inNode.MassFlowRateMaxAvail = unitVent.MaxAirMassFlow;
    1185            2 :             inNode.MassFlowRateMinAvail = unitVent.MaxAirMassFlow;
    1186            2 :             outNode.MassFlowRate = unitVent.MaxAirMassFlow;
    1187            2 :             outNode.MassFlowRateMaxAvail = unitVent.MaxAirMassFlow;
    1188            2 :             outNode.MassFlowRateMinAvail = unitVent.MaxAirMassFlow;
    1189            2 :             oaNode.MassFlowRate = unitVent.OutAirMassFlow;
    1190            2 :             oaNode.MassFlowRateMaxAvail = unitVent.OutAirMassFlow;
    1191            2 :             oaNode.MassFlowRateMinAvail = unitVent.OutAirMassFlow;
    1192            2 :             if (!unitVent.ATMixerExists) {
    1193            0 :                 auto &relNode(state.dataLoopNodes->Node(AirRelNode));
    1194            0 :                 relNode.MassFlowRate = unitVent.OutAirMassFlow;
    1195            0 :                 relNode.MassFlowRateMaxAvail = unitVent.OutAirMassFlow;
    1196            0 :                 relNode.MassFlowRateMinAvail = unitVent.OutAirMassFlow;
    1197              :             }
    1198              :         }
    1199              : 
    1200              :         // Initialize the relief air (same as inlet conditions to the unit ventilator...
    1201              :         // Note that mass flow rates will be taken care of later.
    1202            2 :         if (!unitVent.ATMixerExists) {
    1203            0 :             state.dataLoopNodes->Node(AirRelNode) = state.dataLoopNodes->Node(InNode);
    1204              :         }
    1205            2 :         state.dataUnitVentilators->OAMassFlowRate = 0.0;
    1206              : 
    1207              :         // Just in case the unit is off and conditions do not get sent through
    1208              :         // the unit for some reason, set the outlet conditions equal to the inlet
    1209              :         // conditions of the unit ventilator
    1210            2 :         outNode.Temp = inNode.Temp;
    1211            2 :         outNode.Press = inNode.Press;
    1212            2 :         outNode.HumRat = inNode.HumRat;
    1213            2 :         outNode.Enthalpy = inNode.Enthalpy;
    1214              : 
    1215              :         // These initializations only need to be done once at the start of the iterations...
    1216            2 :         if (FirstHVACIteration) {
    1217              :             // Initialize the outside air conditions...
    1218            0 :             if (!unitVent.ATMixerExists) {
    1219            0 :                 state.dataLoopNodes->Node(OutsideAirNode).Temp = state.dataLoopNodes->Node(OutsideAirNode).OutAirDryBulb;
    1220              :             }
    1221              :         }
    1222            2 :     }
    1223              : 
    1224            6 :     void SizeUnitVentilator(EnergyPlusData &state, int const UnitVentNum)
    1225              :     {
    1226              : 
    1227              :         // SUBROUTINE INFORMATION:
    1228              :         //       AUTHOR         Fred Buhl
    1229              :         //       DATE WRITTEN   February 2002
    1230              :         //       MODIFIED       August 2013 Daeho Kang, add component sizing table entries
    1231              :         //                      July 2014, B. Nigusse, added scalable sizing
    1232              : 
    1233              :         // PURPOSE OF THIS SUBROUTINE:
    1234              :         // This subroutine is for sizing Unit Ventilator components for which flow rates have not been
    1235              :         // specified in the input.
    1236              : 
    1237              :         // METHODOLOGY EMPLOYED:
    1238              :         // Obtains flow rates from the zone sizing arrays and plant sizing data.
    1239              : 
    1240            6 :         auto &unitVent = state.dataUnitVentilators->UnitVent(UnitVentNum);
    1241            6 :         auto &ZoneEqSizing = state.dataSize->ZoneEqSizing(state.dataSize->CurZoneEqNum);
    1242              : 
    1243              :         // SUBROUTINE PARAMETER DEFINITIONS:
    1244              :         static constexpr std::string_view RoutineName("SizeUnitVentilator");
    1245              : 
    1246              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1247            6 :         Real64 DesCoolingLoad = 0.0;
    1248            6 :         Real64 DesHeatingLoad = 0.0;
    1249            6 :         Real64 TempSteamIn = 0.0;
    1250            6 :         Real64 EnthSteamInDry = 0.0;
    1251            6 :         Real64 EnthSteamOutWet = 0.0;
    1252            6 :         Real64 LatentHeatSteam = 0.0;
    1253            6 :         Real64 SteamDensity = 0.0;
    1254            6 :         int CoilWaterOutletNode = 0;
    1255            6 :         std::string CoolingCoilName;
    1256            6 :         std::string CoolingCoilType;
    1257            6 :         Real64 rho = 0.0;
    1258            6 :         Real64 Cp = 0.0;
    1259              : 
    1260              :         Real64 TempSize;  // autosized value of coil input field
    1261              :         int SizingMethod; // Integer representation of sizing method name (e.g., CoolingAirflowSizing, HeatingAirflowSizing, CoolingCapacitySizing,
    1262              :                           // HeatingCapacitySizing, etc.)
    1263              :         bool PrintFlag;   // TRUE when sizing information is reported in the eio file
    1264            6 :         int CapSizingMethod(0);    // capacity sizing methods (HeatingDesignCapacity, CapacityPerFloorArea, FractionOfAutosizedCoolingCapacity, and
    1265              :                                    // FractionOfAutosizedHeatingCapacity )
    1266              :         Real64 WaterCoilSizDeltaT; // water coil deltaT for design water flow rate autosizing
    1267              : 
    1268            6 :         int PltSizHeatNum = 0;
    1269            6 :         bool ErrorsFound = false;
    1270            6 :         bool IsAutoSize = false;
    1271            6 :         Real64 OutAirVolFlowDes = 0.0;
    1272            6 :         Real64 OutAirVolFlowUser = 0.0;
    1273            6 :         Real64 MinOutAirVolFlowDes = 0.0;
    1274            6 :         Real64 MinOutAirVolFlowUser = 0.0;
    1275            6 :         Real64 MaxVolHotWaterFlowDes = 0.0;
    1276            6 :         Real64 MaxVolHotWaterFlowUser = 0.0;
    1277            6 :         Real64 MaxVolHotSteamFlowDes = 0.0;
    1278            6 :         Real64 MaxVolHotSteamFlowUser = 0.0;
    1279            6 :         Real64 MaxVolColdWaterFlowDes = 0.0;
    1280            6 :         Real64 MaxVolColdWaterFlowUser = 0.0;
    1281            6 :         Real64 CoolingAirVolFlowScalable = 0.0;
    1282            6 :         Real64 HeatingAirVolFlowScalable = 0.0;
    1283            6 :         state.dataSize->DataScalableSizingON = false;
    1284            6 :         state.dataSize->DataScalableCapSizingON = false;
    1285            6 :         std::string CompType = state.dataUnitVentilators->cMO_UnitVentilator;
    1286            6 :         std::string CompName = unitVent.Name;
    1287            6 :         state.dataSize->DataZoneNumber = unitVent.ZonePtr;
    1288            6 :         bool DoWaterCoilSizing = false;
    1289              : 
    1290            6 :         state.dataSize->DataFanType = unitVent.fanType;
    1291            6 :         state.dataSize->DataFanIndex = unitVent.Fan_Index;
    1292              :         // unit ventilator is always blow thru
    1293            6 :         state.dataSize->DataFanPlacement = HVAC::FanPlace::BlowThru;
    1294              : 
    1295            6 :         state.dataSize->ZoneCoolingOnlyFan = (unitVent.CoilOption == CoilsUsed::Both) || (unitVent.CoilOption == CoilsUsed::Cooling);
    1296            6 :         state.dataSize->ZoneHeatingOnlyFan = (unitVent.CoilOption == CoilsUsed::Both) || (unitVent.CoilOption == CoilsUsed::Heating);
    1297              : 
    1298            6 :         if (state.dataSize->CurZoneEqNum > 0) {
    1299            6 :             if (unitVent.HVACSizingIndex > 0) {
    1300            3 :                 auto const &zoneHVACSizing = state.dataSize->ZoneHVACSizing(unitVent.HVACSizingIndex);
    1301              : 
    1302              :                 // initialize OA flow for sizing other inputs (e.g., inlet temp, capacity, etc.)
    1303            3 :                 if (unitVent.OutAirVolFlow == DataSizing::AutoSize) {
    1304            3 :                     ZoneEqSizing.OAVolFlow = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).MinOA;
    1305              :                 } else {
    1306            0 :                     ZoneEqSizing.OAVolFlow = unitVent.OutAirVolFlow;
    1307              :                 }
    1308            3 :                 if (unitVent.ATMixerExists) {     // set up ATMixer conditions for scalable capacity sizing
    1309            0 :                     ZoneEqSizing.OAVolFlow = 0.0; // Equipment OA flow should always be 0 when ATMixer is used
    1310            0 :                     SingleDuct::setATMixerSizingProperties(state, unitVent.ATMixerIndex, unitVent.ZonePtr, state.dataSize->CurZoneEqNum);
    1311              :                 }
    1312              : 
    1313              :                 // N1 , \field Maximum Supply Air Flow Rate
    1314            3 :                 PrintFlag = true;
    1315              : 
    1316            3 :                 if (zoneHVACSizing.CoolingSAFMethod > 0 && state.dataSize->ZoneCoolingOnlyFan && !state.dataSize->ZoneHeatingOnlyFan) {
    1317              : 
    1318            0 :                     int SAFMethod = zoneHVACSizing.CoolingSAFMethod;
    1319            0 :                     SizingMethod = HVAC::CoolingAirflowSizing;
    1320            0 :                     ZoneEqSizing.SizingMethod(SizingMethod) = SAFMethod;
    1321            0 :                     switch (SAFMethod) {
    1322            0 :                     case DataSizing::None:
    1323              :                     case DataSizing::SupplyAirFlowRate:
    1324              :                     case DataSizing::FlowPerFloorArea:
    1325              :                     case DataSizing::FractionOfAutosizedCoolingAirflow: {
    1326            0 :                         switch (SAFMethod) {
    1327            0 :                         case DataSizing::SupplyAirFlowRate: {
    1328            0 :                             if (zoneHVACSizing.MaxCoolAirVolFlow > 0.0) {
    1329            0 :                                 ZoneEqSizing.AirVolFlow = zoneHVACSizing.MaxCoolAirVolFlow;
    1330            0 :                                 ZoneEqSizing.SystemAirFlow = true;
    1331              :                             }
    1332            0 :                             TempSize = zoneHVACSizing.MaxCoolAirVolFlow;
    1333            0 :                         } break;
    1334            0 :                         case DataSizing::FlowPerFloorArea: {
    1335            0 :                             ZoneEqSizing.SystemAirFlow = true;
    1336            0 :                             ZoneEqSizing.AirVolFlow =
    1337            0 :                                 zoneHVACSizing.MaxCoolAirVolFlow * state.dataHeatBal->Zone(state.dataSize->DataZoneNumber).FloorArea;
    1338            0 :                             TempSize = ZoneEqSizing.AirVolFlow;
    1339            0 :                             state.dataSize->DataScalableSizingON = true;
    1340            0 :                         } break;
    1341            0 :                         case DataSizing::FractionOfAutosizedCoolingAirflow: {
    1342            0 :                             state.dataSize->DataFracOfAutosizedCoolingAirflow = zoneHVACSizing.MaxCoolAirVolFlow;
    1343            0 :                             TempSize = DataSizing::AutoSize;
    1344            0 :                             state.dataSize->DataScalableSizingON = true;
    1345            0 :                         } break;
    1346            0 :                         default: {
    1347            0 :                             TempSize = zoneHVACSizing.MaxCoolAirVolFlow;
    1348            0 :                         } break;
    1349              :                         }
    1350            0 :                         bool errorsFound = false;
    1351            0 :                         CoolingAirFlowSizer sizingCoolingAirFlow;
    1352            0 :                         sizingCoolingAirFlow.overrideSizingString(state.dataGlobal->isEpJSON ? "maximum_supply_air_flow_rate [m3/s]"
    1353              :                                                                                              : "Maximum Supply Air Flow Rate [m3/s]");
    1354              :                         // sizingCoolingAirFlow.setHVACSizingIndexData(FanCoil(FanCoilNum).HVACSizingIndex);
    1355            0 :                         sizingCoolingAirFlow.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
    1356            0 :                         CoolingAirVolFlowScalable = sizingCoolingAirFlow.size(state, TempSize, errorsFound);
    1357            0 :                     } break;
    1358            0 :                     case DataSizing::FlowPerCoolingCapacity: {
    1359            0 :                         SizingMethod = HVAC::CoolingCapacitySizing;
    1360            0 :                         TempSize = DataSizing::AutoSize;
    1361            0 :                         PrintFlag = false;
    1362            0 :                         state.dataSize->DataScalableSizingON = true;
    1363            0 :                         state.dataSize->DataFlowUsedForSizing = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).DesCoolVolFlow;
    1364            0 :                         CoolingCapacitySizer sizerCoolingCapacity;
    1365            0 :                         sizerCoolingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
    1366            0 :                         state.dataSize->DataAutosizedCoolingCapacity = sizerCoolingCapacity.size(state, TempSize, ErrorsFound);
    1367            0 :                         state.dataSize->DataFlowPerCoolingCapacity = zoneHVACSizing.MaxCoolAirVolFlow;
    1368            0 :                         PrintFlag = true;
    1369            0 :                         TempSize = DataSizing::AutoSize;
    1370            0 :                         bool errorsFound = false;
    1371            0 :                         CoolingAirFlowSizer sizingCoolingAirFlow;
    1372            0 :                         sizingCoolingAirFlow.overrideSizingString(state.dataGlobal->isEpJSON ? "maximum_supply_air_flow_rate [m3/s]"
    1373              :                                                                                              : "Maximum Supply Air Flow Rate [m3/s]");
    1374              :                         // sizingCoolingAirFlow.setHVACSizingIndexData(FanCoil(FanCoilNum).HVACSizingIndex);
    1375            0 :                         sizingCoolingAirFlow.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
    1376            0 :                         CoolingAirVolFlowScalable = sizingCoolingAirFlow.size(state, TempSize, errorsFound);
    1377            0 :                     } break;
    1378            0 :                     default: {
    1379            0 :                     } break;
    1380              :                     }
    1381              :                     // DataScalableSizingON = false;
    1382              : 
    1383            3 :                 } else if (zoneHVACSizing.HeatingSAFMethod > 0 && state.dataSize->ZoneHeatingOnlyFan && !state.dataSize->ZoneCoolingOnlyFan) {
    1384            0 :                     SizingMethod = HVAC::HeatingAirflowSizing;
    1385            0 :                     int SAFMethod = zoneHVACSizing.HeatingSAFMethod;
    1386            0 :                     ZoneEqSizing.SizingMethod(SizingMethod) = SAFMethod;
    1387            0 :                     switch (SAFMethod) {
    1388            0 :                     case DataSizing::None:
    1389              :                     case DataSizing::SupplyAirFlowRate:
    1390              :                     case DataSizing::FlowPerFloorArea:
    1391              :                     case DataSizing::FractionOfAutosizedHeatingAirflow: {
    1392            0 :                         switch (SAFMethod) {
    1393            0 :                         case DataSizing::SupplyAirFlowRate: {
    1394            0 :                             if (zoneHVACSizing.MaxHeatAirVolFlow > 0.0) {
    1395            0 :                                 ZoneEqSizing.AirVolFlow = zoneHVACSizing.MaxHeatAirVolFlow;
    1396            0 :                                 ZoneEqSizing.SystemAirFlow = true;
    1397              :                             }
    1398            0 :                             TempSize = zoneHVACSizing.MaxHeatAirVolFlow;
    1399            0 :                         } break;
    1400            0 :                         case DataSizing::FlowPerFloorArea: {
    1401            0 :                             ZoneEqSizing.SystemAirFlow = true;
    1402            0 :                             ZoneEqSizing.AirVolFlow =
    1403            0 :                                 zoneHVACSizing.MaxHeatAirVolFlow * state.dataHeatBal->Zone(state.dataSize->DataZoneNumber).FloorArea;
    1404            0 :                             TempSize = ZoneEqSizing.AirVolFlow;
    1405            0 :                             state.dataSize->DataScalableSizingON = true;
    1406            0 :                         } break;
    1407            0 :                         case DataSizing::FractionOfAutosizedHeatingAirflow: {
    1408            0 :                             state.dataSize->DataFracOfAutosizedHeatingAirflow = zoneHVACSizing.MaxHeatAirVolFlow;
    1409            0 :                             TempSize = DataSizing::AutoSize;
    1410            0 :                             state.dataSize->DataScalableSizingON = true;
    1411            0 :                         } break;
    1412            0 :                         default: {
    1413            0 :                             TempSize = zoneHVACSizing.MaxHeatAirVolFlow;
    1414            0 :                         } break;
    1415              :                         }
    1416            0 :                         bool errorsFound = false;
    1417            0 :                         HeatingAirFlowSizer sizingHeatingAirFlow;
    1418            0 :                         sizingHeatingAirFlow.overrideSizingString(state.dataGlobal->isEpJSON ? "maximum_supply_air_flow_rate [m3/s]"
    1419              :                                                                                              : "Maximum Supply Air Flow Rate [m3/s]");
    1420              :                         // sizingHeatingAirFlow.setHVACSizingIndexData(FanCoil(FanCoilNum).HVACSizingIndex);
    1421            0 :                         sizingHeatingAirFlow.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
    1422            0 :                         HeatingAirVolFlowScalable = sizingHeatingAirFlow.size(state, TempSize, errorsFound);
    1423            0 :                     } break;
    1424            0 :                     case DataSizing::FlowPerHeatingCapacity: {
    1425            0 :                         TempSize = DataSizing::AutoSize;
    1426            0 :                         PrintFlag = false;
    1427            0 :                         state.dataSize->DataScalableSizingON = true;
    1428            0 :                         state.dataSize->DataFlowUsedForSizing = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).DesHeatVolFlow;
    1429            0 :                         bool errorsFound = false;
    1430            0 :                         HeatingCapacitySizer sizerHeatingCapacity;
    1431            0 :                         sizerHeatingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
    1432            0 :                         state.dataSize->DataAutosizedHeatingCapacity = sizerHeatingCapacity.size(state, TempSize, errorsFound);
    1433            0 :                         state.dataSize->DataFlowPerHeatingCapacity = zoneHVACSizing.MaxHeatAirVolFlow;
    1434            0 :                         PrintFlag = true;
    1435            0 :                         TempSize = DataSizing::AutoSize;
    1436            0 :                         errorsFound = false;
    1437            0 :                         HeatingAirFlowSizer sizingHeatingAirFlow;
    1438            0 :                         sizingHeatingAirFlow.overrideSizingString(state.dataGlobal->isEpJSON ? "maximum_supply_air_flow_rate [m3/s]"
    1439              :                                                                                              : "Maximum Supply Air Flow Rate [m3/s]");
    1440              :                         // sizingHeatingAirFlow.setHVACSizingIndexData(FanCoil(FanCoilNum).HVACSizingIndex);
    1441            0 :                         sizingHeatingAirFlow.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
    1442            0 :                         HeatingAirVolFlowScalable = sizingHeatingAirFlow.size(state, TempSize, errorsFound);
    1443            0 :                     } break;
    1444            0 :                     default: {
    1445            0 :                     } break;
    1446              :                     }
    1447              :                     // DataScalableSizingON = false;
    1448              :                 } else {
    1449              : 
    1450            3 :                     if (unitVent.CoilOption != CoilsUsed::None) {
    1451            0 :                         if (zoneHVACSizing.CoolingSAFMethod > 0) {
    1452            0 :                             int SAFMethod = zoneHVACSizing.CoolingSAFMethod;
    1453            0 :                             SizingMethod = HVAC::CoolingAirflowSizing;
    1454            0 :                             ZoneEqSizing.SizingMethod(SizingMethod) = SAFMethod;
    1455            0 :                             switch (SAFMethod) {
    1456            0 :                             case DataSizing::None:
    1457              :                             case DataSizing::SupplyAirFlowRate:
    1458              :                             case DataSizing::FlowPerFloorArea:
    1459              :                             case DataSizing::FractionOfAutosizedCoolingAirflow: {
    1460            0 :                                 switch (SAFMethod) {
    1461            0 :                                 case DataSizing::SupplyAirFlowRate: {
    1462            0 :                                     if (zoneHVACSizing.MaxCoolAirVolFlow > 0.0) {
    1463            0 :                                         ZoneEqSizing.AirVolFlow = zoneHVACSizing.MaxCoolAirVolFlow;
    1464            0 :                                         ZoneEqSizing.SystemAirFlow = true;
    1465              :                                     }
    1466            0 :                                     TempSize = zoneHVACSizing.MaxCoolAirVolFlow;
    1467            0 :                                 } break;
    1468            0 :                                 case DataSizing::FlowPerFloorArea: {
    1469            0 :                                     ZoneEqSizing.SystemAirFlow = true;
    1470            0 :                                     ZoneEqSizing.AirVolFlow =
    1471            0 :                                         zoneHVACSizing.MaxCoolAirVolFlow * state.dataHeatBal->Zone(state.dataSize->DataZoneNumber).FloorArea;
    1472            0 :                                     TempSize = ZoneEqSizing.AirVolFlow;
    1473            0 :                                     state.dataSize->DataScalableSizingON = true;
    1474            0 :                                 } break;
    1475            0 :                                 case DataSizing::FractionOfAutosizedCoolingAirflow: {
    1476            0 :                                     state.dataSize->DataFracOfAutosizedCoolingAirflow = zoneHVACSizing.MaxCoolAirVolFlow;
    1477            0 :                                     TempSize = DataSizing::AutoSize;
    1478            0 :                                     state.dataSize->DataScalableSizingON = true;
    1479            0 :                                 } break;
    1480            0 :                                 default: {
    1481            0 :                                     TempSize = zoneHVACSizing.MaxCoolAirVolFlow;
    1482            0 :                                 } break;
    1483              :                                 }
    1484            0 :                                 bool errorsFound = false;
    1485            0 :                                 CoolingAirFlowSizer sizingCoolingAirFlow;
    1486            0 :                                 sizingCoolingAirFlow.overrideSizingString(state.dataGlobal->isEpJSON ? "maximum_supply_air_flow_rate [m3/s]"
    1487              :                                                                                                      : "Maximum Supply Air Flow Rate [m3/s]");
    1488              :                                 // sizingCoolingAirFlow.setHVACSizingIndexData(FanCoil(FanCoilNum).HVACSizingIndex);
    1489            0 :                                 sizingCoolingAirFlow.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
    1490            0 :                                 CoolingAirVolFlowScalable = sizingCoolingAirFlow.size(state, TempSize, errorsFound);
    1491            0 :                             } break;
    1492            0 :                             case DataSizing::FlowPerCoolingCapacity: {
    1493            0 :                                 SizingMethod = HVAC::CoolingCapacitySizing;
    1494            0 :                                 TempSize = DataSizing::AutoSize;
    1495            0 :                                 PrintFlag = false;
    1496            0 :                                 state.dataSize->DataScalableSizingON = true;
    1497            0 :                                 state.dataSize->DataFlowUsedForSizing = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).DesCoolVolFlow;
    1498            0 :                                 CoolingCapacitySizer sizerCoolingCapacity;
    1499            0 :                                 sizerCoolingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
    1500            0 :                                 state.dataSize->DataAutosizedCoolingCapacity = sizerCoolingCapacity.size(state, TempSize, ErrorsFound);
    1501            0 :                                 state.dataSize->DataFlowPerCoolingCapacity = zoneHVACSizing.MaxCoolAirVolFlow;
    1502            0 :                                 PrintFlag = true;
    1503            0 :                                 TempSize = DataSizing::AutoSize;
    1504            0 :                                 bool errorsFound = false;
    1505            0 :                                 CoolingAirFlowSizer sizingCoolingAirFlow;
    1506            0 :                                 sizingCoolingAirFlow.overrideSizingString(state.dataGlobal->isEpJSON ? "maximum_supply_air_flow_rate [m3/s]"
    1507              :                                                                                                      : "Maximum Supply Air Flow Rate [m3/s]");
    1508              :                                 // sizingCoolingAirFlow.setHVACSizingIndexData(FanCoil(FanCoilNum).HVACSizingIndex);
    1509            0 :                                 sizingCoolingAirFlow.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
    1510            0 :                                 CoolingAirVolFlowScalable = sizingCoolingAirFlow.size(state, TempSize, errorsFound);
    1511            0 :                             } break;
    1512            0 :                             default: {
    1513            0 :                             } break;
    1514              :                             }
    1515            0 :                         } else if (zoneHVACSizing.HeatingSAFMethod > 0) {
    1516            0 :                             SizingMethod = HVAC::HeatingAirflowSizing;
    1517            0 :                             int SAFMethod = zoneHVACSizing.HeatingSAFMethod;
    1518            0 :                             ZoneEqSizing.SizingMethod(SizingMethod) = SAFMethod;
    1519            0 :                             switch (SAFMethod) {
    1520            0 :                             case DataSizing::None:
    1521              :                             case DataSizing::SupplyAirFlowRate:
    1522              :                             case DataSizing::FlowPerFloorArea:
    1523              :                             case DataSizing::FractionOfAutosizedHeatingAirflow: {
    1524            0 :                                 switch (SAFMethod) {
    1525            0 :                                 case DataSizing::SupplyAirFlowRate: {
    1526            0 :                                     if (zoneHVACSizing.MaxHeatAirVolFlow > 0.0) {
    1527            0 :                                         ZoneEqSizing.AirVolFlow = zoneHVACSizing.MaxHeatAirVolFlow;
    1528            0 :                                         ZoneEqSizing.SystemAirFlow = true;
    1529              :                                     }
    1530            0 :                                     TempSize = zoneHVACSizing.MaxHeatAirVolFlow;
    1531            0 :                                 } break;
    1532            0 :                                 case DataSizing::FlowPerFloorArea: {
    1533            0 :                                     ZoneEqSizing.SystemAirFlow = true;
    1534            0 :                                     ZoneEqSizing.AirVolFlow =
    1535            0 :                                         zoneHVACSizing.MaxHeatAirVolFlow * state.dataHeatBal->Zone(state.dataSize->DataZoneNumber).FloorArea;
    1536            0 :                                     TempSize = ZoneEqSizing.AirVolFlow;
    1537            0 :                                     state.dataSize->DataScalableSizingON = true;
    1538            0 :                                 } break;
    1539            0 :                                 case DataSizing::FractionOfAutosizedHeatingAirflow: {
    1540            0 :                                     state.dataSize->DataFracOfAutosizedHeatingAirflow = zoneHVACSizing.MaxHeatAirVolFlow;
    1541            0 :                                     TempSize = DataSizing::AutoSize;
    1542            0 :                                     state.dataSize->DataScalableSizingON = true;
    1543            0 :                                 } break;
    1544            0 :                                 default: {
    1545            0 :                                     TempSize = zoneHVACSizing.MaxHeatAirVolFlow;
    1546            0 :                                 } break;
    1547              :                                 }
    1548            0 :                                 bool errorsFound = false;
    1549            0 :                                 HeatingAirFlowSizer sizingHeatingAirFlow;
    1550            0 :                                 sizingHeatingAirFlow.overrideSizingString(state.dataGlobal->isEpJSON ? "maximum_supply_air_flow_rate [m3/s]"
    1551              :                                                                                                      : "Maximum Supply Air Flow Rate [m3/s]");
    1552              :                                 // sizingHeatingAirFlow.setHVACSizingIndexData(FanCoil(FanCoilNum).HVACSizingIndex);
    1553            0 :                                 sizingHeatingAirFlow.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
    1554            0 :                                 HeatingAirVolFlowScalable = sizingHeatingAirFlow.size(state, TempSize, errorsFound);
    1555            0 :                             } break;
    1556            0 :                             case DataSizing::FlowPerHeatingCapacity: {
    1557            0 :                                 TempSize = DataSizing::AutoSize;
    1558            0 :                                 PrintFlag = false;
    1559            0 :                                 state.dataSize->DataScalableSizingON = true;
    1560            0 :                                 state.dataSize->DataFlowUsedForSizing = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).DesHeatVolFlow;
    1561            0 :                                 bool errorsFound = false;
    1562            0 :                                 HeatingCapacitySizer sizerHeatingCapacity;
    1563            0 :                                 sizerHeatingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
    1564            0 :                                 state.dataSize->DataAutosizedHeatingCapacity = sizerHeatingCapacity.size(state, TempSize, errorsFound);
    1565            0 :                                 state.dataSize->DataFlowPerHeatingCapacity = zoneHVACSizing.MaxHeatAirVolFlow;
    1566            0 :                                 PrintFlag = true;
    1567            0 :                                 TempSize = DataSizing::AutoSize;
    1568            0 :                                 errorsFound = false;
    1569            0 :                                 HeatingAirFlowSizer sizingHeatingAirFlow;
    1570            0 :                                 sizingHeatingAirFlow.overrideSizingString(state.dataGlobal->isEpJSON ? "maximum_supply_air_flow_rate [m3/s]"
    1571              :                                                                                                      : "Maximum Supply Air Flow Rate [m3/s]");
    1572              :                                 // sizingHeatingAirFlow.setHVACSizingIndexData(FanCoil(FanCoilNum).HVACSizingIndex);
    1573            0 :                                 sizingHeatingAirFlow.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
    1574            0 :                                 HeatingAirVolFlowScalable = sizingHeatingAirFlow.size(state, TempSize, errorsFound);
    1575            0 :                             } break;
    1576            0 :                             default: {
    1577            0 :                             } break;
    1578              :                             }
    1579              :                         }
    1580              :                         // DataScalableSizingON = false;
    1581              :                     } else { // if (unitVent.CoilOption != CoilsUsed::None)
    1582              : 
    1583            3 :                         PrintFlag = true;
    1584            3 :                         if (unitVent.MaxAirVolFlow == DataSizing::AutoSize) {
    1585            0 :                             TempSize = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).MinOA;
    1586              :                         } else {
    1587            3 :                             TempSize = unitVent.MaxAirVolFlow;
    1588              :                         }
    1589            3 :                         bool errorsFound = false;
    1590            3 :                         SystemAirFlowSizer sizerSystemAirFlow;
    1591              :                         // sizerSystemAirFlow.setHVACSizingIndexData(FanCoil(FanCoilNum).HVACSizingIndex);
    1592            3 :                         sizerSystemAirFlow.overrideSizingString(state.dataGlobal->isEpJSON ? "maximum_supply_air_flow_rate [m3/s]"
    1593              :                                                                                            : "Maximum Supply Air Flow Rate [m3/s]");
    1594            3 :                         sizerSystemAirFlow.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
    1595            3 :                         HeatingAirVolFlowScalable = sizerSystemAirFlow.size(state, TempSize, errorsFound);
    1596            3 :                     }
    1597              :                 }
    1598              : 
    1599            3 :                 unitVent.MaxAirVolFlow = max(CoolingAirVolFlowScalable, HeatingAirVolFlowScalable);
    1600              : 
    1601              :             } else {
    1602              :                 // no scalble sizing method has been specified. Sizing proceeds using the method specified in the zoneHVAC object
    1603              :                 // N1 , \field Maximum Supply Air Flow Rate
    1604            3 :                 PrintFlag = true;
    1605            3 :                 if (unitVent.CoilOption == CoilsUsed::None) {
    1606              : 
    1607            3 :                     if (unitVent.MaxAirVolFlow == DataSizing::AutoSize) {
    1608            0 :                         TempSize = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).MinOA;
    1609              :                     } else {
    1610            3 :                         TempSize = unitVent.MaxAirVolFlow;
    1611              :                     }
    1612              : 
    1613              :                 } else {
    1614            0 :                     TempSize = unitVent.MaxAirVolFlow;
    1615              :                 }
    1616            3 :                 bool errorsFound = false;
    1617            3 :                 SystemAirFlowSizer sizerSystemAirFlow;
    1618              :                 // sizerSystemAirFlow.setHVACSizingIndexData(FanCoil(FanCoilNum).HVACSizingIndex);
    1619            3 :                 sizerSystemAirFlow.overrideSizingString(state.dataGlobal->isEpJSON ? "maximum_supply_air_flow_rate [m3/s]"
    1620              :                                                                                    : "Maximum Supply Air Flow Rate [m3/s]");
    1621            3 :                 sizerSystemAirFlow.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
    1622            3 :                 unitVent.MaxAirVolFlow = sizerSystemAirFlow.size(state, TempSize, errorsFound);
    1623            3 :             }
    1624              :         }
    1625              : 
    1626            6 :         IsAutoSize = false;
    1627            6 :         if (unitVent.OutAirVolFlow == DataSizing::AutoSize) {
    1628            6 :             IsAutoSize = true;
    1629              :         }
    1630            6 :         if (state.dataSize->CurZoneEqNum > 0) {
    1631            6 :             if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // Simulation continue
    1632            0 :                 if (unitVent.OutAirVolFlow > 0.0) {
    1633            0 :                     BaseSizer::reportSizerOutput(state,
    1634            0 :                                                  state.dataUnitVentilators->cMO_UnitVentilator,
    1635              :                                                  unitVent.Name,
    1636              :                                                  "User-Specified Maximum Outdoor Air Flow Rate [m3/s]",
    1637              :                                                  unitVent.OutAirVolFlow);
    1638              :                 }
    1639              :             } else {
    1640            6 :                 CheckZoneSizing(state, state.dataUnitVentilators->cMO_UnitVentilator, unitVent.Name);
    1641            6 :                 if (unitVent.OAControlType == OAControl::FixedAmount) {
    1642            2 :                     OutAirVolFlowDes = min(state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).MinOA, unitVent.MaxAirVolFlow);
    1643              :                 } else {
    1644            4 :                     OutAirVolFlowDes = unitVent.MaxAirVolFlow;
    1645              :                 }
    1646              : 
    1647            6 :                 if (IsAutoSize) {
    1648            6 :                     unitVent.OutAirVolFlow = OutAirVolFlowDes;
    1649           12 :                     BaseSizer::reportSizerOutput(state,
    1650            6 :                                                  state.dataUnitVentilators->cMO_UnitVentilator,
    1651              :                                                  unitVent.Name,
    1652              :                                                  "Design Size Maximum Outdoor Air Flow Rate [m3/s]",
    1653              :                                                  OutAirVolFlowDes);
    1654              :                 } else {
    1655            0 :                     if (unitVent.OutAirVolFlow > 0.0 && OutAirVolFlowDes > 0.0) {
    1656            0 :                         OutAirVolFlowUser = unitVent.OutAirVolFlow;
    1657            0 :                         BaseSizer::reportSizerOutput(state,
    1658            0 :                                                      state.dataUnitVentilators->cMO_UnitVentilator,
    1659              :                                                      unitVent.Name,
    1660              :                                                      "Design Size Maximum Outdoor Air Flow Rate [m3/s]",
    1661              :                                                      OutAirVolFlowDes,
    1662              :                                                      "User-Specified Maximum Outdoor Air Flow Rate [m3/s]",
    1663              :                                                      OutAirVolFlowUser);
    1664            0 :                         if (state.dataGlobal->DisplayExtraWarnings) {
    1665            0 :                             if ((std::abs(OutAirVolFlowDes - OutAirVolFlowUser) / OutAirVolFlowUser) > state.dataSize->AutoVsHardSizingThreshold) {
    1666            0 :                                 ShowMessage(state,
    1667            0 :                                             format("SizeUnitVentilator: Potential issue with equipment sizing for {} {}",
    1668            0 :                                                    state.dataUnitVentilators->cMO_UnitVentilator,
    1669            0 :                                                    unitVent.Name));
    1670            0 :                                 ShowContinueError(state, format("User-Specified Maximum Outdoor Air Flow Rate of {:.5R} [m3/s]", OutAirVolFlowUser));
    1671            0 :                                 ShowContinueError(
    1672            0 :                                     state, format("differs from Design Size Maximum Outdoor Air Flow Rate of {:.5R} [m3/s]", OutAirVolFlowDes));
    1673            0 :                                 ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
    1674            0 :                                 ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
    1675              :                             }
    1676              :                         }
    1677              :                     }
    1678              :                 }
    1679              :             }
    1680            6 :             ZoneEqSizing.OAVolFlow = unitVent.OutAirVolFlow;
    1681              : 
    1682            6 :             if (unitVent.ATMixerExists) {     // set up ATMixer conditions for use in component sizing
    1683            0 :                 ZoneEqSizing.OAVolFlow = 0.0; // Equipment OA flow should always be 0 when ATMixer is used
    1684            0 :                 SingleDuct::setATMixerSizingProperties(state, unitVent.ATMixerIndex, unitVent.ZonePtr, state.dataSize->CurZoneEqNum);
    1685              :             }
    1686              :         }
    1687              : 
    1688            6 :         IsAutoSize = false;
    1689            6 :         if (unitVent.MinOutAirVolFlow == DataSizing::AutoSize) {
    1690            0 :             IsAutoSize = true;
    1691              :         }
    1692            6 :         if (state.dataSize->CurZoneEqNum > 0) {
    1693            6 :             if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // Simulation continue
    1694            0 :                 if (unitVent.MinOutAirVolFlow > 0.0) {
    1695            0 :                     BaseSizer::reportSizerOutput(state,
    1696            0 :                                                  state.dataUnitVentilators->cMO_UnitVentilator,
    1697              :                                                  unitVent.Name,
    1698              :                                                  "User-Specified Minimum Outdoor Air Flow Rate [m3/s]",
    1699              :                                                  unitVent.MinOutAirVolFlow);
    1700              :                 }
    1701              :             } else {
    1702            6 :                 CheckZoneSizing(state, state.dataUnitVentilators->cMO_UnitVentilator, unitVent.Name);
    1703            6 :                 MinOutAirVolFlowDes = min(state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).MinOA, unitVent.MaxAirVolFlow);
    1704            6 :                 if (MinOutAirVolFlowDes < HVAC::SmallAirVolFlow) {
    1705            0 :                     MinOutAirVolFlowDes = 0.0;
    1706              :                 }
    1707            6 :                 if (IsAutoSize) {
    1708            0 :                     unitVent.MinOutAirVolFlow = MinOutAirVolFlowDes;
    1709            0 :                     BaseSizer::reportSizerOutput(state,
    1710            0 :                                                  state.dataUnitVentilators->cMO_UnitVentilator,
    1711              :                                                  unitVent.Name,
    1712              :                                                  "Design Size Minimum Outdoor Air Flow Rate [m3/s]",
    1713              :                                                  MinOutAirVolFlowDes);
    1714              :                 } else {
    1715            6 :                     if (unitVent.MinOutAirVolFlow > 0.0 && MinOutAirVolFlowDes > 0.0) {
    1716            0 :                         MinOutAirVolFlowUser = unitVent.MinOutAirVolFlow;
    1717            0 :                         BaseSizer::reportSizerOutput(state,
    1718            0 :                                                      state.dataUnitVentilators->cMO_UnitVentilator,
    1719              :                                                      unitVent.Name,
    1720              :                                                      "Design Size Minimum Outdoor Air Flow Rate [m3/s]",
    1721              :                                                      MinOutAirVolFlowDes,
    1722              :                                                      "User-Specified Minimum Outdoor Air Flow Rate [m3/s]",
    1723              :                                                      MinOutAirVolFlowUser);
    1724            0 :                         if (state.dataGlobal->DisplayExtraWarnings) {
    1725            0 :                             if ((std::abs(MinOutAirVolFlowDes - MinOutAirVolFlowUser) / MinOutAirVolFlowUser) >
    1726            0 :                                 state.dataSize->AutoVsHardSizingThreshold) {
    1727            0 :                                 ShowMessage(state,
    1728            0 :                                             format("SizeUnitVentilator: Potential issue with equipment sizing for {} = \"{}\".",
    1729            0 :                                                    state.dataUnitVentilators->cMO_UnitVentilator,
    1730            0 :                                                    unitVent.Name));
    1731            0 :                                 ShowContinueError(state,
    1732            0 :                                                   format("User-Specified Minimum Outdoor Air Flow Rate of {:.5R} [m3/s]", MinOutAirVolFlowUser));
    1733            0 :                                 ShowContinueError(
    1734            0 :                                     state, format("differs from Design Size Minimum Outdoor Air Flow Rate of {:.5R} [m3/s]", MinOutAirVolFlowDes));
    1735            0 :                                 ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
    1736            0 :                                 ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
    1737              :                             }
    1738              :                         }
    1739              :                     }
    1740              :                 }
    1741              :             }
    1742              :         }
    1743              : 
    1744            6 :         IsAutoSize = false;
    1745            6 :         if (unitVent.MaxVolHotWaterFlow == DataSizing::AutoSize) {
    1746            0 :             IsAutoSize = true;
    1747              :         }
    1748            6 :         if (unitVent.HCoilType == HeatCoilType::Water) {
    1749            0 :             if (state.dataSize->CurZoneEqNum > 0) {
    1750            0 :                 if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // Simulation continue
    1751            0 :                     if (unitVent.MaxVolHotWaterFlow > 0.0) {
    1752            0 :                         BaseSizer::reportSizerOutput(state,
    1753            0 :                                                      state.dataUnitVentilators->cMO_UnitVentilator,
    1754              :                                                      unitVent.Name,
    1755              :                                                      "User-Specified Maximum Hot Water Flow [m3/s]",
    1756              :                                                      unitVent.MaxVolHotWaterFlow);
    1757              :                     }
    1758              :                 } else {
    1759            0 :                     CheckZoneSizing(state, state.dataUnitVentilators->cMO_UnitVentilator, unitVent.Name);
    1760              : 
    1761            0 :                     CoilWaterOutletNode = WaterCoils::GetCoilWaterOutletNode(state, "Coil:Heating:Water", unitVent.HCoilName, ErrorsFound);
    1762            0 :                     if (IsAutoSize) {
    1763            0 :                         PltSizHeatNum = PlantUtilities::MyPlantSizingIndex(
    1764              :                             state, "COIL:HEATING:WATER", unitVent.HCoilName, unitVent.HotControlNode, CoilWaterOutletNode, ErrorsFound);
    1765              : 
    1766            0 :                         if (state.dataWaterCoils->WaterCoil(unitVent.HCoil_Index).UseDesignWaterDeltaTemp) {
    1767            0 :                             WaterCoilSizDeltaT = state.dataWaterCoils->WaterCoil(unitVent.HCoil_Index).DesignWaterDeltaTemp;
    1768            0 :                             DoWaterCoilSizing = true;
    1769              :                         } else {
    1770            0 :                             if (PltSizHeatNum > 0) {
    1771            0 :                                 WaterCoilSizDeltaT = state.dataSize->PlantSizData(PltSizHeatNum).DeltaT;
    1772            0 :                                 DoWaterCoilSizing = true;
    1773              :                             } else {
    1774            0 :                                 DoWaterCoilSizing = false;
    1775              :                                 // If there is no heating Plant Sizing object and autosizing was requested, issue fatal error message
    1776            0 :                                 ShowSevereError(state, "Autosizing of water flow requires a heating loop Sizing:Plant object");
    1777            0 :                                 ShowContinueError(state,
    1778            0 :                                                   format("Occurs in {} = \"{}\"", state.dataUnitVentilators->cMO_UnitVentilator, unitVent.Name));
    1779            0 :                                 ErrorsFound = true;
    1780              :                             }
    1781              :                         }
    1782              : 
    1783            0 :                         if (DoWaterCoilSizing) {
    1784            0 :                             if (state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).DesHeatMassFlow >= HVAC::SmallAirVolFlow) {
    1785            0 :                                 SizingMethod = HVAC::HeatingCapacitySizing;
    1786            0 :                                 if (unitVent.HVACSizingIndex > 0) {
    1787            0 :                                     auto const &zoneHVACSizing = state.dataSize->ZoneHVACSizing(unitVent.HVACSizingIndex);
    1788            0 :                                     CapSizingMethod = zoneHVACSizing.HeatingCapMethod;
    1789            0 :                                     ZoneEqSizing.SizingMethod(SizingMethod) = CapSizingMethod;
    1790            0 :                                     switch (CapSizingMethod) {
    1791            0 :                                     case DataSizing::HeatingDesignCapacity:
    1792              :                                     case DataSizing::CapacityPerFloorArea:
    1793              :                                     case DataSizing::FractionOfAutosizedHeatingCapacity: {
    1794            0 :                                         switch (CapSizingMethod) {
    1795            0 :                                         case DataSizing::HeatingDesignCapacity: {
    1796            0 :                                             if (zoneHVACSizing.ScaledHeatingCapacity > 0.0) {
    1797            0 :                                                 ZoneEqSizing.HeatingCapacity = true;
    1798            0 :                                                 ZoneEqSizing.DesHeatingLoad = zoneHVACSizing.ScaledHeatingCapacity;
    1799              :                                             } else {
    1800            0 :                                                 state.dataSize->DataFlowUsedForSizing =
    1801            0 :                                                     state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).DesHeatVolFlow;
    1802              :                                             }
    1803            0 :                                             TempSize = zoneHVACSizing.ScaledHeatingCapacity;
    1804            0 :                                         } break;
    1805            0 :                                         case DataSizing::CapacityPerFloorArea: {
    1806            0 :                                             ZoneEqSizing.HeatingCapacity = true;
    1807            0 :                                             ZoneEqSizing.DesHeatingLoad = zoneHVACSizing.ScaledHeatingCapacity *
    1808            0 :                                                                           state.dataHeatBal->Zone(state.dataSize->DataZoneNumber).FloorArea;
    1809            0 :                                             state.dataSize->DataScalableCapSizingON = true;
    1810            0 :                                         } break;
    1811            0 :                                         case DataSizing::FractionOfAutosizedHeatingCapacity: {
    1812            0 :                                             state.dataSize->DataFracOfAutosizedHeatingCapacity = zoneHVACSizing.ScaledHeatingCapacity;
    1813            0 :                                             state.dataSize->DataFlowUsedForSizing =
    1814            0 :                                                 state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).DesHeatVolFlow;
    1815            0 :                                             TempSize = DataSizing::AutoSize;
    1816            0 :                                             state.dataSize->DataScalableCapSizingON = true;
    1817            0 :                                         } break;
    1818            0 :                                         default: {
    1819            0 :                                         } break;
    1820              :                                         }
    1821            0 :                                     } break;
    1822            0 :                                     default: {
    1823            0 :                                     } break;
    1824              :                                     }
    1825            0 :                                     PrintFlag = false;
    1826            0 :                                     bool errorsFound = false;
    1827            0 :                                     HeatingCapacitySizer sizerHeatingCapacity;
    1828            0 :                                     sizerHeatingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
    1829            0 :                                     DesHeatingLoad = sizerHeatingCapacity.size(state, TempSize, errorsFound);
    1830            0 :                                     state.dataSize->DataScalableCapSizingON = false;
    1831              :                                 } else {
    1832            0 :                                     PrintFlag = false;
    1833            0 :                                     TempSize = DataSizing::AutoSize;
    1834            0 :                                     state.dataSize->DataFlowUsedForSizing =
    1835            0 :                                         state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).DesHeatVolFlow;
    1836            0 :                                     bool errorsFound = false;
    1837            0 :                                     HeatingCapacitySizer sizerHeatingCapacity;
    1838            0 :                                     sizerHeatingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
    1839            0 :                                     DesHeatingLoad = sizerHeatingCapacity.size(state, TempSize, errorsFound);
    1840            0 :                                 }
    1841            0 :                                 rho = state.dataPlnt->PlantLoop(unitVent.HWplantLoc.loopNum)
    1842            0 :                                           .glycol->getDensity(state, Constant::HWInitConvTemp, RoutineName);
    1843            0 :                                 Cp = state.dataPlnt->PlantLoop(unitVent.HWplantLoc.loopNum)
    1844            0 :                                          .glycol->getSpecificHeat(state, Constant::HWInitConvTemp, RoutineName);
    1845            0 :                                 MaxVolHotWaterFlowDes = DesHeatingLoad / (WaterCoilSizDeltaT * Cp * rho);
    1846              : 
    1847              :                             } else {
    1848            0 :                                 MaxVolHotWaterFlowDes = 0.0;
    1849              :                             }
    1850              :                         }
    1851            0 :                         unitVent.MaxVolHotWaterFlow = MaxVolHotWaterFlowDes;
    1852            0 :                         BaseSizer::reportSizerOutput(state,
    1853            0 :                                                      state.dataUnitVentilators->cMO_UnitVentilator,
    1854              :                                                      unitVent.Name,
    1855              :                                                      "Design Size Maximum Hot Water Flow [m3/s]",
    1856              :                                                      MaxVolHotWaterFlowDes);
    1857              :                     } else {
    1858            0 :                         if (unitVent.MaxVolHotWaterFlow > 0.0 && MaxVolHotWaterFlowDes > 0.0) {
    1859            0 :                             MaxVolHotWaterFlowUser = unitVent.MaxVolHotWaterFlow;
    1860            0 :                             BaseSizer::reportSizerOutput(state,
    1861            0 :                                                          state.dataUnitVentilators->cMO_UnitVentilator,
    1862              :                                                          unitVent.Name,
    1863              :                                                          "Design Size Maximum Hot Water Flow [m3/s]",
    1864              :                                                          MaxVolHotWaterFlowDes,
    1865              :                                                          "User-Specified Maximum Hot Water Flow [m3/s]",
    1866              :                                                          MaxVolHotWaterFlowUser);
    1867            0 :                             if (state.dataGlobal->DisplayExtraWarnings) {
    1868            0 :                                 if ((std::abs(MaxVolHotWaterFlowDes - MaxVolHotWaterFlowUser) / MaxVolHotWaterFlowUser) >
    1869            0 :                                     state.dataSize->AutoVsHardSizingThreshold) {
    1870            0 :                                     ShowMessage(state,
    1871            0 :                                                 format("SizeUnitVentilator: Potential issue with equipment sizing for {} {}",
    1872            0 :                                                        state.dataUnitVentilators->cMO_UnitVentilator,
    1873            0 :                                                        unitVent.Name));
    1874            0 :                                     ShowContinueError(state,
    1875            0 :                                                       format("User-Specified Maximum Hot Water Flow of {:.5R} [m3/s]", MaxVolHotWaterFlowUser));
    1876            0 :                                     ShowContinueError(
    1877            0 :                                         state, format("differs from Design Size Maximum Hot Water Flow of {:.5R} [m3/s]", MaxVolHotWaterFlowDes));
    1878            0 :                                     ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
    1879            0 :                                     ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
    1880              :                                 }
    1881              :                             }
    1882              :                         }
    1883              :                     }
    1884              :                 }
    1885              :             }
    1886              :         } else {
    1887            6 :             unitVent.MaxVolHotWaterFlow = 0.0;
    1888              :         }
    1889              : 
    1890            6 :         IsAutoSize = false;
    1891            6 :         if (unitVent.MaxVolHotSteamFlow == DataSizing::AutoSize) {
    1892            0 :             IsAutoSize = true;
    1893              :         }
    1894            6 :         if (unitVent.HCoilType == HeatCoilType::Steam) {
    1895            0 :             if (state.dataSize->CurZoneEqNum > 0) {
    1896            0 :                 if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // Simulation continue
    1897            0 :                     if (unitVent.MaxVolHotSteamFlow > 0.0) {
    1898            0 :                         BaseSizer::reportSizerOutput(state,
    1899            0 :                                                      state.dataUnitVentilators->cMO_UnitVentilator,
    1900              :                                                      unitVent.Name,
    1901              :                                                      "User-Specified Maximum Steam Flow [m3/s]",
    1902              :                                                      unitVent.MaxVolHotSteamFlow);
    1903              :                     }
    1904              :                 } else {
    1905            0 :                     CheckZoneSizing(state, state.dataUnitVentilators->cMO_UnitVentilator, unitVent.Name);
    1906              : 
    1907            0 :                     int CoilSteamOutletNode = SteamCoils::GetCoilSteamOutletNode(state, "Coil:Heating:Steam", unitVent.HCoilName, ErrorsFound);
    1908            0 :                     if (IsAutoSize) {
    1909            0 :                         PltSizHeatNum = PlantUtilities::MyPlantSizingIndex(
    1910              :                             state, "Coil:Heating:Steam", unitVent.HCoilName, unitVent.HotControlNode, CoilSteamOutletNode, ErrorsFound);
    1911            0 :                         if (PltSizHeatNum > 0) {
    1912            0 :                             if (state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).DesHeatMassFlow >= HVAC::SmallAirVolFlow) {
    1913            0 :                                 SizingMethod = HVAC::HeatingCapacitySizing;
    1914            0 :                                 if (unitVent.HVACSizingIndex > 0) {
    1915            0 :                                     auto const &zoneHVACSizing = state.dataSize->ZoneHVACSizing(unitVent.HVACSizingIndex);
    1916            0 :                                     CapSizingMethod = zoneHVACSizing.HeatingCapMethod;
    1917            0 :                                     ZoneEqSizing.SizingMethod(SizingMethod) = CapSizingMethod;
    1918            0 :                                     switch (CapSizingMethod) {
    1919            0 :                                     case DataSizing::HeatingDesignCapacity:
    1920              :                                     case DataSizing::CapacityPerFloorArea:
    1921              :                                     case DataSizing::FractionOfAutosizedHeatingCapacity: {
    1922            0 :                                         if (CapSizingMethod == DataSizing::HeatingDesignCapacity) {
    1923            0 :                                             if (zoneHVACSizing.ScaledHeatingCapacity > 0.0) {
    1924            0 :                                                 ZoneEqSizing.HeatingCapacity = true;
    1925            0 :                                                 ZoneEqSizing.DesHeatingLoad = zoneHVACSizing.ScaledHeatingCapacity;
    1926              :                                             } else {
    1927            0 :                                                 state.dataSize->DataFlowUsedForSizing =
    1928            0 :                                                     state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).DesHeatVolFlow;
    1929              :                                             }
    1930            0 :                                             TempSize = zoneHVACSizing.ScaledHeatingCapacity;
    1931            0 :                                         } else if (CapSizingMethod == DataSizing::CapacityPerFloorArea) {
    1932            0 :                                             ZoneEqSizing.HeatingCapacity = true;
    1933            0 :                                             ZoneEqSizing.DesHeatingLoad = zoneHVACSizing.ScaledHeatingCapacity *
    1934            0 :                                                                           state.dataHeatBal->Zone(state.dataSize->DataZoneNumber).FloorArea;
    1935            0 :                                             state.dataSize->DataScalableCapSizingON = true;
    1936            0 :                                         } else if (CapSizingMethod == DataSizing::FractionOfAutosizedHeatingCapacity) {
    1937            0 :                                             state.dataSize->DataFracOfAutosizedHeatingCapacity = zoneHVACSizing.ScaledHeatingCapacity;
    1938            0 :                                             state.dataSize->DataFlowUsedForSizing =
    1939            0 :                                                 state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).DesHeatVolFlow;
    1940            0 :                                             TempSize = DataSizing::AutoSize;
    1941            0 :                                             state.dataSize->DataScalableCapSizingON = true;
    1942              :                                         }
    1943            0 :                                     } break;
    1944            0 :                                     default: {
    1945            0 :                                     } break;
    1946              :                                     }
    1947              : 
    1948            0 :                                     PrintFlag = false;
    1949            0 :                                     bool errorsFound = false;
    1950            0 :                                     HeatingCapacitySizer sizerHeatingCapacity;
    1951            0 :                                     sizerHeatingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
    1952            0 :                                     DesHeatingLoad = sizerHeatingCapacity.size(state, TempSize, errorsFound);
    1953            0 :                                     state.dataSize->DataScalableCapSizingON = false;
    1954              :                                 } else {
    1955            0 :                                     PrintFlag = false;
    1956            0 :                                     TempSize = DataSizing::AutoSize;
    1957            0 :                                     state.dataSize->DataFlowUsedForSizing =
    1958            0 :                                         state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).DesHeatVolFlow;
    1959            0 :                                     bool errorsFound = false;
    1960            0 :                                     HeatingCapacitySizer sizerHeatingCapacity;
    1961            0 :                                     sizerHeatingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
    1962            0 :                                     DesHeatingLoad = sizerHeatingCapacity.size(state, TempSize, errorsFound);
    1963            0 :                                 }
    1964            0 :                                 TempSteamIn = 100.00;
    1965            0 :                                 auto *steam = Fluid::GetSteam(state);
    1966            0 :                                 EnthSteamInDry = steam->getSatEnthalpy(state, TempSteamIn, 1.0, RoutineName);
    1967            0 :                                 EnthSteamOutWet = steam->getSatEnthalpy(state, TempSteamIn, 0.0, RoutineName);
    1968            0 :                                 LatentHeatSteam = EnthSteamInDry - EnthSteamOutWet;
    1969            0 :                                 SteamDensity = steam->getSatDensity(state, TempSteamIn, 1.0, RoutineName);
    1970              :                                 Cp =
    1971            0 :                                     Fluid::GetWater(state)->getSpecificHeat(state, state.dataSize->PlantSizData(PltSizHeatNum).ExitTemp, RoutineName);
    1972            0 :                                 MaxVolHotSteamFlowDes =
    1973            0 :                                     DesHeatingLoad / (SteamDensity * (LatentHeatSteam + state.dataSize->PlantSizData(PltSizHeatNum).DeltaT * Cp));
    1974              :                             } else {
    1975            0 :                                 MaxVolHotSteamFlowDes = 0.0;
    1976              :                             }
    1977              :                         } else {
    1978            0 :                             ShowSevereError(state, "Autosizing of Steam flow requires a heating loop Sizing:Plant object");
    1979            0 :                             ShowContinueError(state, format("Occurs in {} = \"{}\"", state.dataUnitVentilators->cMO_UnitVentilator, unitVent.Name));
    1980            0 :                             ErrorsFound = true;
    1981              :                         }
    1982            0 :                         unitVent.MaxVolHotSteamFlow = MaxVolHotSteamFlowDes;
    1983            0 :                         BaseSizer::reportSizerOutput(state,
    1984            0 :                                                      state.dataUnitVentilators->cMO_UnitVentilator,
    1985              :                                                      unitVent.Name,
    1986              :                                                      "Design Size Maximum Steam Flow [m3/s]",
    1987              :                                                      MaxVolHotSteamFlowDes);
    1988              :                     } else {
    1989            0 :                         if (unitVent.MaxVolHotSteamFlow > 0.0 && MaxVolHotSteamFlowDes > 0.0) {
    1990            0 :                             MaxVolHotSteamFlowUser = unitVent.MaxVolHotSteamFlow;
    1991            0 :                             BaseSizer::reportSizerOutput(state,
    1992            0 :                                                          state.dataUnitVentilators->cMO_UnitVentilator,
    1993              :                                                          unitVent.Name,
    1994              :                                                          "Design Size Maximum Steam Flow [m3/s]",
    1995              :                                                          MaxVolHotSteamFlowDes,
    1996              :                                                          "User-Specified Maximum Steam Flow [m3/s]",
    1997              :                                                          MaxVolHotSteamFlowUser);
    1998            0 :                             if (state.dataGlobal->DisplayExtraWarnings) {
    1999            0 :                                 if ((std::abs(MaxVolHotSteamFlowDes - MaxVolHotSteamFlowUser) / MaxVolHotSteamFlowUser) >
    2000            0 :                                     state.dataSize->AutoVsHardSizingThreshold) {
    2001            0 :                                     ShowMessage(state,
    2002            0 :                                                 format("SizeUnitVentilator: Potential issue with equipment sizing for {} = \"{}\"",
    2003            0 :                                                        state.dataUnitVentilators->cMO_UnitVentilator,
    2004            0 :                                                        unitVent.Name));
    2005            0 :                                     ShowContinueError(state, format("User-Specified Maximum Steam Flow of {:.5R} [m3/s]", MaxVolHotSteamFlowUser));
    2006            0 :                                     ShowContinueError(state,
    2007            0 :                                                       format("differs from Design Size Maximum Steam Flow of {:.5R} [m3/s]", MaxVolHotSteamFlowDes));
    2008            0 :                                     ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
    2009            0 :                                     ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
    2010              :                                 }
    2011              :                             }
    2012              :                         }
    2013              :                     }
    2014              :                 }
    2015              :             }
    2016              :         } else {
    2017            6 :             unitVent.MaxVolHotSteamFlow = 0.0;
    2018              :         }
    2019              : 
    2020            6 :         IsAutoSize = false;
    2021            6 :         if (unitVent.MaxVolColdWaterFlow == DataSizing::AutoSize) {
    2022            0 :             IsAutoSize = true;
    2023              :         }
    2024            6 :         if (unitVent.CCoilType == CoolCoilType::Water || unitVent.CCoilType == CoolCoilType::Detailed ||
    2025            6 :             unitVent.CCoilType == CoolCoilType::HXAssisted) {
    2026              : 
    2027            0 :             if (state.dataSize->CurZoneEqNum > 0) {
    2028            0 :                 if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // Simulation continue
    2029            0 :                     if (unitVent.MaxVolColdWaterFlow > 0.0) {
    2030            0 :                         BaseSizer::reportSizerOutput(state,
    2031            0 :                                                      state.dataUnitVentilators->cMO_UnitVentilator,
    2032              :                                                      unitVent.Name,
    2033              :                                                      "User-Specified Maximum Cold Water Flow [m3/s]",
    2034              :                                                      unitVent.MaxVolColdWaterFlow);
    2035              :                     }
    2036              :                 } else {
    2037            0 :                     CheckZoneSizing(state, state.dataUnitVentilators->cMO_UnitVentilator, unitVent.Name);
    2038              : 
    2039            0 :                     if (unitVent.CCoilType == CoolCoilType::HXAssisted) {
    2040            0 :                         CoolingCoilName = HVACHXAssistedCoolingCoil::GetHXDXCoilName(state, unitVent.CCoilTypeCh, unitVent.CCoilName, ErrorsFound);
    2041            0 :                         CoolingCoilType = HVACHXAssistedCoolingCoil::GetHXCoilType(state, unitVent.CCoilTypeCh, unitVent.CCoilName, ErrorsFound);
    2042              :                     } else {
    2043            0 :                         CoolingCoilName = unitVent.CCoilName;
    2044            0 :                         CoolingCoilType = unitVent.CCoilTypeCh;
    2045              :                     }
    2046            0 :                     CoilWaterOutletNode = WaterCoils::GetCoilWaterOutletNode(state, CoolingCoilType, CoolingCoilName, ErrorsFound);
    2047            0 :                     if (IsAutoSize) {
    2048            0 :                         int PltSizCoolNum = PlantUtilities::MyPlantSizingIndex(
    2049              :                             state, CoolingCoilType, CoolingCoilName, unitVent.ColdControlNode, CoilWaterOutletNode, ErrorsFound);
    2050            0 :                         if (state.dataWaterCoils->WaterCoil(unitVent.CCoil_Index).UseDesignWaterDeltaTemp) {
    2051            0 :                             WaterCoilSizDeltaT = state.dataWaterCoils->WaterCoil(unitVent.CCoil_Index).DesignWaterDeltaTemp;
    2052            0 :                             DoWaterCoilSizing = true;
    2053              :                         } else {
    2054            0 :                             if (PltSizCoolNum > 0) {
    2055            0 :                                 WaterCoilSizDeltaT = state.dataSize->PlantSizData(PltSizCoolNum).DeltaT;
    2056            0 :                                 DoWaterCoilSizing = true;
    2057              :                             } else {
    2058            0 :                                 DoWaterCoilSizing = false;
    2059              :                                 // If there is no cooling Plant Sizing object and autosizing was requested, issue fatal error message
    2060            0 :                                 ShowSevereError(state, "Autosizing of water coil requires a cooling loop Sizing:Plant object");
    2061            0 :                                 ShowContinueError(state,
    2062            0 :                                                   format("Occurs in {} = \"{}\"", state.dataUnitVentilators->cMO_UnitVentilator, unitVent.Name));
    2063            0 :                                 ErrorsFound = true;
    2064              :                             }
    2065              :                         }
    2066            0 :                         if (DoWaterCoilSizing) {
    2067            0 :                             if (state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).DesCoolMassFlow >= HVAC::SmallAirVolFlow) {
    2068            0 :                                 SizingMethod = HVAC::CoolingCapacitySizing;
    2069            0 :                                 if (unitVent.HVACSizingIndex > 0) {
    2070            0 :                                     auto const &zoneHVACSizing = state.dataSize->ZoneHVACSizing(unitVent.HVACSizingIndex);
    2071            0 :                                     CapSizingMethod = zoneHVACSizing.CoolingCapMethod;
    2072            0 :                                     ZoneEqSizing.SizingMethod(SizingMethod) = CapSizingMethod;
    2073            0 :                                     switch (CapSizingMethod) {
    2074            0 :                                     case DataSizing::CoolingDesignCapacity:
    2075              :                                     case DataSizing::CapacityPerFloorArea:
    2076              :                                     case DataSizing::FractionOfAutosizedCoolingCapacity: {
    2077            0 :                                         if (CapSizingMethod == DataSizing::CoolingDesignCapacity) {
    2078            0 :                                             if (zoneHVACSizing.ScaledCoolingCapacity > 0.0) {
    2079            0 :                                                 ZoneEqSizing.CoolingCapacity = true;
    2080            0 :                                                 ZoneEqSizing.DesCoolingLoad = zoneHVACSizing.ScaledCoolingCapacity;
    2081              :                                             } else {
    2082            0 :                                                 state.dataSize->DataFlowUsedForSizing =
    2083            0 :                                                     state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).DesCoolVolFlow;
    2084              :                                             }
    2085            0 :                                             TempSize = zoneHVACSizing.ScaledCoolingCapacity;
    2086            0 :                                         } else if (CapSizingMethod == DataSizing::CapacityPerFloorArea) {
    2087            0 :                                             ZoneEqSizing.CoolingCapacity = true;
    2088            0 :                                             ZoneEqSizing.DesCoolingLoad = zoneHVACSizing.ScaledCoolingCapacity *
    2089            0 :                                                                           state.dataHeatBal->Zone(state.dataSize->DataZoneNumber).FloorArea;
    2090            0 :                                             state.dataSize->DataScalableCapSizingON = true;
    2091            0 :                                         } else if (CapSizingMethod == DataSizing::FractionOfAutosizedCoolingCapacity) {
    2092            0 :                                             state.dataSize->DataFracOfAutosizedHeatingCapacity = zoneHVACSizing.ScaledCoolingCapacity;
    2093            0 :                                             state.dataSize->DataFlowUsedForSizing =
    2094            0 :                                                 state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).DesCoolVolFlow;
    2095            0 :                                             TempSize = DataSizing::AutoSize;
    2096            0 :                                             state.dataSize->DataScalableCapSizingON = true;
    2097              :                                         }
    2098            0 :                                     } break;
    2099            0 :                                     default: {
    2100            0 :                                     } break;
    2101              :                                     }
    2102            0 :                                     PrintFlag = false;
    2103            0 :                                     CoolingCapacitySizer sizerCoolingCapacity;
    2104            0 :                                     sizerCoolingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
    2105            0 :                                     DesCoolingLoad = sizerCoolingCapacity.size(state, TempSize, ErrorsFound);
    2106            0 :                                     state.dataSize->DataScalableCapSizingON = false;
    2107              :                                 } else {
    2108            0 :                                     PrintFlag = false;
    2109            0 :                                     TempSize = DataSizing::AutoSize;
    2110            0 :                                     state.dataSize->DataFlowUsedForSizing =
    2111            0 :                                         state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).DesCoolVolFlow;
    2112            0 :                                     CoolingCapacitySizer sizerCoolingCapacity;
    2113            0 :                                     sizerCoolingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
    2114            0 :                                     DesCoolingLoad = sizerCoolingCapacity.size(state, TempSize, ErrorsFound);
    2115            0 :                                 }
    2116            0 :                                 rho = state.dataPlnt->PlantLoop(unitVent.CWPlantLoc.loopNum).glycol->getDensity(state, 5., RoutineName);
    2117            0 :                                 Cp = state.dataPlnt->PlantLoop(unitVent.CWPlantLoc.loopNum).glycol->getSpecificHeat(state, 5., RoutineName);
    2118            0 :                                 MaxVolColdWaterFlowDes = DesCoolingLoad / (WaterCoilSizDeltaT * Cp * rho);
    2119              : 
    2120            0 :                                 if (MaxVolColdWaterFlowDes < 0.0) {
    2121            0 :                                     ShowWarningError(state, "Autosizing of water flow resulted in negative value.");
    2122            0 :                                     ShowContinueError(state,
    2123            0 :                                                       format("Occurs in {} = \"{}\"", state.dataUnitVentilators->cMO_UnitVentilator, unitVent.Name));
    2124            0 :                                     ShowContinueError(state, "...Sizing information found during sizing simulation:");
    2125            0 :                                     ShowContinueError(state, format("...Calculated coil design load = {:.3T} W", DesCoolingLoad));
    2126            0 :                                     ShowContinueError(state, format("...Calculated water flow rate  = {:.3T} m3/s", MaxVolColdWaterFlowDes));
    2127            0 :                                     ShowContinueError(state,
    2128              :                                                       "...Water flow rate will be set to 0. Check sizing inputs for zone and plant, inputs for water "
    2129              :                                                       "cooling coil object, and design day specifications.");
    2130            0 :                                     ShowContinueError(state, "...Consider autosizing all inputs if not already doing so.");
    2131            0 :                                     MaxVolColdWaterFlowDes = 0.0;
    2132              :                                 }
    2133              :                             } else {
    2134            0 :                                 MaxVolColdWaterFlowDes = 0.0;
    2135              :                             }
    2136              :                         }
    2137            0 :                         unitVent.MaxVolColdWaterFlow = MaxVolColdWaterFlowDes;
    2138            0 :                         BaseSizer::reportSizerOutput(state,
    2139            0 :                                                      state.dataUnitVentilators->cMO_UnitVentilator,
    2140              :                                                      unitVent.Name,
    2141              :                                                      "Design Size Maximum Cold Water Flow [m3/s]",
    2142              :                                                      MaxVolColdWaterFlowDes);
    2143              :                     } else {
    2144            0 :                         if (unitVent.MaxVolColdWaterFlow > 0.0 && MaxVolColdWaterFlowDes > 0.0) {
    2145            0 :                             MaxVolColdWaterFlowUser = unitVent.MaxVolColdWaterFlow;
    2146            0 :                             BaseSizer::reportSizerOutput(state,
    2147            0 :                                                          state.dataUnitVentilators->cMO_UnitVentilator,
    2148              :                                                          unitVent.Name,
    2149              :                                                          "Design Size Maximum Cold Water Flow [m3/s]",
    2150              :                                                          MaxVolColdWaterFlowDes,
    2151              :                                                          "User-Specified Maximum Cold Water Flow [m3/s]",
    2152              :                                                          MaxVolColdWaterFlowUser);
    2153            0 :                             if (state.dataGlobal->DisplayExtraWarnings) {
    2154            0 :                                 if ((std::abs(MaxVolColdWaterFlowDes - MaxVolColdWaterFlowUser) / MaxVolColdWaterFlowUser) >
    2155            0 :                                     state.dataSize->AutoVsHardSizingThreshold) {
    2156            0 :                                     ShowMessage(state,
    2157            0 :                                                 format("SizeUnitVentilator: Potential issue with equipment sizing for {} = \"{}\"",
    2158            0 :                                                        state.dataUnitVentilators->cMO_UnitVentilator,
    2159            0 :                                                        unitVent.Name));
    2160            0 :                                     ShowContinueError(state,
    2161            0 :                                                       format("User-Specified Maximum Cold Water Flow of {:.5R} [m3/s]", MaxVolColdWaterFlowUser));
    2162            0 :                                     ShowContinueError(
    2163            0 :                                         state, format("differs from Design Size Maximum Cold Water Flow of {:.5R} [m3/s]", MaxVolColdWaterFlowDes));
    2164            0 :                                     ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
    2165            0 :                                     ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
    2166              :                                 }
    2167              :                             }
    2168              :                         }
    2169              :                     }
    2170              :                 }
    2171              :             }
    2172              :         }
    2173              : 
    2174              :         // set the design air flow rates for the heating and cooling coils
    2175            6 :         if (unitVent.CCoilType == CoolCoilType::HXAssisted) {
    2176            0 :             CoolingCoilName = HVACHXAssistedCoolingCoil::GetHXDXCoilName(state, unitVent.CCoilTypeCh, unitVent.CCoilName, ErrorsFound);
    2177            0 :             CoolingCoilType = HVACHXAssistedCoolingCoil::GetHXCoilType(state, unitVent.CCoilTypeCh, unitVent.CCoilName, ErrorsFound);
    2178              :         } else {
    2179            6 :             CoolingCoilName = unitVent.CCoilName;
    2180            6 :             CoolingCoilType = unitVent.CCoilTypeCh;
    2181              :         }
    2182            6 :         WaterCoils::SetCoilDesFlow(state, CoolingCoilType, CoolingCoilName, unitVent.MaxAirVolFlow, ErrorsFound);
    2183            6 :         WaterCoils::SetCoilDesFlow(state, unitVent.HCoilTypeCh, unitVent.HCoilName, unitVent.MaxAirVolFlow, ErrorsFound);
    2184              : 
    2185            6 :         if (state.dataSize->CurZoneEqNum > 0) {
    2186            6 :             ZoneEqSizing.MaxHWVolFlow = unitVent.MaxVolHotWaterFlow;
    2187            6 :             ZoneEqSizing.MaxCWVolFlow = unitVent.MaxVolColdWaterFlow;
    2188              :         }
    2189              : 
    2190            6 :         if (ErrorsFound) {
    2191            0 :             ShowFatalError(state, "Preceding sizing errors cause program termination");
    2192              :         }
    2193            6 :     }
    2194              : 
    2195            2 :     void CalcUnitVentilator(EnergyPlusData &state,
    2196              :                             int &UnitVentNum,              // number of the current fan coil unit being simulated
    2197              :                             int const ZoneNum,             // number of zone being served
    2198              :                             bool const FirstHVACIteration, // TRUE if 1st HVAC simulation of system timestep
    2199              :                             Real64 &PowerMet,              // Sensible power supplied (W)
    2200              :                             Real64 &LatOutputProvided      // Latent power supplied (kg/s), negative = dehumidification
    2201              :     )
    2202              :     {
    2203              : 
    2204              :         // SUBROUTINE INFORMATION:
    2205              :         //       AUTHOR         Rick Strand
    2206              :         //       DATE WRITTEN   May 2000
    2207              :         //       MODIFIED       Don Shirey, Aug 2009 (LatOutputProvided)
    2208              :         //                      July 2012, Chandan Sharma - FSEC: Added zone sys avail managers
    2209              : 
    2210              :         // PURPOSE OF THIS SUBROUTINE:
    2211              :         // This subroutine mainly controls the action of the unit ventilator
    2212              :         // (or more exactly, it controls the amount of outside air brought in)
    2213              :         // based on the user input for controls and the defined controls
    2214              :         // algorithms.  There are currently (at the initial creation of this
    2215              :         // subroutine) two control methods: variable percent (ASHRAE "Cycle I"
    2216              :         // or "Cycle II") and fixed temperature (ASHRAE "Cycle III").
    2217              : 
    2218              :         // METHODOLOGY EMPLOYED:
    2219              :         // Unit is controlled based on user input and what is happening in the
    2220              :         // simulation.  There are various cases to consider:
    2221              :         // 1. OFF: Unit is schedule off or there is no load on it.  All flow
    2222              :         //    rates are set to zero and the temperatures are set to zone conditions
    2223              :         //    (except for the outside air inlet).
    2224              :         // 2. HEATING/VARIABLE PERCENT: The unit is on, there is a heating load,
    2225              :         //    and variable percent control is specified.  The outside air fraction
    2226              :         //    is set to the minimum outside air fraction (schedule based) and the
    2227              :         //    heating coil is activated.
    2228              :         // 3. HEATING/FIXED TEMPERATURE: The unit is on, there is a heating load,
    2229              :         //    and fixed temperature control is specified.  The outside air fraction
    2230              :         //    is varied in an attempt to obtain a mixed air temperature equal to
    2231              :         //    the user specified temperature (schedule based).  The heating coil
    2232              :         //    is activated, if necessary.
    2233              :         // 4. COOLING/NO COIL: The unit is on, there is a cooling load, and no
    2234              :         //    coil is present or it has been scheduled off.  Set the amount of
    2235              :         //    outside air based on the control type.  Simulate the "mixing box".
    2236              :         // 5. COOLING/WITH COIL: The unit is on, there is a cooling load, and
    2237              :         //    a cooling coil is present and scheduled on.  Tries to use outside
    2238              :         //    air as best as possible and then calls a cooling coil
    2239              :         // Note: controls are strictly temperature based and do not factor
    2240              :         // humidity into the equation (not an enthalpy economy cycle but rather
    2241              :         // a simple return air economy cycle).  In addition, temperature predictions
    2242              :         // are not strict energy balances here in the control routine though
    2243              :         // in the mixing routine an energy balance is preserved.
    2244              : 
    2245              :         // REFERENCES:
    2246              :         // ASHRAE Systems and Equipment Handbook (SI), 1996. page 31.3
    2247              : 
    2248              :         // Using/Aliasing
    2249            2 :         auto &unitVent = state.dataUnitVentilators->UnitVent(UnitVentNum);
    2250              : 
    2251              :         // Smallest allowed temperature difference for comparisons (below this value the temperatures are assumed equal)
    2252            2 :         Real64 constexpr LowTempDiff(0.1);
    2253              :         // Smallest allowed outside air fraction difference for comparison (below this value the fractions are assumed equal)
    2254            2 :         Real64 constexpr LowOAFracDiff(0.01);
    2255            2 :         int constexpr MaxIter(50);
    2256              : 
    2257              :         Real64 AirMassFlow; // air mass flow rate [kg/sec]
    2258              :         Real64 MaxOAFrac;   // maximum possible outside air fraction
    2259              :         Real64 MinOAFrac;   // minimum possible outside air fraction
    2260              :         Real64 Tdesired;    // desired temperature after mixing inlet and outdoor air [degrees C]
    2261              :         Real64 Tinlet;      // temperature of air coming into the unit ventilator [degrees C]
    2262              :         Real64 Toutdoor;    // temperature of outdoor air being introduced into the unit ventilator [degrees C]
    2263              :         Real64 mdot;
    2264              : 
    2265            2 :         switch (unitVent.CoilOption) {
    2266            2 :         case CoilsUsed::Both:
    2267              :         case CoilsUsed::Heating: {
    2268            2 :             switch (unitVent.HCoilType) {
    2269            0 :             case HeatCoilType::Water: {
    2270            0 :                 WaterCoils::CheckWaterCoilSchedule(state, unitVent.HCoilName, unitVent.HCoilSchedValue, unitVent.HCoil_Index);
    2271            0 :             } break;
    2272            0 :             case HeatCoilType::Steam: {
    2273            0 :                 SteamCoils::CheckSteamCoilSchedule(state, "Coil:Heating:Steam", unitVent.HCoilName, unitVent.HCoilSchedValue, unitVent.HCoil_Index);
    2274            0 :             } break;
    2275            0 :             case HeatCoilType::Electric: {
    2276            0 :                 HeatingCoils::CheckHeatingCoilSchedule(
    2277            0 :                     state, "Coil:Heating:Electric", unitVent.HCoilName, unitVent.HCoilSchedValue, unitVent.HCoil_Index);
    2278            0 :             } break;
    2279            2 :             case HeatCoilType::Gas: {
    2280            2 :                 HeatingCoils::CheckHeatingCoilSchedule(
    2281            2 :                     state, "Coil:Heating:Fuel", unitVent.HCoilName, unitVent.HCoilSchedValue, unitVent.HCoil_Index);
    2282            2 :             } break;
    2283            0 :             default: {
    2284            0 :             } break;
    2285              :             }
    2286            2 :         } break;
    2287            0 :         default: {
    2288            0 :         } break;
    2289              :         }
    2290              : 
    2291            2 :         switch (unitVent.CoilOption) {
    2292            0 :         case CoilsUsed::Both:
    2293              :         case CoilsUsed::Cooling: {
    2294            0 :             switch (unitVent.CCoilType) {
    2295            0 :             case CoolCoilType::Water: {
    2296            0 :                 WaterCoils::CheckWaterCoilSchedule(state, unitVent.CCoilName, unitVent.CCoilSchedValue, unitVent.CCoil_Index);
    2297            0 :             } break;
    2298            0 :             case CoolCoilType::Detailed: {
    2299            0 :                 WaterCoils::CheckWaterCoilSchedule(state, unitVent.CCoilName, unitVent.CCoilSchedValue, unitVent.CCoil_Index);
    2300            0 :             } break;
    2301            0 :             case CoolCoilType::HXAssisted: {
    2302            0 :                 HVACHXAssistedCoolingCoil::CheckHXAssistedCoolingCoilSchedule(
    2303            0 :                     state, "CoilSystem:Cooling:Water:HeatExchangerAssisted", unitVent.CCoilName, unitVent.CCoilSchedValue, unitVent.CCoil_Index);
    2304            0 :             } break;
    2305            0 :             default: {
    2306            0 :                 assert(false);
    2307              :             } break;
    2308              :             }
    2309            0 :         } break;
    2310            2 :         default: {
    2311            2 :         } break;
    2312              :         }
    2313              : 
    2314              :         // initialize local variables
    2315            2 :         Real64 QUnitOut = 0.0;
    2316            2 :         Real64 ControlOffset = 0.0;
    2317            2 :         Real64 MaxWaterFlow = 0.0;
    2318            2 :         Real64 MinWaterFlow = 0.0;
    2319            2 :         Real64 NoOutput = 0.0;
    2320            2 :         Real64 FullOutput = 0.0;
    2321            2 :         HVAC::FanOp fanOp = unitVent.fanOp;
    2322            2 :         Real64 PartLoadFrac = 0.0;
    2323              : 
    2324            2 :         auto const &inletNode = state.dataLoopNodes->Node(unitVent.AirInNode);
    2325            2 :         auto const &outletNode = state.dataLoopNodes->Node(unitVent.AirOutNode);
    2326            2 :         auto const &outsideAirNode = state.dataLoopNodes->Node(unitVent.OutsideAirNode);
    2327              : 
    2328            6 :         if ((std::abs(state.dataUnitVentilators->QZnReq) < HVAC::SmallLoad) || (state.dataZoneEnergyDemand->CurDeadBandOrSetback(ZoneNum)) ||
    2329            8 :             (unitVent.availSched->getCurrentVal() <= 0) ||
    2330            4 :             ((unitVent.fanAvailSched->getCurrentVal() <= 0 && !state.dataHVACGlobal->TurnFansOn) || state.dataHVACGlobal->TurnFansOff)) {
    2331              : 
    2332              :             // Unit is off or has no load upon it; set the flow rates to zero and then
    2333              :             // simulate the components with the no flow conditions
    2334            0 :             AirMassFlow = outletNode.MassFlowRate;
    2335            0 :             state.dataUnitVentilators->HCoilOn = false;
    2336            0 :             if (unitVent.HotControlNode > 0) {
    2337            0 :                 mdot = 0.0;
    2338            0 :                 PlantUtilities::SetComponentFlowRate(state, mdot, unitVent.HotControlNode, unitVent.HotCoilOutNodeNum, unitVent.HWplantLoc);
    2339              :             }
    2340            0 :             if (unitVent.ColdControlNode > 0) {
    2341            0 :                 mdot = 0.0;
    2342            0 :                 PlantUtilities::SetComponentFlowRate(state, mdot, unitVent.ColdControlNode, unitVent.ColdCoilOutNodeNum, unitVent.CWPlantLoc);
    2343              :             }
    2344              : 
    2345            0 :             if (fanOp == HVAC::FanOp::Cycling) {
    2346            0 :                 CalcUnitVentilatorComponents(state, UnitVentNum, FirstHVACIteration, QUnitOut, fanOp, PartLoadFrac);
    2347            0 :                 if (inletNode.MassFlowRateMax > 0.0) {
    2348            0 :                     unitVent.FanPartLoadRatio = inletNode.MassFlowRate / inletNode.MassFlowRateMax;
    2349              :                 }
    2350              :             } else {
    2351            0 :                 CalcUnitVentilatorComponents(state, UnitVentNum, FirstHVACIteration, QUnitOut);
    2352              :             }
    2353              :         } else { // Unit is on-->this section is intended to control the outside air and the main
    2354              :             // result is to set the outside air flow rate variable OAMassFlowRate
    2355            2 :             int SolFlag = 0; // # of iterations IF positive, -1 means failed to converge, -2 means bounds are incorrect
    2356            2 :             unitVent.FanPartLoadRatio = 1.0;
    2357            2 :             if (state.dataUnitVentilators->QZnReq > HVAC::SmallLoad) { // HEATING MODE
    2358              : 
    2359            2 :                 int ControlNode = unitVent.HotControlNode;
    2360            2 :                 ControlOffset = unitVent.HotControlOffset;
    2361            2 :                 MaxWaterFlow = unitVent.MaxHotWaterFlow;
    2362            2 :                 MinWaterFlow = unitVent.MinHotWaterFlow;
    2363              :                 // On the first HVAC iteration the system values are given to the controller, but after that
    2364              :                 // the demand limits are in place and there needs to be feedback to the Zone Equipment
    2365            2 :                 if (!FirstHVACIteration && unitVent.HCoilType == HeatCoilType::Water) {
    2366            0 :                     MaxWaterFlow = state.dataLoopNodes->Node(ControlNode).MassFlowRateMaxAvail;
    2367            0 :                     MinWaterFlow = state.dataLoopNodes->Node(ControlNode).MassFlowRateMinAvail;
    2368              :                 }
    2369              : 
    2370            2 :                 state.dataUnitVentilators->HCoilOn = true;
    2371              : 
    2372            2 :                 if (outsideAirNode.MassFlowRate > 0.0) {
    2373            2 :                     MinOAFrac = unitVent.minOASched->getCurrentVal() * (unitVent.MinOutAirMassFlow / outsideAirNode.MassFlowRate);
    2374              :                 } else {
    2375            0 :                     MinOAFrac = 0.0;
    2376              :                 }
    2377            2 :                 MinOAFrac = min(1.0, max(0.0, MinOAFrac));
    2378              : 
    2379            2 :                 if ((!unitVent.HCoilPresent) || (unitVent.HCoilSchedValue <= 0.0)) {
    2380              :                     // In heating mode, but there is no coil to provide heating.  This is handled
    2381              :                     // differently than if there was a heating coil present.  Fixed temperature
    2382              :                     // will still try to vary the amount of outside air to meet the desired
    2383              :                     // mixed air temperature, while variable percent will go to full ventilation
    2384              :                     // when it is most advantageous.
    2385              : 
    2386              :                     {
    2387            0 :                         switch (unitVent.OAControlType) {
    2388            0 :                         case OAControl::FixedAmount: {
    2389              :                             // In this control type, the outdoor air flow rate is fixed to the minimum value
    2390              :                             // which is equal to the maximum value, regardless of all the other conditions.
    2391              : 
    2392            0 :                             state.dataUnitVentilators->OAMassFlowRate = MinOAFrac * outsideAirNode.MassFlowRate;
    2393            0 :                         } break;
    2394            0 :                         case OAControl::VariablePercent: {
    2395              :                             // This algorithm is probably a bit simplistic in that it just bounces
    2396              :                             // back and forth between the maximum outside air and the minimum.  In
    2397              :                             // REAL(r64)ity, a system *might* vary between the two based on the load in
    2398              :                             // the zone.
    2399            0 :                             Tinlet = inletNode.Temp;
    2400            0 :                             Toutdoor = outsideAirNode.Temp;
    2401              : 
    2402            0 :                             if (Tinlet >= Toutdoor) {
    2403              : 
    2404            0 :                                 state.dataUnitVentilators->OAMassFlowRate = MinOAFrac * outsideAirNode.MassFlowRate;
    2405              : 
    2406              :                             } else { // Tinlet < Toutdoor
    2407              : 
    2408            0 :                                 MaxOAFrac = unitVent.maxOASched->getCurrentVal();
    2409            0 :                                 state.dataUnitVentilators->OAMassFlowRate = MaxOAFrac * outsideAirNode.MassFlowRate;
    2410              :                             }
    2411            0 :                         } break;
    2412              : 
    2413            0 :                         case OAControl::FixedTemperature: {
    2414              :                             // In heating mode, the outside air for "fixed temperature" attempts
    2415              :                             // to control the outside air fraction so that a desired temperature
    2416              :                             // is met (if possible).  If this desired temperature is between the
    2417              :                             // outside air temperature and the zone air temperature (inlet air
    2418              :                             // temperature), then this is possible.  If not, the control will try
    2419              :                             // to maximize the amount of air coming from the source that is closer
    2420              :                             // in temperature to the desired temperature.
    2421            0 :                             Tdesired = unitVent.tempSched->getCurrentVal();
    2422            0 :                             Tinlet = inletNode.Temp;
    2423            0 :                             Toutdoor = outsideAirNode.Temp;
    2424            0 :                             MaxOAFrac = 1.0;
    2425              : 
    2426            0 :                             if (std::abs(Tinlet - Toutdoor) <= LowTempDiff) { // no difference in indoor and outdoor conditions-->set OA to minimum
    2427            0 :                                 state.dataUnitVentilators->OAMassFlowRate = MinOAFrac * outsideAirNode.MassFlowRate;
    2428            0 :                             } else if (std::abs(MaxOAFrac - MinOAFrac) <= LowOAFracDiff) { // no difference in outside air fractions
    2429            0 :                                 state.dataUnitVentilators->OAMassFlowRate = MinOAFrac * outsideAirNode.MassFlowRate;
    2430            0 :                             } else if (((Tdesired <= Tinlet) && (Tdesired >= Toutdoor)) || ((Tdesired >= Tinlet) && (Tdesired <= Toutdoor))) {
    2431              :                                 // Desired temperature is between the inlet and outdoor temperatures
    2432              :                                 // so vary the flow rate between no outside air and no recirculation air
    2433              :                                 // then applying the maximum and minimum limits the user has scheduled
    2434              :                                 // to make sure too much/little outside air is being introduced
    2435            0 :                                 state.dataUnitVentilators->OAMassFlowRate = ((Tdesired - Tinlet) / (Toutdoor - Tinlet)) * inletNode.MassFlowRate;
    2436            0 :                                 state.dataUnitVentilators->OAMassFlowRate =
    2437            0 :                                     max(state.dataUnitVentilators->OAMassFlowRate, (MinOAFrac * outsideAirNode.MassFlowRate));
    2438            0 :                                 state.dataUnitVentilators->OAMassFlowRate =
    2439            0 :                                     min(state.dataUnitVentilators->OAMassFlowRate, (MaxOAFrac * outsideAirNode.MassFlowRate));
    2440            0 :                             } else if ((Tdesired < Tinlet) && (Tdesired < Toutdoor)) {
    2441              :                                 // Desired temperature is below both the inlet and outdoor temperatures
    2442              :                                 // so use whichever flow rate (max or min) that will get closer
    2443            0 :                                 if (Tinlet < Toutdoor) { // Tinlet closer to Tdesired so use minimum outside air
    2444            0 :                                     state.dataUnitVentilators->OAMassFlowRate = MinOAFrac * outsideAirNode.MassFlowRate;
    2445              :                                 } else { // Toutdoor closer to Tdesired so use maximum outside air
    2446            0 :                                     state.dataUnitVentilators->OAMassFlowRate = MaxOAFrac * outsideAirNode.MassFlowRate;
    2447              :                                 }
    2448            0 :                             } else if ((Tdesired > Tinlet) && (Tdesired > Toutdoor)) {
    2449              :                                 // Desired temperature is above both the inlet and outdoor temperatures
    2450              :                                 // so use whichever flow rate (max or min) that will get closer
    2451            0 :                                 if (Tinlet > Toutdoor) { // Tinlet closer to Tdesired so use minimum outside air
    2452            0 :                                     state.dataUnitVentilators->OAMassFlowRate = MinOAFrac * outsideAirNode.MassFlowRate;
    2453              :                                 } else { // Toutdoor closer to Tdesired so use maximum outside air
    2454            0 :                                     state.dataUnitVentilators->OAMassFlowRate = MaxOAFrac * outsideAirNode.MassFlowRate;
    2455              :                                 }
    2456              :                             } else {
    2457              :                                 // It should NEVER get to this point, but just in case...
    2458            0 :                                 ShowFatalError(state,
    2459            0 :                                                format("ZoneHVAC:UnitVentilator simulation control: illogical condition for {}", unitVent.Name));
    2460              :                             }
    2461            0 :                         } break;
    2462            0 :                         default: {
    2463            0 :                             assert(false);
    2464              :                         } break;
    2465              :                         }
    2466              :                     }
    2467              : 
    2468            0 :                     if (fanOp == HVAC::FanOp::Cycling) {
    2469            0 :                         CalcUnitVentilatorComponents(state, UnitVentNum, FirstHVACIteration, QUnitOut, fanOp, PartLoadFrac);
    2470            0 :                         if (inletNode.MassFlowRateMax > 0.0) {
    2471            0 :                             unitVent.FanPartLoadRatio = inletNode.MassFlowRate / inletNode.MassFlowRateMax;
    2472              :                         }
    2473              :                     } else {
    2474            0 :                         CalcUnitVentilatorComponents(state, UnitVentNum, FirstHVACIteration, QUnitOut);
    2475              :                     }
    2476              : 
    2477              :                 } else { //  Coil/no coil block
    2478              :                     // There is a heating load and there is a heating coil present (presumably).
    2479              :                     // Variable percent will throttle outside air back to the minimum while
    2480              :                     // fixed temperature will still try to vary the outside air amount to meet
    2481              :                     // the desired mixed air temperature.
    2482              : 
    2483              :                     {
    2484            2 :                         switch (unitVent.OAControlType) {
    2485            0 :                         case OAControl::FixedAmount: {
    2486              :                             // In this control type, the outdoor air flow rate is fixed to the maximum value
    2487              :                             // which is equal to the minimum value, regardless of all the other conditions.
    2488            0 :                             state.dataUnitVentilators->OAMassFlowRate = MinOAFrac * outsideAirNode.MassFlowRate;
    2489            0 :                         } break;
    2490            2 :                         case OAControl::VariablePercent: {
    2491              :                             // In heating mode, the outside air for "variable percent" control
    2492              :                             // is set to the minimum value
    2493            2 :                             state.dataUnitVentilators->OAMassFlowRate = MinOAFrac * outsideAirNode.MassFlowRate;
    2494            2 :                         } break;
    2495              : 
    2496            0 :                         case OAControl::FixedTemperature: {
    2497              :                             // In heating mode, the outside air for "fixed temperature" attempts
    2498              :                             // to control the outside air fraction so that a desired temperature
    2499              :                             // is met (if possible).  If this desired temperature is between the
    2500              :                             // outside air temperature and the zone air temperature (inlet air
    2501              :                             // temperature), then this is possible.  If not, the control will try
    2502              :                             // to maximize the amount of air coming from the source that is closer
    2503              :                             // in temperature to the desired temperature.
    2504            0 :                             Tdesired = unitVent.tempSched->getCurrentVal();
    2505            0 :                             Tinlet = inletNode.Temp;
    2506            0 :                             Toutdoor = outsideAirNode.Temp;
    2507            0 :                             MaxOAFrac = 1.0;
    2508              : 
    2509            0 :                             if (std::abs(Tinlet - Toutdoor) <= LowTempDiff) { // no difference in indoor and outdoor conditions-->set OA to minimum
    2510            0 :                                 state.dataUnitVentilators->OAMassFlowRate = MinOAFrac * outsideAirNode.MassFlowRate;
    2511            0 :                             } else if (std::abs(MaxOAFrac - MinOAFrac) <= LowOAFracDiff) { // no difference in outside air fractions
    2512            0 :                                 state.dataUnitVentilators->OAMassFlowRate = MinOAFrac * outsideAirNode.MassFlowRate;
    2513            0 :                             } else if (((Tdesired <= Tinlet) && (Tdesired >= Toutdoor)) || ((Tdesired >= Tinlet) && (Tdesired <= Toutdoor))) {
    2514              :                                 // Desired temperature is between the inlet and outdoor temperatures
    2515              :                                 // so vary the flow rate between no outside air and no recirculation air
    2516              :                                 // then applying the maximum and minimum limits the user has scheduled
    2517              :                                 // to make sure too much/little outside air is being introduced
    2518            0 :                                 state.dataUnitVentilators->OAMassFlowRate = ((Tdesired - Tinlet) / (Toutdoor - Tinlet)) * inletNode.MassFlowRate;
    2519            0 :                                 state.dataUnitVentilators->OAMassFlowRate =
    2520            0 :                                     max(state.dataUnitVentilators->OAMassFlowRate, (MinOAFrac * outsideAirNode.MassFlowRate));
    2521            0 :                                 state.dataUnitVentilators->OAMassFlowRate =
    2522            0 :                                     min(state.dataUnitVentilators->OAMassFlowRate, (MaxOAFrac * outsideAirNode.MassFlowRate));
    2523            0 :                             } else if ((Tdesired < Tinlet) && (Tdesired < Toutdoor)) {
    2524              :                                 // Desired temperature is below both the inlet and outdoor temperatures
    2525              :                                 // so use whichever flow rate (max or min) that will get closer
    2526            0 :                                 if (Tinlet < Toutdoor) { // Tinlet closer to Tdesired so use minimum outside air
    2527            0 :                                     state.dataUnitVentilators->OAMassFlowRate = MinOAFrac * outsideAirNode.MassFlowRate;
    2528              :                                 } else { // Toutdoor closer to Tdesired so use maximum outside air
    2529            0 :                                     state.dataUnitVentilators->OAMassFlowRate = MaxOAFrac * outsideAirNode.MassFlowRate;
    2530              :                                 }
    2531            0 :                             } else if ((Tdesired > Tinlet) && (Tdesired > Toutdoor)) {
    2532              :                                 // Desired temperature is above both the inlet and outdoor temperatures
    2533              :                                 // so use whichever flow rate (max or min) that will get closer
    2534            0 :                                 if (Tinlet > Toutdoor) { // Tinlet closer to Tdesired so use minimum outside air
    2535            0 :                                     state.dataUnitVentilators->OAMassFlowRate = MinOAFrac * outsideAirNode.MassFlowRate;
    2536              :                                 } else { // Toutdoor closer to Tdesired so use maximum outside air
    2537            0 :                                     state.dataUnitVentilators->OAMassFlowRate = MaxOAFrac * outsideAirNode.MassFlowRate;
    2538              :                                 }
    2539              :                             } else {
    2540              :                                 // It should NEVER get to this point, but just in case...
    2541            0 :                                 ShowFatalError(state,
    2542            0 :                                                format("ZoneHVAC:UnitVentilator simulation control: illogical condition for {}", unitVent.Name));
    2543              :                             }
    2544            0 :                         } break;
    2545            0 :                         default: {
    2546            0 :                             assert(false);
    2547              :                         } break;
    2548              :                         }
    2549              :                     }
    2550              : 
    2551            2 :                     if (fanOp == HVAC::FanOp::Cycling) {
    2552              : 
    2553              :                         // Find part load ratio of unit ventilator coils
    2554            2 :                         PartLoadFrac = 0.0;
    2555            2 :                         CalcUnitVentilatorComponents(state, UnitVentNum, FirstHVACIteration, NoOutput, fanOp, PartLoadFrac);
    2556            2 :                         if ((NoOutput - state.dataUnitVentilators->QZnReq) < HVAC::SmallLoad) {
    2557              :                             // Unit ventilator is unable to meet the load with coil off, set PLR = 1
    2558            2 :                             PartLoadFrac = 1.0;
    2559            2 :                             CalcUnitVentilatorComponents(state, UnitVentNum, FirstHVACIteration, FullOutput, fanOp, PartLoadFrac);
    2560            2 :                             if ((FullOutput - state.dataUnitVentilators->QZnReq) > HVAC::SmallLoad) {
    2561              :                                 // Unit ventilator full load capacity is able to meet the load, Find PLR
    2562              :                                 // Tolerance is in fraction of load, MaxIter = 30, SolFalg = # of iterations or error as appropriate
    2563            0 :                                 auto f = [&state, UnitVentNum, FirstHVACIteration, fanOp](Real64 const PartLoadRatio) {
    2564            0 :                                     Real64 QUnitOut = 0.0; // heating/Cooling provided by unit ventilator [watts]
    2565            0 :                                     CalcUnitVentilatorComponents(state, UnitVentNum, FirstHVACIteration, QUnitOut, fanOp, PartLoadRatio);
    2566            0 :                                     if (state.dataUnitVentilators->QZnReq) {
    2567            0 :                                         return (QUnitOut - state.dataUnitVentilators->QZnReq) / state.dataUnitVentilators->QZnReq;
    2568              :                                     } else
    2569            0 :                                         return 0.0;
    2570            0 :                                 };
    2571            0 :                                 General::SolveRoot(state, 0.001, MaxIter, SolFlag, PartLoadFrac, f, 0.0, 1.0);
    2572              :                             }
    2573              :                         }
    2574              : 
    2575            2 :                         CalcUnitVentilatorComponents(state, UnitVentNum, FirstHVACIteration, QUnitOut, fanOp, PartLoadFrac);
    2576            2 :                         unitVent.PartLoadFrac = PartLoadFrac;
    2577            2 :                         unitVent.FanPartLoadRatio = PartLoadFrac;
    2578              : 
    2579              :                     } else { // Not a cycling operating mode
    2580              : 
    2581              :                         {
    2582            0 :                             switch (unitVent.HCoilType) {
    2583            0 :                             case HeatCoilType::Water: {
    2584              :                                 // control water flow to obtain output matching QZnReq
    2585            0 :                                 ControlCompOutput(state,
    2586            0 :                                                   unitVent.Name,
    2587            0 :                                                   state.dataUnitVentilators->cMO_UnitVentilator,
    2588              :                                                   UnitVentNum,
    2589              :                                                   FirstHVACIteration,
    2590            0 :                                                   state.dataUnitVentilators->QZnReq,
    2591              :                                                   ControlNode,
    2592              :                                                   MaxWaterFlow,
    2593              :                                                   MinWaterFlow,
    2594              :                                                   ControlOffset,
    2595            0 :                                                   unitVent.ControlCompTypeNum,
    2596            0 :                                                   unitVent.CompErrIndex,
    2597              :                                                   _,
    2598              :                                                   _,
    2599              :                                                   _,
    2600              :                                                   _,
    2601              :                                                   _,
    2602            0 :                                                   unitVent.HWplantLoc);
    2603            0 :                             } break;
    2604            0 :                             case HeatCoilType::Gas:
    2605              :                             case HeatCoilType::Electric:
    2606              :                             case HeatCoilType::Steam: {
    2607            0 :                                 CalcUnitVentilatorComponents(state, UnitVentNum, FirstHVACIteration, QUnitOut);
    2608            0 :                             } break;
    2609            0 :                             default: {
    2610            0 :                                 assert(false);
    2611              :                             } break;
    2612              :                             }
    2613              :                         }
    2614              :                     }
    2615              :                 } //  Coil/no coil block
    2616              : 
    2617              :             } else { // COOLING MODE
    2618              : 
    2619            0 :                 int ControlNode = unitVent.ColdControlNode;
    2620            0 :                 ControlOffset = unitVent.ColdControlOffset;
    2621            0 :                 MaxWaterFlow = unitVent.MaxColdWaterFlow;
    2622            0 :                 MinWaterFlow = unitVent.MinColdWaterFlow;
    2623              :                 // On the first HVAC iteration the system values are given to the controller, but after that
    2624              :                 // the demand limits are in place and there needs to be feedback to the Zone Equipment
    2625            0 :                 if ((!FirstHVACIteration) && (ControlNode > 0) && (unitVent.CCoilPresent)) {
    2626            0 :                     MaxWaterFlow = state.dataLoopNodes->Node(ControlNode).MassFlowRateMaxAvail;
    2627            0 :                     MinWaterFlow = state.dataLoopNodes->Node(ControlNode).MassFlowRateMinAvail;
    2628              :                 }
    2629            0 :                 state.dataUnitVentilators->HCoilOn = false;
    2630              : 
    2631            0 :                 Tinlet = inletNode.Temp;
    2632            0 :                 Toutdoor = outsideAirNode.Temp;
    2633              : 
    2634            0 :                 if (outsideAirNode.MassFlowRate > 0.0) {
    2635            0 :                     MinOAFrac = unitVent.minOASched->getCurrentVal() * (unitVent.MinOutAirMassFlow / outsideAirNode.MassFlowRate);
    2636              :                 } else {
    2637            0 :                     MinOAFrac = 0.0;
    2638              :                 }
    2639            0 :                 MinOAFrac = min(1.0, max(0.0, MinOAFrac));
    2640              : 
    2641            0 :                 if ((!unitVent.CCoilPresent) || (unitVent.CCoilSchedValue <= 0.0)) {
    2642              :                     // In cooling mode, but there is no coil to provide cooling.  This is handled
    2643              :                     // differently than if there was a cooling coil present.  Fixed temperature
    2644              :                     // will still try to vary the amount of outside air to meet the desired
    2645              :                     // mixed air temperature, while variable percent will go to full ventilation
    2646              :                     // when it is most advantageous.
    2647              :                     {
    2648            0 :                         switch (unitVent.OAControlType) {
    2649            0 :                         case OAControl::FixedAmount: {
    2650              :                             // In this control type, the outdoor air flow rate is fixed to the maximum value
    2651              :                             // which is equal to the minimum value, regardless of all the other conditions.
    2652            0 :                             state.dataUnitVentilators->OAMassFlowRate = MinOAFrac * outsideAirNode.MassFlowRate;
    2653            0 :                         } break;
    2654            0 :                         case OAControl::VariablePercent: {
    2655            0 :                             state.dataUnitVentilators->OAMassFlowRate = SetOAMassFlowRateForCoolingVariablePercent(
    2656            0 :                                 state, UnitVentNum, MinOAFrac, outsideAirNode.MassFlowRate, unitVent.maxOASched->getCurrentVal(), Tinlet, Toutdoor);
    2657            0 :                         } break;
    2658              : 
    2659            0 :                         case OAControl::FixedTemperature: {
    2660              :                             // This is basically the same algorithm as for the heating case...
    2661            0 :                             Tdesired = unitVent.tempSched->getCurrentVal();
    2662            0 :                             MaxOAFrac = 1.0;
    2663              : 
    2664            0 :                             if (std::abs(Tinlet - Toutdoor) <= LowTempDiff) { // no difference in indoor and outdoor conditions-->set OA to minimum
    2665            0 :                                 state.dataUnitVentilators->OAMassFlowRate = MinOAFrac * outsideAirNode.MassFlowRate;
    2666            0 :                             } else if (std::abs(MaxOAFrac - MinOAFrac) <= LowOAFracDiff) { // no difference in outside air fractions
    2667            0 :                                 state.dataUnitVentilators->OAMassFlowRate = MinOAFrac * outsideAirNode.MassFlowRate;
    2668            0 :                             } else if (((Tdesired <= Tinlet) && (Tdesired >= Toutdoor)) || ((Tdesired >= Tinlet) && (Tdesired <= Toutdoor))) {
    2669              :                                 // Desired temperature is between the inlet and outdoor temperatures
    2670              :                                 // so vary the flow rate between no outside air and no recirculation air
    2671              :                                 // then applying the maximum and minimum limits the user has scheduled
    2672              :                                 // to make sure too much/little outside air is being introduced
    2673            0 :                                 state.dataUnitVentilators->OAMassFlowRate = ((Tdesired - Tinlet) / (Toutdoor - Tinlet)) * inletNode.MassFlowRate;
    2674            0 :                                 state.dataUnitVentilators->OAMassFlowRate =
    2675            0 :                                     max(state.dataUnitVentilators->OAMassFlowRate, (MinOAFrac * outsideAirNode.MassFlowRate));
    2676            0 :                                 state.dataUnitVentilators->OAMassFlowRate =
    2677            0 :                                     min(state.dataUnitVentilators->OAMassFlowRate, (MaxOAFrac * outsideAirNode.MassFlowRate));
    2678            0 :                             } else if ((Tdesired < Tinlet) && (Tdesired < Toutdoor)) {
    2679              :                                 // Desired temperature is below both the inlet and outdoor temperatures
    2680              :                                 // so use whichever flow rate (max or min) that will get closer
    2681            0 :                                 if (Tinlet < Toutdoor) { // Tinlet closer to Tdesired so use minimum outside air
    2682            0 :                                     state.dataUnitVentilators->OAMassFlowRate = MinOAFrac * outsideAirNode.MassFlowRate;
    2683              :                                 } else { // Toutdoor closer to Tdesired so use maximum outside air
    2684            0 :                                     state.dataUnitVentilators->OAMassFlowRate = MaxOAFrac * outsideAirNode.MassFlowRate;
    2685              :                                 }
    2686            0 :                             } else if ((Tdesired > Tinlet) && (Tdesired > Toutdoor)) {
    2687              :                                 // Desired temperature is above both the inlet and outdoor temperatures
    2688              :                                 // so use whichever flow rate (max or min) that will get closer
    2689            0 :                                 if (Tinlet > Toutdoor) { // Tinlet closer to Tdesired so use minimum outside air
    2690            0 :                                     state.dataUnitVentilators->OAMassFlowRate = MinOAFrac * outsideAirNode.MassFlowRate;
    2691              :                                 } else { // Toutdoor closer to Tdesired so use maximum outside air
    2692            0 :                                     state.dataUnitVentilators->OAMassFlowRate = MaxOAFrac * outsideAirNode.MassFlowRate;
    2693              :                                 }
    2694              :                             } else {
    2695              :                                 // It should NEVER get to this point, but just in case...
    2696            0 :                                 ShowFatalError(state,
    2697            0 :                                                format("ZoneHVAC:UnitVentilator simulation control: illogical condition for {}", unitVent.Name));
    2698              :                             }
    2699            0 :                         } break;
    2700            0 :                         default: {
    2701            0 :                             assert(false);
    2702              :                         } break;
    2703              :                         }
    2704              :                     }
    2705              : 
    2706            0 :                     if (fanOp == HVAC::FanOp::Cycling) {
    2707            0 :                         CalcUnitVentilatorComponents(state, UnitVentNum, FirstHVACIteration, QUnitOut, fanOp, PartLoadFrac);
    2708            0 :                         if (inletNode.MassFlowRateMax > 0.0) {
    2709            0 :                             unitVent.FanPartLoadRatio = inletNode.MassFlowRate / inletNode.MassFlowRateMax;
    2710              :                         }
    2711              :                     } else {
    2712            0 :                         CalcUnitVentilatorComponents(state, UnitVentNum, FirstHVACIteration, QUnitOut);
    2713              :                     }
    2714              : 
    2715              :                 } else {
    2716              :                     // There is a cooling load and there is a cooling coil present (presumably).
    2717              :                     // Variable percent will throttle outside air back to the minimum while
    2718              :                     // fixed temperature will still try to vary the outside air amount to meet
    2719              :                     // the desired mixed air temperature.
    2720              : 
    2721              :                     {
    2722            0 :                         switch (unitVent.OAControlType) {
    2723            0 :                         case OAControl::FixedAmount: {
    2724              :                             // In this control type, the outdoor air flow rate is fixed to the maximum value
    2725              :                             // which is equal to the minimum value, regardless of all the other conditions.
    2726            0 :                             state.dataUnitVentilators->OAMassFlowRate = MinOAFrac * outsideAirNode.MassFlowRate;
    2727            0 :                         } break;
    2728              : 
    2729            0 :                         case OAControl::VariablePercent: {
    2730            0 :                             state.dataUnitVentilators->OAMassFlowRate = SetOAMassFlowRateForCoolingVariablePercent(
    2731            0 :                                 state, UnitVentNum, MinOAFrac, outsideAirNode.MassFlowRate, unitVent.maxOASched->getCurrentVal(), Tinlet, Toutdoor);
    2732            0 :                         } break;
    2733              : 
    2734            0 :                         case OAControl::FixedTemperature: {
    2735              :                             // This is basically the same algorithm as for the heating case...
    2736            0 :                             Tdesired = unitVent.tempSched->getCurrentVal();
    2737              : 
    2738            0 :                             MaxOAFrac = 1.0;
    2739              : 
    2740            0 :                             if (std::abs(Tinlet - Toutdoor) <= LowTempDiff) { // no difference in indoor and outdoor conditions-->set OA to minimum
    2741            0 :                                 state.dataUnitVentilators->OAMassFlowRate = MinOAFrac * outsideAirNode.MassFlowRate;
    2742            0 :                             } else if (std::abs(MaxOAFrac - MinOAFrac) <= LowOAFracDiff) { // no difference in outside air fractions
    2743            0 :                                 state.dataUnitVentilators->OAMassFlowRate = MinOAFrac * outsideAirNode.MassFlowRate;
    2744            0 :                             } else if (((Tdesired <= Tinlet) && (Tdesired >= Toutdoor)) || ((Tdesired >= Tinlet) && (Tdesired <= Toutdoor))) {
    2745              :                                 // Desired temperature is between the inlet and outdoor temperatures
    2746              :                                 // so vary the flow rate between no outside air and no recirculation air
    2747              :                                 // then applying the maximum and minimum limits the user has scheduled
    2748              :                                 // to make sure too much/little outside air is being introduced
    2749            0 :                                 state.dataUnitVentilators->OAMassFlowRate = ((Tdesired - Tinlet) / (Toutdoor - Tinlet)) * inletNode.MassFlowRate;
    2750            0 :                                 state.dataUnitVentilators->OAMassFlowRate =
    2751            0 :                                     max(state.dataUnitVentilators->OAMassFlowRate, (MinOAFrac * outsideAirNode.MassFlowRate));
    2752            0 :                                 state.dataUnitVentilators->OAMassFlowRate =
    2753            0 :                                     min(state.dataUnitVentilators->OAMassFlowRate, (MaxOAFrac * outsideAirNode.MassFlowRate));
    2754            0 :                             } else if ((Tdesired < Tinlet) && (Tdesired < Toutdoor)) {
    2755              :                                 // Desired temperature is below both the inlet and outdoor temperatures
    2756              :                                 // so use whichever flow rate (max or min) that will get closer
    2757            0 :                                 if (Tinlet < Toutdoor) { // Tinlet closer to Tdesired so use minimum outside air
    2758            0 :                                     state.dataUnitVentilators->OAMassFlowRate = MinOAFrac * outsideAirNode.MassFlowRate;
    2759              :                                 } else { // Toutdoor closer to Tdesired so use maximum outside air
    2760            0 :                                     state.dataUnitVentilators->OAMassFlowRate = MaxOAFrac * outsideAirNode.MassFlowRate;
    2761              :                                 }
    2762            0 :                             } else if ((Tdesired > Tinlet) && (Tdesired > Toutdoor)) {
    2763              :                                 // Desired temperature is above both the inlet and outdoor temperatures
    2764              :                                 // so use whichever flow rate (max or min) that will get closer
    2765            0 :                                 if (Tinlet > Toutdoor) { // Tinlet closer to Tdesired so use minimum outside air
    2766            0 :                                     state.dataUnitVentilators->OAMassFlowRate = MinOAFrac * outsideAirNode.MassFlowRate;
    2767              :                                 } else { // Toutdoor closer to Tdesired so use maximum outside air
    2768            0 :                                     state.dataUnitVentilators->OAMassFlowRate = MaxOAFrac * outsideAirNode.MassFlowRate;
    2769              :                                 }
    2770              :                             } else {
    2771              :                                 // It should NEVER get to this point, but just in case...
    2772            0 :                                 ShowFatalError(state,
    2773            0 :                                                format("ZoneHVAC:UnitVentilator simulation control: illogical condition for {}", unitVent.Name));
    2774              :                             }
    2775            0 :                         } break;
    2776            0 :                         default: {
    2777            0 :                             assert(false);
    2778              :                         } break;
    2779              :                         }
    2780              :                     }
    2781              : 
    2782            0 :                     if (fanOp == HVAC::FanOp::Cycling) {
    2783              : 
    2784            0 :                         state.dataUnitVentilators->HCoilOn = false;
    2785              :                         // Find part load ratio of unit ventilator coils
    2786            0 :                         PartLoadFrac = 0.0;
    2787            0 :                         CalcUnitVentilatorComponents(state, UnitVentNum, FirstHVACIteration, NoOutput, fanOp, PartLoadFrac);
    2788            0 :                         if ((NoOutput - state.dataUnitVentilators->QZnReq) > HVAC::SmallLoad) {
    2789              :                             // Unit ventilator is unable to meet the load with coil off, set PLR = 1
    2790            0 :                             PartLoadFrac = 1.0;
    2791            0 :                             CalcUnitVentilatorComponents(state, UnitVentNum, FirstHVACIteration, FullOutput, fanOp, PartLoadFrac);
    2792            0 :                             if ((FullOutput - state.dataUnitVentilators->QZnReq) < HVAC::SmallLoad) {
    2793              :                                 // Unit ventilator full load capacity is able to meet the load, Find PLR
    2794              :                                 // Tolerance is in fraction of load, MaxIter = 30, SolFalg = # of iterations or error as appropriate
    2795            0 :                                 auto f = [&state, UnitVentNum, FirstHVACIteration, fanOp](Real64 const PartLoadRatio) {
    2796            0 :                                     Real64 QUnitOut = 0.0; // heating/Cooling provided by unit ventilator [watts]
    2797              : 
    2798              :                                     // Convert parameters to usable variables
    2799            0 :                                     CalcUnitVentilatorComponents(state, UnitVentNum, FirstHVACIteration, QUnitOut, fanOp, PartLoadRatio);
    2800            0 :                                     if (state.dataUnitVentilators->QZnReq) {
    2801            0 :                                         return (QUnitOut - state.dataUnitVentilators->QZnReq) / state.dataUnitVentilators->QZnReq;
    2802              :                                     }
    2803            0 :                                     return 0.0;
    2804            0 :                                 };
    2805            0 :                                 General::SolveRoot(state, 0.001, MaxIter, SolFlag, PartLoadFrac, f, 0.0, 1.0);
    2806              :                             }
    2807              :                         }
    2808            0 :                         CalcUnitVentilatorComponents(state, UnitVentNum, FirstHVACIteration, QUnitOut, fanOp, PartLoadFrac);
    2809            0 :                         unitVent.PartLoadFrac = PartLoadFrac;
    2810            0 :                         unitVent.FanPartLoadRatio = PartLoadFrac;
    2811              : 
    2812              :                     } else { // NOT a cycling operating mode
    2813              :                         // control water flow to obtain output matching QZnReq
    2814            0 :                         state.dataUnitVentilators->HCoilOn = false;
    2815            0 :                         ControlCompOutput(state,
    2816            0 :                                           unitVent.Name,
    2817            0 :                                           state.dataUnitVentilators->cMO_UnitVentilator,
    2818              :                                           UnitVentNum,
    2819              :                                           FirstHVACIteration,
    2820            0 :                                           state.dataUnitVentilators->QZnReq,
    2821              :                                           ControlNode,
    2822              :                                           MaxWaterFlow,
    2823              :                                           MinWaterFlow,
    2824              :                                           ControlOffset,
    2825            0 :                                           unitVent.ControlCompTypeNum,
    2826            0 :                                           unitVent.CompErrIndex,
    2827              :                                           _,
    2828              :                                           _,
    2829              :                                           _,
    2830              :                                           _,
    2831              :                                           _,
    2832            0 :                                           unitVent.CWPlantLoc);
    2833              : 
    2834              :                     } // end from IF (fanOp .EQ. HVAC::FanOp::Cycling) THEN
    2835              :                 }
    2836              : 
    2837              :             } // ...end of HEATING/COOLING IF-THEN block
    2838              : 
    2839            2 :             AirMassFlow = outletNode.MassFlowRate;
    2840            2 :             QUnitOut = AirMassFlow *
    2841            2 :                        (Psychrometrics::PsyHFnTdbW(outletNode.Temp, inletNode.HumRat) - Psychrometrics::PsyHFnTdbW(inletNode.Temp, inletNode.HumRat));
    2842              : 
    2843              :         } // ...end of unit ON/OFF IF-THEN block
    2844              : 
    2845            2 :         Real64 QTotUnitOut = AirMassFlow * (outletNode.Enthalpy - inletNode.Enthalpy);
    2846              : 
    2847              :         // Report variables...
    2848            2 :         unitVent.HeatPower = max(0.0, QUnitOut);
    2849            2 :         unitVent.SensCoolPower = std::abs(min(0.0, QUnitOut));
    2850            2 :         unitVent.TotCoolPower = std::abs(min(0.0, QTotUnitOut));
    2851            2 :         unitVent.ElecPower = state.dataFans->fans(unitVent.Fan_Index)->totalPower;
    2852              : 
    2853            2 :         PowerMet = QUnitOut;
    2854            2 :         LatOutputProvided = AirMassFlow * (outletNode.HumRat - inletNode.HumRat); // Latent rate (kg/s), dehumid = negative;
    2855            2 :     }
    2856              : 
    2857            6 :     void CalcUnitVentilatorComponents(EnergyPlusData &state,
    2858              :                                       int const UnitVentNum,                         // Unit index in unit ventilator array
    2859              :                                       bool const FirstHVACIteration,                 // flag for 1st HVAV iteration in the time step
    2860              :                                       Real64 &LoadMet,                               // load met by unit (watts)
    2861              :                                       ObjexxFCL::Optional<HVAC::FanOp const> fanOp,  // Fan Type
    2862              :                                       ObjexxFCL::Optional<Real64 const> PartLoadFrac // Part Load Ratio of coil and fan
    2863              :     )
    2864              :     {
    2865              : 
    2866              :         // SUBROUTINE INFORMATION:
    2867              :         //       AUTHOR         Rick Strand
    2868              :         //       DATE WRITTEN   May 2000
    2869              :         //       MODIFIED       July 2012, Chandan Sharma - FSEC: Added zone sys avail managers
    2870              : 
    2871              :         // PURPOSE OF THIS SUBROUTINE:
    2872              :         // This subroutine launches the individual component simulations.
    2873              :         // This is called either when the unit is off to carry null conditions
    2874              :         // through the unit or during control iterations to continue updating
    2875              :         // what is going on within the unit.
    2876              : 
    2877              :         // METHODOLOGY EMPLOYED:
    2878              :         // Simply calls the different components in order.  Only slight wrinkles
    2879              :         // here are that the unit ventilator has it's own outside air mixer and
    2880              :         // that a cooling coil must be present in order to call a cooling coil
    2881              :         // simulation.  Other than that, the subroutine is very straightforward.
    2882              : 
    2883            6 :         auto &unitVent = state.dataUnitVentilators->UnitVent(UnitVentNum);
    2884              : 
    2885              :         Real64 mdot; // hot water or steam mass flow rate for current time step
    2886              : 
    2887            6 :         auto &inletNode = state.dataLoopNodes->Node(unitVent.AirInNode);
    2888            6 :         auto &outletNode = state.dataLoopNodes->Node(unitVent.AirOutNode);
    2889            6 :         state.dataUnitVentilators->ZoneNode = state.dataZoneEquip->ZoneEquipConfig(unitVent.ZonePtr).ZoneNode;
    2890            6 :         Real64 QCoilReq = state.dataUnitVentilators->QZnReq;
    2891              : 
    2892            6 :         if (fanOp != HVAC::FanOp::Cycling) {
    2893              : 
    2894            0 :             if (unitVent.ATMixerExists) {
    2895            0 :                 state.dataUnitVentilators->ATMixOutNode = unitVent.ATMixerOutNode;
    2896            0 :                 state.dataUnitVentilators->ATMixerPriNode = unitVent.ATMixerPriNode;
    2897            0 :                 if (unitVent.ATMixerType == HVAC::MixerType::InletSide) {
    2898              :                     // set the primary air inlet mass flow rate
    2899            0 :                     state.dataLoopNodes->Node(state.dataUnitVentilators->ATMixerPriNode).MassFlowRate =
    2900            0 :                         min(min(state.dataLoopNodes->Node(state.dataUnitVentilators->ATMixerPriNode).MassFlowRateMaxAvail,
    2901            0 :                                 state.dataUnitVentilators->OAMassFlowRate),
    2902              :                             inletNode.MassFlowRate);
    2903              :                     // now calculate the the mixer outlet conditions (and the secondary air inlet flow rate)
    2904            0 :                     SingleDuct::SimATMixer(state, unitVent.ATMixerName, FirstHVACIteration, unitVent.ATMixerIndex);
    2905              :                 }
    2906              :             } else {
    2907            0 :                 SimUnitVentOAMixer(state, UnitVentNum, fanOp);
    2908              :             }
    2909            0 :             if (unitVent.fanType != HVAC::FanType::SystemModel) {
    2910            0 :                 state.dataFans->fans(unitVent.Fan_Index)->simulate(state, FirstHVACIteration);
    2911              :             } else {
    2912            0 :                 state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0; // used for cycling fan, set to 1.0 to be sure
    2913            0 :                 state.dataFans->fans(unitVent.Fan_Index)->simulate(state, FirstHVACIteration);
    2914              :             }
    2915              : 
    2916            0 :             if (unitVent.CCoilPresent) {
    2917            0 :                 if (unitVent.CCoilType == CoolCoilType::HXAssisted) {
    2918            0 :                     HVACHXAssistedCoolingCoil::SimHXAssistedCoolingCoil(
    2919            0 :                         state, unitVent.CCoilName, FirstHVACIteration, HVAC::CompressorOp::On, 0.0, unitVent.CCoil_Index, HVAC::FanOp::Continuous);
    2920              :                 } else {
    2921            0 :                     WaterCoils::SimulateWaterCoilComponents(state, unitVent.CCoilName, FirstHVACIteration, unitVent.CCoil_Index);
    2922              :                 }
    2923              :             }
    2924              : 
    2925            0 :             if (unitVent.HCoilPresent) {
    2926              : 
    2927              :                 {
    2928            0 :                     switch (unitVent.HCoilType) {
    2929            0 :                     case HeatCoilType::Water: {
    2930            0 :                         WaterCoils::SimulateWaterCoilComponents(state, unitVent.HCoilName, FirstHVACIteration, unitVent.HCoil_Index);
    2931            0 :                     } break;
    2932            0 :                     case HeatCoilType::Steam: {
    2933            0 :                         if (!state.dataUnitVentilators->HCoilOn) {
    2934            0 :                             QCoilReq = 0.0;
    2935              :                         } else {
    2936            0 :                             int HCoilInAirNode = unitVent.FanOutletNode;
    2937            0 :                             Real64 CpAirZn = Psychrometrics::PsyCpAirFnW(state.dataLoopNodes->Node(unitVent.AirInNode).HumRat);
    2938            0 :                             QCoilReq = state.dataUnitVentilators->QZnReq -
    2939            0 :                                        state.dataLoopNodes->Node(HCoilInAirNode).MassFlowRate * CpAirZn *
    2940            0 :                                            (state.dataLoopNodes->Node(HCoilInAirNode).Temp - state.dataLoopNodes->Node(unitVent.AirInNode).Temp);
    2941              :                         }
    2942              : 
    2943            0 :                         if (QCoilReq < 0.0) QCoilReq = 0.0; // a heating coil can only heat, not cool
    2944              : 
    2945            0 :                         SteamCoils::SimulateSteamCoilComponents(state, unitVent.HCoilName, FirstHVACIteration, unitVent.HCoil_Index, QCoilReq);
    2946            0 :                     } break;
    2947            0 :                     case HeatCoilType::Electric:
    2948              :                     case HeatCoilType::Gas: {
    2949            0 :                         if (!state.dataUnitVentilators->HCoilOn) {
    2950            0 :                             QCoilReq = 0.0;
    2951              :                         } else {
    2952            0 :                             int HCoilInAirNode = unitVent.FanOutletNode;
    2953            0 :                             Real64 CpAirZn = Psychrometrics::PsyCpAirFnW(state.dataLoopNodes->Node(unitVent.AirInNode).HumRat);
    2954            0 :                             QCoilReq = state.dataUnitVentilators->QZnReq -
    2955            0 :                                        state.dataLoopNodes->Node(HCoilInAirNode).MassFlowRate * CpAirZn *
    2956            0 :                                            (state.dataLoopNodes->Node(HCoilInAirNode).Temp - state.dataLoopNodes->Node(unitVent.AirInNode).Temp);
    2957              :                         }
    2958              : 
    2959            0 :                         if (QCoilReq < 0.0) QCoilReq = 0.0; // a heating coil can only heat, not cool
    2960              : 
    2961            0 :                         HeatingCoils::SimulateHeatingCoilComponents(state, unitVent.HCoilName, FirstHVACIteration, QCoilReq, unitVent.HCoil_Index);
    2962            0 :                     } break;
    2963            0 :                     default: {
    2964            0 :                         assert(false);
    2965              :                     } break;
    2966              :                     }
    2967              :                 }
    2968              : 
    2969              :             } // (UnitVent(UnitVentNum)%HCoilPresent)
    2970              : 
    2971              :         } else { // Fan is Fan:OnOff and is cycling
    2972              : 
    2973            6 :             inletNode.MassFlowRate = inletNode.MassFlowRateMax * PartLoadFrac;
    2974              :             // Set the fan inlet node maximum available mass flow rates for cycling fans
    2975            6 :             inletNode.MassFlowRateMaxAvail = inletNode.MassFlowRate;
    2976              : 
    2977            6 :             if (unitVent.ATMixerExists) {
    2978            6 :                 state.dataUnitVentilators->ATMixOutNode = unitVent.ATMixerOutNode;
    2979            6 :                 state.dataUnitVentilators->ATMixerPriNode = unitVent.ATMixerPriNode;
    2980            6 :                 if (unitVent.ATMixerType == HVAC::MixerType::InletSide) {
    2981              :                     // set the primary air inlet mass flow rate
    2982            3 :                     state.dataLoopNodes->Node(state.dataUnitVentilators->ATMixerPriNode).MassFlowRate =
    2983            3 :                         min(min(state.dataLoopNodes->Node(state.dataUnitVentilators->ATMixerPriNode).MassFlowRateMaxAvail,
    2984            3 :                                 state.dataUnitVentilators->OAMassFlowRate),
    2985              :                             inletNode.MassFlowRate);
    2986              :                     // now calculate the mixer outlet conditions (and the secondary air inlet flow rate)
    2987            3 :                     SingleDuct::SimATMixer(state, unitVent.ATMixerName, FirstHVACIteration, unitVent.ATMixerIndex);
    2988              :                 }
    2989              :             } else {
    2990            0 :                 SimUnitVentOAMixer(state, UnitVentNum, fanOp);
    2991              :             }
    2992              : 
    2993            6 :             state.dataFans->fans(unitVent.Fan_Index)->simulate(state, FirstHVACIteration, _, _);
    2994              : 
    2995            6 :             if (unitVent.CCoilPresent) {
    2996              : 
    2997              :                 // where is mdot set ?
    2998            0 :                 CalcMdotCCoilCycFan(state, mdot, QCoilReq, state.dataUnitVentilators->QZnReq, UnitVentNum, PartLoadFrac);
    2999            0 :                 PlantUtilities::SetComponentFlowRate(state, mdot, unitVent.ColdControlNode, unitVent.ColdCoilOutNodeNum, unitVent.CWPlantLoc);
    3000              : 
    3001            0 :                 if (unitVent.CCoilType == CoolCoilType::HXAssisted) {
    3002            0 :                     HVACHXAssistedCoolingCoil::SimHXAssistedCoolingCoil(
    3003            0 :                         state, unitVent.CCoilName, FirstHVACIteration, HVAC::CompressorOp::On, PartLoadFrac, unitVent.CCoil_Index, fanOp);
    3004              :                 } else {
    3005            0 :                     WaterCoils::SimulateWaterCoilComponents(
    3006            0 :                         state, unitVent.CCoilName, FirstHVACIteration, unitVent.CCoil_Index, QCoilReq, fanOp, PartLoadFrac);
    3007              :                 }
    3008              :             }
    3009              : 
    3010            6 :             if (unitVent.HCoilPresent) {
    3011              : 
    3012              :                 {
    3013            6 :                     switch (unitVent.HCoilType) {
    3014            0 :                     case HeatCoilType::Water: {
    3015            0 :                         if (!state.dataUnitVentilators->HCoilOn) {
    3016            0 :                             QCoilReq = 0.0;
    3017            0 :                             mdot = 0.0;
    3018              :                         } else {
    3019            0 :                             int HCoilInAirNode = unitVent.FanOutletNode;
    3020            0 :                             Real64 CpAirZn = Psychrometrics::PsyCpAirFnW(state.dataLoopNodes->Node(unitVent.AirInNode).HumRat);
    3021            0 :                             QCoilReq = state.dataUnitVentilators->QZnReq -
    3022            0 :                                        state.dataLoopNodes->Node(HCoilInAirNode).MassFlowRate * CpAirZn *
    3023            0 :                                            (state.dataLoopNodes->Node(HCoilInAirNode).Temp - state.dataLoopNodes->Node(unitVent.AirInNode).Temp);
    3024            0 :                             mdot = unitVent.MaxHotWaterFlow * PartLoadFrac;
    3025              :                         }
    3026              : 
    3027            0 :                         if (QCoilReq < 0.0) QCoilReq = 0.0; // a heating coil can only heat, not cool
    3028            0 :                         PlantUtilities::SetComponentFlowRate(state, mdot, unitVent.HotControlNode, unitVent.HotCoilOutNodeNum, unitVent.HWplantLoc);
    3029            0 :                         WaterCoils::SimulateWaterCoilComponents(
    3030            0 :                             state, unitVent.HCoilName, FirstHVACIteration, unitVent.HCoil_Index, QCoilReq, fanOp, PartLoadFrac);
    3031            0 :                     } break;
    3032            0 :                     case HeatCoilType::Steam: {
    3033            0 :                         if (!state.dataUnitVentilators->HCoilOn) {
    3034            0 :                             QCoilReq = 0.0;
    3035            0 :                             mdot = 0.0;
    3036              :                         } else {
    3037            0 :                             int HCoilInAirNode = unitVent.FanOutletNode;
    3038            0 :                             Real64 CpAirZn = Psychrometrics::PsyCpAirFnW(state.dataLoopNodes->Node(unitVent.AirInNode).HumRat);
    3039            0 :                             QCoilReq = state.dataUnitVentilators->QZnReq -
    3040            0 :                                        state.dataLoopNodes->Node(HCoilInAirNode).MassFlowRate * CpAirZn *
    3041            0 :                                            (state.dataLoopNodes->Node(HCoilInAirNode).Temp - state.dataLoopNodes->Node(unitVent.AirInNode).Temp);
    3042            0 :                             mdot = unitVent.MaxHotSteamFlow * PartLoadFrac;
    3043              :                         }
    3044              : 
    3045            0 :                         if (QCoilReq < 0.0) QCoilReq = 0.0;
    3046            0 :                         PlantUtilities::SetComponentFlowRate(state, mdot, unitVent.HotControlNode, unitVent.HotCoilOutNodeNum, unitVent.HWplantLoc);
    3047            0 :                         SteamCoils::SimulateSteamCoilComponents(
    3048            0 :                             state, unitVent.HCoilName, FirstHVACIteration, unitVent.HCoil_Index, QCoilReq, _, fanOp, PartLoadFrac);
    3049            0 :                     } break;
    3050            6 :                     case HeatCoilType::Electric:
    3051              :                     case HeatCoilType::Gas: {
    3052            6 :                         if (!state.dataUnitVentilators->HCoilOn) {
    3053            0 :                             QCoilReq = 0.0;
    3054              :                         } else {
    3055            6 :                             int HCoilInAirNode = unitVent.FanOutletNode;
    3056            6 :                             Real64 CpAirZn = Psychrometrics::PsyCpAirFnW(state.dataLoopNodes->Node(unitVent.AirInNode).HumRat);
    3057            6 :                             QCoilReq = state.dataUnitVentilators->QZnReq -
    3058            6 :                                        state.dataLoopNodes->Node(HCoilInAirNode).MassFlowRate * CpAirZn *
    3059            6 :                                            (state.dataLoopNodes->Node(HCoilInAirNode).Temp - state.dataLoopNodes->Node(unitVent.AirInNode).Temp);
    3060              :                         }
    3061            6 :                         if (QCoilReq < 0.0) QCoilReq = 0.0;
    3062           12 :                         HeatingCoils::SimulateHeatingCoilComponents(
    3063            6 :                             state, unitVent.HCoilName, FirstHVACIteration, QCoilReq, unitVent.HCoil_Index, _, _, fanOp, PartLoadFrac);
    3064            6 :                     } break;
    3065            0 :                     default: {
    3066            0 :                         assert(false);
    3067              :                     } break;
    3068              :                     }
    3069              :                 }
    3070              :             }
    3071              :         }
    3072            6 :         Real64 AirMassFlow = outletNode.MassFlowRate;
    3073              :         // calculate delivered load
    3074            6 :         if (unitVent.ATMixerExists) {
    3075            6 :             auto &ATMixOutNode(state.dataLoopNodes->Node(state.dataUnitVentilators->ATMixOutNode));
    3076            6 :             auto &ATMixerPriNode(state.dataLoopNodes->Node(state.dataUnitVentilators->ATMixerPriNode));
    3077            6 :             if (unitVent.ATMixerType == HVAC::MixerType::SupplySide) {
    3078              :                 // set the primary air inlet mass flow rate
    3079            3 :                 ATMixerPriNode.MassFlowRate = min(ATMixerPriNode.MassFlowRateMaxAvail, state.dataUnitVentilators->OAMassFlowRate);
    3080              :                 // now calculate the the mixer outlet conditions (and the secondary air inlet flow rate)
    3081            3 :                 SingleDuct::SimATMixer(state, unitVent.ATMixerName, FirstHVACIteration, unitVent.ATMixerIndex);
    3082            3 :                 Real64 SpecHumMin = min(ATMixOutNode.HumRat, inletNode.HumRat); // (kg moisture / kg moist air)
    3083            6 :                 LoadMet = ATMixOutNode.MassFlowRate *
    3084            3 :                           (Psychrometrics::PsyHFnTdbW(ATMixOutNode.Temp, SpecHumMin) - Psychrometrics::PsyHFnTdbW(inletNode.Temp, SpecHumMin));
    3085              :             } else {
    3086              :                 // ATM Mixer on inlet side
    3087            3 :                 auto &zoneNode(state.dataLoopNodes->Node(state.dataUnitVentilators->ZoneNode));
    3088            3 :                 LoadMet = AirMassFlow *
    3089            3 :                           (Psychrometrics::PsyHFnTdbW(outletNode.Temp, zoneNode.HumRat) - Psychrometrics::PsyHFnTdbW(zoneNode.Temp, zoneNode.HumRat));
    3090              :             }
    3091              :         } else {
    3092            0 :             LoadMet = AirMassFlow *
    3093            0 :                       (Psychrometrics::PsyHFnTdbW(outletNode.Temp, inletNode.HumRat) - Psychrometrics::PsyHFnTdbW(inletNode.Temp, inletNode.HumRat));
    3094              :         }
    3095            6 :     }
    3096              : 
    3097            0 :     void SimUnitVentOAMixer(EnergyPlusData &state,
    3098              :                             int const UnitVentNum,  // Unit index in unit ventilator array
    3099              :                             HVAC::FanOp const fanOp // unit ventilator fan operating mode
    3100              :     )
    3101              :     {
    3102              : 
    3103              :         // SUBROUTINE INFORMATION:
    3104              :         //       AUTHOR         Rick Strand
    3105              :         //       DATE WRITTEN   May 2000
    3106              : 
    3107              :         // PURPOSE OF THIS SUBROUTINE:
    3108              :         // This responsibility of this subroutine is to set the air flow rates
    3109              :         // through the mixing box portion of the unit ventilator and then perform
    3110              :         // an energy balance to arrive at outlet conditions which then would
    3111              :         // serve as inlet conditions to the coils (or outlet conditions for
    3112              :         // the device).  There is some question as to whether this needs to be
    3113              :         // called every time the coils and fan are called since how the fans and
    3114              :         // coil operate won't presumable change how the mixer operates.  The
    3115              :         // method in which this routine is called is slightly cleaner though
    3116              :         // from a code readability standpoint though less efficient.
    3117              : 
    3118              :         // METHODOLOGY EMPLOYED:
    3119              :         // The OAMassFlowRate has already been calculated in the main control
    3120              :         // algorithm.  Use this flow rate to establish all of the other flow
    3121              :         // rates and perform an energy balance on the mixing of the return and
    3122              :         // outdoor air streams.
    3123              : 
    3124            0 :         auto &unitVent = state.dataUnitVentilators->UnitVent(UnitVentNum);
    3125            0 :         auto &airRelNode = state.dataLoopNodes->Node(unitVent.AirReliefNode);
    3126            0 :         auto const &inletNode = state.dataLoopNodes->Node(unitVent.AirInNode);
    3127            0 :         auto &OAMixOutNode = state.dataLoopNodes->Node(unitVent.OAMixerOutNode);
    3128            0 :         auto &outsideAirNode = state.dataLoopNodes->Node(unitVent.OutsideAirNode);
    3129            0 :         Real64 OutAirMassFlowRate = state.dataUnitVentilators->OAMassFlowRate;
    3130              : 
    3131              :         // Limit the outdoor air mass flow rate if cycling fan
    3132            0 :         if (fanOp == HVAC::FanOp::Cycling) {
    3133            0 :             OutAirMassFlowRate = min(state.dataUnitVentilators->OAMassFlowRate, inletNode.MassFlowRate);
    3134              :         }
    3135              : 
    3136              :         // "Resolve" the air flow rates...
    3137            0 :         outsideAirNode.MassFlowRate = OutAirMassFlowRate;
    3138            0 :         outsideAirNode.MassFlowRateMinAvail = OutAirMassFlowRate;
    3139            0 :         outsideAirNode.MassFlowRateMaxAvail = OutAirMassFlowRate;
    3140              : 
    3141            0 :         airRelNode.MassFlowRate = OutAirMassFlowRate;
    3142            0 :         airRelNode.MassFlowRateMinAvail = OutAirMassFlowRate;
    3143            0 :         airRelNode.MassFlowRateMaxAvail = OutAirMassFlowRate;
    3144              : 
    3145            0 :         OAMixOutNode.MassFlowRate = inletNode.MassFlowRate;
    3146            0 :         OAMixOutNode.MassFlowRateMinAvail = inletNode.MassFlowRate;
    3147            0 :         OAMixOutNode.MassFlowRateMaxAvail = inletNode.MassFlowRate;
    3148              : 
    3149              :         // "Inlet" conditions for InletNode and OutsideAirNode have already
    3150              :         // been set elsewhere so we just need to set the "outlet" conditions
    3151            0 :         airRelNode.Temp = inletNode.Temp;
    3152            0 :         airRelNode.Press = inletNode.Press;
    3153            0 :         airRelNode.HumRat = inletNode.HumRat;
    3154            0 :         airRelNode.Enthalpy = inletNode.Enthalpy;
    3155              : 
    3156            0 :         Real64 OAFraction = 0.0; // Outside air fraction of inlet air
    3157            0 :         if (inletNode.MassFlowRate > 0.0) {
    3158            0 :             OAFraction = outsideAirNode.MassFlowRate / inletNode.MassFlowRate;
    3159              :         }
    3160              : 
    3161              :         // Perform an energy and moisture mass balance on the mixing portion of the unit ventilator
    3162            0 :         OAMixOutNode.Enthalpy = OAFraction * outsideAirNode.Enthalpy + (1.0 - OAFraction) * inletNode.Enthalpy;
    3163            0 :         OAMixOutNode.HumRat = OAFraction * outsideAirNode.HumRat + (1.0 - OAFraction) * inletNode.HumRat;
    3164              : 
    3165              :         // Find the other key state points based on calculated conditions
    3166            0 :         OAMixOutNode.Temp = Psychrometrics::PsyTdbFnHW(OAMixOutNode.Enthalpy, OAMixOutNode.HumRat);
    3167            0 :         OAMixOutNode.Press = inletNode.Press;
    3168              : 
    3169            0 :         if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    3170            0 :             airRelNode.CO2 = inletNode.CO2;
    3171            0 :             OAMixOutNode.CO2 = OAFraction * outsideAirNode.CO2 + (1.0 - OAFraction) * inletNode.CO2;
    3172              :         }
    3173            0 :         if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    3174            0 :             airRelNode.GenContam = inletNode.GenContam;
    3175            0 :             OAMixOutNode.GenContam = OAFraction * outsideAirNode.GenContam + (1.0 - OAFraction) * inletNode.GenContam;
    3176              :         }
    3177            0 :     }
    3178              : 
    3179            2 :     void ReportUnitVentilator(EnergyPlusData &state, int const UnitVentNum) // Unit index in unit ventilator array
    3180              :     {
    3181              : 
    3182              :         // SUBROUTINE INFORMATION:
    3183              :         //       AUTHOR         Rick Strand
    3184              :         //       DATE WRITTEN   May 2000
    3185              : 
    3186              :         // Using/Aliasing
    3187            2 :         Real64 TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
    3188            2 :         auto &unitVent = state.dataUnitVentilators->UnitVent(UnitVentNum);
    3189              : 
    3190            2 :         unitVent.HeatEnergy = unitVent.HeatPower * TimeStepSysSec;
    3191            2 :         unitVent.SensCoolEnergy = unitVent.SensCoolPower * TimeStepSysSec;
    3192            2 :         unitVent.TotCoolEnergy = unitVent.TotCoolPower * TimeStepSysSec;
    3193            2 :         unitVent.ElecEnergy = unitVent.ElecPower * TimeStepSysSec;
    3194              : 
    3195            2 :         if (unitVent.FirstPass) { // reset sizing flags so other zone equipment can size normally
    3196            2 :             if (!state.dataGlobal->SysSizingCalc) {
    3197            0 :                 DataSizing::resetHVACSizingGlobals(state, state.dataSize->CurZoneEqNum, 0, unitVent.FirstPass);
    3198              :             }
    3199              :         }
    3200            2 :     }
    3201              : 
    3202            1 :     int GetUnitVentilatorOutAirNode(EnergyPlusData &state, int const UnitVentNum)
    3203              :     {
    3204              : 
    3205              :         // FUNCTION INFORMATION:
    3206              :         //       AUTHOR         B Griffith
    3207              :         //       DATE WRITTEN   Dec  2006
    3208              : 
    3209              :         int GetUnitVentilatorOutAirNode;
    3210              : 
    3211            1 :         if (state.dataUnitVentilators->GetUnitVentilatorInputFlag) {
    3212            0 :             GetUnitVentilatorInput(state);
    3213            0 :             state.dataUnitVentilators->GetUnitVentilatorInputFlag = false;
    3214              :         }
    3215              : 
    3216            1 :         GetUnitVentilatorOutAirNode = 0;
    3217            1 :         if (UnitVentNum > 0 && UnitVentNum <= state.dataUnitVentilators->NumOfUnitVents) {
    3218            1 :             GetUnitVentilatorOutAirNode = state.dataUnitVentilators->UnitVent(UnitVentNum).OutsideAirNode;
    3219              :         }
    3220              : 
    3221            1 :         return GetUnitVentilatorOutAirNode;
    3222              :     }
    3223              : 
    3224            1 :     int GetUnitVentilatorZoneInletAirNode(EnergyPlusData &state, int const UnitVentNum)
    3225              :     {
    3226              : 
    3227              :         // FUNCTION INFORMATION:
    3228              :         //       AUTHOR         B Griffith
    3229              :         //       DATE WRITTEN   Dec  2006
    3230              : 
    3231              :         int GetUnitVentilatorZoneInletAirNode;
    3232              : 
    3233            1 :         if (state.dataUnitVentilators->GetUnitVentilatorInputFlag) {
    3234            0 :             GetUnitVentilatorInput(state);
    3235            0 :             state.dataUnitVentilators->GetUnitVentilatorInputFlag = false;
    3236              :         }
    3237              : 
    3238            1 :         GetUnitVentilatorZoneInletAirNode = 0;
    3239            1 :         if (UnitVentNum > 0 && UnitVentNum <= state.dataUnitVentilators->NumOfUnitVents) {
    3240            1 :             GetUnitVentilatorZoneInletAirNode = state.dataUnitVentilators->UnitVent(UnitVentNum).AirOutNode;
    3241              :         }
    3242              : 
    3243            1 :         return GetUnitVentilatorZoneInletAirNode;
    3244              :     }
    3245              : 
    3246            1 :     int GetUnitVentilatorMixedAirNode(EnergyPlusData &state, int const UnitVentNum)
    3247              :     {
    3248              : 
    3249              :         // FUNCTION INFORMATION:
    3250              :         //       AUTHOR         B Griffith
    3251              :         //       DATE WRITTEN   Dec  2006
    3252              : 
    3253              :         int GetUnitVentilatorMixedAirNode;
    3254              : 
    3255            1 :         if (state.dataUnitVentilators->GetUnitVentilatorInputFlag) {
    3256            0 :             GetUnitVentilatorInput(state);
    3257            0 :             state.dataUnitVentilators->GetUnitVentilatorInputFlag = false;
    3258              :         }
    3259              : 
    3260            1 :         GetUnitVentilatorMixedAirNode = 0;
    3261            1 :         if (UnitVentNum > 0 && UnitVentNum <= state.dataUnitVentilators->NumOfUnitVents) {
    3262            1 :             GetUnitVentilatorMixedAirNode = state.dataUnitVentilators->UnitVent(UnitVentNum).OAMixerOutNode;
    3263              :         }
    3264              : 
    3265            1 :         return GetUnitVentilatorMixedAirNode;
    3266              :     }
    3267              : 
    3268            1 :     int GetUnitVentilatorReturnAirNode(EnergyPlusData &state, int const UnitVentNum)
    3269              :     {
    3270              : 
    3271              :         // FUNCTION INFORMATION:
    3272              :         //       AUTHOR         B Griffith
    3273              :         //       DATE WRITTEN   Dec  2006
    3274              : 
    3275              :         int GetUnitVentilatorReturnAirNode;
    3276              : 
    3277            1 :         if (state.dataUnitVentilators->GetUnitVentilatorInputFlag) {
    3278            0 :             GetUnitVentilatorInput(state);
    3279            0 :             state.dataUnitVentilators->GetUnitVentilatorInputFlag = false;
    3280              :         }
    3281              : 
    3282            1 :         GetUnitVentilatorReturnAirNode = 0;
    3283            1 :         if (UnitVentNum > 0 && UnitVentNum <= state.dataUnitVentilators->NumOfUnitVents) {
    3284            1 :             GetUnitVentilatorReturnAirNode = state.dataUnitVentilators->UnitVent(UnitVentNum).AirInNode;
    3285              :         }
    3286              : 
    3287            1 :         return GetUnitVentilatorReturnAirNode;
    3288              :     }
    3289              : 
    3290            1 :     int getUnitVentilatorIndex(EnergyPlusData &state, std::string_view CompName)
    3291              :     {
    3292            1 :         if (state.dataUnitVentilators->GetUnitVentilatorInputFlag) {
    3293            0 :             GetUnitVentilatorInput(state);
    3294            0 :             state.dataUnitVentilators->GetUnitVentilatorInputFlag = false;
    3295              :         }
    3296            1 :         for (int UnitVentNum = 1; UnitVentNum <= state.dataUnitVentilators->NumOfUnitVents; ++UnitVentNum) {
    3297            1 :             if (Util::SameString(state.dataUnitVentilators->UnitVent(UnitVentNum).Name, CompName)) {
    3298            1 :                 return UnitVentNum;
    3299              :             }
    3300              :         }
    3301              : 
    3302            0 :         return 0;
    3303              :     }
    3304              : 
    3305            7 :     Real64 SetOAMassFlowRateForCoolingVariablePercent(EnergyPlusData &state,
    3306              :                                                       int const UnitVentNum,     // Unit Ventilator index
    3307              :                                                       Real64 const MinOAFrac,    // Minimum Outside Air Fraction
    3308              :                                                       Real64 const MassFlowRate, // Design Outside Air Mass Flow Rate
    3309              :                                                       Real64 const MaxOAFrac,    // Maximum Outside Air Fraction
    3310              :                                                       Real64 const Tinlet,       // Inlet Temperature to Unit or Zone Temperature
    3311              :                                                       Real64 const Toutdoor      // Outdoor Air Temperature
    3312              :     )
    3313              :     {
    3314              : 
    3315            7 :         Real64 ActualOAMassFlowRate = 0.0; // Result or return value
    3316              : 
    3317            7 :         if (Tinlet <= Toutdoor) {
    3318              : 
    3319            1 :             ActualOAMassFlowRate = MinOAFrac * MassFlowRate;
    3320              : 
    3321              :         } else { // Tinlet > Toutdoor
    3322              :             // Use cooler outside air to provide "free" cooling without over-cooling.
    3323              :             // First, use a simple load equals mass flow times Cp time Delta T equation to find OA Mass Flow Rate.
    3324              :             // This must include the enthalpy difference across the fan.  Otherwise, this will potentially put a
    3325              :             // small load on the cooling coil (if it exists) or will leave a small load that is not met when it could be.
    3326              :             // Then, limit the OA Mass Flow Rate between the MinOA flow and the MaxOA flow.
    3327              : 
    3328            6 :             auto &unitVent = state.dataUnitVentilators->UnitVent(UnitVentNum);
    3329            6 :             Real64 EnthDiffAcrossFan(0.0); // Temperature difference across the fan
    3330            6 :             if (!unitVent.ATMixerExists) {
    3331            4 :                 EnthDiffAcrossFan =
    3332            4 :                     state.dataLoopNodes->Node(unitVent.FanOutletNode).Enthalpy - state.dataLoopNodes->Node(unitVent.OAMixerOutNode).Enthalpy;
    3333              :             } else {
    3334            2 :                 if (unitVent.ATMixerType == HVAC::MixerType::InletSide) {
    3335            1 :                     EnthDiffAcrossFan =
    3336            1 :                         state.dataLoopNodes->Node(unitVent.FanOutletNode).Enthalpy - state.dataLoopNodes->Node(unitVent.ATMixerOutNode).Enthalpy;
    3337              :                 }
    3338            2 :                 if (unitVent.ATMixerType == HVAC::MixerType::SupplySide) {
    3339            1 :                     EnthDiffAcrossFan =
    3340            1 :                         state.dataLoopNodes->Node(unitVent.FanOutletNode).Enthalpy - state.dataLoopNodes->Node(unitVent.AirInNode).Enthalpy;
    3341              :                 }
    3342              :             }
    3343              : 
    3344            6 :             ActualOAMassFlowRate = (std::abs(state.dataUnitVentilators->QZnReq) + (MassFlowRate * std::abs(EnthDiffAcrossFan))) /
    3345            6 :                                    (Psychrometrics::PsyCpAirFnW(state.dataEnvrn->OutHumRat) * (Tinlet - Toutdoor));
    3346              : 
    3347            6 :             ActualOAMassFlowRate = max(ActualOAMassFlowRate, (MinOAFrac * MassFlowRate));
    3348            6 :             ActualOAMassFlowRate = min(ActualOAMassFlowRate, (MaxOAFrac * MassFlowRate));
    3349              :         }
    3350              : 
    3351            7 :         return ActualOAMassFlowRate;
    3352              :     }
    3353              : 
    3354            4 :     void CalcMdotCCoilCycFan(EnergyPlusData &state,
    3355              :                              Real64 &mdot,              // mass flow rate
    3356              :                              Real64 &QCoilReq,          // Remaining load to cooling coil
    3357              :                              Real64 const QZnReq,       // Zone load to setpoint
    3358              :                              int const UnitVentNum,     // Unit Ventilator index
    3359              :                              Real64 const PartLoadRatio // Part load ratio for unit ventilator
    3360              :     )
    3361              :     {
    3362              : 
    3363            4 :         if (QZnReq >= 0.0) { // Heating requested so no cooling coil needed
    3364            2 :             mdot = 0.0;
    3365              :         } else { // Cooling so set first guess at flow rate
    3366            2 :             mdot = state.dataUnitVentilators->UnitVent(UnitVentNum).MaxColdWaterFlow * PartLoadRatio;
    3367              :         }
    3368              : 
    3369              :         // Check to see what outside air will do, "turn off" cooling coil if OA can handle the load
    3370            4 :         int CCoilInAirNode = state.dataUnitVentilators->UnitVent(UnitVentNum).FanOutletNode;
    3371            4 :         int AirInNode = state.dataUnitVentilators->UnitVent(UnitVentNum).AirInNode;
    3372            4 :         Real64 CpAirZn = Psychrometrics::PsyCpAirFnW(state.dataLoopNodes->Node(AirInNode).HumRat);
    3373            4 :         QCoilReq = QZnReq - state.dataLoopNodes->Node(CCoilInAirNode).MassFlowRate * CpAirZn *
    3374            4 :                                 (state.dataLoopNodes->Node(CCoilInAirNode).Temp - state.dataLoopNodes->Node(AirInNode).Temp);
    3375            4 :         if (QCoilReq > -HVAC::SmallLoad) {
    3376            2 :             QCoilReq = 0.0;
    3377            2 :             mdot = 0.0;
    3378              :         }
    3379            4 :     }
    3380              : 
    3381              : } // namespace UnitVentilator
    3382              : 
    3383              : } // namespace EnergyPlus
        

Generated by: LCOV version 2.0-1