LCOV - code coverage report
Current view: top level - EnergyPlus - UnitVentilator.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 1007 1909 52.8 %
Date: 2023-01-17 19:17:23 Functions: 18 18 100.0 %

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

Generated by: LCOV version 1.13