LCOV - code coverage report
Current view: top level - EnergyPlus - UnitVentilator.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 51.9 % 1870 971
Test Date: 2025-06-02 07:23:51 Functions: 94.1 % 17 16

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

Generated by: LCOV version 2.0-1