LCOV - code coverage report
Current view: top level - EnergyPlus - UnitVentilator.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 995 1896 52.5 %
Date: 2024-08-23 23:50:59 Functions: 16 17 94.1 %

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

Generated by: LCOV version 1.14