LCOV - code coverage report
Current view: top level - EnergyPlus - Fans.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 1019 1372 74.3 %
Date: 2023-01-17 19:17:23 Functions: 26 29 89.7 %

          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/Fmath.hh>
      53             : 
      54             : // EnergyPlus Headers
      55             : #include <AirflowNetwork/Solver.hpp>
      56             : #include <EnergyPlus/Autosizing/SystemAirFlowSizing.hh>
      57             : #include <EnergyPlus/BranchNodeConnections.hh>
      58             : #include <EnergyPlus/CurveManager.hh>
      59             : #include <EnergyPlus/Data/EnergyPlusData.hh>
      60             : #include <EnergyPlus/DataContaminantBalance.hh>
      61             : #include <EnergyPlus/DataEnvironment.hh>
      62             : #include <EnergyPlus/DataHeatBalance.hh>
      63             : #include <EnergyPlus/DataIPShortCuts.hh>
      64             : #include <EnergyPlus/DataLoopNode.hh>
      65             : #include <EnergyPlus/DataPrecisionGlobals.hh>
      66             : #include <EnergyPlus/DataSizing.hh>
      67             : #include <EnergyPlus/DataZoneEquipment.hh>
      68             : #include <EnergyPlus/EMSManager.hh>
      69             : #include <EnergyPlus/Fans.hh>
      70             : #include <EnergyPlus/FaultsManager.hh>
      71             : #include <EnergyPlus/GlobalNames.hh>
      72             : #include <EnergyPlus/HVACFan.hh>
      73             : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      74             : #include <EnergyPlus/NodeInputManager.hh>
      75             : #include <EnergyPlus/OutputProcessor.hh>
      76             : #include <EnergyPlus/OutputReportPredefined.hh>
      77             : #include <EnergyPlus/Psychrometrics.hh>
      78             : #include <EnergyPlus/ScheduleManager.hh>
      79             : #include <EnergyPlus/UtilityRoutines.hh>
      80             : 
      81             : namespace EnergyPlus::Fans {
      82             : // Module containing the fan simulation routines
      83             : 
      84             : // MODULE INFORMATION:
      85             : //       AUTHOR         Richard J. Liesen
      86             : //       DATE WRITTEN   April 1998
      87             : //       MODIFIED       Shirey, May 2001
      88             : //                      Griffith, May 2009, EMS changes
      89             : //                      Craig Wray 22Aug2010 Added Fan Component Model
      90             : //       RE-ENGINEERED  na
      91             : 
      92             : // PURPOSE OF THIS MODULE:
      93             : // To encapsulate the data and algorithms required to
      94             : // manage the Fan System Component
      95             : 
      96             : // Using/Aliasing
      97             : using namespace DataLoopNode;
      98             : using DataHVACGlobals::cFanTypes;
      99             : using DataHVACGlobals::FanType_ComponentModel;
     100             : using DataHVACGlobals::FanType_SimpleConstVolume;
     101             : using DataHVACGlobals::FanType_SimpleOnOff;
     102             : using DataHVACGlobals::FanType_SimpleVAV;
     103             : using DataHVACGlobals::FanType_ZoneExhaust;
     104             : using DataHVACGlobals::FixedMin;
     105             : using DataHVACGlobals::MinFrac;
     106             : using DataHVACGlobals::SmallAirVolFlow;
     107             : using EMSManager::ManageEMS;
     108             : using Psychrometrics::PsyCpAirFnW;
     109             : using Psychrometrics::PsyRhoAirFnPbTdbW;
     110             : using Psychrometrics::PsyTdbFnHW;
     111             : using namespace ScheduleManager;
     112             : 
     113             : constexpr std::array<std::string_view, static_cast<int>(AvailabilityManagerCoupling::Num)> couplingsUC = {"COUPLED", "DECOUPLED"};
     114             : 
     115   138406141 : void SimulateFanComponents(EnergyPlusData &state,
     116             :                            std::string_view const CompName,
     117             :                            bool const FirstHVACIteration,
     118             :                            int &CompIndex,
     119             :                            Optional<Real64 const> SpeedRatio,
     120             :                            Optional_bool_const ZoneCompTurnFansOn,  // Turn fans ON signal from ZoneHVAC component
     121             :                            Optional_bool_const ZoneCompTurnFansOff, // Turn Fans OFF signal from ZoneHVAC component
     122             :                            Optional<Real64 const> PressureRise      // Pressure difference to use for DeltaPress
     123             : )
     124             : {
     125             : 
     126             :     // SUBROUTINE INFORMATION:
     127             :     //       AUTHOR         Richard Liesen
     128             :     //       DATE WRITTEN   February 1998
     129             :     //       MODIFIED       Chandan Sharma, March 2011 - FSEC: Added logic for ZoneHVAC sys avail managers
     130             :     //       RE-ENGINEERED  na
     131             : 
     132             :     // PURPOSE OF THIS SUBROUTINE:
     133             :     // This subroutine manages Fan component simulation.
     134             : 
     135             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     136             :     int FanNum; // current fan number
     137             : 
     138   138406141 :     auto &Fan(state.dataFans->Fan);
     139             : 
     140             :     // Obtains and Allocates fan related parameters from input file
     141   138406141 :     if (state.dataFans->GetFanInputFlag) { // First time subroutine has been entered
     142          28 :         GetFanInput(state);
     143          28 :         state.dataFans->GetFanInputFlag = false;
     144             :     }
     145             : 
     146   138406141 :     if (CompIndex == 0) {
     147         951 :         FanNum = UtilityRoutines::FindItemInList(CompName, Fan, &FanEquipConditions::FanName);
     148         951 :         if (FanNum == 0) {
     149           0 :             ShowFatalError(state, "SimulateFanComponents: Fan not found=" + std::string{CompName});
     150             :         }
     151         951 :         CompIndex = FanNum;
     152             :     } else {
     153   138405190 :         FanNum = CompIndex;
     154   138405190 :         if (FanNum > state.dataFans->NumFans || FanNum < 1) {
     155           0 :             ShowFatalError(
     156             :                 state,
     157           0 :                 format(
     158           0 :                     "SimulateFanComponents: Invalid CompIndex passed={}, Number of Fans={}, Fan name={}", FanNum, state.dataFans->NumFans, CompName));
     159             :         }
     160   138405190 :         if (state.dataFans->CheckEquipName(FanNum)) {
     161        1943 :             if (!CompName.empty() && CompName != Fan(FanNum).FanName) {
     162           0 :                 ShowFatalError(state,
     163           0 :                                format("SimulateFanComponents: Invalid CompIndex passed={}, Fan name={}, stored Fan Name for that index={}",
     164             :                                       FanNum,
     165             :                                       CompName,
     166           0 :                                       Fan(FanNum).FanName));
     167             :             }
     168        1943 :             state.dataFans->CheckEquipName(FanNum) = false;
     169             :         }
     170             :     }
     171             : 
     172   138406141 :     state.dataFans->LocalTurnFansOn = false;
     173   138406141 :     state.dataFans->LocalTurnFansOff = false;
     174             :     // With the correct FanNum Initialize
     175   138406141 :     InitFan(state, FanNum, FirstHVACIteration); // Initialize all fan related parameters
     176             : 
     177   138406141 :     if (present(ZoneCompTurnFansOn) && present(ZoneCompTurnFansOff)) {
     178             :         // Set module-level logic flags equal to ZoneCompTurnFansOn and ZoneCompTurnFansOff values passed into this routine
     179             :         // for ZoneHVAC components with system availability managers defined.
     180             :         // The module-level flags get used in the other subroutines (e.g., SimSimpleFan,SimVariableVolumeFan and SimOnOffFan)
     181    18797476 :         state.dataFans->LocalTurnFansOn = ZoneCompTurnFansOn;
     182    18797476 :         state.dataFans->LocalTurnFansOff = ZoneCompTurnFansOff;
     183             :     } else {
     184             :         // Set module-level logic flags equal to the global LocalTurnFansOn and LocalTurnFansOff variables for all other cases.
     185   119608665 :         state.dataFans->LocalTurnFansOn = state.dataHVACGlobal->TurnFansOn;
     186   119608665 :         state.dataFans->LocalTurnFansOff = state.dataHVACGlobal->TurnFansOff;
     187             :     }
     188             : 
     189             :     // Calculate the Correct Fan Model with the current FanNum
     190   138406141 :     if (Fan(FanNum).FanType_Num == FanType_SimpleConstVolume) {
     191    11873687 :         SimSimpleFan(state, FanNum);
     192   126532454 :     } else if (Fan(FanNum).FanType_Num == FanType_SimpleVAV) {
     193    17080494 :         if (present(PressureRise)) {
     194       28596 :             SimVariableVolumeFan(state, FanNum, PressureRise);
     195             :         } else {
     196    17051898 :             SimVariableVolumeFan(state, FanNum);
     197             :         }
     198   109451960 :     } else if (Fan(FanNum).FanType_Num == FanType_SimpleOnOff) {
     199   107762510 :         SimOnOffFan(state, FanNum, SpeedRatio);
     200     1689450 :     } else if (Fan(FanNum).FanType_Num == FanType_ZoneExhaust) {
     201     1632157 :         SimZoneExhaustFan(state, FanNum);
     202       57293 :     } else if (Fan(FanNum).FanType_Num == FanType_ComponentModel) {
     203       57293 :         SimComponentModelFan(state, FanNum);
     204             :     }
     205             : 
     206             :     // Update the current fan to the outlet nodes
     207   138406141 :     UpdateFan(state, FanNum);
     208             : 
     209             :     // Report the current fan
     210   138406141 :     ReportFan(state, FanNum);
     211   138406141 : }
     212             : 
     213             : // Get Input Section of the Module
     214             : //******************************************************************************
     215             : 
     216         546 : void GetFanInput(EnergyPlusData &state)
     217             : {
     218             : 
     219             :     // SUBROUTINE INFORMATION:
     220             :     //       AUTHOR         Richard Liesen
     221             :     //       DATE WRITTEN   April 1998
     222             :     //       MODIFIED       Shirey, May 2001
     223             :     //       RE-ENGINEERED  na
     224             : 
     225             :     // PURPOSE OF THIS SUBROUTINE:
     226             :     // Obtains input data for fans and stores it in fan data structures
     227             : 
     228             :     // Using/Aliasing
     229             :     using BranchNodeConnections::TestCompSet;
     230             :     using Curve::GetCurveIndex;
     231             :     using NodeInputManager::GetOnlySingleNode;
     232             : 
     233             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     234             :     int FanNum;       // The fan that you are currently loading input into
     235             :     int NumSimpFan;   // The number of Simple Const Vol Fans
     236             :     int NumVarVolFan; // The number of Simple Variable Vol Fans
     237             :     int NumOnOff;     // The number of Simple on-off Fans
     238             :     int NumZoneExhFan;
     239             :     int SimpFanNum;
     240             :     int OnOffFanNum;
     241             :     int VarVolFanNum;
     242             :     int ExhFanNum;
     243             :     int NVPerfNum;
     244             :     bool NVPerfFanFound;
     245             :     int NumCompModelFan;
     246             :     int CompModelFanNum;
     247             :     int NumAlphas;
     248             :     int NumNums;
     249             :     int checkNum;
     250             :     int IOStat;
     251         546 :     bool ErrorsFound(false);                                        // If errors detected in input
     252             :     static constexpr std::string_view RoutineName("GetFanInput: "); // include trailing blank space
     253        1092 :     Array1D_string cAlphaFieldNames;
     254        1092 :     Array1D_string cNumericFieldNames;
     255        1092 :     Array1D_bool lNumericFieldBlanks;
     256        1092 :     Array1D_bool lAlphaFieldBlanks;
     257        1092 :     Array1D_string cAlphaArgs;
     258        1092 :     Array1D<Real64> rNumericArgs;
     259        1092 :     std::string cCurrentModuleObject;
     260             :     int NumParams;
     261             :     int MaxAlphas;
     262             :     int MaxNumbers;
     263             : 
     264         546 :     auto &Fan(state.dataFans->Fan);
     265         546 :     auto &FanNumericFields(state.dataFans->FanNumericFields);
     266         546 :     auto &UniqueFanNames(state.dataFans->UniqueFanNames);
     267         546 :     auto &NightVentPerf(state.dataFans->NightVentPerf);
     268             : 
     269         546 :     state.dataFans->GetFanInputFlag = false;
     270             : 
     271         546 :     MaxAlphas = 0;
     272         546 :     MaxNumbers = 0;
     273         546 :     NumSimpFan = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Fan:ConstantVolume");
     274         546 :     if (NumSimpFan > 0) {
     275         200 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, "Fan:ConstantVolume", NumParams, NumAlphas, NumNums);
     276         200 :         MaxAlphas = max(MaxAlphas, NumAlphas);
     277         200 :         MaxNumbers = max(MaxNumbers, NumNums);
     278             :     }
     279         546 :     NumVarVolFan = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Fan:VariableVolume");
     280         546 :     if (NumVarVolFan > 0) {
     281         250 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, "Fan:VariableVolume", NumParams, NumAlphas, NumNums);
     282         250 :         MaxAlphas = max(MaxAlphas, NumAlphas);
     283         250 :         MaxNumbers = max(MaxNumbers, NumNums);
     284             :     }
     285         546 :     NumOnOff = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Fan:OnOff");
     286         546 :     if (NumOnOff > 0) {
     287         167 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, "Fan:OnOff", NumParams, NumAlphas, NumNums);
     288         167 :         MaxAlphas = max(MaxAlphas, NumAlphas);
     289         167 :         MaxNumbers = max(MaxNumbers, NumNums);
     290             :     }
     291         546 :     NumZoneExhFan = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Fan:ZoneExhaust");
     292         546 :     if (NumZoneExhFan > 0) {
     293          43 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, "Fan:ZoneExhaust", NumParams, NumAlphas, NumNums);
     294          43 :         MaxAlphas = max(MaxAlphas, NumAlphas);
     295          43 :         MaxNumbers = max(MaxNumbers, NumNums);
     296             :     }
     297         546 :     state.dataFans->NumNightVentPerf = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "FanPerformance:NightVentilation");
     298         546 :     if (state.dataFans->NumNightVentPerf > 0) {
     299           0 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, "FanPerformance:NightVentilation", NumParams, NumAlphas, NumNums);
     300           0 :         MaxAlphas = max(MaxAlphas, NumAlphas);
     301           0 :         MaxNumbers = max(MaxNumbers, NumNums);
     302             :     }
     303             : 
     304         546 :     NumCompModelFan = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Fan:ComponentModel");
     305         546 :     if (NumCompModelFan > 0) {
     306           4 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, "Fan:ComponentModel", NumParams, NumAlphas, NumNums);
     307           4 :         MaxAlphas = max(MaxAlphas, NumAlphas);
     308           4 :         MaxNumbers = max(MaxNumbers, NumNums);
     309             :     }
     310             : 
     311         546 :     cAlphaArgs.allocate(MaxAlphas);
     312         546 :     cAlphaFieldNames.allocate(MaxAlphas);
     313         546 :     lAlphaFieldBlanks.dimension(MaxAlphas, false);
     314         546 :     cNumericFieldNames.allocate(MaxNumbers);
     315         546 :     lNumericFieldBlanks.dimension(MaxNumbers, false);
     316         546 :     rNumericArgs.dimension(MaxNumbers, 0.0);
     317             : 
     318         546 :     state.dataFans->NumFans = NumSimpFan + NumVarVolFan + NumZoneExhFan + NumOnOff + NumCompModelFan;
     319         546 :     if (state.dataFans->NumFans > 0) {
     320         546 :         Fan.allocate(state.dataFans->NumFans);
     321         546 :         FanNumericFields.allocate(state.dataFans->NumFans);
     322         546 :         UniqueFanNames.reserve(state.dataFans->NumFans);
     323             :     }
     324         546 :     state.dataFans->CheckEquipName.dimension(state.dataFans->NumFans, true);
     325             : 
     326        1050 :     for (SimpFanNum = 1; SimpFanNum <= NumSimpFan; ++SimpFanNum) {
     327         504 :         FanNum = SimpFanNum;
     328         504 :         cCurrentModuleObject = "Fan:ConstantVolume";
     329         504 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     330             :                                                                  cCurrentModuleObject,
     331             :                                                                  SimpFanNum,
     332             :                                                                  cAlphaArgs,
     333             :                                                                  NumAlphas,
     334             :                                                                  rNumericArgs,
     335             :                                                                  NumNums,
     336             :                                                                  IOStat,
     337             :                                                                  lNumericFieldBlanks,
     338             :                                                                  lAlphaFieldBlanks,
     339             :                                                                  cAlphaFieldNames,
     340             :                                                                  cNumericFieldNames);
     341             : 
     342         504 :         FanNumericFields(FanNum).FieldNames.allocate(MaxNumbers);
     343         504 :         FanNumericFields(FanNum).FieldNames = "";
     344         504 :         FanNumericFields(FanNum).FieldNames = cNumericFieldNames;
     345             : 
     346         504 :         GlobalNames::VerifyUniqueInterObjectName(state, UniqueFanNames, cAlphaArgs(1), cCurrentModuleObject, cAlphaFieldNames(1), ErrorsFound);
     347         504 :         Fan(FanNum).FanName = cAlphaArgs(1);
     348         504 :         Fan(FanNum).FanType = cCurrentModuleObject;
     349         504 :         Fan(FanNum).AvailSchedName = cAlphaArgs(2);
     350         504 :         if (lAlphaFieldBlanks(2)) {
     351           0 :             Fan(FanNum).AvailSchedPtrNum = DataGlobalConstants::ScheduleAlwaysOn;
     352             :         } else {
     353         504 :             Fan(FanNum).AvailSchedPtrNum = GetScheduleIndex(state, cAlphaArgs(2));
     354         504 :             if (Fan(FanNum).AvailSchedPtrNum == 0) {
     355           0 :                 ShowSevereError(state,
     356           0 :                                 std::string{RoutineName} + cCurrentModuleObject + ": invalid " + cAlphaFieldNames(2) + " entered =" + cAlphaArgs(2) +
     357           0 :                                     " for " + cAlphaFieldNames(1) + '=' + cAlphaArgs(1));
     358           0 :                 ErrorsFound = true;
     359             :             }
     360             :         }
     361         504 :         Fan(FanNum).FanType_Num = FanType_SimpleConstVolume;
     362             : 
     363         504 :         Fan(FanNum).FanEff = rNumericArgs(1);
     364         504 :         Fan(FanNum).DeltaPress = rNumericArgs(2);
     365         504 :         Fan(FanNum).MaxAirFlowRate = rNumericArgs(3);
     366         504 :         if (Fan(FanNum).MaxAirFlowRate == 0.0) {
     367           0 :             ShowWarningError(state,
     368           0 :                              cCurrentModuleObject + "=\"" + Fan(FanNum).FanName +
     369             :                                  "\" has specified 0.0 max air flow rate. It will not be used in the simulation.");
     370             :         }
     371         504 :         Fan(FanNum).MaxAirFlowRateIsAutosizable = true;
     372         504 :         Fan(FanNum).MotEff = rNumericArgs(4);
     373         504 :         Fan(FanNum).MotInAirFrac = rNumericArgs(5);
     374         504 :         Fan(FanNum).MinAirFlowRate = 0.0;
     375             : 
     376         504 :         Fan(FanNum).InletNodeNum = GetOnlySingleNode(state,
     377         504 :                                                      cAlphaArgs(3),
     378             :                                                      ErrorsFound,
     379             :                                                      DataLoopNode::ConnectionObjectType::FanConstantVolume,
     380         504 :                                                      cAlphaArgs(1),
     381             :                                                      DataLoopNode::NodeFluidType::Air,
     382             :                                                      DataLoopNode::ConnectionType::Inlet,
     383             :                                                      NodeInputManager::CompFluidStream::Primary,
     384         504 :                                                      ObjectIsNotParent);
     385         504 :         Fan(FanNum).OutletNodeNum = GetOnlySingleNode(state,
     386         504 :                                                       cAlphaArgs(4),
     387             :                                                       ErrorsFound,
     388             :                                                       DataLoopNode::ConnectionObjectType::FanConstantVolume,
     389         504 :                                                       cAlphaArgs(1),
     390             :                                                       DataLoopNode::NodeFluidType::Air,
     391             :                                                       DataLoopNode::ConnectionType::Outlet,
     392             :                                                       NodeInputManager::CompFluidStream::Primary,
     393         504 :                                                       ObjectIsNotParent);
     394             : 
     395         504 :         if (NumAlphas > 4) {
     396         182 :             Fan(FanNum).EndUseSubcategoryName = cAlphaArgs(5);
     397             :         } else {
     398         322 :             Fan(FanNum).EndUseSubcategoryName = "General";
     399             :         }
     400             : 
     401         504 :         TestCompSet(state, cCurrentModuleObject, cAlphaArgs(1), cAlphaArgs(3), cAlphaArgs(4), "Air Nodes");
     402             : 
     403             :     } // end Number of Simple FAN Loop
     404             : 
     405         968 :     for (VarVolFanNum = 1; VarVolFanNum <= NumVarVolFan; ++VarVolFanNum) {
     406         422 :         FanNum = NumSimpFan + VarVolFanNum;
     407         422 :         cCurrentModuleObject = "Fan:VariableVolume";
     408         422 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     409             :                                                                  cCurrentModuleObject,
     410             :                                                                  VarVolFanNum,
     411             :                                                                  cAlphaArgs,
     412             :                                                                  NumAlphas,
     413             :                                                                  rNumericArgs,
     414             :                                                                  NumNums,
     415             :                                                                  IOStat,
     416             :                                                                  lNumericFieldBlanks,
     417             :                                                                  lAlphaFieldBlanks,
     418             :                                                                  cAlphaFieldNames,
     419             :                                                                  cNumericFieldNames);
     420             : 
     421         422 :         FanNumericFields(FanNum).FieldNames.allocate(MaxNumbers);
     422         422 :         FanNumericFields(FanNum).FieldNames = "";
     423         422 :         FanNumericFields(FanNum).FieldNames = cNumericFieldNames;
     424             : 
     425         422 :         GlobalNames::VerifyUniqueInterObjectName(state, UniqueFanNames, cAlphaArgs(1), cCurrentModuleObject, cAlphaFieldNames(1), ErrorsFound);
     426         422 :         Fan(FanNum).FanName = cAlphaArgs(1);
     427         422 :         Fan(FanNum).FanType = cCurrentModuleObject;
     428         422 :         Fan(FanNum).AvailSchedName = cAlphaArgs(2);
     429         422 :         if (lAlphaFieldBlanks(2)) {
     430           0 :             Fan(FanNum).AvailSchedPtrNum = DataGlobalConstants::ScheduleAlwaysOn;
     431             :         } else {
     432         422 :             Fan(FanNum).AvailSchedPtrNum = GetScheduleIndex(state, cAlphaArgs(2));
     433         422 :             if (Fan(FanNum).AvailSchedPtrNum == 0) {
     434           0 :                 ShowSevereError(state,
     435           0 :                                 std::string{RoutineName} + cCurrentModuleObject + ": invalid " + cAlphaFieldNames(2) + " entered =" + cAlphaArgs(2) +
     436           0 :                                     " for " + cAlphaFieldNames(1) + '=' + cAlphaArgs(1));
     437           0 :                 ErrorsFound = true;
     438             :             }
     439             :         }
     440         422 :         Fan(FanNum).FanType_Num = FanType_SimpleVAV;
     441             : 
     442         422 :         Fan(FanNum).FanEff = rNumericArgs(1);
     443         422 :         Fan(FanNum).DeltaPress = rNumericArgs(2);
     444         422 :         Fan(FanNum).MaxAirFlowRate = rNumericArgs(3);
     445         422 :         if (Fan(FanNum).MaxAirFlowRate == 0.0) {
     446           0 :             ShowWarningError(state,
     447           0 :                              cCurrentModuleObject + "=\"" + Fan(FanNum).FanName +
     448             :                                  "\" has specified 0.0 max air flow rate. It will not be used in the simulation.");
     449             :         }
     450         422 :         Fan(FanNum).MaxAirFlowRateIsAutosizable = true;
     451         422 :         if (UtilityRoutines::SameString(cAlphaArgs(3), "Fraction")) {
     452         254 :             Fan(FanNum).FanMinAirFracMethod = MinFrac;
     453         168 :         } else if (UtilityRoutines::SameString(cAlphaArgs(3), "FixedFlowRate")) {
     454         168 :             Fan(FanNum).FanMinAirFracMethod = FixedMin;
     455             :         } else {
     456           0 :             ShowSevereError(state, cAlphaFieldNames(3) + " should be either Fraction or FixedFlowRate.");
     457           0 :             ShowContinueError(state, "Occurs in " + Fan(FanNum).FanName + " object.");
     458           0 :             ErrorsFound = true;
     459             :         }
     460             :         //        Fan(FanNum)%MinAirFlowRate= rNumericArgs(4)
     461         422 :         Fan(FanNum).FanMinFrac = rNumericArgs(4);
     462         422 :         Fan(FanNum).FanFixedMin = rNumericArgs(5);
     463         422 :         Fan(FanNum).MotEff = rNumericArgs(6);
     464         422 :         Fan(FanNum).MotInAirFrac = rNumericArgs(7);
     465         422 :         Fan(FanNum).FanCoeff(1) = rNumericArgs(8);
     466         422 :         Fan(FanNum).FanCoeff(2) = rNumericArgs(9);
     467         422 :         Fan(FanNum).FanCoeff(3) = rNumericArgs(10);
     468         422 :         Fan(FanNum).FanCoeff(4) = rNumericArgs(11);
     469         422 :         Fan(FanNum).FanCoeff(5) = rNumericArgs(12);
     470         422 :         if (Fan(FanNum).FanCoeff(1) == 0.0 && Fan(FanNum).FanCoeff(2) == 0.0 && Fan(FanNum).FanCoeff(3) == 0.0 && Fan(FanNum).FanCoeff(4) == 0.0 &&
     471           0 :             Fan(FanNum).FanCoeff(5) == 0.0) {
     472           0 :             ShowWarningError(state, "Fan Coefficients are all zero.  No Fan power will be reported.");
     473           0 :             ShowContinueError(state, "For " + cCurrentModuleObject + ", Fan=" + cAlphaArgs(1));
     474             :         }
     475         422 :         Fan(FanNum).InletNodeNum = GetOnlySingleNode(state,
     476         422 :                                                      cAlphaArgs(4),
     477             :                                                      ErrorsFound,
     478             :                                                      DataLoopNode::ConnectionObjectType::FanVariableVolume,
     479         422 :                                                      cAlphaArgs(1),
     480             :                                                      DataLoopNode::NodeFluidType::Air,
     481             :                                                      DataLoopNode::ConnectionType::Inlet,
     482             :                                                      NodeInputManager::CompFluidStream::Primary,
     483         422 :                                                      ObjectIsNotParent);
     484         422 :         Fan(FanNum).OutletNodeNum = GetOnlySingleNode(state,
     485         422 :                                                       cAlphaArgs(5),
     486             :                                                       ErrorsFound,
     487             :                                                       DataLoopNode::ConnectionObjectType::FanVariableVolume,
     488         422 :                                                       cAlphaArgs(1),
     489             :                                                       DataLoopNode::NodeFluidType::Air,
     490             :                                                       DataLoopNode::ConnectionType::Outlet,
     491             :                                                       NodeInputManager::CompFluidStream::Primary,
     492         422 :                                                       ObjectIsNotParent);
     493             : 
     494         422 :         if (NumAlphas > 5) {
     495         180 :             Fan(FanNum).EndUseSubcategoryName = cAlphaArgs(6);
     496             :         } else {
     497         242 :             Fan(FanNum).EndUseSubcategoryName = "General";
     498             :         }
     499             : 
     500         422 :         TestCompSet(state, cCurrentModuleObject, cAlphaArgs(1), cAlphaArgs(4), cAlphaArgs(5), "Air Nodes");
     501             : 
     502             :     } // end Number of Variable Volume FAN Loop
     503             : 
     504         687 :     for (ExhFanNum = 1; ExhFanNum <= NumZoneExhFan; ++ExhFanNum) {
     505         141 :         FanNum = NumSimpFan + NumVarVolFan + ExhFanNum;
     506         141 :         cCurrentModuleObject = "Fan:ZoneExhaust";
     507         141 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     508             :                                                                  cCurrentModuleObject,
     509             :                                                                  ExhFanNum,
     510             :                                                                  cAlphaArgs,
     511             :                                                                  NumAlphas,
     512             :                                                                  rNumericArgs,
     513             :                                                                  NumNums,
     514             :                                                                  IOStat,
     515             :                                                                  lNumericFieldBlanks,
     516             :                                                                  lAlphaFieldBlanks,
     517             :                                                                  cAlphaFieldNames,
     518             :                                                                  cNumericFieldNames);
     519             : 
     520         141 :         FanNumericFields(FanNum).FieldNames.allocate(MaxNumbers);
     521         141 :         FanNumericFields(FanNum).FieldNames = "";
     522         141 :         FanNumericFields(FanNum).FieldNames = cNumericFieldNames;
     523             : 
     524         141 :         GlobalNames::VerifyUniqueInterObjectName(state, UniqueFanNames, cAlphaArgs(1), cCurrentModuleObject, cAlphaFieldNames(1), ErrorsFound);
     525         141 :         Fan(FanNum).FanName = cAlphaArgs(1);
     526         141 :         Fan(FanNum).FanType = cCurrentModuleObject;
     527         141 :         Fan(FanNum).AvailSchedName = cAlphaArgs(2);
     528         141 :         if (lAlphaFieldBlanks(2)) {
     529           0 :             Fan(FanNum).AvailSchedPtrNum = DataGlobalConstants::ScheduleAlwaysOn;
     530             :         } else {
     531         141 :             Fan(FanNum).AvailSchedPtrNum = GetScheduleIndex(state, cAlphaArgs(2));
     532         141 :             if (Fan(FanNum).AvailSchedPtrNum == 0) {
     533           0 :                 ShowSevereError(state,
     534           0 :                                 std::string{RoutineName} + cCurrentModuleObject + ": invalid " + cAlphaFieldNames(2) + " entered =" + cAlphaArgs(2) +
     535           0 :                                     " for " + cAlphaFieldNames(1) + '=' + cAlphaArgs(1));
     536           0 :                 ErrorsFound = true;
     537             :             } else {
     538         141 :                 if (HasFractionalScheduleValue(state, Fan(FanNum).AvailSchedPtrNum)) {
     539           0 :                     ShowWarningError(state,
     540           0 :                                      cCurrentModuleObject + "=\"" + Fan(FanNum).FanName + "\" has fractional values in Schedule=" + cAlphaArgs(2) +
     541             :                                          ". Only 0.0 in the schedule value turns the fan off.");
     542             :                 }
     543             :             }
     544             :         }
     545         141 :         Fan(FanNum).FanType_Num = FanType_ZoneExhaust;
     546             : 
     547         141 :         Fan(FanNum).FanEff = rNumericArgs(1);
     548         141 :         Fan(FanNum).DeltaPress = rNumericArgs(2);
     549         141 :         Fan(FanNum).MaxAirFlowRate = rNumericArgs(3);
     550         141 :         Fan(FanNum).MaxAirFlowRateIsAutosizable = false;
     551         141 :         Fan(FanNum).MotEff = 1.0;
     552         141 :         Fan(FanNum).MotInAirFrac = 1.0;
     553         141 :         Fan(FanNum).MinAirFlowRate = 0.0;
     554         141 :         Fan(FanNum).RhoAirStdInit = state.dataEnvrn->StdRhoAir;
     555         141 :         Fan(FanNum).MaxAirMassFlowRate = Fan(FanNum).MaxAirFlowRate * Fan(FanNum).RhoAirStdInit;
     556             : 
     557         141 :         if (Fan(FanNum).MaxAirFlowRate == 0.0) {
     558           0 :             ShowWarningError(state,
     559           0 :                              cCurrentModuleObject + "=\"" + Fan(FanNum).FanName +
     560             :                                  "\" has specified 0.0 max air flow rate. It will not be used in the simulation.");
     561             :         }
     562             : 
     563         141 :         Fan(FanNum).InletNodeNum = GetOnlySingleNode(state,
     564         141 :                                                      cAlphaArgs(3),
     565             :                                                      ErrorsFound,
     566             :                                                      DataLoopNode::ConnectionObjectType::FanZoneExhaust,
     567         141 :                                                      cAlphaArgs(1),
     568             :                                                      DataLoopNode::NodeFluidType::Air,
     569             :                                                      DataLoopNode::ConnectionType::Inlet,
     570             :                                                      NodeInputManager::CompFluidStream::Primary,
     571         141 :                                                      ObjectIsNotParent);
     572         141 :         Fan(FanNum).OutletNodeNum = GetOnlySingleNode(state,
     573         141 :                                                       cAlphaArgs(4),
     574             :                                                       ErrorsFound,
     575             :                                                       DataLoopNode::ConnectionObjectType::FanZoneExhaust,
     576         141 :                                                       cAlphaArgs(1),
     577             :                                                       DataLoopNode::NodeFluidType::Air,
     578             :                                                       DataLoopNode::ConnectionType::Outlet,
     579             :                                                       NodeInputManager::CompFluidStream::Primary,
     580         141 :                                                       ObjectIsNotParent);
     581             : 
     582         141 :         if (NumAlphas > 4 && !lAlphaFieldBlanks(5)) {
     583         137 :             Fan(FanNum).EndUseSubcategoryName = cAlphaArgs(5);
     584             :         } else {
     585           4 :             Fan(FanNum).EndUseSubcategoryName = "General";
     586             :         }
     587             : 
     588         141 :         if (NumAlphas > 5 && !lAlphaFieldBlanks(6)) {
     589           0 :             Fan(FanNum).FlowFractSchedNum = GetScheduleIndex(state, cAlphaArgs(6));
     590           0 :             if (Fan(FanNum).FlowFractSchedNum == 0) {
     591           0 :                 ShowSevereError(state,
     592           0 :                                 std::string{RoutineName} + cCurrentModuleObject + ": invalid " + cAlphaFieldNames(6) + " entered =" + cAlphaArgs(6) +
     593           0 :                                     " for " + cAlphaFieldNames(1) + '=' + cAlphaArgs(1));
     594           0 :                 ErrorsFound = true;
     595           0 :             } else if (Fan(FanNum).FlowFractSchedNum > 0) {
     596           0 :                 if (!CheckScheduleValueMinMax(state, Fan(FanNum).FlowFractSchedNum, ">=", 0.0, "<=", 1.0)) {
     597           0 :                     ShowSevereError(state,
     598           0 :                                     std::string{RoutineName} + cCurrentModuleObject + ": invalid " + cAlphaFieldNames(6) + " for " +
     599           0 :                                         cAlphaFieldNames(1) + '=' + cAlphaArgs(1));
     600           0 :                     ShowContinueError(state, "Error found in " + cAlphaFieldNames(6) + " = " + cAlphaArgs(6));
     601           0 :                     ShowContinueError(state, "Schedule values must be (>=0., <=1.)");
     602           0 :                     ErrorsFound = true;
     603             :                 }
     604             :             }
     605             :         } else {
     606         141 :             Fan(FanNum).FlowFractSchedNum = DataGlobalConstants::ScheduleAlwaysOn;
     607             :         }
     608             : 
     609         141 :         if (NumAlphas > 6 && !lAlphaFieldBlanks(7)) {
     610           6 :             Fan(FanNum).AvailManagerMode = static_cast<AvailabilityManagerCoupling>(getEnumerationValue(couplingsUC, cAlphaArgs(7)));
     611           6 :             if (Fan(FanNum).AvailManagerMode == AvailabilityManagerCoupling::Invalid) {
     612           0 :                 ShowSevereError(state,
     613           0 :                                 std::string{RoutineName} + cCurrentModuleObject + ": invalid " + cAlphaFieldNames(7) + " entered =" + cAlphaArgs(7) +
     614           0 :                                     " for " + cAlphaFieldNames(1) + '=' + cAlphaArgs(1));
     615           0 :                 ErrorsFound = true;
     616             :             }
     617             :         } else {
     618         135 :             Fan(FanNum).AvailManagerMode = AvailabilityManagerCoupling::Coupled;
     619             :         }
     620             : 
     621         141 :         if (NumAlphas > 7 && !lAlphaFieldBlanks(8)) {
     622           0 :             Fan(FanNum).MinTempLimitSchedNum = GetScheduleIndex(state, cAlphaArgs(8));
     623           0 :             if (Fan(FanNum).MinTempLimitSchedNum == 0) {
     624           0 :                 ShowSevereError(state,
     625           0 :                                 std::string{RoutineName} + cCurrentModuleObject + ": invalid " + cAlphaFieldNames(8) + " entered =" + cAlphaArgs(8) +
     626           0 :                                     " for " + cAlphaFieldNames(1) + '=' + cAlphaArgs(1));
     627           0 :                 ErrorsFound = true;
     628             :             }
     629             :         } else {
     630         141 :             Fan(FanNum).MinTempLimitSchedNum = 0;
     631             :         }
     632             : 
     633         141 :         if (NumAlphas > 8 && !lAlphaFieldBlanks(9)) {
     634             : 
     635          32 :             if (state.dataHeatBal->ZoneAirMassFlow.ZoneFlowAdjustment != DataHeatBalance::AdjustmentType::NoAdjustReturnAndMixing) {
     636             :                 // do not include adjusted for "balanced" exhaust flow in the zone total return calculation
     637           0 :                 ShowWarningError(state,
     638           0 :                                  std::string{RoutineName} + cCurrentModuleObject + ": invalid " + cAlphaFieldNames(9) + " = " + cAlphaArgs(9) +
     639           0 :                                      " for " + cAlphaFieldNames(1) + '=' + cAlphaArgs(1));
     640           0 :                 ShowContinueError(state, "When zone air mass flow balance is enforced, this input field should be left blank.");
     641           0 :                 ShowContinueError(state, "This schedule will be ignored in the simulation.");
     642           0 :                 Fan(FanNum).BalancedFractSchedNum = 0;
     643             :             } else {
     644          32 :                 Fan(FanNum).BalancedFractSchedNum = GetScheduleIndex(state, cAlphaArgs(9));
     645          32 :                 if (Fan(FanNum).BalancedFractSchedNum == 0) {
     646           0 :                     ShowSevereError(state,
     647           0 :                                     std::string{RoutineName} + cCurrentModuleObject + ": invalid " + cAlphaFieldNames(9) +
     648           0 :                                         " entered =" + cAlphaArgs(9) + " for " + cAlphaFieldNames(1) + '=' + cAlphaArgs(1));
     649           0 :                     ErrorsFound = true;
     650          32 :                 } else if (Fan(FanNum).BalancedFractSchedNum > 0) {
     651          32 :                     if (!CheckScheduleValueMinMax(state, Fan(FanNum).BalancedFractSchedNum, ">=", 0.0, "<=", 1.0)) {
     652           0 :                         ShowSevereError(state,
     653           0 :                                         std::string{RoutineName} + cCurrentModuleObject + ": invalid " + cAlphaFieldNames(9) + " for " +
     654           0 :                                             cAlphaFieldNames(1) + '=' + cAlphaArgs(1));
     655           0 :                         ShowContinueError(state, "Error found in " + cAlphaFieldNames(9) + " = " + cAlphaArgs(9));
     656           0 :                         ShowContinueError(state, "Schedule values must be (>=0., <=1.)");
     657           0 :                         ErrorsFound = true;
     658             :                     }
     659             :                 }
     660             :             }
     661             :         } else {
     662         109 :             Fan(FanNum).BalancedFractSchedNum = 0;
     663             :         }
     664             : 
     665             :     } // end of Zone Exhaust Fan loop
     666             : 
     667        1418 :     for (OnOffFanNum = 1; OnOffFanNum <= NumOnOff; ++OnOffFanNum) {
     668         872 :         FanNum = NumSimpFan + NumVarVolFan + NumZoneExhFan + OnOffFanNum;
     669         872 :         cCurrentModuleObject = "Fan:OnOff";
     670         872 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     671             :                                                                  cCurrentModuleObject,
     672             :                                                                  OnOffFanNum,
     673             :                                                                  cAlphaArgs,
     674             :                                                                  NumAlphas,
     675             :                                                                  rNumericArgs,
     676             :                                                                  NumNums,
     677             :                                                                  IOStat,
     678             :                                                                  lNumericFieldBlanks,
     679             :                                                                  lAlphaFieldBlanks,
     680             :                                                                  cAlphaFieldNames,
     681             :                                                                  cNumericFieldNames);
     682             : 
     683         872 :         FanNumericFields(FanNum).FieldNames.allocate(MaxNumbers);
     684         872 :         FanNumericFields(FanNum).FieldNames = "";
     685         872 :         FanNumericFields(FanNum).FieldNames = cNumericFieldNames;
     686             : 
     687         872 :         GlobalNames::VerifyUniqueInterObjectName(state, UniqueFanNames, cAlphaArgs(1), cCurrentModuleObject, cAlphaFieldNames(1), ErrorsFound);
     688         872 :         Fan(FanNum).FanName = cAlphaArgs(1);
     689         872 :         Fan(FanNum).FanType = cCurrentModuleObject;
     690         872 :         Fan(FanNum).AvailSchedName = cAlphaArgs(2);
     691         872 :         if (lAlphaFieldBlanks(2)) {
     692           0 :             Fan(FanNum).AvailSchedPtrNum = DataGlobalConstants::ScheduleAlwaysOn;
     693             :         } else {
     694         872 :             Fan(FanNum).AvailSchedPtrNum = GetScheduleIndex(state, cAlphaArgs(2));
     695         872 :             if (Fan(FanNum).AvailSchedPtrNum == 0) {
     696           0 :                 ShowSevereError(state,
     697           0 :                                 std::string{RoutineName} + cCurrentModuleObject + ": invalid " + cAlphaFieldNames(2) + " entered =" + cAlphaArgs(2) +
     698           0 :                                     " for " + cAlphaFieldNames(1) + '=' + cAlphaArgs(1));
     699           0 :                 ErrorsFound = true;
     700             :             }
     701             :         }
     702         872 :         Fan(FanNum).FanType_Num = FanType_SimpleOnOff;
     703             : 
     704         872 :         Fan(FanNum).FanEff = rNumericArgs(1);
     705         872 :         Fan(FanNum).DeltaPress = rNumericArgs(2);
     706         872 :         Fan(FanNum).MaxAirFlowRate = rNumericArgs(3);
     707         872 :         if (Fan(FanNum).MaxAirFlowRate == 0.0) {
     708           0 :             ShowWarningError(state,
     709           0 :                              cCurrentModuleObject + "=\"" + Fan(FanNum).FanName +
     710             :                                  "\" has specified 0.0 max air flow rate. It will not be used in the simulation.");
     711             :         }
     712         872 :         Fan(FanNum).MaxAirFlowRateIsAutosizable = true;
     713             :         //       the following two structure variables are set here, as well as in InitFan, for the Heat Pump:Water Heater object
     714             :         //       (Standard Rating procedure may be called before BeginEnvirFlag is set to TRUE, if so MaxAirMassFlowRate = 0)
     715         872 :         Fan(FanNum).RhoAirStdInit = state.dataEnvrn->StdRhoAir;
     716         872 :         Fan(FanNum).MaxAirMassFlowRate = Fan(FanNum).MaxAirFlowRate * Fan(FanNum).RhoAirStdInit;
     717             : 
     718         872 :         Fan(FanNum).MotEff = rNumericArgs(4);
     719         872 :         Fan(FanNum).MotInAirFrac = rNumericArgs(5);
     720         872 :         Fan(FanNum).MinAirFlowRate = 0.0;
     721             : 
     722         872 :         Fan(FanNum).InletNodeNum = GetOnlySingleNode(state,
     723         872 :                                                      cAlphaArgs(3),
     724             :                                                      ErrorsFound,
     725             :                                                      DataLoopNode::ConnectionObjectType::FanOnOff,
     726         872 :                                                      cAlphaArgs(1),
     727             :                                                      DataLoopNode::NodeFluidType::Air,
     728             :                                                      DataLoopNode::ConnectionType::Inlet,
     729             :                                                      NodeInputManager::CompFluidStream::Primary,
     730         872 :                                                      ObjectIsNotParent);
     731         872 :         Fan(FanNum).OutletNodeNum = GetOnlySingleNode(state,
     732         872 :                                                       cAlphaArgs(4),
     733             :                                                       ErrorsFound,
     734             :                                                       DataLoopNode::ConnectionObjectType::FanOnOff,
     735         872 :                                                       cAlphaArgs(1),
     736             :                                                       DataLoopNode::NodeFluidType::Air,
     737             :                                                       DataLoopNode::ConnectionType::Outlet,
     738             :                                                       NodeInputManager::CompFluidStream::Primary,
     739         872 :                                                       ObjectIsNotParent);
     740             : 
     741         872 :         if (NumAlphas > 4 && !lAlphaFieldBlanks(5)) {
     742          25 :             Fan(FanNum).FanPowerRatAtSpeedRatCurveIndex = GetCurveIndex(state, cAlphaArgs(5));
     743             :         }
     744             : 
     745         872 :         if (NumAlphas > 5 && !lAlphaFieldBlanks(6)) {
     746          10 :             Fan(FanNum).FanEffRatioCurveIndex = GetCurveIndex(state, cAlphaArgs(6));
     747             :         }
     748             : 
     749         872 :         if (NumAlphas > 6 && !lAlphaFieldBlanks(7)) {
     750         383 :             Fan(FanNum).EndUseSubcategoryName = cAlphaArgs(7);
     751             :         } else {
     752         489 :             Fan(FanNum).EndUseSubcategoryName = "General";
     753             :         }
     754             : 
     755         872 :         TestCompSet(state, cCurrentModuleObject, cAlphaArgs(1), cAlphaArgs(3), cAlphaArgs(4), "Air Nodes");
     756             : 
     757             :     } // end Number of Simple  ON-OFF FAN Loop
     758             : 
     759         546 :     cCurrentModuleObject = "FanPerformance:NightVentilation";
     760         546 :     state.dataFans->NumNightVentPerf = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     761             : 
     762         546 :     if (state.dataFans->NumNightVentPerf > 0) {
     763           0 :         NightVentPerf.allocate(state.dataFans->NumNightVentPerf);
     764           0 :         for (auto &e : NightVentPerf) {
     765           0 :             e.FanName.clear();
     766           0 :             e.FanEff = 0.0;
     767           0 :             e.DeltaPress = 0.0;
     768           0 :             e.MaxAirFlowRate = 0.0;
     769           0 :             e.MotEff = 0.0;
     770           0 :             e.MotInAirFrac = 0.0;
     771           0 :             e.MaxAirMassFlowRate = 0.0;
     772             :         }
     773             :     }
     774             :     // input the night ventilation performance objects
     775         546 :     for (NVPerfNum = 1; NVPerfNum <= state.dataFans->NumNightVentPerf; ++NVPerfNum) {
     776           0 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     777             :                                                                  cCurrentModuleObject,
     778             :                                                                  NVPerfNum,
     779             :                                                                  cAlphaArgs,
     780             :                                                                  NumAlphas,
     781             :                                                                  rNumericArgs,
     782             :                                                                  NumNums,
     783             :                                                                  IOStat,
     784             :                                                                  lNumericFieldBlanks,
     785             :                                                                  lAlphaFieldBlanks,
     786             :                                                                  cAlphaFieldNames,
     787             :                                                                  cNumericFieldNames);
     788           0 :         UtilityRoutines::IsNameEmpty(state, cAlphaArgs(1), cCurrentModuleObject, ErrorsFound);
     789           0 :         NightVentPerf(NVPerfNum).FanName = cAlphaArgs(1);
     790           0 :         NightVentPerf(NVPerfNum).FanEff = rNumericArgs(1);
     791           0 :         NightVentPerf(NVPerfNum).DeltaPress = rNumericArgs(2);
     792           0 :         NightVentPerf(NVPerfNum).MaxAirFlowRate = rNumericArgs(3);
     793           0 :         NightVentPerf(NVPerfNum).MotEff = rNumericArgs(4);
     794           0 :         NightVentPerf(NVPerfNum).MotInAirFrac = rNumericArgs(5);
     795             :         // find the corresponding fan
     796           0 :         NVPerfFanFound = false;
     797           0 :         for (FanNum = 1; FanNum <= state.dataFans->NumFans; ++FanNum) {
     798           0 :             if (NightVentPerf(NVPerfNum).FanName == Fan(FanNum).FanName) {
     799           0 :                 NVPerfFanFound = true;
     800           0 :                 Fan(FanNum).NVPerfNum = NVPerfNum;
     801           0 :                 break;
     802             :             }
     803             :         }
     804           0 :         if (!NVPerfFanFound) {
     805           0 :             ShowSevereError(state, cCurrentModuleObject + ", fan name not found=" + cAlphaArgs(1));
     806           0 :             ErrorsFound = true;
     807             :         }
     808             :     }
     809             : 
     810         550 :     for (CompModelFanNum = 1; CompModelFanNum <= NumCompModelFan; ++CompModelFanNum) {
     811           4 :         FanNum = NumSimpFan + NumVarVolFan + NumZoneExhFan + NumOnOff + CompModelFanNum;
     812             : 
     813           4 :         cCurrentModuleObject = "Fan:ComponentModel";
     814           4 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     815             :                                                                  cCurrentModuleObject,
     816             :                                                                  CompModelFanNum,
     817             :                                                                  cAlphaArgs,
     818             :                                                                  NumAlphas,
     819             :                                                                  rNumericArgs,
     820             :                                                                  NumNums,
     821             :                                                                  IOStat,
     822             :                                                                  lNumericFieldBlanks,
     823             :                                                                  lAlphaFieldBlanks,
     824             :                                                                  cAlphaFieldNames,
     825             :                                                                  cNumericFieldNames);
     826             : 
     827           4 :         FanNumericFields(FanNum).FieldNames.allocate(MaxNumbers);
     828           4 :         FanNumericFields(FanNum).FieldNames = "";
     829           4 :         FanNumericFields(FanNum).FieldNames = cNumericFieldNames;
     830             : 
     831           4 :         GlobalNames::VerifyUniqueInterObjectName(state, UniqueFanNames, cAlphaArgs(1), cCurrentModuleObject, cAlphaFieldNames(1), ErrorsFound);
     832           4 :         Fan(FanNum).FanName = cAlphaArgs(1); // Fan name
     833           4 :         Fan(FanNum).FanType = cCurrentModuleObject;
     834             : 
     835           4 :         Fan(FanNum).InletNodeNum = GetOnlySingleNode(state,
     836           4 :                                                      cAlphaArgs(2),
     837             :                                                      ErrorsFound,
     838             :                                                      DataLoopNode::ConnectionObjectType::FanComponentModel,
     839           4 :                                                      cAlphaArgs(1),
     840             :                                                      DataLoopNode::NodeFluidType::Air,
     841             :                                                      DataLoopNode::ConnectionType::Inlet,
     842             :                                                      NodeInputManager::CompFluidStream::Primary,
     843           4 :                                                      ObjectIsNotParent); // Air inlet node name
     844           4 :         Fan(FanNum).OutletNodeNum = GetOnlySingleNode(state,
     845           4 :                                                       cAlphaArgs(3),
     846             :                                                       ErrorsFound,
     847             :                                                       DataLoopNode::ConnectionObjectType::FanComponentModel,
     848           4 :                                                       cAlphaArgs(1),
     849             :                                                       DataLoopNode::NodeFluidType::Air,
     850             :                                                       DataLoopNode::ConnectionType::Outlet,
     851             :                                                       NodeInputManager::CompFluidStream::Primary,
     852           4 :                                                       ObjectIsNotParent); // Air outlet node name
     853             : 
     854           4 :         TestCompSet(state, cCurrentModuleObject, cAlphaArgs(1), cAlphaArgs(2), cAlphaArgs(3), "Air Nodes");
     855             : 
     856           4 :         Fan(FanNum).AvailSchedName = cAlphaArgs(4); // Availability schedule name
     857           4 :         if (lAlphaFieldBlanks(4)) {
     858           0 :             Fan(FanNum).AvailSchedPtrNum = 0;
     859             :         } else {
     860           4 :             Fan(FanNum).AvailSchedPtrNum = GetScheduleIndex(state, cAlphaArgs(4));
     861           4 :             if (Fan(FanNum).AvailSchedPtrNum == 0) {
     862           0 :                 ShowSevereError(state,
     863           0 :                                 std::string{RoutineName} + cCurrentModuleObject + ": invalid " + cAlphaFieldNames(4) + " entered =" + cAlphaArgs(4) +
     864           0 :                                     " for " + cAlphaFieldNames(1) + '=' + cAlphaArgs(1));
     865           0 :                 ErrorsFound = true;
     866             :             }
     867             :         }
     868             : 
     869           4 :         Fan(FanNum).FanType_Num = FanType_ComponentModel;
     870             : 
     871           4 :         Fan(FanNum).MaxAirFlowRate = rNumericArgs(1);
     872           4 :         if (Fan(FanNum).MaxAirFlowRate == 0.0) {
     873           0 :             ShowWarningError(state,
     874           0 :                              cCurrentModuleObject + "=\"" + Fan(FanNum).FanName +
     875             :                                  "\" has specified 0.0 max air flow rate. It will not be used in the simulation.");
     876             :         }
     877           4 :         Fan(FanNum).MaxAirFlowRateIsAutosizable = true;
     878           4 :         Fan(FanNum).MinAirFlowRate = rNumericArgs(2);
     879             : 
     880           4 :         Fan(FanNum).FanSizingFactor = rNumericArgs(3);                              // Fan max airflow sizing factor [-]
     881           4 :         Fan(FanNum).FanWheelDia = rNumericArgs(4);                                  // Fan wheel outer diameter [m]
     882           4 :         Fan(FanNum).FanOutletArea = rNumericArgs(5);                                // Fan outlet area [m2]
     883           4 :         Fan(FanNum).FanMaxEff = rNumericArgs(6);                                    // Fan maximum static efficiency [-]
     884           4 :         Fan(FanNum).EuMaxEff = rNumericArgs(7);                                     // Euler number at Fan maximum static efficiency [-]
     885           4 :         Fan(FanNum).FanMaxDimFlow = rNumericArgs(8);                                // Fan maximum dimensionless airflow [-]
     886           4 :         Fan(FanNum).PulleyDiaRatio = rNumericArgs(9);                               // Motor/fan pulley diameter ratio [-]
     887           4 :         Fan(FanNum).BeltMaxTorque = rNumericArgs(10);                               // Belt maximum torque [N-m, autosizable]
     888           4 :         Fan(FanNum).BeltSizingFactor = rNumericArgs(11);                            // Belt sizing factor [-]
     889           4 :         Fan(FanNum).BeltTorqueTrans = rNumericArgs(12);                             // Belt fractional torque transition Region 1-2 [-]
     890           4 :         Fan(FanNum).MotorMaxSpd = rNumericArgs(13);                                 // Motor maximum speed [rpm]
     891           4 :         Fan(FanNum).MotorMaxOutPwr = rNumericArgs(14);                              // Motor maximum output power [W, autosizable]
     892           4 :         Fan(FanNum).MotorSizingFactor = rNumericArgs(15);                           // Motor sizing factor [-]
     893           4 :         Fan(FanNum).MotInAirFrac = rNumericArgs(16);                                // Fraction of fan and motor losses to airstream [-]
     894           4 :         Fan(FanNum).VFDEffType = cAlphaArgs(5);                                     // VFD efficiency type [Speed or Power]
     895           4 :         Fan(FanNum).VFDMaxOutPwr = rNumericArgs(17);                                // VFD maximum output power [W, autosizable]
     896           4 :         Fan(FanNum).VFDSizingFactor = rNumericArgs(18);                             // VFD sizing factor [-]
     897           4 :         Fan(FanNum).PressRiseCurveIndex = GetCurveIndex(state, cAlphaArgs(6));      // Fan pressure rise curve
     898           4 :         Fan(FanNum).PressResetCurveIndex = GetCurveIndex(state, cAlphaArgs(7));     // Duct static pressure reset curve
     899           4 :         Fan(FanNum).PLFanEffNormCurveIndex = GetCurveIndex(state, cAlphaArgs(8));   // Fan part-load eff (normal) curve
     900           4 :         Fan(FanNum).PLFanEffStallCurveIndex = GetCurveIndex(state, cAlphaArgs(9));  // Fan part-load eff (stall) curve
     901           4 :         Fan(FanNum).DimFlowNormCurveIndex = GetCurveIndex(state, cAlphaArgs(10));   // Fan dim airflow (normal) curve
     902           4 :         Fan(FanNum).DimFlowStallCurveIndex = GetCurveIndex(state, cAlphaArgs(11));  // Fan dim airflow (stall) curve
     903           4 :         Fan(FanNum).BeltMaxEffCurveIndex = GetCurveIndex(state, cAlphaArgs(12));    // Belt max eff curve
     904           4 :         Fan(FanNum).PLBeltEffReg1CurveIndex = GetCurveIndex(state, cAlphaArgs(13)); // Belt part-load eff Region 1 curve
     905           4 :         Fan(FanNum).PLBeltEffReg2CurveIndex = GetCurveIndex(state, cAlphaArgs(14)); // Belt part-load eff Region 2 curve
     906           4 :         Fan(FanNum).PLBeltEffReg3CurveIndex = GetCurveIndex(state, cAlphaArgs(15)); // Belt part-load eff Region 3 curve
     907           4 :         Fan(FanNum).MotorMaxEffCurveIndex = GetCurveIndex(state, cAlphaArgs(16));   // Motor max eff curve
     908           4 :         Fan(FanNum).PLMotorEffCurveIndex = GetCurveIndex(state, cAlphaArgs(17));    // Motor part-load eff curve
     909           4 :         Fan(FanNum).VFDEffCurveIndex = GetCurveIndex(state, cAlphaArgs(18));        // VFD eff curve
     910             : 
     911           4 :         if (NumAlphas > 18) {
     912           0 :             Fan(FanNum).EndUseSubcategoryName = cAlphaArgs(19);
     913             :         } else {
     914           4 :             Fan(FanNum).EndUseSubcategoryName = "General";
     915             :         }
     916             : 
     917             :     } // end Number of Component Model FAN Loop
     918             : 
     919         546 :     cAlphaArgs.deallocate();
     920         546 :     cAlphaFieldNames.deallocate();
     921         546 :     lAlphaFieldBlanks.deallocate();
     922         546 :     cNumericFieldNames.deallocate();
     923         546 :     lNumericFieldBlanks.deallocate();
     924         546 :     rNumericArgs.deallocate();
     925             : 
     926             :     // Check Fans
     927        2489 :     for (FanNum = 1; FanNum <= state.dataFans->NumFans; ++FanNum) {
     928       41375 :         for (checkNum = FanNum + 1; checkNum <= state.dataFans->NumFans; ++checkNum) {
     929       39432 :             if (Fan(FanNum).InletNodeNum == Fan(checkNum).InletNodeNum) {
     930           0 :                 ErrorsFound = true;
     931           0 :                 ShowSevereError(state, "GetFanInput, duplicate fan inlet node names, must be unique for fans.");
     932           0 :                 ShowContinueError(state,
     933           0 :                                   "Fan=" + Fan(FanNum).FanType + ':' + Fan(FanNum).FanName + " and Fan=" + Fan(checkNum).FanType + ':' +
     934           0 :                                       Fan(checkNum).FanName + '.');
     935           0 :                 ShowContinueError(state, "Inlet Node Name=\"" + state.dataLoopNodes->NodeID(Fan(FanNum).InletNodeNum) + "\".");
     936             :             }
     937       39432 :             if (Fan(FanNum).OutletNodeNum == Fan(checkNum).OutletNodeNum) {
     938           0 :                 ErrorsFound = true;
     939           0 :                 ShowSevereError(state, "GetFanInput, duplicate fan outlet node names, must be unique for fans.");
     940           0 :                 ShowContinueError(state,
     941           0 :                                   "Fan=" + Fan(FanNum).FanType + ':' + Fan(FanNum).FanName + " and Fan=" + Fan(checkNum).FanType + ':' +
     942           0 :                                       Fan(checkNum).FanName + '.');
     943           0 :                 ShowContinueError(state, "Outlet Node Name=\"" + state.dataLoopNodes->NodeID(Fan(FanNum).OutletNodeNum) + "\".");
     944             :             }
     945             :         }
     946             :     }
     947             : 
     948         546 :     if (ErrorsFound) {
     949           0 :         ShowFatalError(state, std::string{RoutineName} + "Errors found in input.  Program terminates.");
     950             :     }
     951             : 
     952        2489 :     for (FanNum = 1; FanNum <= state.dataFans->NumFans; ++FanNum) {
     953             :         // Setup Report variables for the Fans  CurrentModuleObject='Fans'
     954        7772 :         SetupOutputVariable(state,
     955             :                             "Fan Electricity Rate",
     956             :                             OutputProcessor::Unit::W,
     957        1943 :                             Fan(FanNum).FanPower,
     958             :                             OutputProcessor::SOVTimeStepType::System,
     959             :                             OutputProcessor::SOVStoreType::Average,
     960        3886 :                             Fan(FanNum).FanName);
     961        7772 :         SetupOutputVariable(state,
     962             :                             "Fan Rise in Air Temperature",
     963             :                             OutputProcessor::Unit::deltaC,
     964        1943 :                             Fan(FanNum).DeltaTemp,
     965             :                             OutputProcessor::SOVTimeStepType::System,
     966             :                             OutputProcessor::SOVStoreType::Average,
     967        3886 :                             Fan(FanNum).FanName);
     968        7772 :         SetupOutputVariable(state,
     969             :                             "Fan Heat Gain to Air",
     970             :                             OutputProcessor::Unit::W,
     971        1943 :                             Fan(FanNum).PowerLossToAir,
     972             :                             OutputProcessor::SOVTimeStepType::System,
     973             :                             OutputProcessor::SOVStoreType::Average,
     974        3886 :                             Fan(FanNum).FanName);
     975        9715 :         SetupOutputVariable(state,
     976             :                             "Fan Electricity Energy",
     977             :                             OutputProcessor::Unit::J,
     978        1943 :                             Fan(FanNum).FanEnergy,
     979             :                             OutputProcessor::SOVTimeStepType::System,
     980             :                             OutputProcessor::SOVStoreType::Summed,
     981        1943 :                             Fan(FanNum).FanName,
     982             :                             _,
     983             :                             "Electricity",
     984             :                             "Fans",
     985        1943 :                             Fan(FanNum).EndUseSubcategoryName,
     986        1943 :                             "System");
     987        7772 :         SetupOutputVariable(state,
     988             :                             "Fan Air Mass Flow Rate",
     989             :                             OutputProcessor::Unit::kg_s,
     990        1943 :                             Fan(FanNum).OutletAirMassFlowRate,
     991             :                             OutputProcessor::SOVTimeStepType::System,
     992             :                             OutputProcessor::SOVStoreType::Average,
     993        3886 :                             Fan(FanNum).FanName);
     994        1943 :         if ((Fan(FanNum).FanType_Num == FanType_ZoneExhaust) && (Fan(FanNum).BalancedFractSchedNum > 0)) {
     995         128 :             SetupOutputVariable(state,
     996             :                                 "Fan Unbalanced Air Mass Flow Rate",
     997             :                                 OutputProcessor::Unit::kg_s,
     998          32 :                                 Fan(FanNum).UnbalancedOutletMassFlowRate,
     999             :                                 OutputProcessor::SOVTimeStepType::System,
    1000             :                                 OutputProcessor::SOVStoreType::Average,
    1001          64 :                                 Fan(FanNum).FanName);
    1002         128 :             SetupOutputVariable(state,
    1003             :                                 "Fan Balanced Air Mass Flow Rate",
    1004             :                                 OutputProcessor::Unit::kg_s,
    1005          32 :                                 Fan(FanNum).BalancedOutletMassFlowRate,
    1006             :                                 OutputProcessor::SOVTimeStepType::System,
    1007             :                                 OutputProcessor::SOVStoreType::Average,
    1008          64 :                                 Fan(FanNum).FanName);
    1009             :         }
    1010             : 
    1011        1943 :         if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
    1012             : 
    1013         638 :             SetupEMSInternalVariable(state, "Fan Maximum Mass Flow Rate", Fan(FanNum).FanName, "[kg/s]", Fan(FanNum).MaxAirMassFlowRate);
    1014        2552 :             SetupEMSActuator(state,
    1015             :                              "Fan",
    1016         638 :                              Fan(FanNum).FanName,
    1017             :                              "Fan Air Mass Flow Rate",
    1018             :                              "[kg/s]",
    1019         638 :                              Fan(FanNum).EMSMaxMassFlowOverrideOn,
    1020        1914 :                              Fan(FanNum).EMSAirMassFlowValue);
    1021         638 :             SetupEMSInternalVariable(state, "Fan Nominal Pressure Rise", Fan(FanNum).FanName, "[Pa]", Fan(FanNum).DeltaPress);
    1022        2552 :             SetupEMSActuator(state,
    1023             :                              "Fan",
    1024         638 :                              Fan(FanNum).FanName,
    1025             :                              "Fan Pressure Rise",
    1026             :                              "[Pa]",
    1027         638 :                              Fan(FanNum).EMSFanPressureOverrideOn,
    1028        1914 :                              Fan(FanNum).EMSFanPressureValue);
    1029         638 :             SetupEMSInternalVariable(state, "Fan Nominal Total Efficiency", Fan(FanNum).FanName, "[fraction]", Fan(FanNum).FanEff);
    1030        2552 :             SetupEMSActuator(
    1031        2552 :                 state, "Fan", Fan(FanNum).FanName, "Fan Total Efficiency", "[fraction]", Fan(FanNum).EMSFanEffOverrideOn, Fan(FanNum).EMSFanEffValue);
    1032             : 
    1033        2552 :             SetupEMSActuator(state,
    1034             :                              "Fan",
    1035         638 :                              Fan(FanNum).FanName,
    1036             :                              "Fan Autosized Air Flow Rate",
    1037             :                              "[m3/s]",
    1038         638 :                              Fan(FanNum).MaxAirFlowRateEMSOverrideOn,
    1039        1914 :                              Fan(FanNum).MaxAirFlowRateEMSOverrideValue);
    1040             :         }
    1041             :     }
    1042             : 
    1043        1418 :     for (OnOffFanNum = 1; OnOffFanNum <= NumOnOff; ++OnOffFanNum) {
    1044         872 :         FanNum = NumSimpFan + NumVarVolFan + NumZoneExhFan + OnOffFanNum;
    1045        3488 :         SetupOutputVariable(state,
    1046             :                             "Fan Runtime Fraction",
    1047             :                             OutputProcessor::Unit::None,
    1048         872 :                             Fan(FanNum).FanRuntimeFraction,
    1049             :                             OutputProcessor::SOVTimeStepType::System,
    1050             :                             OutputProcessor::SOVStoreType::Average,
    1051        1744 :                             Fan(FanNum).FanName);
    1052             :     }
    1053             : 
    1054             :     bool anyRan;
    1055         546 :     ManageEMS(state, EMSManager::EMSCallFrom::ComponentGetInput, anyRan, ObjexxFCL::Optional_int_const());
    1056         546 :     state.dataFans->MySizeFlag.dimension(state.dataFans->NumFans, true);
    1057         546 : }
    1058             : 
    1059             : // End of Get Input subroutines for the HB Module
    1060             : //******************************************************************************
    1061             : 
    1062             : // Beginning Initialization Section of the Module
    1063             : //******************************************************************************
    1064             : 
    1065   138406141 : void InitFan(EnergyPlusData &state,
    1066             :              int const FanNum,
    1067             :              [[maybe_unused]] bool const FirstHVACIteration // unused1208
    1068             : )
    1069             : {
    1070             : 
    1071             :     // SUBROUTINE INFORMATION:
    1072             :     //       AUTHOR         Richard J. Liesen
    1073             :     //       DATE WRITTEN   February 1998
    1074             :     //       MODIFIED       na
    1075             :     //       RE-ENGINEERED  na
    1076             : 
    1077             :     // PURPOSE OF THIS SUBROUTINE:
    1078             :     // This subroutine is for initializations of the Fan Components.
    1079             : 
    1080             :     // METHODOLOGY EMPLOYED:
    1081             :     // Uses the status flags to trigger initializations.
    1082             : 
    1083             :     // Using/Aliasing
    1084             :     using DataZoneEquipment::CheckZoneEquipmentList;
    1085             : 
    1086             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1087             :     int InletNode;
    1088             :     int OutletNode;
    1089             :     int OutNode;
    1090             :     int Loop;
    1091             : 
    1092   138406141 :     auto &Fan(state.dataFans->Fan);
    1093   138406141 :     auto &NightVentPerf(state.dataFans->NightVentPerf);
    1094             : 
    1095   138406141 :     if (state.dataFans->MyOneTimeFlag) {
    1096             : 
    1097         546 :         state.dataFans->MyEnvrnFlag.dimension(state.dataFans->NumFans, true);
    1098             : 
    1099         546 :         state.dataFans->MyOneTimeFlag = false;
    1100             :     }
    1101             : 
    1102             :     // need to check all fans to see if they are on Zone Equipment List or issue warning
    1103   138406141 :     if (!state.dataFans->ZoneEquipmentListChecked && state.dataZoneEquip->ZoneEquipInputsFilled) {
    1104         546 :         state.dataFans->ZoneEquipmentListChecked = true;
    1105        2489 :         for (Loop = 1; Loop <= state.dataFans->NumFans; ++Loop) {
    1106        1943 :             if (!UtilityRoutines::SameString(Fan(Loop).FanType, "Fan:ZoneExhaust")) continue;
    1107         141 :             if (CheckZoneEquipmentList(state, Fan(Loop).FanType, Fan(Loop).FanName)) continue;
    1108           0 :             ShowSevereError(state,
    1109           0 :                             "InitFans: Fan=[" + Fan(Loop).FanType + ',' + Fan(Loop).FanName +
    1110             :                                 "] is not on any ZoneHVAC:EquipmentList.  It will not be simulated.");
    1111             :         }
    1112             :     }
    1113             : 
    1114   138406141 :     if (!state.dataGlobal->SysSizingCalc && state.dataFans->MySizeFlag(FanNum)) {
    1115             : 
    1116        1942 :         SizeFan(state, FanNum);
    1117             :         // Set the loop cycling flag
    1118        1942 :         if (Fan(FanNum).FanType_Num == FanType_SimpleOnOff) {
    1119         872 :             if (state.dataSize->CurSysNum > 0) {
    1120         404 :                 state.dataAirLoop->AirLoopControlInfo(state.dataSize->CurSysNum).CyclingFan = true;
    1121             :             }
    1122             :         }
    1123             : 
    1124        1942 :         state.dataFans->MySizeFlag(FanNum) = false;
    1125             :     }
    1126             : 
    1127             :     // Do the Begin Environment initializations
    1128   138406141 :     if (state.dataGlobal->BeginEnvrnFlag && state.dataFans->MyEnvrnFlag(FanNum)) {
    1129             : 
    1130             :         // For all Fan inlet nodes convert the Volume flow to a mass flow
    1131             :         // unused0909    InNode = Fan(FanNum)%InletNodeNum
    1132       12132 :         OutNode = Fan(FanNum).OutletNodeNum;
    1133       12132 :         Fan(FanNum).RhoAirStdInit = state.dataEnvrn->StdRhoAir;
    1134             : 
    1135             :         // Change the Volume Flow Rates to Mass Flow Rates
    1136             : 
    1137       12132 :         Fan(FanNum).MaxAirMassFlowRate = Fan(FanNum).MaxAirFlowRate * Fan(FanNum).RhoAirStdInit;
    1138       12132 :         if (Fan(FanNum).FanMinAirFracMethod == MinFrac) {
    1139       10854 :             Fan(FanNum).MinAirFlowRate = Fan(FanNum).MaxAirFlowRate * Fan(FanNum).FanMinFrac;
    1140       10854 :             Fan(FanNum).MinAirMassFlowRate = Fan(FanNum).MinAirFlowRate * Fan(FanNum).RhoAirStdInit;
    1141        1278 :         } else if (Fan(FanNum).FanMinAirFracMethod == FixedMin) {
    1142        1278 :             Fan(FanNum).MinAirFlowRate = Fan(FanNum).FanFixedMin;
    1143        1278 :             Fan(FanNum).MinAirMassFlowRate = Fan(FanNum).MinAirFlowRate * Fan(FanNum).RhoAirStdInit;
    1144             :         }
    1145       12132 :         if (Fan(FanNum).NVPerfNum > 0) {
    1146           0 :             NightVentPerf(Fan(FanNum).NVPerfNum).MaxAirMassFlowRate = NightVentPerf(Fan(FanNum).NVPerfNum).MaxAirFlowRate * Fan(FanNum).RhoAirStdInit;
    1147             :         }
    1148             : 
    1149             :         // Init the Node Control variables
    1150       12132 :         state.dataLoopNodes->Node(OutNode).MassFlowRateMax = Fan(FanNum).MaxAirMassFlowRate;
    1151             :         // According to the IO Ref guide:
    1152             :         // "Note that this field is only used to calculate the fan power.
    1153             :         // This field does not enforce the system air flow rate during simulation"
    1154             :         // Node(OutNode).MassFlowRateMin = Fan(FanNum).MinAirMassFlowRate;
    1155             : 
    1156             :         // Initialize all report variables to a known state at beginning of simulation
    1157       12132 :         Fan(FanNum).FanPower = 0.0;
    1158       12132 :         Fan(FanNum).DeltaTemp = 0.0;
    1159       12132 :         Fan(FanNum).PowerLossToAir = 0.0;
    1160       12132 :         Fan(FanNum).FanEnergy = 0.0;
    1161             : 
    1162       12132 :         state.dataFans->MyEnvrnFlag(FanNum) = false;
    1163             :     }
    1164             : 
    1165   138406141 :     if (!state.dataGlobal->BeginEnvrnFlag) {
    1166   138081715 :         state.dataFans->MyEnvrnFlag(FanNum) = true;
    1167             :     }
    1168             : 
    1169             :     // Do the Begin Day initializations
    1170             :     // none
    1171             : 
    1172             :     // Do the begin HVAC time step initializations
    1173             :     // none
    1174             : 
    1175             :     // Do the following initializations (every time step): This should be the info from
    1176             :     // the previous components outlets or the node data in this section.
    1177             : 
    1178             :     // Do a check and make sure that the max and min available(control) flow is
    1179             :     // between the physical max and min for the Fan while operating.
    1180             : 
    1181   138406141 :     InletNode = Fan(FanNum).InletNodeNum;
    1182   138406141 :     OutletNode = Fan(FanNum).OutletNodeNum;
    1183             : 
    1184   138406141 :     Fan(FanNum).MassFlowRateMaxAvail =
    1185   138406141 :         min(state.dataLoopNodes->Node(OutletNode).MassFlowRateMax, state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail);
    1186   138406141 :     Fan(FanNum).MassFlowRateMinAvail =
    1187   138406141 :         min(max(state.dataLoopNodes->Node(OutletNode).MassFlowRateMin, state.dataLoopNodes->Node(InletNode).MassFlowRateMinAvail),
    1188   138406141 :             state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail);
    1189             : 
    1190             :     // Load the node data in this section for the component simulation
    1191             :     // First need to make sure that the MassFlowRate is between the max and min avail.
    1192   138406141 :     if (Fan(FanNum).FanType_Num != FanType_ZoneExhaust) {
    1193   136773984 :         Fan(FanNum).InletAirMassFlowRate = min(state.dataLoopNodes->Node(InletNode).MassFlowRate, Fan(FanNum).MassFlowRateMaxAvail);
    1194   136773984 :         Fan(FanNum).InletAirMassFlowRate = max(Fan(FanNum).InletAirMassFlowRate, Fan(FanNum).MassFlowRateMinAvail);
    1195             :     } else { // zone exhaust fans
    1196     1632157 :         Fan(FanNum).MassFlowRateMaxAvail = Fan(FanNum).MaxAirMassFlowRate;
    1197     1632157 :         Fan(FanNum).MassFlowRateMinAvail = 0.0;
    1198     1632157 :         if (Fan(FanNum).FlowFractSchedNum > 0) { // modulate flow
    1199           0 :             Fan(FanNum).InletAirMassFlowRate = Fan(FanNum).MassFlowRateMaxAvail * GetCurrentScheduleValue(state, Fan(FanNum).FlowFractSchedNum);
    1200           0 :             Fan(FanNum).InletAirMassFlowRate = max(0.0, Fan(FanNum).InletAirMassFlowRate);
    1201             :         } else { // always run at max
    1202     1632157 :             Fan(FanNum).InletAirMassFlowRate = Fan(FanNum).MassFlowRateMaxAvail;
    1203             :         }
    1204     1632157 :         if (Fan(FanNum).EMSMaxMassFlowOverrideOn)
    1205           0 :             Fan(FanNum).InletAirMassFlowRate = min(Fan(FanNum).EMSAirMassFlowValue, Fan(FanNum).MassFlowRateMaxAvail);
    1206             :     }
    1207             : 
    1208             :     // Then set the other conditions
    1209   138406141 :     Fan(FanNum).InletAirTemp = state.dataLoopNodes->Node(InletNode).Temp;
    1210   138406141 :     Fan(FanNum).InletAirHumRat = state.dataLoopNodes->Node(InletNode).HumRat;
    1211   138406141 :     Fan(FanNum).InletAirEnthalpy = state.dataLoopNodes->Node(InletNode).Enthalpy;
    1212   138406141 : }
    1213             : 
    1214        1943 : void SizeFan(EnergyPlusData &state, int const FanNum)
    1215             : {
    1216             : 
    1217             :     // SUBROUTINE INFORMATION:
    1218             :     //       AUTHOR         Fred Buhl
    1219             :     //       DATE WRITTEN   September 2001
    1220             :     //       MODIFIED       Craig Wray August 2010 - added fan, belt, motor, and VFD component sizing
    1221             :     //                      August 2013 Daeho Kang, add component sizing table entries
    1222             :     //       RE-ENGINEERED  na
    1223             : 
    1224             :     // PURPOSE OF THIS SUBROUTINE:
    1225             :     // This subroutine is for sizing fans for which flow rates have not been
    1226             :     // specified in the input, or when fan component sizes have not been specified
    1227             : 
    1228             :     // METHODOLOGY EMPLOYED:
    1229             :     // Obtains flow rates from the zone or system sizing arrays.
    1230             : 
    1231             :     // Using/Aliasing
    1232             :     using namespace DataSizing;
    1233             :     using namespace OutputReportPredefined;
    1234             :     using Curve::CurveValue;
    1235             :     using Curve::GetCurveIndex;
    1236             : 
    1237             :     // SUBROUTINE PARAMETER DEFINITIONS:
    1238             :     static constexpr std::string_view RoutineName("SizeFan: "); // include trailing blank space
    1239             : 
    1240             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1241             :     int NVPerfNum;              // Index to night ventialation performance object
    1242        3886 :     std::string equipName;      // Equipment name
    1243             :     Real64 RatedPower;          // Rated fan power [W]
    1244             :     Real64 RhoAir;              // Air density [kg/m3]
    1245             :     Real64 FanVolFlow;          // Fan volumetric airflow [m3/s]
    1246             :     Real64 DuctStaticPress;     // Duct static pressure setpoint [Pa]
    1247             :     Real64 DeltaPressTot;       // Total pressure rise across fan [N/m2 = Pa]
    1248             :     Real64 FanOutletVelPress;   // Fan outlet velocity pressure [Pa]
    1249             :     Real64 EulerNum;            // Fan Euler number [-]
    1250             :     Real64 NormalizedEulerNum;  // Normalized Fan Euler number [-]
    1251             :     Real64 FanDimFlow;          // Fan dimensionless airflow [-]
    1252             :     Real64 FanSpdRadS;          // Fan shaft rotational speed [rad/s]
    1253             :     Real64 MotorSpeed;          // Motor shaft rotational speed [rpm]
    1254             :     Real64 XbeltMax;            // Factor for belt max eff curve [ln hp]
    1255             :     Real64 FanTrqRatio;         // Ratio of fan torque to max fan torque [-]
    1256             :     Real64 BeltPLEff;           // Belt normalized (part-load) efficiency [-]
    1257             :     Real64 XmotorMax;           // Factor for motor max eff curve [ln hp]
    1258             :     Real64 MotorOutPwrRatio;    // Ratio of motor output power to max motor output power [-]
    1259             :     Real64 MotorPLEff;          // Motor normalized (part-load) efficiency [-]
    1260        1943 :     Real64 VFDSpdRatio(0.0);    // Ratio of motor speed to motor max speed [-]
    1261        1943 :     Real64 VFDOutPwrRatio(0.0); // Ratio of VFD output power to max VFD output power [-]
    1262        3886 :     std::string CompName;       // component name
    1263        3886 :     std::string CompType;       // component type
    1264        3886 :     std::string SizingString;   // input field sizing description (e.g., Nominal Capacity)
    1265        1943 :     bool bPRINT = true;         // TRUE if sizing is reported to output (eio)
    1266             :     Real64 TempFlow;            // autosized flow rate of fan [m3/s]
    1267        1943 :     int FieldNum = 2;           // IDD numeric field number where input field description is found
    1268        1943 :     int NumFansSized = 0;       // counter used to deallocate temporary string array after all fans have been sized
    1269             : 
    1270        1943 :     auto &Fan(state.dataFans->Fan);
    1271        1943 :     auto &FanNumericFields(state.dataFans->FanNumericFields);
    1272        1943 :     auto &NightVentPerf(state.dataFans->NightVentPerf);
    1273             : 
    1274        1943 :     if (Fan(FanNum).FanType_Num == FanType_ComponentModel) {
    1275           4 :         FieldNum = 1;
    1276             :     } else {
    1277        1939 :         FieldNum = 3;
    1278             :     }
    1279        1943 :     SizingString = FanNumericFields(FanNum).FieldNames(FieldNum) + " [m3/s]";
    1280             : 
    1281        1943 :     TempFlow = Fan(FanNum).MaxAirFlowRate;
    1282        1943 :     state.dataSize->DataAutosizable = Fan(FanNum).MaxAirFlowRateIsAutosizable;
    1283        1943 :     CompType = Fan(FanNum).FanType;
    1284        1943 :     CompName = Fan(FanNum).FanName;
    1285        1943 :     state.dataSize->DataEMSOverrideON = Fan(FanNum).MaxAirFlowRateEMSOverrideOn;
    1286        1943 :     state.dataSize->DataEMSOverride = Fan(FanNum).MaxAirFlowRateEMSOverrideValue;
    1287             : 
    1288        1943 :     bool errorsFound = false;
    1289        3886 :     SystemAirFlowSizer sizerSystemAirFlow;
    1290        1943 :     sizerSystemAirFlow.overrideSizingString(SizingString);
    1291        1943 :     sizerSystemAirFlow.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
    1292        1943 :     Fan(FanNum).MaxAirFlowRate = sizerSystemAirFlow.size(state, TempFlow, errorsFound);
    1293             : 
    1294        1943 :     state.dataSize->DataAutosizable = true;
    1295        1943 :     state.dataSize->DataEMSOverrideON = false;
    1296        1943 :     state.dataSize->DataEMSOverride = 0.0;
    1297             : 
    1298        1943 :     FanVolFlow = Fan(FanNum).MaxAirFlowRate; // Maximum volumetric airflow through fan [m3/s at standard conditions]
    1299        1943 :     if (Fan(FanNum).FanType_Num == FanType_ComponentModel) {
    1300             :         // Get air density at standard conditions and get mass airflow through fan
    1301             :         // From WeatherManager:
    1302             :         //   StdBaroPress=(101.325d0*(1.0d0-2.25577d-05*WeatherFileElevation)**5.2559d0)*1000.d0
    1303             :         //   StdRhoAir=PsyRhoAirFnPbTdbW(StdBaroPress,20,0)
    1304             :         // From PsychRoutines:
    1305             :         //   w=MAX(dw,1.0d-5)
    1306             :         //   rhoair = pb/(287.d0*(tdb+DataGlobalConstants::KelvinConv())*(1.0d0+1.6077687d0*w))
    1307           4 :         RhoAir = state.dataEnvrn->StdRhoAir;
    1308             : 
    1309             :         // Adjust max fan volumetric airflow using fan sizing factor
    1310           4 :         FanVolFlow *= Fan(FanNum).FanSizingFactor; //[m3/s at standard conditions]
    1311             : 
    1312             :         // Calculate max fan static pressure rise using max fan volumetric flow, std air density, air-handling system characteristics,
    1313             :         //   and Sherman-Wray system curve model (assumes static pressure surrounding air distribution system is zero)
    1314           4 :         DuctStaticPress = CurveValue(state, Fan(FanNum).PressResetCurveIndex, FanVolFlow);               // Duct static pressure setpoint [Pa]
    1315           4 :         DeltaPressTot = CurveValue(state, Fan(FanNum).PressRiseCurveIndex, FanVolFlow, DuctStaticPress); // Max fan total pressure rise [Pa]
    1316           4 :         FanOutletVelPress = 0.5 * RhoAir * pow_2(FanVolFlow / Fan(FanNum).FanOutletArea);                // Max fan outlet velocity pressure [Pa]
    1317             :         // Outlet velocity pressure cannot exceed total pressure rise
    1318           4 :         FanOutletVelPress = min(FanOutletVelPress, DeltaPressTot);
    1319           4 :         Fan(FanNum).DeltaPress = DeltaPressTot - FanOutletVelPress; // Max fan static pressure rise [Pa]
    1320             : 
    1321             :         // Calculate max fan air power using volumetric flow abd corresponding fan static pressure rise
    1322           4 :         Fan(FanNum).FanAirPower = FanVolFlow * Fan(FanNum).DeltaPress; //[W]
    1323             : 
    1324             :         // Calculate fan wheel efficiency at max fan volumetric flow and corresponding fan static pressure rise,
    1325             :         //   using fan characteristics and Wray dimensionless fan static efficiency model
    1326           4 :         EulerNum = (Fan(FanNum).DeltaPress * pow_4(Fan(FanNum).FanWheelDia)) / (RhoAir * pow_2(FanVolFlow)); //[-]
    1327           4 :         NormalizedEulerNum = std::log10(EulerNum / Fan(FanNum).EuMaxEff);
    1328           4 :         if (NormalizedEulerNum <= 0.0) {
    1329           3 :             Fan(FanNum).FanWheelEff = CurveValue(state, Fan(FanNum).PLFanEffNormCurveIndex, NormalizedEulerNum);
    1330             :         } else {
    1331           1 :             Fan(FanNum).FanWheelEff = CurveValue(state, Fan(FanNum).PLFanEffStallCurveIndex, NormalizedEulerNum);
    1332             :         }
    1333           4 :         Fan(FanNum).FanWheelEff *= Fan(FanNum).FanMaxEff;             // [-]
    1334           4 :         Fan(FanNum).FanWheelEff = max(Fan(FanNum).FanWheelEff, 0.01); // Minimum efficiency is 1% to avoid numerical errors
    1335             : 
    1336             :         // Calculate max fan shaft power using fan air power and fan efficiency
    1337             :         // at max fan static pressure rise and max fan volumetric flow
    1338           4 :         Fan(FanNum).FanShaftPower = (Fan(FanNum).FanAirPower / Fan(FanNum).FanWheelEff); //[W]
    1339           4 :         Fan(FanNum).FanShaftPwrMax = Fan(FanNum).FanShaftPower;                          //[W]
    1340             : 
    1341             :         // Calculate fan shaft speed, motor speed, and fan torque using Wray dimensionless fan airflow model
    1342           4 :         if (NormalizedEulerNum <= 0.0) {
    1343           3 :             FanDimFlow = CurveValue(state, Fan(FanNum).DimFlowNormCurveIndex, NormalizedEulerNum); //[-]
    1344             :         } else {
    1345           1 :             FanDimFlow = CurveValue(state, Fan(FanNum).DimFlowStallCurveIndex, NormalizedEulerNum); //[-]
    1346             :         }
    1347           4 :         FanSpdRadS = FanVolFlow / (FanDimFlow * Fan(FanNum).FanMaxDimFlow * pow_3(Fan(FanNum).FanWheelDia)); //[rad/s]
    1348           4 :         Fan(FanNum).FanSpd = FanSpdRadS * 9.549296586;                                                       //[rpm, conversion factor is 30/PI]
    1349             : 
    1350           4 :         if (Fan(FanNum).PulleyDiaRatio == AutoSize) {
    1351             :             // WRITE(*,*) 'Autosizing pulley drive ratio'
    1352           4 :             Fan(FanNum).PulleyDiaRatio = Fan(FanNum).FanSpd / Fan(FanNum).MotorMaxSpd; //[-]
    1353             :         }
    1354             : 
    1355             :         // For direct-drive, should have PulleyDiaRatio = 1
    1356           4 :         MotorSpeed = Fan(FanNum).FanSpd / Fan(FanNum).PulleyDiaRatio; //[rpm]
    1357             : 
    1358             :         // Check for inconsistent drive ratio and motor speed, and report design fan speed with warning
    1359           4 :         if (MotorSpeed > (Fan(FanNum).MotorMaxSpd + 1.e-5)) {
    1360           0 :             ShowWarningError(state,
    1361           0 :                              "Drive ratio for " + Fan(FanNum).FanType + ": " + Fan(FanNum).FanName +
    1362             :                                  " is too low at design conditions -- check motor speed and drive ratio inputs");
    1363           0 :             ShowContinueError(state, format("...Design fan speed [rev/min]: {:.2R}", Fan(FanNum).FanSpd));
    1364             :         }
    1365             : 
    1366           4 :         Fan(FanNum).FanTrq = Fan(FanNum).FanShaftPower / FanSpdRadS; //[N-m]
    1367             : 
    1368           4 :         if (Fan(FanNum).BeltMaxTorque == AutoSize) {
    1369             :             // WRITE(*,*) 'Autosizing fan belt'
    1370           4 :             Fan(FanNum).BeltMaxTorque = Fan(FanNum).FanTrq; //[N-m]
    1371             :         }
    1372             :         // Adjust max belt torque using belt sizing factor
    1373           4 :         Fan(FanNum).BeltMaxTorque *= Fan(FanNum).BeltSizingFactor; //[N-m]
    1374             : 
    1375             :         // Check for undersized belt and report design size with warning
    1376           4 :         if (Fan(FanNum).FanTrq > (Fan(FanNum).BeltMaxTorque + 1.e-5)) {
    1377           0 :             ShowWarningError(
    1378           0 :                 state, "Belt for " + Fan(FanNum).FanType + ": " + Fan(FanNum).FanName + " is undersized at design conditions -- check belt inputs");
    1379           0 :             ShowContinueError(state, format("...Design belt output torque (without oversizing) [Nm]: {:.2R}", Fan(FanNum).FanTrq));
    1380             :         }
    1381             : 
    1382             :         // Calculate belt max efficiency using correlations and coefficients based on AMCA data
    1383             :         // Direct-drive is represented using curve coefficients such that "belt" max eff and PL eff = 1.0
    1384           4 :         XbeltMax = std::log(Fan(FanNum).FanShaftPwrMax / 746.0); // Natural log of belt output power in hp
    1385           4 :         if (Fan(FanNum).BeltMaxEffCurveIndex != 0) {
    1386           4 :             Fan(FanNum).BeltMaxEff = std::exp(CurveValue(state, Fan(FanNum).BeltMaxEffCurveIndex, XbeltMax)); //[-]
    1387             :         } else {
    1388           0 :             Fan(FanNum).BeltMaxEff = 1.0; // No curve specified - use constant efficiency
    1389             :         }
    1390             : 
    1391             :         // Calculate belt part-load drive efficiency and input power using correlations and coefficients based on ACEEE data
    1392           4 :         FanTrqRatio = Fan(FanNum).FanTrq / Fan(FanNum).BeltMaxTorque; //[-]
    1393           4 :         if ((FanTrqRatio <= Fan(FanNum).BeltTorqueTrans) && (Fan(FanNum).PLBeltEffReg1CurveIndex != 0)) {
    1394           0 :             BeltPLEff = CurveValue(state, Fan(FanNum).PLBeltEffReg1CurveIndex, FanTrqRatio); //[-]
    1395             :         } else {
    1396           4 :             if ((FanTrqRatio > Fan(FanNum).BeltTorqueTrans) && (FanTrqRatio <= 1.0) && (Fan(FanNum).PLBeltEffReg2CurveIndex != 0)) {
    1397           4 :                 BeltPLEff = CurveValue(state, Fan(FanNum).PLBeltEffReg2CurveIndex, FanTrqRatio); //[-]
    1398             :             } else {
    1399           0 :                 if ((FanTrqRatio > 1.0) && (Fan(FanNum).PLBeltEffReg3CurveIndex != 0)) {
    1400           0 :                     BeltPLEff = CurveValue(state, Fan(FanNum).PLBeltEffReg3CurveIndex, FanTrqRatio); //[-]
    1401             :                 } else {
    1402           0 :                     BeltPLEff = 1.0; // Direct drive or no curve specified - use constant efficiency
    1403             :                 }
    1404             :             }
    1405             :         }
    1406           4 :         Fan(FanNum).BeltEff = Fan(FanNum).BeltMaxEff * BeltPLEff;                     //[-]
    1407           4 :         Fan(FanNum).BeltEff = max(Fan(FanNum).BeltEff, 0.01);                         // Minimum efficiency is 1% to avoid numerical errors
    1408           4 :         Fan(FanNum).BeltInputPower = Fan(FanNum).FanShaftPower / Fan(FanNum).BeltEff; //[W]
    1409             : 
    1410           4 :         if (Fan(FanNum).MotorMaxOutPwr == AutoSize) {
    1411             :             // WRITE(*,*) 'Autosizing fan motor'
    1412           4 :             Fan(FanNum).MotorMaxOutPwr = Fan(FanNum).BeltInputPower;
    1413             :         }
    1414             :         // Adjust max motor output power using motor sizing factor
    1415           4 :         Fan(FanNum).MotorMaxOutPwr *= Fan(FanNum).MotorSizingFactor; //[W]
    1416             : 
    1417             :         // Check for undersized motor and report design size with warning
    1418           4 :         if (Fan(FanNum).BeltInputPower > (Fan(FanNum).MotorMaxOutPwr + 1.e-5)) {
    1419           0 :             ShowWarningError(
    1420           0 :                 state, "Motor for " + Fan(FanNum).FanType + ": " + Fan(FanNum).FanName + " is undersized at design conditions -- check motor inputs");
    1421           0 :             ShowContinueError(state, format("...Design motor output power (without oversizing) [W]: {:.2R}", Fan(FanNum).BeltInputPower));
    1422             :         }
    1423             : 
    1424             :         // Calculate motor max efficiency using correlations and coefficients based on MotorMaster+ data
    1425           4 :         XmotorMax = std::log(Fan(FanNum).MotorMaxOutPwr / 746.0); // Natural log of motor output power in hp
    1426           4 :         if (Fan(FanNum).MotorMaxEffCurveIndex != 0) {
    1427           4 :             Fan(FanNum).MotorMaxEff = CurveValue(state, Fan(FanNum).MotorMaxEffCurveIndex, XmotorMax); //[-]
    1428             :         } else {
    1429           0 :             Fan(FanNum).MotorMaxEff = 1.0; // No curve specified - use constant efficiency
    1430             :         }
    1431             : 
    1432             :         // Calculate motor part-load efficiency and input power using correlations and coefficients based on MotorMaster+ data
    1433           4 :         MotorOutPwrRatio = Fan(FanNum).BeltInputPower / Fan(FanNum).MotorMaxOutPwr; //[-]
    1434           4 :         if (Fan(FanNum).PLMotorEffCurveIndex != 0) {
    1435           4 :             MotorPLEff = CurveValue(state, Fan(FanNum).PLMotorEffCurveIndex, MotorOutPwrRatio); //[-]
    1436             :         } else {
    1437           0 :             MotorPLEff = 1.0; // No curve specified - use constant efficiency
    1438             :         }
    1439           4 :         Fan(FanNum).MotEff = Fan(FanNum).MotorMaxEff * MotorPLEff; //[-]
    1440           4 :         Fan(FanNum).MotEff = max(Fan(FanNum).MotEff, 0.01);        // Minimum efficiency is 1% to avoid numerical errors
    1441             : 
    1442             :         // Calculate motor input power using belt input power and motor efficiency
    1443           4 :         Fan(FanNum).MotorInputPower = Fan(FanNum).BeltInputPower / Fan(FanNum).MotEff; //[W]
    1444             : 
    1445             :         // Calculate max VFD efficiency and input power using correlations and coefficients based on VFD type
    1446           4 :         if ((Fan(FanNum).VFDEffType == "SPEED") && (Fan(FanNum).VFDEffCurveIndex != 0)) {
    1447           0 :             VFDSpdRatio = MotorSpeed / Fan(FanNum).MotorMaxSpd;                                //[-]
    1448           0 :             Fan(FanNum).VFDEff = CurveValue(state, Fan(FanNum).VFDEffCurveIndex, VFDSpdRatio); //[-]
    1449             :         } else {
    1450           4 :             if ((Fan(FanNum).VFDEffType == "POWER") && (Fan(FanNum).VFDEffCurveIndex != 0)) {
    1451           4 :                 if (Fan(FanNum).VFDMaxOutPwr == AutoSize) {
    1452             :                     // WRITE(*,*) 'Autosizing fan VFD'
    1453           4 :                     Fan(FanNum).VFDMaxOutPwr = Fan(FanNum).MotorInputPower;
    1454             :                 }
    1455             :                 // Adjust max VFD output power using VFD sizing factor
    1456           4 :                 Fan(FanNum).VFDMaxOutPwr *= Fan(FanNum).VFDSizingFactor; //[W]
    1457             : 
    1458             :                 // Check for undersized VFD and report design size with warning
    1459           4 :                 if (Fan(FanNum).MotorInputPower > (Fan(FanNum).VFDMaxOutPwr + 1.e-5)) {
    1460           0 :                     ShowWarningError(state,
    1461           0 :                                      "VFD for " + Fan(FanNum).FanType + ": " + Fan(FanNum).FanName +
    1462             :                                          " is undersized at design conditions -- check VFD inputs");
    1463           0 :                     ShowContinueError(state, format("...Design VFD output power (without oversizing) [W]: {:.2R}", Fan(FanNum).MotorInputPower));
    1464             :                 }
    1465             : 
    1466           4 :                 VFDOutPwrRatio = Fan(FanNum).MotorInputPower / Fan(FanNum).VFDMaxOutPwr;              //[-]
    1467           4 :                 Fan(FanNum).VFDEff = CurveValue(state, Fan(FanNum).VFDEffCurveIndex, VFDOutPwrRatio); //[-]
    1468             :             } else {
    1469             :                 // No curve specified - use constant efficiency
    1470           0 :                 Fan(FanNum).VFDMaxOutPwr = 0.0;
    1471           0 :                 Fan(FanNum).VFDEff = 0.97;
    1472             :             }
    1473             :         }
    1474           4 :         Fan(FanNum).VFDEff = max(Fan(FanNum).VFDEff, 0.01); // Minimum efficiency is 1% to avoid numerical errors
    1475             : 
    1476             :         // Calculate VFD "rated" input power using motor input power and VFD efficiency
    1477           4 :         RatedPower = Fan(FanNum).MotorInputPower / Fan(FanNum).VFDEff; //[W]
    1478             : 
    1479             :         // Calculate combined fan system efficiency: includes fan, belt, motor, and VFD
    1480             :         // Equivalent to Fan(FanNum)%FanAirPower / Fan(FanNum)%FanPower
    1481           4 :         Fan(FanNum).FanEff = Fan(FanNum).FanWheelEff * Fan(FanNum).BeltEff * Fan(FanNum).MotEff * Fan(FanNum).VFDEff;
    1482             : 
    1483             :         // Report fan, belt, motor, and VFD characteristics at design condition to .eio file
    1484           4 :         BaseSizer::reportSizerOutput(state, Fan(FanNum).FanType, Fan(FanNum).FanName, "Design Fan Airflow [m3/s]", FanVolFlow);
    1485           4 :         BaseSizer::reportSizerOutput(state, Fan(FanNum).FanType, Fan(FanNum).FanName, "Design Fan Static Pressure Rise [Pa]", Fan(FanNum).DeltaPress);
    1486           4 :         BaseSizer::reportSizerOutput(state, Fan(FanNum).FanType, Fan(FanNum).FanName, "Design Fan Shaft Power [W]", Fan(FanNum).FanShaftPower);
    1487           4 :         BaseSizer::reportSizerOutput(state, Fan(FanNum).FanType, Fan(FanNum).FanName, "Design Motor Output Power [W]", Fan(FanNum).MotorMaxOutPwr);
    1488           4 :         BaseSizer::reportSizerOutput(state, Fan(FanNum).FanType, Fan(FanNum).FanName, "Design VFD Output Power [W]", Fan(FanNum).VFDMaxOutPwr);
    1489           4 :         BaseSizer::reportSizerOutput(state, Fan(FanNum).FanType, Fan(FanNum).FanName, "Rated Power [W]", RatedPower);
    1490           4 :         BaseSizer::reportSizerOutput(state, Fan(FanNum).FanType, Fan(FanNum).FanName, "Drive Ratio []", Fan(FanNum).PulleyDiaRatio);
    1491           4 :         BaseSizer::reportSizerOutput(state, Fan(FanNum).FanType, Fan(FanNum).FanName, "Design Belt Output Torque [Nm]", Fan(FanNum).BeltMaxTorque);
    1492           4 :         BaseSizer::reportSizerOutput(state, Fan(FanNum).FanType, Fan(FanNum).FanName, "Design Fan Efficiency  []", Fan(FanNum).FanWheelEff);
    1493           4 :         BaseSizer::reportSizerOutput(state, Fan(FanNum).FanType, Fan(FanNum).FanName, "Maximum Belt Efficiency []", Fan(FanNum).BeltMaxEff);
    1494           4 :         BaseSizer::reportSizerOutput(state, Fan(FanNum).FanType, Fan(FanNum).FanName, "Design Belt Efficiency []", Fan(FanNum).BeltEff);
    1495           4 :         BaseSizer::reportSizerOutput(state, Fan(FanNum).FanType, Fan(FanNum).FanName, "Maximum Motor Efficiency []", Fan(FanNum).MotorMaxEff);
    1496           4 :         BaseSizer::reportSizerOutput(state, Fan(FanNum).FanType, Fan(FanNum).FanName, "Design Motor Efficiency []", Fan(FanNum).MotEff);
    1497           4 :         BaseSizer::reportSizerOutput(state, Fan(FanNum).FanType, Fan(FanNum).FanName, "Design VFD Efficiency []", Fan(FanNum).VFDEff);
    1498           4 :         BaseSizer::reportSizerOutput(state, Fan(FanNum).FanType, Fan(FanNum).FanName, "Design Combined Efficiency []", Fan(FanNum).FanEff);
    1499             :     } // End fan component sizing
    1500             : 
    1501        1943 :     equipName = Fan(FanNum).FanName;
    1502             : 
    1503             :     // Rearrange order to match table and use FanVolFlow to calculate RatedPower
    1504             :     // ALSO generates values if Component Model fan, for which DeltaPress and FanEff vary with flow
    1505        1943 :     PreDefTableEntry(state, state.dataOutRptPredefined->pdchFanType, equipName, Fan(FanNum).FanType);
    1506        1943 :     PreDefTableEntry(state, state.dataOutRptPredefined->pdchFanTotEff, equipName, Fan(FanNum).FanEff);
    1507        1943 :     PreDefTableEntry(state, state.dataOutRptPredefined->pdchFanDeltaP, equipName, Fan(FanNum).DeltaPress);
    1508        1943 :     PreDefTableEntry(state, state.dataOutRptPredefined->pdchFanVolFlow, equipName, FanVolFlow);
    1509        1943 :     RatedPower = FanVolFlow * Fan(FanNum).DeltaPress / Fan(FanNum).FanEff; // total fan power
    1510        1943 :     if (Fan(FanNum).FanType_Num != FanType_ComponentModel) {
    1511        1939 :         Fan(FanNum).DesignPointFEI =
    1512        1939 :             HVACFan::FanSystem::report_fei(state, FanVolFlow, RatedPower, Fan(FanNum).DeltaPress, state.dataEnvrn->StdRhoAir);
    1513             :     }
    1514        1943 :     PreDefTableEntry(state, state.dataOutRptPredefined->pdchFanPwr, equipName, RatedPower);
    1515        1943 :     if (FanVolFlow != 0.0) {
    1516        1934 :         PreDefTableEntry(state, state.dataOutRptPredefined->pdchFanPwrPerFlow, equipName, RatedPower / FanVolFlow);
    1517             :     }
    1518        1943 :     PreDefTableEntry(state, state.dataOutRptPredefined->pdchFanMotorIn, equipName, Fan(FanNum).MotInAirFrac);
    1519        1943 :     PreDefTableEntry(state, state.dataOutRptPredefined->pdchFanEndUse, equipName, Fan(FanNum).EndUseSubcategoryName);
    1520        1943 :     PreDefTableEntry(state, state.dataOutRptPredefined->pdchFanEnergyIndex, equipName, Fan(FanNum).DesignPointFEI);
    1521             : 
    1522        1943 :     NVPerfNum = Fan(FanNum).NVPerfNum;
    1523        1943 :     if (NVPerfNum > 0) {
    1524           0 :         if (NightVentPerf(NVPerfNum).MaxAirFlowRate == AutoSize) {
    1525           0 :             NightVentPerf(NVPerfNum).MaxAirFlowRate = Fan(FanNum).MaxAirFlowRate;
    1526             :         }
    1527             :     }
    1528             : 
    1529             :     // Now that sizing is done, do check if the design point of fan is covered in the fault Fan Curve
    1530        1943 :     if (Fan(FanNum).FaultyFilterFlag) {
    1531           1 :         int jFault_AirFilter = Fan(FanNum).FaultyFilterIndex;
    1532             : 
    1533             :         // Check fault availability schedules
    1534           1 :         if (!state.dataFaultsMgr->FaultsFouledAirFilters(jFault_AirFilter).CheckFaultyAirFilterFanCurve(state)) {
    1535           0 :             ShowSevereError(state, "FaultModel:Fouling:AirFilter = \"" + state.dataFaultsMgr->FaultsFouledAirFilters(jFault_AirFilter).Name + "\"");
    1536           0 :             ShowContinueError(state,
    1537           0 :                               "Invalid Fan Curve Name = \"" + state.dataFaultsMgr->FaultsFouledAirFilters(jFault_AirFilter).FaultyAirFilterFanCurve +
    1538             :                                   "\" does not cover ");
    1539           0 :             ShowContinueError(state, "the operational point of Fan " + Fan(FanNum).FanName);
    1540           0 :             ShowFatalError(state,
    1541           0 :                            "SizeFan: Invalid FaultModel:Fouling:AirFilter=" + state.dataFaultsMgr->FaultsFouledAirFilters(jFault_AirFilter).Name);
    1542             :         }
    1543             :     }
    1544             : 
    1545        1943 :     if (++NumFansSized == state.dataFans->NumFans) FanNumericFields.deallocate(); // remove temporary array for field names at end of sizing
    1546        1943 : }
    1547             : 
    1548    11873687 : void SimSimpleFan(EnergyPlusData &state, int const FanNum)
    1549             : {
    1550             : 
    1551             :     // SUBROUTINE INFORMATION:
    1552             :     //       AUTHOR         Unknown
    1553             :     //       DATE WRITTEN   Unknown
    1554             :     //       MODIFIED       Brent Griffith, May 2009, added EMS override
    1555             :     //                      Chandan Sharma, March 2011, FSEC: Added LocalTurnFansOn and LocalTurnFansOff
    1556             :     //                      Rongpeng Zhang, April 2015, added faulty fan operations due to fouling air filters
    1557             :     //       RE-ENGINEERED  na
    1558             : 
    1559             :     // PURPOSE OF THIS SUBROUTINE:
    1560             :     // This subroutine simulates the simple constant volume fan.
    1561             : 
    1562             :     // METHODOLOGY EMPLOYED:
    1563             :     // Converts design pressure rise and efficiency into fan power and temperature rise
    1564             :     // Constant fan pressure rise is assumed.
    1565             : 
    1566             :     // REFERENCES:
    1567             :     // ASHRAE HVAC 2 Toolkit, page 2-3 (FANSIM)
    1568             : 
    1569             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1570             :     Real64 RhoAir;
    1571             :     Real64 DeltaPress; // [N/m2]
    1572             :     Real64 FanEff;
    1573             :     Real64 MotInAirFrac;
    1574             :     Real64 MotEff;
    1575             :     Real64 MassFlow;      // [kg/sec]
    1576             :     Real64 FanShaftPower; // power delivered to fan shaft
    1577             : 
    1578             :     int NVPerfNum;
    1579             : 
    1580    11873687 :     auto &Fan(state.dataFans->Fan);
    1581    11873687 :     auto &NightVentPerf(state.dataFans->NightVentPerf);
    1582             : 
    1583    11873687 :     NVPerfNum = Fan(FanNum).NVPerfNum;
    1584             : 
    1585    11873687 :     if (state.dataHVACGlobal->NightVentOn && NVPerfNum > 0) {
    1586           0 :         DeltaPress = NightVentPerf(NVPerfNum).DeltaPress;
    1587           0 :         FanEff = NightVentPerf(NVPerfNum).FanEff;
    1588           0 :         MotEff = NightVentPerf(NVPerfNum).MotEff;
    1589           0 :         MotInAirFrac = NightVentPerf(NVPerfNum).MotInAirFrac;
    1590             :     } else {
    1591    11873687 :         DeltaPress = Fan(FanNum).DeltaPress;
    1592    11873687 :         FanEff = Fan(FanNum).FanEff;
    1593    11873687 :         MotEff = Fan(FanNum).MotEff;
    1594    11873687 :         MotInAirFrac = Fan(FanNum).MotInAirFrac;
    1595             :     }
    1596             : 
    1597             :     // For a Constant Volume Simple Fan the Max Flow Rate is the Flow Rate for the fan
    1598             :     // unused0909   Tin        = Fan(FanNum)%InletAirTemp
    1599             :     // unused0909   Win        = Fan(FanNum)%InletAirHumRat
    1600    11873687 :     RhoAir = Fan(FanNum).RhoAirStdInit;
    1601    11873687 :     MassFlow = Fan(FanNum).InletAirMassFlowRate;
    1602             : 
    1603             :     // Faulty fan operations
    1604             :     // Update MassFlow & DeltaPress if there are fouling air filters corresponding to the fan
    1605    11873687 :     if (Fan(FanNum).FaultyFilterFlag && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) &&
    1606           0 :         (!state.dataGlobal->KickOffSimulation)) {
    1607             : 
    1608           0 :         int iFault = Fan(FanNum).FaultyFilterIndex;
    1609             : 
    1610             :         // Check fault availability schedules
    1611           0 :         if (GetCurrentScheduleValue(state, state.dataFaultsMgr->FaultsFouledAirFilters(iFault).AvaiSchedPtr) > 0.0) {
    1612           0 :             Real64 FanDesignFlowRateDec = 0; // Decrease of the Fan Design Volume Flow Rate [m3/sec]
    1613             : 
    1614           0 :             FanDesignFlowRateDec = CalFaultyFanAirFlowReduction(
    1615             :                 state,
    1616           0 :                 Fan(FanNum).FanName,
    1617           0 :                 Fan(FanNum).MaxAirFlowRate,
    1618           0 :                 Fan(FanNum).DeltaPress,
    1619           0 :                 (GetCurrentScheduleValue(state, state.dataFaultsMgr->FaultsFouledAirFilters(iFault).FaultyAirFilterPressFracSchePtr) - 1) *
    1620           0 :                     Fan(FanNum).DeltaPress,
    1621           0 :                 state.dataFaultsMgr->FaultsFouledAirFilters(iFault).FaultyAirFilterFanCurvePtr);
    1622             : 
    1623             :             // Update MassFlow & DeltaPress of the fan
    1624           0 :             MassFlow = min(MassFlow, Fan(FanNum).MaxAirMassFlowRate - FanDesignFlowRateDec * RhoAir);
    1625           0 :             DeltaPress = GetCurrentScheduleValue(state, state.dataFaultsMgr->FaultsFouledAirFilters(iFault).FaultyAirFilterPressFracSchePtr) *
    1626           0 :                          Fan(FanNum).DeltaPress;
    1627             :         }
    1628             :     }
    1629             : 
    1630             :     // EMS overwrite MassFlow, DeltaPress, and FanEff
    1631    11873687 :     if (Fan(FanNum).EMSMaxMassFlowOverrideOn) MassFlow = Fan(FanNum).EMSAirMassFlowValue;
    1632    11873687 :     if (Fan(FanNum).EMSFanPressureOverrideOn) DeltaPress = Fan(FanNum).EMSFanPressureValue;
    1633    11873687 :     if (Fan(FanNum).EMSFanEffOverrideOn) FanEff = Fan(FanNum).EMSFanEffValue;
    1634             : 
    1635    11873687 :     MassFlow = min(MassFlow, Fan(FanNum).MaxAirMassFlowRate);
    1636    11873687 :     MassFlow = max(MassFlow, Fan(FanNum).MinAirMassFlowRate);
    1637             : 
    1638             :     // Determine the Fan Schedule for the Time step
    1639    36148354 :     if ((GetCurrentScheduleValue(state, Fan(FanNum).AvailSchedPtrNum) > 0.0 || state.dataFans->LocalTurnFansOn) &&
    1640    32484307 :         !state.dataFans->LocalTurnFansOff && MassFlow > 0.0) {
    1641             :         // Fan is operating
    1642     9870914 :         Fan(FanNum).FanPower = max(0.0, MassFlow * DeltaPress / (FanEff * RhoAir)); // total fan power
    1643     9870914 :         FanShaftPower = MotEff * Fan(FanNum).FanPower;                              // power delivered to shaft
    1644     9870914 :         Fan(FanNum).PowerLossToAir = FanShaftPower + (Fan(FanNum).FanPower - FanShaftPower) * MotInAirFrac;
    1645     9870914 :         Fan(FanNum).OutletAirEnthalpy = Fan(FanNum).InletAirEnthalpy + Fan(FanNum).PowerLossToAir / MassFlow;
    1646             :         // This fan does not change the moisture or Mass Flow across the component
    1647     9870914 :         Fan(FanNum).OutletAirHumRat = Fan(FanNum).InletAirHumRat;
    1648     9870914 :         Fan(FanNum).OutletAirMassFlowRate = MassFlow;
    1649     9870914 :         Fan(FanNum).OutletAirTemp = PsyTdbFnHW(Fan(FanNum).OutletAirEnthalpy, Fan(FanNum).OutletAirHumRat);
    1650             : 
    1651             :     } else {
    1652             :         // Fan is off and not operating no power consumed and mass flow rate.
    1653     2002773 :         Fan(FanNum).FanPower = 0.0;
    1654     2002773 :         FanShaftPower = 0.0;
    1655     2002773 :         Fan(FanNum).PowerLossToAir = 0.0;
    1656     2002773 :         Fan(FanNum).OutletAirMassFlowRate = 0.0;
    1657     2002773 :         Fan(FanNum).OutletAirHumRat = Fan(FanNum).InletAirHumRat;
    1658     2002773 :         Fan(FanNum).OutletAirEnthalpy = Fan(FanNum).InletAirEnthalpy;
    1659     2002773 :         Fan(FanNum).OutletAirTemp = Fan(FanNum).InletAirTemp;
    1660             :         // Set the Control Flow variables to 0.0 flow when OFF.
    1661     2002773 :         Fan(FanNum).MassFlowRateMaxAvail = 0.0;
    1662     2002773 :         Fan(FanNum).MassFlowRateMinAvail = 0.0;
    1663             :     }
    1664    11873687 : }
    1665             : 
    1666    17080494 : void SimVariableVolumeFan(EnergyPlusData &state, int const FanNum, Optional<Real64 const> PressureRise)
    1667             : {
    1668             : 
    1669             :     // SUBROUTINE INFORMATION:
    1670             :     //       AUTHOR         Unknown
    1671             :     //       DATE WRITTEN   Unknown
    1672             :     //       MODIFIED       Phil Haves
    1673             :     //                      Brent Griffith, May 2009 for EMS
    1674             :     //                      Chandan Sharma, March 2011, FSEC: Added LocalTurnFansOn and LocalTurnFansOff
    1675             :     //                      Rongpeng Zhang, April 2015, added faulty fan operations due to fouling air filters
    1676             :     //       RE-ENGINEERED  na
    1677             : 
    1678             :     // PURPOSE OF THIS SUBROUTINE:
    1679             :     // This subroutine simulates the simple variable volume fan.
    1680             : 
    1681             :     // METHODOLOGY EMPLOYED:
    1682             :     // Converts design pressure rise and efficiency into fan power and temperature rise
    1683             :     // Constant fan pressure rise is assumed.
    1684             :     // Uses curves of fan power fraction vs. fan part load to determine fan power at
    1685             :     // off design conditions.
    1686             : 
    1687             :     // REFERENCES:
    1688             :     // ASHRAE HVAC 2 Toolkit, page 2-3 (FANSIM)
    1689             : 
    1690             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1691             :     Real64 RhoAir;
    1692             :     Real64 DeltaPress; // [N/m2 = Pa]
    1693             :     Real64 FanEff;     // Total fan efficiency - combined efficiency of fan, drive train,
    1694             :     // motor and variable speed controller (if any)
    1695             :     Real64 MaxAirFlowRate;
    1696             :     Real64 MaxAirMassFlowRate;
    1697             :     Real64 MotInAirFrac;
    1698             :     Real64 MotEff;
    1699             :     Real64 MassFlow; // [kg/sec]
    1700             :     Real64 PartLoadFrac;
    1701             :     Real64 MinFlowFrac;           // Variable Volume Fan Min Flow Fraction [-]
    1702    17080494 :     Real64 FlowFracForPower(0.0); // Variable Volume Fan Flow Fraction for power calcs[-]
    1703    17080494 :     Real64 FlowFracActual(0.0);   // actual VAV fan flow fraction
    1704             :     Real64 FanShaftPower;         // power delivered to fan shaft
    1705             :     int NVPerfNum;
    1706             : 
    1707             :     // added to address the fan heat issue during low air flow conditions
    1708             :     Real64 MinFlowFracLimitFanHeat; // Minimum Fan Flow Fraction Limit for Fan Heat at Low Airflow [-]
    1709             :     Real64 FanPoweratLowMinimum;    // Fan Power at Low Minimum Airflow [W]
    1710             :     Real64 PartLoadFracatLowMin;
    1711             :     Real64 DeltaTAcrossFan; // Air temperature rise across the fan due to fan heat [C]
    1712             : 
    1713             :     // Simple Variable Volume Fan - default values from DOE-2
    1714             :     // Type of Fan          Coeff1       Coeff2       Coeff3        Coeff4      Coeff5
    1715             :     // INLET VANE DAMPERS   0.35071223   0.30850535   -0.54137364   0.87198823  0.000
    1716             :     // DISCHARGE DAMPERS    0.37073425   0.97250253   -0.34240761   0.000       0.000
    1717             :     // VARIABLE SPEED MOTOR 0.0015302446 0.0052080574  1.1086242   -0.11635563  0.000
    1718             : 
    1719    17080494 :     auto &Fan(state.dataFans->Fan);
    1720    17080494 :     auto &NightVentPerf(state.dataFans->NightVentPerf);
    1721             : 
    1722    17080494 :     NVPerfNum = Fan(FanNum).NVPerfNum;
    1723    17080494 :     MaxAirFlowRate = Fan(FanNum).MaxAirFlowRate;
    1724             : 
    1725    17080494 :     if (state.dataHVACGlobal->NightVentOn && NVPerfNum > 0) {
    1726           0 :         DeltaPress = NightVentPerf(NVPerfNum).DeltaPress;
    1727           0 :         FanEff = NightVentPerf(NVPerfNum).FanEff;
    1728           0 :         MotEff = NightVentPerf(NVPerfNum).MotEff;
    1729           0 :         MotInAirFrac = NightVentPerf(NVPerfNum).MotInAirFrac;
    1730           0 :         MaxAirMassFlowRate = NightVentPerf(NVPerfNum).MaxAirMassFlowRate;
    1731             :     } else {
    1732    17080494 :         if (present(PressureRise)) {
    1733       28596 :             DeltaPress = PressureRise;
    1734             :         } else {
    1735    17051898 :             DeltaPress = Fan(FanNum).DeltaPress;
    1736             :         }
    1737    17080494 :         FanEff = Fan(FanNum).FanEff;
    1738    17080494 :         MotEff = Fan(FanNum).MotEff;
    1739    17080494 :         MotInAirFrac = Fan(FanNum).MotInAirFrac;
    1740    17080494 :         MaxAirMassFlowRate = Fan(FanNum).MaxAirMassFlowRate;
    1741             :     }
    1742             : 
    1743             :     // unused0909  Tin         = Fan(FanNum)%InletAirTemp
    1744             :     // unused0909  Win         = Fan(FanNum)%InletAirHumRat
    1745    17080494 :     RhoAir = Fan(FanNum).RhoAirStdInit;
    1746    17080494 :     MassFlow = Fan(FanNum).InletAirMassFlowRate;
    1747             : 
    1748             :     // Faulty fan operations
    1749             :     // Update MassFlow & DeltaPress if there are fouling air filters corresponding to the fan
    1750    34181765 :     if (Fan(FanNum).FaultyFilterFlag && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) &&
    1751    17085630 :         (!state.dataGlobal->KickOffSimulation) && (!Fan(FanNum).EMSMaxMassFlowOverrideOn)) {
    1752             : 
    1753        2568 :         int iFault = Fan(FanNum).FaultyFilterIndex;
    1754             : 
    1755             :         // Check fault availability schedules
    1756        2568 :         if (GetCurrentScheduleValue(state, state.dataFaultsMgr->FaultsFouledAirFilters(iFault).AvaiSchedPtr) > 0.0) {
    1757        2568 :             Real64 FanDesignFlowRateDec = 0; // Decrease of the Fan Design Volume Flow Rate [m3/sec]
    1758             : 
    1759       12840 :             FanDesignFlowRateDec = CalFaultyFanAirFlowReduction(
    1760             :                 state,
    1761        2568 :                 Fan(FanNum).FanName,
    1762        2568 :                 Fan(FanNum).MaxAirFlowRate,
    1763        2568 :                 Fan(FanNum).DeltaPress,
    1764        2568 :                 (GetCurrentScheduleValue(state, state.dataFaultsMgr->FaultsFouledAirFilters(iFault).FaultyAirFilterPressFracSchePtr) - 1) *
    1765        2568 :                     Fan(FanNum).DeltaPress,
    1766        2568 :                 state.dataFaultsMgr->FaultsFouledAirFilters(iFault).FaultyAirFilterFanCurvePtr);
    1767             : 
    1768             :             // Update MassFlow & DeltaPress of the fan
    1769        2568 :             MaxAirFlowRate = Fan(FanNum).MaxAirFlowRate - FanDesignFlowRateDec;
    1770        2568 :             MaxAirMassFlowRate = Fan(FanNum).MaxAirMassFlowRate - FanDesignFlowRateDec * RhoAir;
    1771        5136 :             DeltaPress = GetCurrentScheduleValue(state, state.dataFaultsMgr->FaultsFouledAirFilters(iFault).FaultyAirFilterPressFracSchePtr) *
    1772        2568 :                          Fan(FanNum).DeltaPress;
    1773             :         }
    1774             :     }
    1775             : 
    1776             :     // EMS overwrite MassFlow, DeltaPress, and FanEff
    1777    17080494 :     if (Fan(FanNum).EMSFanPressureOverrideOn) DeltaPress = Fan(FanNum).EMSFanPressureValue;
    1778    17080494 :     if (Fan(FanNum).EMSFanEffOverrideOn) FanEff = Fan(FanNum).EMSFanEffValue;
    1779    17080494 :     if (Fan(FanNum).EMSMaxMassFlowOverrideOn) MassFlow = Fan(FanNum).EMSAirMassFlowValue;
    1780             : 
    1781    17080494 :     MassFlow = min(MassFlow, MaxAirMassFlowRate);
    1782             : 
    1783             :     // Determine the Fan Schedule for the Time step
    1784    53478978 :     if ((GetCurrentScheduleValue(state, Fan(FanNum).AvailSchedPtrNum) > 0.0 || state.dataFans->LocalTurnFansOn) &&
    1785    47984538 :         !state.dataFans->LocalTurnFansOff && MassFlow > 0.0) {
    1786             :         // Fan is operating - calculate power loss and enthalpy rise
    1787             :         //  Fan(FanNum)%FanPower = PartLoadFrac*FullMassFlow*DeltaPress/(FanEff*RhoAir) ! total fan power
    1788             :         // Calculate and check limits on fraction of system flow
    1789             :         // unused0909    MaxFlowFrac = 1.0
    1790             :         // MinFlowFrac is calculated from the ration of the volume flows and is non-dimensional
    1791    15326563 :         MinFlowFrac = Fan(FanNum).MinAirFlowRate / MaxAirFlowRate;
    1792             :         // The actual flow fraction is calculated from MassFlow and the MaxVolumeFlow * AirDensity
    1793    15326563 :         FlowFracActual = MassFlow / MaxAirMassFlowRate;
    1794             : 
    1795             :         // Calculate the part Load Fraction             (PH 7/13/03)
    1796             : 
    1797    15326563 :         FlowFracForPower = max(MinFlowFrac, min(FlowFracActual, 1.0)); // limit flow fraction to allowed range
    1798    15326563 :         if (state.dataHVACGlobal->NightVentOn && NVPerfNum > 0) {
    1799           0 :             PartLoadFrac = 1.0;
    1800             :         } else {
    1801    45979689 :             PartLoadFrac = Fan(FanNum).FanCoeff(1) + Fan(FanNum).FanCoeff(2) * FlowFracForPower + Fan(FanNum).FanCoeff(3) * pow_2(FlowFracForPower) +
    1802    30653126 :                            Fan(FanNum).FanCoeff(4) * pow_3(FlowFracForPower) + Fan(FanNum).FanCoeff(5) * pow_4(FlowFracForPower);
    1803             :         }
    1804             : 
    1805    15326563 :         Fan(FanNum).FanPower = max(0.0, PartLoadFrac * MaxAirMassFlowRate * DeltaPress / (FanEff * RhoAir)); // total fan power (PH 7/13/03)
    1806             : 
    1807    15326563 :         FanShaftPower = MotEff * Fan(FanNum).FanPower; // power delivered to shaft
    1808    15326563 :         Fan(FanNum).PowerLossToAir = FanShaftPower + (Fan(FanNum).FanPower - FanShaftPower) * MotInAirFrac;
    1809    15326563 :         Fan(FanNum).OutletAirEnthalpy = Fan(FanNum).InletAirEnthalpy + Fan(FanNum).PowerLossToAir / MassFlow;
    1810             :         // This fan does not change the moisture or Mass Flow across the component
    1811    15326563 :         Fan(FanNum).OutletAirHumRat = Fan(FanNum).InletAirHumRat;
    1812    15326563 :         Fan(FanNum).OutletAirMassFlowRate = MassFlow;
    1813    15326563 :         Fan(FanNum).OutletAirTemp = PsyTdbFnHW(Fan(FanNum).OutletAirEnthalpy, Fan(FanNum).OutletAirHumRat);
    1814             : 
    1815             :         // KHL/FB, 2/10/2011. NFP implemented as CR 8338.
    1816             :         // When fan air flow is less than 10%, the fan power curve is linearized between the 10% to 0% to
    1817             :         //  avoid the unrealistic high temperature rise across the fan.
    1818             :         // TH, 2/15/2011
    1819             :         // This change caused diffs for VAV systems when fan runs at less than 10% flow conditions.
    1820             :         //  A potential way to improve is to check the temperature rise across the fan first,
    1821             :         //  if it is too high (say > 20C) then applies the code.
    1822    15326563 :         DeltaTAcrossFan = Fan(FanNum).OutletAirTemp - Fan(FanNum).InletAirTemp;
    1823    15326563 :         if (DeltaTAcrossFan > 20.0) {
    1824           0 :             MinFlowFracLimitFanHeat = 0.10;
    1825           0 :             if (FlowFracForPower < MinFlowFracLimitFanHeat) {
    1826           0 :                 PartLoadFracatLowMin = Fan(FanNum).FanCoeff(1) + Fan(FanNum).FanCoeff(2) * MinFlowFracLimitFanHeat +
    1827           0 :                                        Fan(FanNum).FanCoeff(3) * pow_2(MinFlowFracLimitFanHeat) +
    1828           0 :                                        Fan(FanNum).FanCoeff(4) * pow_3(MinFlowFracLimitFanHeat) +
    1829           0 :                                        Fan(FanNum).FanCoeff(5) * pow_4(MinFlowFracLimitFanHeat);
    1830           0 :                 FanPoweratLowMinimum = PartLoadFracatLowMin * MaxAirMassFlowRate * DeltaPress / (FanEff * RhoAir);
    1831           0 :                 Fan(FanNum).FanPower = max(0.0, FlowFracForPower * FanPoweratLowMinimum / MinFlowFracLimitFanHeat);
    1832           0 :             } else if (FlowFracActual < MinFlowFracLimitFanHeat) {
    1833           0 :                 PartLoadFracatLowMin = Fan(FanNum).FanCoeff(1) + Fan(FanNum).FanCoeff(2) * MinFlowFracLimitFanHeat +
    1834           0 :                                        Fan(FanNum).FanCoeff(3) * pow_2(MinFlowFracLimitFanHeat) +
    1835           0 :                                        Fan(FanNum).FanCoeff(4) * pow_3(MinFlowFracLimitFanHeat) +
    1836           0 :                                        Fan(FanNum).FanCoeff(5) * pow_4(MinFlowFracLimitFanHeat);
    1837           0 :                 FanPoweratLowMinimum = PartLoadFracatLowMin * MaxAirMassFlowRate * DeltaPress / (FanEff * RhoAir);
    1838           0 :                 Fan(FanNum).FanPower = max(0.0, FlowFracActual * FanPoweratLowMinimum / MinFlowFracLimitFanHeat);
    1839             :             }
    1840           0 :             FanShaftPower = MotEff * Fan(FanNum).FanPower; // power delivered to shaft
    1841           0 :             Fan(FanNum).PowerLossToAir = FanShaftPower + (Fan(FanNum).FanPower - FanShaftPower) * MotInAirFrac;
    1842           0 :             Fan(FanNum).OutletAirEnthalpy = Fan(FanNum).InletAirEnthalpy + Fan(FanNum).PowerLossToAir / MassFlow;
    1843             :             // This fan does not change the moisture or Mass Flow across the component
    1844           0 :             Fan(FanNum).OutletAirHumRat = Fan(FanNum).InletAirHumRat;
    1845           0 :             Fan(FanNum).OutletAirMassFlowRate = MassFlow;
    1846           0 :             Fan(FanNum).OutletAirTemp = PsyTdbFnHW(Fan(FanNum).OutletAirEnthalpy, Fan(FanNum).OutletAirHumRat);
    1847             :         }
    1848             : 
    1849             :     } else {
    1850             :         // Fan is off and not operating no power consumed and mass flow rate.
    1851     1753931 :         Fan(FanNum).FanPower = 0.0;
    1852     1753931 :         FanShaftPower = 0.0;
    1853     1753931 :         Fan(FanNum).PowerLossToAir = 0.0;
    1854     1753931 :         Fan(FanNum).OutletAirMassFlowRate = 0.0;
    1855     1753931 :         Fan(FanNum).OutletAirHumRat = Fan(FanNum).InletAirHumRat;
    1856     1753931 :         Fan(FanNum).OutletAirEnthalpy = Fan(FanNum).InletAirEnthalpy;
    1857     1753931 :         Fan(FanNum).OutletAirTemp = Fan(FanNum).InletAirTemp;
    1858             :         // Set the Control Flow variables to 0.0 flow when OFF.
    1859     1753931 :         Fan(FanNum).MassFlowRateMaxAvail = 0.0;
    1860     1753931 :         Fan(FanNum).MassFlowRateMinAvail = 0.0;
    1861             :     }
    1862    17080494 : }
    1863             : 
    1864   107762510 : void SimOnOffFan(EnergyPlusData &state, int const FanNum, Optional<Real64 const> SpeedRatio)
    1865             : {
    1866             : 
    1867             :     // SUBROUTINE INFORMATION:
    1868             :     //       AUTHOR         Unknown
    1869             :     //       DATE WRITTEN   Unknown
    1870             :     //       MODIFIED       Shirey, May 2001
    1871             :     //                      R. Raustad - FSEC, Jan 2009 - added SpeedRatio for multi-speed fans
    1872             :     //                      Brent Griffith, May 2009 for EMS
    1873             :     //                      Chandan Sharma, March 2011, FSEC: Added LocalTurnFansOn and LocalTurnFansOff
    1874             :     //                      Rongpeng Zhang, April 2015, added faulty fan operations due to fouling air filters
    1875             :     //       RE-ENGINEERED  na
    1876             : 
    1877             :     // PURPOSE OF THIS SUBROUTINE:
    1878             :     // This subroutine simulates the simple on/off fan.
    1879             : 
    1880             :     // METHODOLOGY EMPLOYED:
    1881             :     // Converts design pressure rise and efficiency into fan power and temperature rise
    1882             :     // Constant fan pressure rise is assumed.
    1883             :     // Uses curves of fan power fraction vs. fan part load to determine fan power at
    1884             :     // off design conditions.
    1885             :     // Same as simple (constant volume) fan, except added part-load curve input
    1886             : 
    1887             :     // REFERENCES:
    1888             :     // ASHRAE HVAC 2 Toolkit, page 2-3 (FANSIM)
    1889             : 
    1890             :     // Using/Aliasing
    1891             :     using Curve::CurveValue;
    1892             : 
    1893             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1894             :     Real64 RhoAir;
    1895             :     Real64 DeltaPress; // [N/m2]
    1896             :     Real64 FanEff;
    1897             :     Real64 MassFlow;             // [kg/sec]
    1898             :     Real64 MaxAirMassFlowRate;   // [kg/sec]
    1899             :     Real64 PartLoadRatio;        // Ratio of actual mass flow rate to max mass flow rate
    1900             :     Real64 FlowFrac;             // Actual Fan Flow Fraction = actual mass flow rate / max air mass flow rate
    1901             :     Real64 FanShaftPower;        // power delivered to fan shaft
    1902             :     Real64 SpeedRaisedToPower;   // Result of the speed ratio raised to the power of n (Curve object)
    1903             :     Real64 EffRatioAtSpeedRatio; // Efficiency ratio at current speed ratio (Curve object)
    1904             : 
    1905   107762510 :     auto &Fan(state.dataFans->Fan);
    1906             : 
    1907   107762510 :     MassFlow = Fan(FanNum).InletAirMassFlowRate;
    1908   107762510 :     MaxAirMassFlowRate = Fan(FanNum).MaxAirMassFlowRate;
    1909   107762510 :     DeltaPress = Fan(FanNum).DeltaPress;
    1910   107762510 :     FanEff = Fan(FanNum).FanEff;
    1911   107762510 :     RhoAir = Fan(FanNum).RhoAirStdInit;
    1912             : 
    1913             :     // Faulty fan operations
    1914             :     // Update MassFlow & DeltaPress if there are fouling air filters corresponding to the fan
    1915   215525020 :     if (Fan(FanNum).FaultyFilterFlag && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) &&
    1916   107762510 :         (!state.dataGlobal->KickOffSimulation) && (!Fan(FanNum).EMSMaxMassFlowOverrideOn)) {
    1917             : 
    1918           0 :         int iFault = Fan(FanNum).FaultyFilterIndex;
    1919             : 
    1920             :         // Check fault availability schedules
    1921           0 :         if (GetCurrentScheduleValue(state, state.dataFaultsMgr->FaultsFouledAirFilters(iFault).AvaiSchedPtr) > 0.0) {
    1922           0 :             Real64 FanDesignFlowRateDec = 0; // Decrease of the Fan Design Volume Flow Rate [m3/sec]
    1923             : 
    1924           0 :             FanDesignFlowRateDec = CalFaultyFanAirFlowReduction(
    1925             :                 state,
    1926           0 :                 Fan(FanNum).FanName,
    1927           0 :                 Fan(FanNum).MaxAirFlowRate,
    1928           0 :                 Fan(FanNum).DeltaPress,
    1929           0 :                 (GetCurrentScheduleValue(state, state.dataFaultsMgr->FaultsFouledAirFilters(iFault).FaultyAirFilterPressFracSchePtr) - 1) *
    1930           0 :                     Fan(FanNum).DeltaPress,
    1931           0 :                 state.dataFaultsMgr->FaultsFouledAirFilters(iFault).FaultyAirFilterFanCurvePtr);
    1932             : 
    1933             :             // Update MassFlow & DeltaPress of the fan
    1934           0 :             MaxAirMassFlowRate = Fan(FanNum).MaxAirMassFlowRate - FanDesignFlowRateDec * RhoAir;
    1935           0 :             DeltaPress = GetCurrentScheduleValue(state, state.dataFaultsMgr->FaultsFouledAirFilters(iFault).FaultyAirFilterPressFracSchePtr) *
    1936           0 :                          Fan(FanNum).DeltaPress;
    1937             :         }
    1938             :     }
    1939             : 
    1940             :     // EMS overwrite MassFlow, DeltaPress, and FanEff
    1941   107762510 :     if (Fan(FanNum).EMSMaxMassFlowOverrideOn) MassFlow = Fan(FanNum).EMSAirMassFlowValue;
    1942   107762510 :     if (Fan(FanNum).EMSFanPressureOverrideOn) DeltaPress = Fan(FanNum).EMSFanPressureValue;
    1943   107762510 :     if (Fan(FanNum).EMSFanEffOverrideOn) FanEff = Fan(FanNum).EMSFanEffValue;
    1944             : 
    1945   107762510 :     MassFlow = min(MassFlow, MaxAirMassFlowRate);
    1946   107762510 :     MassFlow = max(MassFlow, Fan(FanNum).MinAirMassFlowRate);
    1947   107762510 :     Fan(FanNum).FanRuntimeFraction = 0.0;
    1948             : 
    1949             :     // Determine the Fan Schedule for the Time step
    1950   324304035 :     if ((GetCurrentScheduleValue(state, Fan(FanNum).AvailSchedPtrNum) > 0.0 || state.dataFans->LocalTurnFansOn) &&
    1951   321398136 :         !state.dataFans->LocalTurnFansOff && MassFlow > 0.0 && Fan(FanNum).MaxAirMassFlowRate > 0.0) {
    1952             :         // The actual flow fraction is calculated from MassFlow and the MaxVolumeFlow * AirDensity
    1953    91027777 :         FlowFrac = MassFlow / MaxAirMassFlowRate;
    1954             : 
    1955             :         // Calculate the part load ratio, can't be greater than 1
    1956    91027777 :         PartLoadRatio = min(1.0, FlowFrac);
    1957             :         // Fan is operating
    1958    91027777 :         if (state.dataHVACGlobal->OnOffFanPartLoadFraction <= 0.0) {
    1959           0 :             ShowRecurringWarningErrorAtEnd(state, "Fan:OnOff, OnOffFanPartLoadFraction <= 0.0, Reset to 1.0", state.dataFans->ErrCount);
    1960           0 :             state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0; // avoid divide by zero or negative PLF
    1961             :         }
    1962             : 
    1963    91027777 :         if (state.dataHVACGlobal->OnOffFanPartLoadFraction < 0.7) {
    1964       56758 :             state.dataHVACGlobal->OnOffFanPartLoadFraction = 0.7; // a warning message is already issued from the DX coils or gas heating coil
    1965             :         }
    1966             : 
    1967             :         // Keep fan runtime fraction between 0.0 and 1.0, and RTF >= PLR
    1968    91027777 :         if (state.dataHVACGlobal->OnOffFanPartLoadFraction >= 1.0) {
    1969    85363482 :             Fan(FanNum).FanRuntimeFraction = PartLoadRatio;
    1970             :         } else {
    1971     5664295 :             Fan(FanNum).FanRuntimeFraction = max(0.0, min(1.0, PartLoadRatio / state.dataHVACGlobal->OnOffFanPartLoadFraction));
    1972             :         }
    1973             :         // The fan speed ratio (passed from parent) determines the fan power according to fan laws
    1974    91027777 :         if (present(SpeedRatio)) {
    1975             :             //    Fan(FanNum)%FanPower = MassFlow*DeltaPress/(FanEff*RhoAir*OnOffFanPartLoadFraction)! total fan power
    1976    89063771 :             Fan(FanNum).FanPower = max(0.0, MaxAirMassFlowRate * Fan(FanNum).FanRuntimeFraction * DeltaPress / (FanEff * RhoAir));
    1977             : 
    1978             :             //    Do not modify fan power calculation unless fan power vs speed ratio curve is used.
    1979    89063771 :             if (Fan(FanNum).FanPowerRatAtSpeedRatCurveIndex > 0) {
    1980             : 
    1981             :                 //      adjust RTF to be in line with speed ratio (i.e., MaxAirMassFlowRate is not MAX when SpeedRatio /= 1)
    1982             :                 //      PLR = Mdot/MAXFlow => Mdot/(MAXFlow * SpeedRatio), RTF = PLR/PLF => PLR/SpeedRatio/PLF = RTF / SpeedRatio
    1983      201002 :                 if (SpeedRatio > 0.0) Fan(FanNum).FanRuntimeFraction = min(1.0, Fan(FanNum).FanRuntimeFraction / SpeedRatio);
    1984             : 
    1985      201002 :                 SpeedRaisedToPower = CurveValue(state, Fan(FanNum).FanPowerRatAtSpeedRatCurveIndex, SpeedRatio);
    1986      201002 :                 if (SpeedRaisedToPower < 0.0) {
    1987           0 :                     if (Fan(FanNum).OneTimePowerRatioCheck && !state.dataGlobal->WarmupFlag) {
    1988           0 :                         ShowSevereError(state, cFanTypes(Fan(FanNum).FanType_Num) + " = " + Fan(FanNum).FanName + "\"");
    1989           0 :                         ShowContinueError(state, "Error in Fan Power Ratio curve. Curve output less than 0.0.");
    1990           0 :                         ShowContinueError(state, format("Curve output = {:.5T}, fan speed ratio = {:.5T}", SpeedRaisedToPower, SpeedRatio));
    1991           0 :                         ShowContinueError(state, "Check curve coefficients to ensure proper power ratio as a function of fan speed ratio.");
    1992           0 :                         ShowContinueError(state, "Resetting Fan Power Ratio curve output to 0.0 and the simulation continues.");
    1993           0 :                         ShowContinueErrorTimeStamp(state, "Occurrence info:");
    1994           0 :                         Fan(FanNum).OneTimePowerRatioCheck = false;
    1995             :                     }
    1996           0 :                     SpeedRaisedToPower = 0.0;
    1997             :                 }
    1998      201002 :                 if (Fan(FanNum).FanEffRatioCurveIndex > 0 && !state.dataGlobal->WarmupFlag) {
    1999       30543 :                     EffRatioAtSpeedRatio = CurveValue(state, Fan(FanNum).FanEffRatioCurveIndex, SpeedRatio);
    2000       30543 :                     if (EffRatioAtSpeedRatio < 0.01) {
    2001           0 :                         if (Fan(FanNum).OneTimeEffRatioCheck && !state.dataGlobal->WarmupFlag) {
    2002           0 :                             ShowSevereError(state, cFanTypes(Fan(FanNum).FanType_Num) + " = " + Fan(FanNum).FanName + "\"");
    2003           0 :                             ShowContinueError(state, "Error in Fan Efficiency Ratio curve. Curve output less than 0.01.");
    2004           0 :                             ShowContinueError(state, format("Curve output = {:.5T}, fan speed ratio = {:.5T}", EffRatioAtSpeedRatio, SpeedRatio));
    2005           0 :                             ShowContinueError(state, "Check curve coefficients to ensure proper efficiency ratio as a function of fan speed ratio.");
    2006           0 :                             ShowContinueError(state, "Resetting Fan Efficiency Ratio curve output to 0.01 and the simulation continues.");
    2007           0 :                             ShowContinueErrorTimeStamp(state, "Occurrence info:");
    2008           0 :                             Fan(FanNum).OneTimeEffRatioCheck = false;
    2009             :                         }
    2010           0 :                         EffRatioAtSpeedRatio = 0.01;
    2011             :                     }
    2012             :                 } else {
    2013      170459 :                     EffRatioAtSpeedRatio = 1.0;
    2014             :                 }
    2015      201002 :                 Fan(FanNum).FanPower *= SpeedRaisedToPower / EffRatioAtSpeedRatio;
    2016             :             }
    2017             :         } else {
    2018     1964006 :             Fan(FanNum).FanPower = max(0.0, MaxAirMassFlowRate * Fan(FanNum).FanRuntimeFraction * DeltaPress / (FanEff * RhoAir)); // total fan power
    2019             :         }
    2020             : 
    2021             :         // OnOffFanPartLoadFraction is passed via DataHVACGlobals from the cooling or heating coil that is
    2022             :         //   requesting the fan to operate in cycling fan/cycling coil mode
    2023    91027777 :         state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;      // reset to 1 in case other on/off fan is called without a part load curve
    2024    91027777 :         FanShaftPower = Fan(FanNum).MotEff * Fan(FanNum).FanPower; // power delivered to shaft
    2025    91027777 :         Fan(FanNum).PowerLossToAir = FanShaftPower + (Fan(FanNum).FanPower - FanShaftPower) * Fan(FanNum).MotInAirFrac;
    2026    91027777 :         Fan(FanNum).OutletAirEnthalpy = Fan(FanNum).InletAirEnthalpy + Fan(FanNum).PowerLossToAir / MassFlow;
    2027             :         // This fan does not change the moisture or Mass Flow across the component
    2028    91027777 :         Fan(FanNum).OutletAirHumRat = Fan(FanNum).InletAirHumRat;
    2029    91027777 :         Fan(FanNum).OutletAirMassFlowRate = MassFlow;
    2030             :         //   Fan(FanNum)%OutletAirTemp = Tin + PowerLossToAir/(MassFlow*PsyCpAirFnW(Win,Tin))
    2031    91027777 :         Fan(FanNum).OutletAirTemp = PsyTdbFnHW(Fan(FanNum).OutletAirEnthalpy, Fan(FanNum).OutletAirHumRat);
    2032             :     } else {
    2033             :         // Fan is off and not operating no power consumed and mass flow rate.
    2034    16734733 :         Fan(FanNum).FanPower = 0.0;
    2035    16734733 :         FanShaftPower = 0.0;
    2036    16734733 :         Fan(FanNum).PowerLossToAir = 0.0;
    2037    16734733 :         Fan(FanNum).OutletAirMassFlowRate = 0.0;
    2038    16734733 :         Fan(FanNum).OutletAirHumRat = Fan(FanNum).InletAirHumRat;
    2039    16734733 :         Fan(FanNum).OutletAirEnthalpy = Fan(FanNum).InletAirEnthalpy;
    2040    16734733 :         Fan(FanNum).OutletAirTemp = Fan(FanNum).InletAirTemp;
    2041             :         // Set the Control Flow variables to 0.0 flow when OFF.
    2042    16734733 :         Fan(FanNum).MassFlowRateMaxAvail = 0.0;
    2043    16734733 :         Fan(FanNum).MassFlowRateMinAvail = 0.0;
    2044             :     }
    2045   107762510 : }
    2046             : 
    2047     1632157 : void SimZoneExhaustFan(EnergyPlusData &state, int const FanNum)
    2048             : {
    2049             : 
    2050             :     // SUBROUTINE INFORMATION:
    2051             :     //       AUTHOR         Fred Buhl
    2052             :     //       DATE WRITTEN   Jan 2000
    2053             :     //       MODIFIED       Brent Griffith, May 2009 for EMS
    2054             :     //                      Brent Griffith, Feb 2013 controls upgrade
    2055             :     //       RE-ENGINEERED  na
    2056             : 
    2057             :     // PURPOSE OF THIS SUBROUTINE:
    2058             :     // This subroutine simulates the Zone Exhaust Fan
    2059             : 
    2060             :     // METHODOLOGY EMPLOYED:
    2061             :     // Converts design pressure rise and efficiency into fan power and temperature rise
    2062             :     // Constant fan pressure rise is assumed.
    2063             : 
    2064             :     // REFERENCES:
    2065             :     // ASHRAE HVAC 2 Toolkit, page 2-3 (FANSIM)
    2066             : 
    2067             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2068             :     Real64 RhoAir;
    2069             :     Real64 DeltaPress; // [N/m2]
    2070             :     Real64 FanEff;
    2071             :     Real64 MassFlow;           // [kg/sec]
    2072             :     Real64 Tin;                // [C]
    2073     1632157 :     bool FanIsRunning = false; // There seems to be a missing else case below unless false is assumed
    2074             : 
    2075     1632157 :     auto &Fan(state.dataFans->Fan);
    2076             : 
    2077     1632157 :     DeltaPress = Fan(FanNum).DeltaPress;
    2078     1632157 :     if (Fan(FanNum).EMSFanPressureOverrideOn) DeltaPress = Fan(FanNum).EMSFanPressureValue;
    2079             : 
    2080     1632157 :     FanEff = Fan(FanNum).FanEff;
    2081     1632157 :     if (Fan(FanNum).EMSFanEffOverrideOn) FanEff = Fan(FanNum).EMSFanEffValue;
    2082             : 
    2083             :     // For a Constant Volume Simple Fan the Max Flow Rate is the Flow Rate for the fan
    2084     1632157 :     Tin = Fan(FanNum).InletAirTemp;
    2085     1632157 :     RhoAir = Fan(FanNum).RhoAirStdInit;
    2086     1632157 :     MassFlow = Fan(FanNum).InletAirMassFlowRate;
    2087             : 
    2088             :     //  When the AvailManagerMode == ExhaustFanCoupledToAvailManagers then the
    2089             :     //  Exhaust Fan is  interlocked with air loop availability via global TurnFansOn and TurnFansOff variables.
    2090             :     //  There is now the option to control if user wants to decouple air loop operation and exhaust fan operation
    2091             :     //  (zone air mass balance issues). If in the future want to allow for zone level local availability manager
    2092             :     //  then the optional arguments ZoneCompTurnFansOn and ZoneCompTurnFansOff will need
    2093             :     //  to be passed to SimulateFanComponents, and TurnFansOn must be changed to LocalTurnFansOn
    2094             :     //  and TurnFansOff to LocalTurnFansOff in the IF statement below.
    2095             : 
    2096             :     // apply controls to determine if operating
    2097     1632157 :     if (Fan(FanNum).AvailManagerMode == AvailabilityManagerCoupling::Coupled) {
    2098     4467422 :         if (((GetCurrentScheduleValue(state, Fan(FanNum).AvailSchedPtrNum) > 0.0) || state.dataHVACGlobal->TurnFansOn) &&
    2099     3790784 :             !state.dataHVACGlobal->TurnFansOff && MassFlow > 0.0) { // available
    2100     1180089 :             if (Fan(FanNum).MinTempLimitSchedNum > 0) {
    2101           0 :                 if (Tin >= GetCurrentScheduleValue(state, Fan(FanNum).MinTempLimitSchedNum)) {
    2102           0 :                     FanIsRunning = true;
    2103             :                 } else {
    2104           0 :                     FanIsRunning = false;
    2105             :                 }
    2106             :             } else {
    2107     1180089 :                 FanIsRunning = true;
    2108             :             }
    2109             :         } else {
    2110      243527 :             FanIsRunning = false;
    2111             :         }
    2112             : 
    2113      208541 :     } else if (Fan(FanNum).AvailManagerMode == AvailabilityManagerCoupling::Decoupled) {
    2114      208541 :         if (GetCurrentScheduleValue(state, Fan(FanNum).AvailSchedPtrNum) > 0.0 && MassFlow > 0.0) {
    2115      204497 :             if (Fan(FanNum).MinTempLimitSchedNum > 0) {
    2116           0 :                 if (Tin >= GetCurrentScheduleValue(state, Fan(FanNum).MinTempLimitSchedNum)) {
    2117           0 :                     FanIsRunning = true;
    2118             :                 } else {
    2119           0 :                     FanIsRunning = false;
    2120             :                 }
    2121             :             } else {
    2122      204497 :                 FanIsRunning = true;
    2123             :             }
    2124             :         } else {
    2125        4044 :             FanIsRunning = false;
    2126             :         }
    2127             :     }
    2128             : 
    2129     1632157 :     if (FanIsRunning) {
    2130             :         // Fan is operating
    2131     1384586 :         Fan(FanNum).FanPower = max(0.0, MassFlow * DeltaPress / (FanEff * RhoAir)); // total fan power
    2132     1384586 :         Fan(FanNum).PowerLossToAir = Fan(FanNum).FanPower;
    2133     1384586 :         Fan(FanNum).OutletAirEnthalpy = Fan(FanNum).InletAirEnthalpy + Fan(FanNum).PowerLossToAir / MassFlow;
    2134             :         // This fan does not change the moisture or Mass Flow across the component
    2135     1384586 :         Fan(FanNum).OutletAirHumRat = Fan(FanNum).InletAirHumRat;
    2136     1384586 :         Fan(FanNum).OutletAirMassFlowRate = MassFlow;
    2137     1384586 :         Fan(FanNum).OutletAirTemp = PsyTdbFnHW(Fan(FanNum).OutletAirEnthalpy, Fan(FanNum).OutletAirHumRat);
    2138             : 
    2139             :     } else {
    2140             :         // Fan is off and not operating no power consumed and mass flow rate.
    2141      247571 :         Fan(FanNum).FanPower = 0.0;
    2142      247571 :         Fan(FanNum).PowerLossToAir = 0.0;
    2143      247571 :         Fan(FanNum).OutletAirMassFlowRate = 0.0;
    2144      247571 :         Fan(FanNum).OutletAirHumRat = Fan(FanNum).InletAirHumRat;
    2145      247571 :         Fan(FanNum).OutletAirEnthalpy = Fan(FanNum).InletAirEnthalpy;
    2146      247571 :         Fan(FanNum).OutletAirTemp = Fan(FanNum).InletAirTemp;
    2147             :         // Set the Control Flow variables to 0.0 flow when OFF.
    2148      247571 :         Fan(FanNum).MassFlowRateMaxAvail = 0.0;
    2149      247571 :         Fan(FanNum).MassFlowRateMinAvail = 0.0;
    2150      247571 :         Fan(FanNum).InletAirMassFlowRate = 0.0;
    2151             :     }
    2152     1632157 : }
    2153             : 
    2154       57293 : void SimComponentModelFan(EnergyPlusData &state, int const FanNum)
    2155             : {
    2156             : 
    2157             :     // SUBROUTINE INFORMATION:
    2158             :     //       AUTHOR         Craig Wray, LBNL
    2159             :     //       DATE WRITTEN   Feb 2010
    2160             :     //       MODIFIED       Chandan Sharma, March 2011, FSEC: Added LocalTurnFansOn and LocalTurnFansOff
    2161             :     //       RE-ENGINEERED  na
    2162             : 
    2163             :     // PURPOSE OF THIS SUBROUTINE:
    2164             :     // This subroutine simulates the component model fan.
    2165             : 
    2166             :     // METHODOLOGY EMPLOYED:
    2167             :     // Calculate fan volumetric flow and corresponding fan static pressure rise,
    2168             :     //    using air-handling system characteristics and Sherman-Wray system curve model
    2169             :     // Calculate fan air power using volumetric flow and fan static pressure rise
    2170             :     // Calculate fan wheel efficiency using fan volumetric flow, fan static pressure rise,
    2171             :     //   fan characteristics, and Wray dimensionless fan static efficiency model
    2172             :     // Calculate fan shaft power using fan air power and fan static efficiency
    2173             :     // Calculate fan shaft speed and torque using Wray dimensionless fan airflow model
    2174             :     // Calculate belt part-load efficiency using correlations and coefficients based on ACEEE data
    2175             :     // Calculate belt input power using fan shaft power and belt efficiency
    2176             :     // Calculate motor part-load efficiency using correlations and coefficients based on MotorMaster+ data
    2177             :     // Calculate motor input power using belt input power and motor efficiency
    2178             :     // Calculate VFD efficiency using correlations and coefficients based on DOE data
    2179             :     // Calculate VFD input power using motor input power and VFD efficiency
    2180             :     // Calculate combined efficiency of fan, belt, motor, and VFD
    2181             :     // Calculate air temperature rise due to fan (and belt+motor if in airstream) power entering air-handler airflow
    2182             :     // Calculate output node conditions
    2183             : 
    2184             :     // Using/Aliasing
    2185             :     using Curve::CurveValue;
    2186             :     using Curve::GetCurveIndex;
    2187             :     using namespace OutputReportPredefined;
    2188             : 
    2189             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2190             :     int NVPerfNum;
    2191             : 
    2192             :     Real64 MaxAirMassFlowRate; // Fan Max mass airflow [kg/s]
    2193             :     Real64 MotInAirFrac;       // Fraction of fan power input to airstream
    2194             : 
    2195             :     // Local variables
    2196             :     Real64 RhoAir;              // Air density [kg/m3]
    2197             :     Real64 MassFlow;            // Fan mass airflow [kg/s]
    2198             :     Real64 FanVolFlow;          // Fan volumetric airflow [m3/s]
    2199             :     Real64 DuctStaticPress;     // Duct static pressure setpoint [Pa]
    2200             :     Real64 DeltaPressTot;       // Total pressure rise across fan [N/m2 = Pa]
    2201             :     Real64 FanOutletVelPress;   // Fan outlet velocity pressure [Pa]
    2202             :     Real64 EulerNum;            // Fan Euler number [-]
    2203             :     Real64 NormalizedEulerNum;  // Normalized Fan Euler number [-]
    2204             :     Real64 FanDimFlow;          // Fan dimensionless airflow [-]
    2205             :     Real64 FanSpdRadS;          // Fan shaft rotational speed [rad/s]
    2206             :     Real64 MotorSpeed;          // Motor shaft rotational speed [rpm]
    2207             :     Real64 FanTrqRatio;         // Ratio of fan torque to max fan torque [-]
    2208             :     Real64 BeltPLEff;           // Belt normalized (part-load) efficiency [-]
    2209             :     Real64 MotorOutPwrRatio;    // Ratio of motor output power to max motor output power [-]
    2210             :     Real64 MotorPLEff;          // Motor normalized (part-load) efficiency [-]
    2211       57293 :     Real64 VFDSpdRatio(0.0);    // Ratio of motor speed to motor max speed [-]
    2212       57293 :     Real64 VFDOutPwrRatio(0.0); // Ratio of VFD output power to max VFD output power [-]
    2213             :     Real64 FanEnthalpyChange;   // Air enthalpy change due to fan, belt, and motor losses [kJ/kg]
    2214             : 
    2215       57293 :     auto &NightVentPerf(state.dataFans->NightVentPerf);
    2216       57293 :     auto &Fan(state.dataFans->Fan);
    2217             : 
    2218             :     // Get inputs for night ventilation option
    2219       57293 :     NVPerfNum = Fan(FanNum).NVPerfNum;
    2220             : 
    2221       57293 :     if (state.dataHVACGlobal->NightVentOn && NVPerfNum > 0) {
    2222           0 :         MotInAirFrac = NightVentPerf(NVPerfNum).MotInAirFrac;
    2223           0 :         MaxAirMassFlowRate = NightVentPerf(NVPerfNum).MaxAirMassFlowRate;
    2224             :     } else {
    2225       57293 :         MotInAirFrac = Fan(FanNum).MotInAirFrac;
    2226       57293 :         MaxAirMassFlowRate = Fan(FanNum).MaxAirMassFlowRate;
    2227             :     }
    2228             : 
    2229             :     //  IF (Fan(FanNum)%EMSFanPressureOverrideOn) DeltaPress = Fan(FanNum)%EMSFanPressureValue
    2230             :     //  IF (Fan(FanNum)%EMSFanEffOverrideOn) FanEff = Fan(FanNum)%EMSFanEffValue
    2231             : 
    2232             :     // Get air density at standard conditions and get mass airflow through fan
    2233             :     // From WeatherManager:
    2234             :     //   StdBaroPress=(101.325d0*(1.0d0-2.25577d-05*WeatherFileElevation)**5.2559d0)*1000.d0
    2235             :     //   StdRhoAir=PsyRhoAirFnPbTdbW(StdBaroPress,20,0)
    2236             :     // From PsychRoutines:
    2237             :     //   w=MAX(dw,1.0d-5)
    2238             :     //   rhoair = pb/(287.d0*(tdb+DataGlobalConstants::KelvinConv())*(1.0d0+1.6077687d0*w))
    2239       57293 :     RhoAir = Fan(FanNum).RhoAirStdInit;
    2240       57293 :     MassFlow = min(Fan(FanNum).InletAirMassFlowRate, Fan(FanNum).MaxAirMassFlowRate);
    2241             : 
    2242             :     //  IF (Fan(FanNum)%EMSMaxMassFlowOverrideOn) MassFlow   = Fan(FanNum)%EMSAirMassFlowValue
    2243             : 
    2244             :     // Determine the Fan Schedule for the Time step
    2245      171879 :     if ((GetCurrentScheduleValue(state, Fan(FanNum).AvailSchedPtrNum) > 0.0 || state.dataFans->LocalTurnFansOn) &&
    2246      171879 :         !state.dataFans->LocalTurnFansOff && MassFlow > 0.0) {
    2247             :         // Fan is operating - calculate fan pressure rise, component efficiencies and power, and also air enthalpy rise
    2248             : 
    2249             :         // Calculate fan static pressure rise using fan volumetric flow, std air density, air-handling system characteristics,
    2250             :         //   and Sherman-Wray system curve model (assumes static pressure surrounding air distribution system is zero)
    2251       46997 :         FanVolFlow = MassFlow / RhoAir;                                                                  //[m3/s at standard conditions]
    2252       46997 :         DuctStaticPress = CurveValue(state, Fan(FanNum).PressResetCurveIndex, FanVolFlow);               // Duct static pressure setpoint [Pa]
    2253       46997 :         DeltaPressTot = CurveValue(state, Fan(FanNum).PressRiseCurveIndex, FanVolFlow, DuctStaticPress); // Fan total pressure rise [Pa]
    2254       46997 :         FanOutletVelPress = 0.5 * RhoAir * pow_2(FanVolFlow / Fan(FanNum).FanOutletArea);                // Fan outlet velocity pressure [Pa]
    2255             :         // Outlet velocity pressure cannot exceed total pressure rise
    2256       46997 :         FanOutletVelPress = min(FanOutletVelPress, DeltaPressTot);
    2257       46997 :         Fan(FanNum).DeltaPress = DeltaPressTot - FanOutletVelPress; // Fan static pressure rise [Pa]
    2258             : 
    2259             :         //    IF (Fan(FanNum)%EMSFanPressureOverrideOn) DeltaPress = Fan(FanNum)%EMSFanPressureValue
    2260             : 
    2261             :         // Calculate fan static air power using volumetric flow and fan static pressure rise
    2262       46997 :         Fan(FanNum).FanAirPower = FanVolFlow * Fan(FanNum).DeltaPress; //[W]
    2263             : 
    2264             :         // Calculate fan wheel efficiency using fan volumetric flow, fan static pressure rise,
    2265             :         //   fan characteristics, and Wray dimensionless fan static efficiency model
    2266       46997 :         EulerNum = (Fan(FanNum).DeltaPress * pow_4(Fan(FanNum).FanWheelDia)) / (RhoAir * pow_2(FanVolFlow)); //[-]
    2267       46997 :         NormalizedEulerNum = std::log10(EulerNum / Fan(FanNum).EuMaxEff);
    2268       46997 :         if (NormalizedEulerNum <= 0.0) {
    2269       14568 :             Fan(FanNum).FanWheelEff = CurveValue(state, Fan(FanNum).PLFanEffNormCurveIndex, NormalizedEulerNum);
    2270             :         } else {
    2271       32429 :             Fan(FanNum).FanWheelEff = CurveValue(state, Fan(FanNum).PLFanEffStallCurveIndex, NormalizedEulerNum);
    2272             :         }
    2273       46997 :         Fan(FanNum).FanWheelEff *= Fan(FanNum).FanMaxEff;             // [-]
    2274       46997 :         Fan(FanNum).FanWheelEff = max(Fan(FanNum).FanWheelEff, 0.01); // Minimum efficiency is 1% to avoid numerical errors
    2275             : 
    2276             :         // Calculate fan shaft power using fan static air power and fan static efficiency
    2277       46997 :         Fan(FanNum).FanShaftPower = Fan(FanNum).FanAirPower / Fan(FanNum).FanWheelEff; //[W]
    2278             : 
    2279             :         // Calculate fan shaft speed, fan torque, and motor speed using Wray dimensionless fan airflow model
    2280       46997 :         if (NormalizedEulerNum <= 0.0) {
    2281       14568 :             FanDimFlow = CurveValue(state, Fan(FanNum).DimFlowNormCurveIndex, NormalizedEulerNum); //[-]
    2282             :         } else {
    2283       32429 :             FanDimFlow = CurveValue(state, Fan(FanNum).DimFlowStallCurveIndex, NormalizedEulerNum); //[-]
    2284             :         }
    2285       46997 :         FanSpdRadS = FanVolFlow / (FanDimFlow * Fan(FanNum).FanMaxDimFlow * pow_3(Fan(FanNum).FanWheelDia)); //[rad/s]
    2286       46997 :         Fan(FanNum).FanTrq = Fan(FanNum).FanShaftPower / FanSpdRadS;                                         //[N-m]
    2287       46997 :         Fan(FanNum).FanSpd = FanSpdRadS * 9.549296586;                                                       //[rpm, conversion factor is 30/PI]
    2288       46997 :         MotorSpeed = Fan(FanNum).FanSpd * Fan(FanNum).PulleyDiaRatio;                                        //[rpm]
    2289             : 
    2290             :         // Calculate belt part-load drive efficiency using correlations and coefficients based on ACEEE data
    2291             :         // Direct-drive is represented using curve coefficients such that "belt" max eff and PL eff = 1.0
    2292       46997 :         FanTrqRatio = Fan(FanNum).FanTrq / Fan(FanNum).BeltMaxTorque; //[-]
    2293       46997 :         if ((FanTrqRatio <= Fan(FanNum).BeltTorqueTrans) && (Fan(FanNum).PLBeltEffReg1CurveIndex != 0)) {
    2294        3681 :             BeltPLEff = CurveValue(state, Fan(FanNum).PLBeltEffReg1CurveIndex, FanTrqRatio); //[-]
    2295             :         } else {
    2296       43316 :             if ((FanTrqRatio > Fan(FanNum).BeltTorqueTrans) && (FanTrqRatio <= 1.0) && (Fan(FanNum).PLBeltEffReg2CurveIndex != 0)) {
    2297       43316 :                 BeltPLEff = CurveValue(state, Fan(FanNum).PLBeltEffReg2CurveIndex, FanTrqRatio); //[-]
    2298             :             } else {
    2299           0 :                 if ((FanTrqRatio > 1.0) && (Fan(FanNum).PLBeltEffReg3CurveIndex != 0)) {
    2300           0 :                     BeltPLEff = CurveValue(state, Fan(FanNum).PLBeltEffReg3CurveIndex, FanTrqRatio); //[-]
    2301             :                 } else {
    2302           0 :                     BeltPLEff = 1.0; // Direct drive or no curve specified - use constant efficiency
    2303             :                 }
    2304             :             }
    2305             :         }
    2306       46997 :         Fan(FanNum).BeltEff = Fan(FanNum).BeltMaxEff * BeltPLEff; //[-]
    2307       46997 :         Fan(FanNum).BeltEff = max(Fan(FanNum).BeltEff, 0.01);     // Minimum efficiency is 1% to avoid numerical errors
    2308             : 
    2309             :         // Calculate belt input power using fan shaft power and belt efficiency
    2310       46997 :         Fan(FanNum).BeltInputPower = Fan(FanNum).FanShaftPower / Fan(FanNum).BeltEff; //[W]
    2311             : 
    2312             :         // Calculate motor part-load efficiency using correlations and coefficients based on MotorMaster+ data
    2313       46997 :         MotorOutPwrRatio = Fan(FanNum).BeltInputPower / Fan(FanNum).MotorMaxOutPwr; //[-]
    2314       46997 :         if (Fan(FanNum).PLMotorEffCurveIndex != 0) {
    2315       46997 :             MotorPLEff = CurveValue(state, Fan(FanNum).PLMotorEffCurveIndex, MotorOutPwrRatio); //[-]
    2316             :         } else {
    2317           0 :             MotorPLEff = 1.0; // No curve specified - use constant efficiency
    2318             :         }
    2319       46997 :         Fan(FanNum).MotEff = Fan(FanNum).MotorMaxEff * MotorPLEff; //[-]
    2320       46997 :         Fan(FanNum).MotEff = max(Fan(FanNum).MotEff, 0.01);        // Minimum efficiency is 1% to avoid numerical errors
    2321             : 
    2322             :         // Calculate motor input power using belt input power and motor efficiency
    2323       46997 :         Fan(FanNum).MotorInputPower = Fan(FanNum).BeltInputPower / Fan(FanNum).MotEff; //[W]
    2324             : 
    2325             :         // Calculate VFD efficiency using correlations and coefficients based on VFD type
    2326       46997 :         if ((Fan(FanNum).VFDEffType == "SPEED") && (Fan(FanNum).VFDEffCurveIndex != 0)) {
    2327           0 :             VFDSpdRatio = MotorSpeed / Fan(FanNum).MotorMaxSpd;                                //[-]
    2328           0 :             Fan(FanNum).VFDEff = CurveValue(state, Fan(FanNum).VFDEffCurveIndex, VFDSpdRatio); //[-]
    2329             :         } else {
    2330       46997 :             if ((Fan(FanNum).VFDEffType == "POWER") && (Fan(FanNum).VFDEffCurveIndex != 0)) {
    2331       46997 :                 VFDOutPwrRatio = Fan(FanNum).MotorInputPower / Fan(FanNum).VFDMaxOutPwr;              //[-]
    2332       46997 :                 Fan(FanNum).VFDEff = CurveValue(state, Fan(FanNum).VFDEffCurveIndex, VFDOutPwrRatio); //[-]
    2333             :             } else {
    2334             :                 // No curve specified - use constant efficiency
    2335           0 :                 Fan(FanNum).VFDMaxOutPwr = 0.0;
    2336           0 :                 Fan(FanNum).VFDEff = 0.97;
    2337             :             }
    2338             :         }
    2339       46997 :         Fan(FanNum).VFDEff = max(Fan(FanNum).VFDEff, 0.01); // Minimum efficiency is 1% to avoid numerical errors
    2340             : 
    2341             :         // Calculate VFD input power using motor input power and VFD efficiency
    2342       46997 :         Fan(FanNum).VFDInputPower = Fan(FanNum).MotorInputPower / Fan(FanNum).VFDEff; //[W]
    2343       46997 :         Fan(FanNum).FanPower = Fan(FanNum).VFDInputPower;                             //[W]
    2344             : 
    2345             :         // Calculate combined fan system efficiency: includes fan, belt, motor, and VFD
    2346             :         // Equivalent to Fan(FanNum)%FanAirPower / Fan(FanNum)%FanPower
    2347       46997 :         Fan(FanNum).FanEff = Fan(FanNum).FanWheelEff * Fan(FanNum).BeltEff * Fan(FanNum).MotEff * Fan(FanNum).VFDEff;
    2348             : 
    2349             :         //    IF (Fan(FanNum)%EMSFanEffOverrideOn) FanEff = Fan(FanNum)%EMSFanEffValue
    2350             : 
    2351             :         // Calculate air enthalpy and temperature rise from power entering air stream from fan wheel, belt, and motor
    2352             :         // Assumes MotInAirFrac applies to belt and motor but NOT to VFD
    2353       46997 :         Fan(FanNum).PowerLossToAir =
    2354       46997 :             Fan(FanNum).FanShaftPower + (Fan(FanNum).MotorInputPower - Fan(FanNum).FanShaftPower) * Fan(FanNum).MotInAirFrac; //[W]
    2355       46997 :         FanEnthalpyChange = Fan(FanNum).PowerLossToAir / MassFlow;                                                            //[kJ/kg]
    2356       46997 :         Fan(FanNum).OutletAirEnthalpy = Fan(FanNum).InletAirEnthalpy + FanEnthalpyChange;                                     //[kJ/kg]
    2357             : 
    2358             :         // This fan does not change the moisture or mass flow across the component
    2359       46997 :         Fan(FanNum).OutletAirHumRat = Fan(FanNum).InletAirHumRat; //[-]
    2360       46997 :         Fan(FanNum).OutletAirMassFlowRate = MassFlow;             //[kg/s]
    2361       46997 :         Fan(FanNum).OutletAirTemp = PsyTdbFnHW(Fan(FanNum).OutletAirEnthalpy, Fan(FanNum).OutletAirHumRat);
    2362             :     } else {
    2363             :         // Fan is OFF and not operating -- no power consumed and zero mass flow rate
    2364       10296 :         Fan(FanNum).FanPower = 0.0;
    2365       10296 :         Fan(FanNum).FanShaftPower = 0.0;
    2366       10296 :         Fan(FanNum).PowerLossToAir = 0.0;
    2367       10296 :         Fan(FanNum).OutletAirMassFlowRate = 0.0;
    2368       10296 :         Fan(FanNum).OutletAirHumRat = Fan(FanNum).InletAirHumRat;
    2369       10296 :         Fan(FanNum).OutletAirEnthalpy = Fan(FanNum).InletAirEnthalpy;
    2370       10296 :         Fan(FanNum).OutletAirTemp = Fan(FanNum).InletAirTemp;
    2371             :         // Set the Control Flow variables to 0.0 flow when OFF.
    2372       10296 :         Fan(FanNum).MassFlowRateMaxAvail = 0.0;
    2373       10296 :         Fan(FanNum).MassFlowRateMinAvail = 0.0;
    2374             : 
    2375       10296 :         Fan(FanNum).DeltaPress = 0.0;
    2376       10296 :         Fan(FanNum).FanAirPower = 0.0;
    2377       10296 :         Fan(FanNum).FanWheelEff = 0.0;
    2378       10296 :         Fan(FanNum).FanSpd = 0.0;
    2379       10296 :         Fan(FanNum).FanTrq = 0.0;
    2380       10296 :         Fan(FanNum).BeltEff = 0.0;
    2381       10296 :         Fan(FanNum).BeltInputPower = 0.0;
    2382       10296 :         Fan(FanNum).MotEff = 0.0;
    2383       10296 :         Fan(FanNum).MotorInputPower = 0.0;
    2384       10296 :         Fan(FanNum).VFDEff = 0.0;
    2385       10296 :         Fan(FanNum).VFDInputPower = 0.0;
    2386       10296 :         Fan(FanNum).FanEff = 0.0;
    2387             :     }
    2388       57293 : }
    2389             : 
    2390   138406141 : void UpdateFan(EnergyPlusData &state, int const FanNum)
    2391             : {
    2392             : 
    2393             :     // SUBROUTINE INFORMATION:
    2394             :     //       AUTHOR         Richard Liesen
    2395             :     //       DATE WRITTEN   April 1998
    2396             :     //       MODIFIED       L. Gu, Feb. 1, 2007, No unbalance airflow when Zone Exhaust Fans are used in the AirflowNetwork
    2397             :     //       RE-ENGINEERED  na
    2398             : 
    2399             :     // PURPOSE OF THIS SUBROUTINE:
    2400             :     // This subroutine updates the fan outlet nodes.
    2401             : 
    2402             :     // METHODOLOGY EMPLOYED:
    2403             :     // Data is moved from the fan data structure to the fan outlet nodes.
    2404             : 
    2405             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2406             :     int OutletNode;
    2407             :     int InletNode;
    2408             : 
    2409   138406141 :     auto &Fan(state.dataFans->Fan);
    2410             : 
    2411   138406141 :     OutletNode = Fan(FanNum).OutletNodeNum;
    2412   138406141 :     InletNode = Fan(FanNum).InletNodeNum;
    2413             : 
    2414             :     // Set the outlet air nodes of the fan
    2415   138406141 :     state.dataLoopNodes->Node(OutletNode).MassFlowRate = Fan(FanNum).OutletAirMassFlowRate;
    2416   138406141 :     state.dataLoopNodes->Node(OutletNode).Temp = Fan(FanNum).OutletAirTemp;
    2417   138406141 :     state.dataLoopNodes->Node(OutletNode).HumRat = Fan(FanNum).OutletAirHumRat;
    2418   138406141 :     state.dataLoopNodes->Node(OutletNode).Enthalpy = Fan(FanNum).OutletAirEnthalpy;
    2419             :     // Set the outlet nodes for properties that just pass through & not used
    2420   138406141 :     state.dataLoopNodes->Node(OutletNode).Quality = state.dataLoopNodes->Node(InletNode).Quality;
    2421   138406141 :     state.dataLoopNodes->Node(OutletNode).Press = state.dataLoopNodes->Node(InletNode).Press;
    2422             : 
    2423             :     // Set the Node Flow Control Variables from the Fan Control Variables
    2424   138406141 :     state.dataLoopNodes->Node(OutletNode).MassFlowRateMaxAvail = Fan(FanNum).MassFlowRateMaxAvail;
    2425   138406141 :     state.dataLoopNodes->Node(OutletNode).MassFlowRateMinAvail = Fan(FanNum).MassFlowRateMinAvail;
    2426             : 
    2427   138406141 :     if (Fan(FanNum).FanType_Num == FanType_ZoneExhaust) {
    2428     1632157 :         state.dataLoopNodes->Node(InletNode).MassFlowRate = Fan(FanNum).InletAirMassFlowRate;
    2429     1632157 :         if (state.afn->AirflowNetworkNumOfExhFan == 0) {
    2430     1331350 :             state.dataHVACGlobal->UnbalExhMassFlow = Fan(FanNum).InletAirMassFlowRate;
    2431     1331350 :             if (Fan(FanNum).BalancedFractSchedNum > 0) {
    2432      334744 :                 state.dataHVACGlobal->BalancedExhMassFlow =
    2433      334744 :                     state.dataHVACGlobal->UnbalExhMassFlow * GetCurrentScheduleValue(state, Fan(FanNum).BalancedFractSchedNum);
    2434      334744 :                 state.dataHVACGlobal->UnbalExhMassFlow = state.dataHVACGlobal->UnbalExhMassFlow - state.dataHVACGlobal->BalancedExhMassFlow;
    2435             :             } else {
    2436      996606 :                 state.dataHVACGlobal->BalancedExhMassFlow = 0.0;
    2437             :             }
    2438             :         } else {
    2439      300807 :             state.dataHVACGlobal->UnbalExhMassFlow = 0.0;
    2440      300807 :             state.dataHVACGlobal->BalancedExhMassFlow = 0.0;
    2441             :         }
    2442     1632157 :         Fan(FanNum).UnbalancedOutletMassFlowRate = state.dataHVACGlobal->UnbalExhMassFlow;
    2443     1632157 :         Fan(FanNum).BalancedOutletMassFlowRate = state.dataHVACGlobal->BalancedExhMassFlow;
    2444             :     }
    2445             : 
    2446   138406141 :     if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    2447      828819 :         state.dataLoopNodes->Node(OutletNode).CO2 = state.dataLoopNodes->Node(InletNode).CO2;
    2448             :     }
    2449             : 
    2450   138406141 :     if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    2451      236471 :         state.dataLoopNodes->Node(OutletNode).GenContam = state.dataLoopNodes->Node(InletNode).GenContam;
    2452             :     }
    2453   138406141 : }
    2454             : 
    2455   138406141 : void ReportFan(EnergyPlusData &state, int const FanNum)
    2456             : {
    2457             : 
    2458             :     // SUBROUTINE INFORMATION:
    2459             :     //       AUTHOR         Richard Liesen
    2460             :     //       DATE WRITTEN   April 1998
    2461             :     //       MODIFIED       na
    2462             :     //       RE-ENGINEERED  na
    2463             : 
    2464             :     // PURPOSE OF THIS SUBROUTINE:
    2465             :     // This subroutine updates the report variables for the fans.
    2466             : 
    2467             :     // Using/Aliasing
    2468   138406141 :     auto &TimeStepSys = state.dataHVACGlobal->TimeStepSys;
    2469             : 
    2470   138406141 :     auto &Fan(state.dataFans->Fan);
    2471             : 
    2472   138406141 :     Fan(FanNum).FanEnergy = Fan(FanNum).FanPower * TimeStepSys * DataGlobalConstants::SecInHour;
    2473   138406141 :     Fan(FanNum).DeltaTemp = Fan(FanNum).OutletAirTemp - Fan(FanNum).InletAirTemp;
    2474             : 
    2475   138406141 :     if (Fan(FanNum).FanType_Num == FanType_SimpleOnOff) {
    2476   107762510 :         if (Fan(FanNum).AirLoopNum > 0) {
    2477     3746957 :             state.dataAirLoop->AirLoopAFNInfo(Fan(FanNum).AirLoopNum).AFNLoopOnOffFanRTF = Fan(FanNum).FanRuntimeFraction;
    2478             :         }
    2479             :     }
    2480   138406141 : }
    2481             : 
    2482        1980 : void GetFanIndex(EnergyPlusData &state, std::string const &FanName, int &FanIndex, bool &ErrorsFound, std::string_view ThisObjectType)
    2483             : {
    2484             : 
    2485             :     // SUBROUTINE INFORMATION:
    2486             :     //       AUTHOR         Linda Lawrie
    2487             :     //       DATE WRITTEN   June 2004
    2488             :     //       MODIFIED       na
    2489             :     //       RE-ENGINEERED  na
    2490             : 
    2491             :     // PURPOSE OF THIS SUBROUTINE:
    2492             :     // This subroutine sets an index for a given fan -- issues error message if that fan
    2493             :     // is not legal fan.
    2494             : 
    2495        1980 :     if (state.dataFans->GetFanInputFlag) { // First time subroutine has been entered
    2496         326 :         GetFanInput(state);
    2497         326 :         state.dataFans->GetFanInputFlag = false;
    2498             :     }
    2499             : 
    2500        1980 :     FanIndex = UtilityRoutines::FindItemInList(FanName, state.dataFans->Fan, &FanEquipConditions::FanName);
    2501        1980 :     if (FanIndex == 0) {
    2502           0 :         if (!ThisObjectType.empty()) {
    2503           0 :             ShowSevereError(state, fmt::format("{}, GetFanIndex: Fan not found={}", ThisObjectType, FanName));
    2504             :         } else {
    2505           0 :             ShowSevereError(state, "GetFanIndex: Fan not found=" + FanName);
    2506             :         }
    2507           0 :         ErrorsFound = true;
    2508             :     }
    2509        1980 : }
    2510             : 
    2511       15108 : void GetFanVolFlow(EnergyPlusData &state, int const FanIndex, Real64 &FanVolFlow)
    2512             : {
    2513             : 
    2514             :     // SUBROUTINE INFORMATION:
    2515             :     //       AUTHOR         Richard Raustad
    2516             :     //       DATE WRITTEN   August 2005
    2517             :     //       MODIFIED       na
    2518             :     //       RE-ENGINEERED  na
    2519             : 
    2520             :     // PURPOSE OF THIS SUBROUTINE:
    2521             :     // This subroutine gets the fan volumetric flow for use by zone equipment (e.g. Packaged Terminal Heat Pump)
    2522             :     // Zone equipment must ensure that a properly sized fan is used to meet the maximum supply air flow rate
    2523             : 
    2524       15108 :     if (FanIndex == 0) {
    2525           0 :         FanVolFlow = 0.0;
    2526             :     } else {
    2527       15108 :         FanVolFlow = state.dataFans->Fan(FanIndex).MaxAirFlowRate;
    2528             :     }
    2529       15108 : }
    2530             : 
    2531    11098771 : Real64 GetFanPower(EnergyPlusData &state, int const FanIndex)
    2532             : {
    2533             : 
    2534             :     // SUBROUTINE INFORMATION:
    2535             :     //       AUTHOR         B. Griffith
    2536             :     //       DATE WRITTEN   July 2012
    2537             :     //       MODIFIED       na
    2538             :     //       RE-ENGINEERED  na
    2539             : 
    2540             :     // PURPOSE OF THIS SUBROUTINE:
    2541             :     // This subroutine gets the fan power draw
    2542             : 
    2543    11098771 :     if (FanIndex == 0) {
    2544     3505791 :         return 0.0;
    2545             :     } else {
    2546     7592980 :         return state.dataFans->Fan(FanIndex).FanPower;
    2547             :     }
    2548             : }
    2549             : 
    2550        3946 : void GetFanType(EnergyPlusData &state,
    2551             :                 std::string const &FanName,            // Fan name
    2552             :                 int &FanType,                          // returned fantype number
    2553             :                 bool &ErrorsFound,                     // error indicator
    2554             :                 std::string_view const ThisObjectType, // parent object type (for error message)
    2555             :                 std::string_view const ThisObjectName  // parent object name (for error message)
    2556             : )
    2557             : {
    2558             : 
    2559             :     // SUBROUTINE INFORMATION:
    2560             :     //       AUTHOR         Richard Raustad
    2561             :     //       DATE WRITTEN   August 2005
    2562             :     //       MODIFIED       na
    2563             :     //       RE-ENGINEERED  na
    2564             : 
    2565             :     // PURPOSE OF THIS SUBROUTINE:
    2566             :     // This subroutine sets an integer type for a given fan -- issues error message if that fan
    2567             :     // is not a legal fan.
    2568             : 
    2569             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2570             :     int FanIndex;
    2571             : 
    2572        3946 :     auto &Fan(state.dataFans->Fan);
    2573             : 
    2574        3946 :     if (state.dataFans->GetFanInputFlag) { // First time subroutine has been entered
    2575         181 :         GetFanInput(state);
    2576         181 :         state.dataFans->GetFanInputFlag = false;
    2577             :     }
    2578             : 
    2579        3946 :     FanIndex = UtilityRoutines::FindItemInList(FanName, Fan, &FanEquipConditions::FanName);
    2580        3946 :     if (FanIndex == 0) {
    2581           0 :         if ((!ThisObjectType.empty()) && (!ThisObjectName.empty())) {
    2582           0 :             ShowSevereError(state, fmt::format("GetFanType: {}=\"{}\", invalid Fan specified=\"{}\".", ThisObjectType, ThisObjectName, FanName));
    2583           0 :         } else if (!ThisObjectType.empty()) {
    2584           0 :             ShowSevereError(state, fmt::format("{}, GetFanType: Fan not found={}", ThisObjectType, FanName));
    2585             :         } else {
    2586           0 :             ShowSevereError(state, "GetFanType: Fan not found=" + FanName);
    2587             :         }
    2588           0 :         FanType = 0;
    2589           0 :         ErrorsFound = true;
    2590             :     } else {
    2591        3946 :         FanType = Fan(FanIndex).FanType_Num;
    2592             :     }
    2593        3946 : }
    2594             : 
    2595        4961 : Real64 GetFanDesignVolumeFlowRate(EnergyPlusData &state,
    2596             :                                   std::string_view FanType,   // must match fan types in this module
    2597             :                                   std::string_view FanName,   // must match fan names for the fan type
    2598             :                                   bool &ErrorsFound,          // set to true if problem
    2599             :                                   Optional_int_const FanIndex // index to fan
    2600             : )
    2601             : {
    2602             : 
    2603             :     // FUNCTION INFORMATION:
    2604             :     //       AUTHOR         Linda Lawrie
    2605             :     //       DATE WRITTEN   February 2006
    2606             :     //       MODIFIED       R. Raustad, Aug 2007 - added optional fan index
    2607             :     //       RE-ENGINEERED  na
    2608             : 
    2609             :     // PURPOSE OF THIS FUNCTION:
    2610             :     // This function looks up the design volume flow rate for the given fan and returns it.  If
    2611             :     // incorrect fan type or name is given, ErrorsFound is returned as true and value is returned
    2612             :     // as negative.
    2613             : 
    2614             :     // Return value
    2615             :     Real64 DesignVolumeFlowRate; // returned flow rate of matched fan
    2616             : 
    2617             :     // FUNCTION LOCAL VARIABLE DECLARATIONS:
    2618             :     int WhichFan;
    2619             : 
    2620        4961 :     auto &Fan(state.dataFans->Fan);
    2621             : 
    2622             :     // Obtains and Allocates fan related parameters from input file
    2623        4961 :     if (state.dataFans->GetFanInputFlag) { // First time subroutine has been entered
    2624           0 :         GetFanInput(state);
    2625           0 :         state.dataFans->GetFanInputFlag = false;
    2626             :     }
    2627             : 
    2628        4961 :     if (present(FanIndex)) {
    2629        4217 :         DesignVolumeFlowRate = Fan(FanIndex).MaxAirFlowRate;
    2630             :     } else {
    2631         744 :         WhichFan = UtilityRoutines::FindItemInList(FanName, Fan, &FanEquipConditions::FanName);
    2632         744 :         if (WhichFan != 0) {
    2633         744 :             DesignVolumeFlowRate = Fan(WhichFan).MaxAirFlowRate;
    2634             :         } else {
    2635           0 :             ShowSevereError(
    2636           0 :                 state, "GetFanDesignVolumeFlowRate: Could not find Fan, Type=\"" + std::string{FanType} + "\" Name=\"" + std::string{FanName} + "\"");
    2637           0 :             ShowContinueError(state, "... Design Volume Flow rate returned as -1000.");
    2638           0 :             ErrorsFound = true;
    2639           0 :             DesignVolumeFlowRate = -1000.0;
    2640             :         }
    2641             :     }
    2642             : 
    2643        4961 :     return DesignVolumeFlowRate;
    2644             : }
    2645             : 
    2646         633 : int GetFanInletNode(EnergyPlusData &state,
    2647             :                     std::string_view FanType, // must match fan types in this module
    2648             :                     std::string_view FanName, // must match fan names for the fan type
    2649             :                     bool &ErrorsFound         // set to true if problem
    2650             : )
    2651             : {
    2652             : 
    2653             :     // FUNCTION INFORMATION:
    2654             :     //       AUTHOR         Linda Lawrie
    2655             :     //       DATE WRITTEN   February 2006
    2656             :     //       MODIFIED       na
    2657             :     //       RE-ENGINEERED  na
    2658             : 
    2659             :     // PURPOSE OF THIS FUNCTION:
    2660             :     // This function looks up the given fan and returns the inlet node.  If
    2661             :     // incorrect fan type or name is given, ErrorsFound is returned as true and value is returned
    2662             :     // as zero.
    2663             : 
    2664             :     // Return value
    2665             :     int NodeNumber; // returned outlet node of matched fan
    2666             : 
    2667             :     // FUNCTION LOCAL VARIABLE DECLARATIONS:
    2668             :     int WhichFan;
    2669             : 
    2670         633 :     auto &Fan(state.dataFans->Fan);
    2671             : 
    2672             :     // Obtains and Allocates fan related parameters from input file
    2673         633 :     if (state.dataFans->GetFanInputFlag) { // First time subroutine has been entered
    2674          10 :         GetFanInput(state);
    2675          10 :         state.dataFans->GetFanInputFlag = false;
    2676             :     }
    2677             : 
    2678         633 :     WhichFan = UtilityRoutines::FindItemInList(FanName, Fan, &FanEquipConditions::FanName);
    2679         633 :     if (WhichFan != 0) {
    2680         633 :         NodeNumber = Fan(WhichFan).InletNodeNum;
    2681             :     } else {
    2682           0 :         ShowSevereError(state, "GetFanInletNode: Could not find Fan, Type=\"" + std::string{FanType} + "\" Name=\"" + std::string{FanName} + "\"");
    2683           0 :         ErrorsFound = true;
    2684           0 :         NodeNumber = 0;
    2685             :     }
    2686             : 
    2687         633 :     return NodeNumber;
    2688             : }
    2689             : 
    2690           0 : int getFanInNodeIndex(EnergyPlusData &state,
    2691             :                       int const FanIndex, // fan index
    2692             :                       bool &ErrorsFound   // set to true if problem
    2693             : )
    2694             : {
    2695             : 
    2696           0 :     int NodeNumber = 0; // returned outlet node of matched fan
    2697             : 
    2698           0 :     auto &Fan(state.dataFans->Fan);
    2699             : 
    2700             :     // Obtains and Allocates fan related parameters from input file
    2701           0 :     if (state.dataFans->GetFanInputFlag) { // First time subroutine has been entered
    2702           0 :         GetFanInput(state);
    2703           0 :         state.dataFans->GetFanInputFlag = false;
    2704             :     }
    2705             : 
    2706           0 :     if (FanIndex != 0) {
    2707           0 :         NodeNumber = Fan(FanIndex).InletNodeNum;
    2708             :     } else {
    2709           0 :         ShowSevereError(state, "getFanInNodeIndex: Could not find Fan");
    2710           0 :         ErrorsFound = true;
    2711             :     }
    2712             : 
    2713           0 :     return NodeNumber;
    2714             : }
    2715             : 
    2716         889 : int GetFanOutletNode(EnergyPlusData &state,
    2717             :                      std::string const &FanType, // must match fan types in this module
    2718             :                      std::string const &FanName, // must match fan names for the fan type
    2719             :                      bool &ErrorsFound           // set to true if problem
    2720             : )
    2721             : {
    2722             : 
    2723             :     // FUNCTION INFORMATION:
    2724             :     //       AUTHOR         Linda Lawrie
    2725             :     //       DATE WRITTEN   February 2006
    2726             :     //       MODIFIED       na
    2727             :     //       RE-ENGINEERED  na
    2728             : 
    2729             :     // PURPOSE OF THIS FUNCTION:
    2730             :     // This function looks up the given fan and returns the outlet node.  If
    2731             :     // incorrect fan type or name is given, ErrorsFound is returned as true and value is returned
    2732             :     // as zero.
    2733             : 
    2734             :     // Return value
    2735             :     int NodeNumber; // returned outlet node of matched fan
    2736             : 
    2737             :     // FUNCTION LOCAL VARIABLE DECLARATIONS:
    2738             :     int WhichFan;
    2739             : 
    2740         889 :     auto &Fan(state.dataFans->Fan);
    2741             : 
    2742             :     // Obtains and Allocates fan related parameters from input file
    2743         889 :     if (state.dataFans->GetFanInputFlag) { // First time subroutine has been entered
    2744           1 :         GetFanInput(state);
    2745           1 :         state.dataFans->GetFanInputFlag = false;
    2746             :     }
    2747             : 
    2748         889 :     WhichFan = UtilityRoutines::FindItemInList(FanName, Fan, &FanEquipConditions::FanName);
    2749         889 :     if (WhichFan != 0) {
    2750         889 :         NodeNumber = Fan(WhichFan).OutletNodeNum;
    2751             :     } else {
    2752           0 :         ShowSevereError(state, "GetFanOutletNode: Could not find Fan, Type=\"" + FanType + "\" Name=\"" + FanName + "\"");
    2753           0 :         ErrorsFound = true;
    2754           0 :         NodeNumber = 0;
    2755             :     }
    2756             : 
    2757         889 :     return NodeNumber;
    2758             : }
    2759             : 
    2760         811 : int GetFanAvailSchPtr(EnergyPlusData &state,
    2761             :                       std::string const &FanType, // must match fan types in this module
    2762             :                       std::string const &FanName, // must match fan names for the fan type
    2763             :                       bool &ErrorsFound           // set to true if problem
    2764             : )
    2765             : {
    2766             : 
    2767             :     // FUNCTION INFORMATION:
    2768             :     //       AUTHOR         Richard Raustad
    2769             :     //       DATE WRITTEN   September 2007
    2770             :     //       MODIFIED       na
    2771             :     //       RE-ENGINEERED  na
    2772             : 
    2773             :     // PURPOSE OF THIS FUNCTION:
    2774             :     // This function looks up the given fan and returns the availability schedule pointer.  If
    2775             :     // incorrect fan type or name is given, ErrorsFound is returned as true and value is returned
    2776             :     // as zero.
    2777             : 
    2778             :     // Return value
    2779             :     int FanAvailSchPtr; // returned availability schedule pointer of matched fan
    2780             : 
    2781             :     // FUNCTION LOCAL VARIABLE DECLARATIONS:
    2782             :     int WhichFan;
    2783             : 
    2784         811 :     auto &Fan(state.dataFans->Fan);
    2785             : 
    2786             :     // Obtains and Allocates fan related parameters from input file
    2787         811 :     if (state.dataFans->GetFanInputFlag) { // First time subroutine has been entered
    2788           0 :         GetFanInput(state);
    2789           0 :         state.dataFans->GetFanInputFlag = false;
    2790             :     }
    2791             : 
    2792         811 :     WhichFan = UtilityRoutines::FindItemInList(FanName, Fan, &FanEquipConditions::FanName);
    2793         811 :     if (WhichFan != 0) {
    2794         811 :         FanAvailSchPtr = Fan(WhichFan).AvailSchedPtrNum;
    2795             :     } else {
    2796           0 :         ShowSevereError(state, "GetFanAvailSchPtr: Could not find Fan, Type=\"" + FanType + "\" Name=\"" + FanName + "\"");
    2797           0 :         ErrorsFound = true;
    2798           0 :         FanAvailSchPtr = 0;
    2799             :     }
    2800             : 
    2801         811 :     return FanAvailSchPtr;
    2802             : }
    2803             : 
    2804         560 : int GetFanSpeedRatioCurveIndex(EnergyPlusData &state,
    2805             :                                std::string &FanType, // must match fan types in this module (set if nonzero index passed)
    2806             :                                std::string &FanName, // must match fan names for the fan type (set if nonzero index passed)
    2807             :                                Optional_int IndexIn  // optional fan index if fan type and name are unknown or index needs setting
    2808             : )
    2809             : {
    2810             : 
    2811             :     // FUNCTION INFORMATION:
    2812             :     //       AUTHOR         Richard Raustad
    2813             :     //       DATE WRITTEN   September 2009
    2814             :     //       MODIFIED       na
    2815             :     //       RE-ENGINEERED  na
    2816             : 
    2817             :     // PURPOSE OF THIS FUNCTION:
    2818             :     // This function looks up the given fan and returns the fan speed curve pointer.  If
    2819             :     // incorrect fan type or name is given, ErrorsFound is returned as true and value is returned
    2820             :     // as zero. If optional index argument is passed along with fan type and name, the index is set.
    2821             : 
    2822             :     // Return value
    2823             :     int FanSpeedRatioCurveIndex; // index to fan speed ratio curve object
    2824             : 
    2825             :     // FUNCTION LOCAL VARIABLE DECLARATIONS:
    2826             :     int WhichFan;
    2827             : 
    2828         560 :     auto &Fan(state.dataFans->Fan);
    2829             : 
    2830             :     // Obtains and Allocates fan related parameters from input file
    2831         560 :     if (state.dataFans->GetFanInputFlag) { // First time subroutine has been entered
    2832           0 :         GetFanInput(state);
    2833           0 :         state.dataFans->GetFanInputFlag = false;
    2834             :     }
    2835             : 
    2836         560 :     if (present(IndexIn)) {
    2837         560 :         if (IndexIn > 0) {
    2838         560 :             WhichFan = IndexIn;
    2839         560 :             FanType = Fan(WhichFan).FanType;
    2840         560 :             FanName = Fan(WhichFan).FanName;
    2841             :         } else {
    2842           0 :             WhichFan = UtilityRoutines::FindItemInList(FanName, Fan, &FanEquipConditions::FanName);
    2843           0 :             IndexIn = WhichFan;
    2844             :         }
    2845             :     } else {
    2846           0 :         WhichFan = UtilityRoutines::FindItemInList(FanName, Fan, &FanEquipConditions::FanName);
    2847             :     }
    2848             : 
    2849         560 :     if (WhichFan != 0) {
    2850         560 :         FanSpeedRatioCurveIndex = Fan(WhichFan).FanPowerRatAtSpeedRatCurveIndex;
    2851             :     } else {
    2852           0 :         ShowSevereError(state, "GetFanSpeedRatioCurveIndex: Could not find Fan, Type=\"" + FanType + "\" Name=\"" + FanName + "\"");
    2853           0 :         FanSpeedRatioCurveIndex = 0;
    2854             :     }
    2855             : 
    2856         560 :     return FanSpeedRatioCurveIndex;
    2857             : }
    2858             : 
    2859           0 : void SetFanData(EnergyPlusData &state,
    2860             :                 int const FanNum,                     // Index of fan
    2861             :                 bool &ErrorsFound,                    // Set to true if certain errors found
    2862             :                 std::string const &FanName,           // Name of fan
    2863             :                 Optional<Real64 const> MaxAirVolFlow, // Fan air volumetric flow rate    [m3/s]
    2864             :                 Optional<Real64 const> MinAirVolFlow  // Fan air volumetric flow rate    [m3/s]
    2865             : )
    2866             : {
    2867             : 
    2868             :     // SUBROUTINE INFORMATION:
    2869             :     //       AUTHOR         Richard Raustad
    2870             :     //       DATE WRITTEN   October 2007
    2871             :     //       MODIFIED       na
    2872             :     //       RE-ENGINEERED  na
    2873             : 
    2874             :     // PURPOSE OF THIS SUBROUTINE:
    2875             :     // This routine was designed for to autosize the HeatExchanger:AirToAir:SensibleAndLatent using
    2876             :     // information from the ZoneHVAC:EnergyRecoveryVentilator object.
    2877             :     // This is an illustration of setting data from an outside source.
    2878             : 
    2879             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2880             :     int WhichFan; // index to generic HX
    2881             : 
    2882           0 :     auto &Fan(state.dataFans->Fan);
    2883             : 
    2884             :     // Obtains and Allocates fan related parameters from input file
    2885           0 :     if (state.dataFans->GetFanInputFlag) { // First time subroutine has been entered
    2886           0 :         GetFanInput(state);
    2887           0 :         state.dataFans->GetFanInputFlag = false;
    2888             :     }
    2889             : 
    2890           0 :     if (FanNum == 0) {
    2891           0 :         WhichFan = UtilityRoutines::FindItemInList(FanName, Fan, &FanEquipConditions::FanName);
    2892             :     } else {
    2893           0 :         WhichFan = FanNum;
    2894             :     }
    2895             : 
    2896           0 :     if (WhichFan <= 0 || WhichFan > state.dataFans->NumFans) {
    2897           0 :         ShowSevereError(state, "SetFanData: Could not find fan = \"" + FanName + "\"");
    2898           0 :         ErrorsFound = true;
    2899           0 :         return;
    2900             :     }
    2901             : 
    2902           0 :     if (present(MaxAirVolFlow)) {
    2903           0 :         Fan(WhichFan).MaxAirFlowRate = MaxAirVolFlow;
    2904             :     }
    2905             : 
    2906           0 :     if (present(MinAirVolFlow)) {
    2907           0 :         Fan(WhichFan).MinAirFlowRate = MinAirVolFlow;
    2908             :     }
    2909             : }
    2910             : 
    2911           0 : [[maybe_unused]] Real64 FanDesDT(EnergyPlusData &state,
    2912             :                                  int const FanNum,                        // index of fan in Fan array
    2913             :                                  [[maybe_unused]] Real64 const FanVolFlow // fan volumetric flow rate [m3/s]
    2914             : )
    2915             : {
    2916             :     // FUNCTION INFORMATION:
    2917             :     //       AUTHOR         Fred Buhl
    2918             :     //       DATE WRITTEN   August 2014
    2919             :     //       MODIFIED
    2920             :     //       RE-ENGINEERED  na
    2921             : 
    2922             :     // PURPOSE OF THIS FUNCTION:
    2923             :     // This function calculates and returns the design fan delta T from the fan input data
    2924             : 
    2925             :     // METHODOLOGY EMPLOYED:
    2926             :     // Simple fan:  Qdot,tot = (Vdot*deltaP)/Eff,tot
    2927             :     //              Qdot,air = Eff,mot*Qdot,tot + (Qdot,tot - Eff,mot*Qdot,tot)*Frac,mot-in-airstream
    2928             :     //              Qdot,air = cp,air*rho,air*Vdot*deltaT
    2929             : 
    2930             :     // REFERENCES: EnergyPlus Engineering Reference
    2931             : 
    2932             :     // Return value
    2933             :     Real64 DesignDeltaT; // returned delta T of matched fan [delta deg C]
    2934             : 
    2935             :     // FUNCTION LOCAL VARIABLE DECLARATIONS:
    2936             :     Real64 RhoAir;       // density of air [kg/m3]
    2937             :     Real64 CpAir;        // specific heat of air [J/kg-K]
    2938             :     Real64 DeltaP;       // fan design pressure rise [N/m2]
    2939             :     Real64 TotEff;       // fan design total efficiency
    2940             :     Real64 MotEff;       // fan design motor efficiency
    2941             :     Real64 MotInAirFrac; // fraction of motor in the air stream
    2942             : 
    2943           0 :     auto &Fan(state.dataFans->Fan);
    2944             : 
    2945           0 :     if (FanNum == 0) {
    2946           0 :         DesignDeltaT = 0.0;
    2947           0 :     } else if (Fan(FanNum).FanType_Num != FanType_ComponentModel) {
    2948           0 :         DeltaP = Fan(FanNum).DeltaPress;
    2949           0 :         TotEff = Fan(FanNum).FanEff;
    2950           0 :         MotEff = Fan(FanNum).MotEff;
    2951           0 :         MotInAirFrac = Fan(FanNum).MotInAirFrac;
    2952           0 :         RhoAir = state.dataEnvrn->StdRhoAir;
    2953           0 :         CpAir = PsyCpAirFnW(DataPrecisionGlobals::constant_zero);
    2954           0 :         DesignDeltaT = (DeltaP / (RhoAir * CpAir * TotEff)) * (MotEff + MotInAirFrac * (1.0 - MotEff));
    2955             :     } else {
    2956           0 :         DesignDeltaT = 0.0;
    2957             :     }
    2958             : 
    2959           0 :     return DesignDeltaT;
    2960             : 
    2961             : } // FanDesDT
    2962             : 
    2963        2568 : Real64 CalFaultyFanAirFlowReduction(EnergyPlusData &state,
    2964             :                                     std::string const &FanName,          // name of the fan
    2965             :                                     Real64 const FanDesignAirFlowRate,   // Fan Design Volume Flow Rate [m3/sec]
    2966             :                                     Real64 const FanDesignDeltaPress,    // Fan Design Delta Pressure [Pa]
    2967             :                                     Real64 const FanFaultyDeltaPressInc, // Increase of Fan Delta Pressure in the Faulty Case [Pa]
    2968             :                                     int const FanCurvePtr                // Fan Curve Index
    2969             : )
    2970             : {
    2971             : 
    2972             :     // SUBROUTINE INFORMATION:
    2973             :     //       AUTHOR         Rongpeng Zhang
    2974             :     //       DATE WRITTEN   Apr. 2015
    2975             :     //       MODIFIED       na
    2976             :     //       RE-ENGINEERED  na
    2977             : 
    2978             :     // PURPOSE OF THIS SUBROUTINE:
    2979             :     // Calculate the decrease of the fan air flow rate, given the fan curve
    2980             :     // and the increase of fan pressure rise due to fouling air filters
    2981             : 
    2982             :     // Using/Aliasing
    2983             :     using namespace Curve;
    2984             : 
    2985             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2986             :     Real64 FanFaultyAirFlowRate; // Fan Volume Flow Rate in the Faulty Case [m3/sec]
    2987             :     Real64 FanCalDeltaPress;     // Calculated Fan Delta Pressure for temp use [Pa]
    2988             :     Real64 FanCalDeltaPresstemp; // Calculated Fan Delta Pressure for temp use [Pa]
    2989             : 
    2990             :     // Check whether the fan curve covers the design operational point of the fan
    2991        2568 :     FanCalDeltaPress = CurveValue(state, FanCurvePtr, FanDesignAirFlowRate);
    2992        2568 :     if ((FanCalDeltaPress < 0.9 * FanDesignDeltaPress) || (FanCalDeltaPress > 1.1 * FanDesignDeltaPress)) {
    2993           0 :         ShowWarningError(state, "The design operational point of the fan " + FanName + " does not fall ");
    2994           0 :         ShowContinueError(state, "on the fan curve provided in the FaultModel:Fouling:AirFilter object. ");
    2995           0 :         return 0.0;
    2996             :     }
    2997             : 
    2998             :     // Calculate the Fan Volume Flow Rate in the Faulty Case
    2999        2568 :     FanFaultyAirFlowRate = FanDesignAirFlowRate;
    3000        2568 :     FanCalDeltaPresstemp = CurveValue(state, FanCurvePtr, FanFaultyAirFlowRate);
    3001        2568 :     FanCalDeltaPress = FanCalDeltaPresstemp;
    3002             : 
    3003     1630680 :     while (FanCalDeltaPress < (FanDesignDeltaPress + FanFaultyDeltaPressInc)) {
    3004      814056 :         FanFaultyAirFlowRate = FanFaultyAirFlowRate - 0.005;
    3005      814056 :         FanCalDeltaPresstemp = CurveValue(state, FanCurvePtr, FanFaultyAirFlowRate);
    3006             : 
    3007     1628112 :         if ((FanCalDeltaPresstemp <= FanCalDeltaPress) ||
    3008      814056 :             (FanFaultyAirFlowRate <= state.dataCurveManager->PerfCurve(FanCurvePtr).inputLimits[0].min)) {
    3009             :             // The new operational point of the fan go beyond the fan selection range
    3010           0 :             ShowWarningError(state, "The operational point of the fan " + FanName + " may go beyond the fan selection ");
    3011           0 :             ShowContinueError(state, "range in the faulty fouling air filter cases");
    3012           0 :             break;
    3013             :         }
    3014             : 
    3015      814056 :         FanCalDeltaPress = FanCalDeltaPresstemp;
    3016             :     }
    3017             : 
    3018        2568 :     return FanDesignAirFlowRate - FanFaultyAirFlowRate;
    3019             : }
    3020             : 
    3021         362 : Real64 FanDesHeatGain(EnergyPlusData &state,
    3022             :                       int const FanNum,       // index of fan in Fan array
    3023             :                       Real64 const FanVolFlow // fan volumetric flow rate [m3/s]
    3024             : )
    3025             : {
    3026             :     // FUNCTION INFORMATION:
    3027             :     //       AUTHOR         Fred Buhl
    3028             :     //       DATE WRITTEN   August 2014
    3029             :     //       MODIFIED
    3030             :     //       RE-ENGINEERED  na
    3031             : 
    3032             :     // PURPOSE OF THIS FUNCTION:
    3033             :     // This function calculates and returns the design fan heat gain from the fan input data
    3034             : 
    3035             :     // METHODOLOGY EMPLOYED:
    3036             :     // Simple fan:  Qdot,tot = (Vdot*deltaP)/Eff,tot
    3037             :     //              Qdot,air = Eff,mot*Qdot,tot + (Qdot,tot - Eff,mot*Qdot,tot)*Frac,mot-in-airstream
    3038             : 
    3039             :     // REFERENCES: EnergyPlus Engineering Reference
    3040             : 
    3041             :     // Return value
    3042             :     Real64 DesignHeatGain; // returned heat gain of matched fan [W]
    3043             : 
    3044             :     // FUNCTION LOCAL VARIABLE DECLARATIONS:
    3045             :     Real64 DeltaP;       // fan design pressure rise [N/m2]
    3046             :     Real64 TotEff;       // fan design total efficiency
    3047             :     Real64 MotEff;       // fan design motor efficiency
    3048             :     Real64 MotInAirFrac; // fraction of motor in the air stream
    3049             :     Real64 FanPowerTot;  // total fan power consumption [W]
    3050             : 
    3051         362 :     auto &Fan(state.dataFans->Fan);
    3052             : 
    3053         362 :     if (FanNum == 0) {
    3054           0 :         DesignHeatGain = 0.0;
    3055         362 :     } else if (Fan(FanNum).FanType_Num != FanType_ComponentModel) {
    3056         362 :         DeltaP = Fan(FanNum).DeltaPress;
    3057         362 :         TotEff = Fan(FanNum).FanEff;
    3058         362 :         MotEff = Fan(FanNum).MotEff;
    3059         362 :         MotInAirFrac = Fan(FanNum).MotInAirFrac;
    3060         362 :         FanPowerTot = (FanVolFlow * DeltaP) / TotEff;
    3061         362 :         DesignHeatGain = MotEff * FanPowerTot + (FanPowerTot - MotEff * FanPowerTot) * MotInAirFrac;
    3062             :     } else {
    3063           0 :         if (!state.dataGlobal->SysSizingCalc && state.dataFans->MySizeFlag(FanNum)) {
    3064           0 :             SizeFan(state, FanNum);
    3065           0 :             state.dataFans->MySizeFlag(FanNum) = false;
    3066             :         }
    3067           0 :         DesignHeatGain = Fan(FanNum).FanShaftPower + (Fan(FanNum).MotorInputPower - Fan(FanNum).FanShaftPower) * Fan(FanNum).MotInAirFrac;
    3068             :     }
    3069             : 
    3070         362 :     return DesignHeatGain;
    3071             : 
    3072             : } // FanDesHeatGain
    3073             : 
    3074       11856 : void FanInputsForDesHeatGain(EnergyPlusData &state,
    3075             :                              int const fanIndex,
    3076             :                              Real64 &deltaP,
    3077             :                              Real64 &motEff,
    3078             :                              Real64 &totEff,
    3079             :                              Real64 &motInAirFrac,
    3080             :                              Real64 &fanShaftPow,
    3081             :                              Real64 &motInPower,
    3082             :                              bool &fanCompModel)
    3083             : {
    3084       11856 :     deltaP = 0.0;
    3085       11856 :     motEff = 0.0;
    3086       11856 :     totEff = 0.0;
    3087       11856 :     motInAirFrac = 0.0;
    3088       11856 :     fanShaftPow = 0.0;
    3089       11856 :     motInPower = 0.0;
    3090       11856 :     fanCompModel = false;
    3091             : 
    3092       11856 :     auto &Fan(state.dataFans->Fan);
    3093             : 
    3094       11856 :     if (fanIndex <= 0) {
    3095          15 :         return;
    3096       11841 :     } else if (Fan(fanIndex).FanType_Num != FanType_ComponentModel) {
    3097       11830 :         deltaP = Fan(fanIndex).DeltaPress;
    3098       11830 :         motEff = Fan(fanIndex).MotEff;
    3099       11830 :         totEff = Fan(fanIndex).FanEff;
    3100       11830 :         motInAirFrac = Fan(fanIndex).MotInAirFrac;
    3101             :     } else {
    3102          11 :         if (!state.dataGlobal->SysSizingCalc && state.dataFans->MySizeFlag(fanIndex)) {
    3103           1 :             SizeFan(state, fanIndex);
    3104           1 :             state.dataFans->MySizeFlag(fanIndex) = false;
    3105             :         }
    3106          11 :         fanCompModel = true;
    3107          11 :         fanShaftPow = Fan(fanIndex).FanShaftPower;
    3108          11 :         motInPower = Fan(fanIndex).MotorInputPower;
    3109          11 :         motInAirFrac = Fan(fanIndex).MotInAirFrac;
    3110             :     }
    3111             : }
    3112             : 
    3113          23 : void SetFanAirLoopNumber(EnergyPlusData &state, int const FanIndex, int const AirLoopNum)
    3114             : {
    3115          23 :     state.dataFans->Fan(FanIndex).AirLoopNum = AirLoopNum;
    3116          23 : }
    3117             : 
    3118        2313 : } // namespace EnergyPlus::Fans

Generated by: LCOV version 1.13