LCOV - code coverage report
Current view: top level - EnergyPlus - MixedAir.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 2136 2921 73.1 %
Date: 2023-01-17 19:17:23 Functions: 54 57 94.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             : #include <string>
      51             : 
      52             : // ObjexxFCL Headers
      53             : #include <ObjexxFCL/Array.functions.hh>
      54             : #include <ObjexxFCL/Fmath.hh>
      55             : 
      56             : // EnergyPlus Headers
      57             : #include <EnergyPlus/Autosizing/Base.hh>
      58             : #include <EnergyPlus/BranchNodeConnections.hh>
      59             : #include <EnergyPlus/CurveManager.hh>
      60             : #include <EnergyPlus/Data/EnergyPlusData.hh>
      61             : #include <EnergyPlus/DataAirLoop.hh>
      62             : #include <EnergyPlus/DataContaminantBalance.hh>
      63             : #include <EnergyPlus/DataDefineEquip.hh>
      64             : #include <EnergyPlus/DataEnvironment.hh>
      65             : #include <EnergyPlus/DataHVACGlobals.hh>
      66             : #include <EnergyPlus/DataHeatBalance.hh>
      67             : #include <EnergyPlus/DataIPShortCuts.hh>
      68             : #include <EnergyPlus/DataLoopNode.hh>
      69             : #include <EnergyPlus/DataSizing.hh>
      70             : #include <EnergyPlus/DataZoneControls.hh>
      71             : #include <EnergyPlus/DataZoneEnergyDemands.hh>
      72             : #include <EnergyPlus/DataZoneEquipment.hh>
      73             : #include <EnergyPlus/DesiccantDehumidifiers.hh>
      74             : #include <EnergyPlus/EMSManager.hh>
      75             : #include <EnergyPlus/EvaporativeCoolers.hh>
      76             : #include <EnergyPlus/Fans.hh>
      77             : #include <EnergyPlus/FaultsManager.hh>
      78             : #include <EnergyPlus/General.hh>
      79             : #include <EnergyPlus/GeneralRoutines.hh>
      80             : #include <EnergyPlus/GlobalNames.hh>
      81             : #include <EnergyPlus/HVACControllers.hh>
      82             : #include <EnergyPlus/HVACDXHeatPumpSystem.hh>
      83             : #include <EnergyPlus/HVACFan.hh>
      84             : #include <EnergyPlus/HVACHXAssistedCoolingCoil.hh>
      85             : #include <EnergyPlus/HVACVariableRefrigerantFlow.hh>
      86             : #include <EnergyPlus/HeatRecovery.hh>
      87             : #include <EnergyPlus/HeatingCoils.hh>
      88             : #include <EnergyPlus/Humidifiers.hh>
      89             : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      90             : #include <EnergyPlus/MixedAir.hh>
      91             : #include <EnergyPlus/NodeInputManager.hh>
      92             : #include <EnergyPlus/OutAirNodeManager.hh>
      93             : #include <EnergyPlus/OutputProcessor.hh>
      94             : #include <EnergyPlus/OutputReportPredefined.hh>
      95             : #include <EnergyPlus/PhotovoltaicThermalCollectors.hh>
      96             : #include <EnergyPlus/Psychrometrics.hh>
      97             : #include <EnergyPlus/ScheduleManager.hh>
      98             : #include <EnergyPlus/SetPointManager.hh>
      99             : #include <EnergyPlus/SimAirServingZones.hh>
     100             : #include <EnergyPlus/SteamCoils.hh>
     101             : #include <EnergyPlus/TranspiredCollector.hh>
     102             : #include <EnergyPlus/UnitarySystem.hh>
     103             : #include <EnergyPlus/UserDefinedComponents.hh>
     104             : #include <EnergyPlus/UtilityRoutines.hh>
     105             : #include <EnergyPlus/WaterCoils.hh>
     106             : 
     107             : namespace EnergyPlus::MixedAir {
     108             : 
     109             : // Module containing the routines dealing with the mixed air portion
     110             : // of the HVAC air loop.
     111             : 
     112             : // MODULE INFORMATION:
     113             : //       AUTHOR         Fred Buhl
     114             : //       DATE WRITTEN   October 1998
     115             : //       MODIFIED       Shirey/Raustad FSEC, June/Aug 2003, Jan 2004
     116             : //                      Lawrie, March 2006 - Module order (per template)
     117             : //                      Craig Wray 22Aug2010 - Added Fan ComponentModel
     118             : //                      Chandan Sharma, FSEC, 25Aug 2011 - Added ProportionalControl
     119             : //                           to enhance CO2 based DCV control
     120             : //                      Feb 2013 Bereket Nigusse, FSEC
     121             : //                        Added DX Coil Model For 100% OA systems
     122             : //       RE-ENGINEERED  na
     123             : 
     124             : // PURPOSE OF THIS MODULE:
     125             : // To encapsulate the data and algorithms required to
     126             : // simulate the mixed air portion of the EPlus air loop.
     127             : 
     128             : // METHODOLOGY EMPLOYED:
     129             : // An algorithmic controller will be employed - there is no attempt to
     130             : // simulate real controllers for the economizer. The mixed air controller
     131             : // will sense various node conditions and set some node flow rates.  Mixed
     132             : // air components will operate with predetermined flow rates.
     133             : 
     134             : // Using/Aliasing
     135             : using namespace DataLoopNode;
     136             : using namespace DataAirLoop;
     137             : using namespace DataEnvironment;
     138             : using namespace DataHVACGlobals;
     139             : using namespace ScheduleManager;
     140             : using namespace DataSizing;
     141             : using namespace FaultsManager;
     142             : 
     143         771 : Array1D_string const CurrentModuleObjects(8,
     144             :                                           {"AirLoopHVAC:OutdoorAirSystem",
     145             :                                            "AirLoopHVAC:OutdoorAirSystem:EquipmentList",
     146             :                                            "AirLoopHVAC:ControllerList",
     147             :                                            "AvailabilityManagerAssignmentList",
     148             :                                            "Controller:OutdoorAir",
     149             :                                            "ZoneHVAC:EnergyRecoveryVentilator:Controller",
     150             :                                            "Controller:MechanicalVentilation",
     151         771 :                                            "OutdoorAir:Mixer"});
     152             : 
     153             : constexpr std::array<std::string_view, static_cast<int>(DataSizing::SysOAMethod::Num)> SOAMNamesUC{"ZONESUM",
     154             :                                                                                                    "STANDARD62.1VENTILATIONRATEPROCEDURE",
     155             :                                                                                                    "INDOORAIRQUALITYPROCEDURE",
     156             :                                                                                                    "PROPORTIONALCONTROLBASEDONOCCUPANCYSCHEDULE",
     157             :                                                                                                    "INDOORAIRQUALITYPROCEDUREGENERICCONTAMINANT",
     158             :                                                                                                    "INDOORAIRQUALITYPROCEDURECOMBINED",
     159             :                                                                                                    "PROPORTIONALCONTROLBASEDONDESIGNOCCUPANCY",
     160             :                                                                                                    "PROPORTIONALCONTROLBASEDONDESIGNOARATE",
     161             :                                                                                                    "STANDARD62.1SIMPLIFIEDPROCEDURE",
     162             :                                                                                                    "STANDARD62.1VENTILATIONRATEPROCEDUREWITHLIMIT"};
     163             : 
     164             : constexpr std::array<std::string_view, static_cast<int>(SimAirServingZones::CompType::Num)> CompTypeNamesUC{
     165             :     "OUTDOORAIR:MIXER",
     166             :     "FAN:CONSTANTVOLUME",
     167             :     "FAN:VARIABLEVOLUME",
     168             :     "COIL:COOLING:WATER",
     169             :     "COIL:HEATING:WATER",
     170             :     "COIL:HEATING:STEAM",
     171             :     "COIL:COOLING:WATER:DETAILEDGEOMETRY",
     172             :     "COIL:HEATING:ELECTRIC",
     173             :     "COIL:HEATING:FUEL",
     174             :     "COILSYSTEM:COOLING:WATER:HEATEXCHANGERASSISTED",
     175             :     "COIL:HEATING:DESUPERHEATER",
     176             :     "COILSYSTEM:COOLING:DX",
     177             :     "HEATEXCHANGER:AIRTOAIR:FLATPLATE",
     178             :     "DEHUMIDIFIER:DESICCANT:NOFANS",
     179             :     "SOLARCOLLECTOR:UNGLAZEDTRANSPIRED",
     180             :     "EVAPORATIVECOOLER:DIRECT:CELDEKPAD",
     181             :     "AIRLOOPHVAC:UNITARY:FURNACE:HEATONLY",
     182             :     "AIRLOOPHVAC:UNITARY:FURNACE:HEATCOOL",
     183             :     "HUMIDIFIER:STEAM:ELECTRIC",
     184             :     "DUCT",
     185             :     "AIRLOOPHVAC:UNITARYHEATCOOL:VAVCHANGEOVERBYPASS",
     186             :     "AIRLOOPHVAC:UNITARYHEATPUMP:AIRTOAIR:MULTISPEED",
     187             :     "FAN:COMPONENTMODEL",
     188             :     "COILSYSTEM:HEATING:DX",
     189             :     "COIL:USERDEFINED",
     190             :     "FAN:SYSTEMMODEL",
     191             :     "AIRLOOPHVAC:UNITARYSYSTEM",
     192             :     "ZONEHVAC:TERMINALUNIT:VARIABLEREFRIGERANTFLOW",
     193             :     "SOLARCOLLECTOR:FLATPLATE:PHOTOVOLTAICTHERMAL",
     194             :     "COILSYSTEM:COOLING:WATER"};
     195             : 
     196             : static constexpr std::array<std::string_view, static_cast<int>(DataSizing::SysOAMethod::Num)> printSysOAMethod{
     197             :     "ZoneSum,",
     198             :     "Standard62.1VentilationRateProcedure,",
     199             :     "IndoorAirQualityProcedure,",
     200             :     "ProportionalControlBasedOnOccupancySchedule,",
     201             :     "IndoorAirQualityGenericContaminant,",
     202             :     "IndoorAirQualityProcedureCombined,",
     203             :     "ProportionalControlBasedOnDesignOccupancy,",
     204             :     "ProportionalControlBasedOnDesignOARate,",
     205             :     "Standard62.1SimplifiedProcedure,",
     206             :     "Standard62.1VentilationRateProcedureWithLimit,"};
     207             : 
     208         977 : Real64 OAGetFlowRate(EnergyPlusData &state, int OAPtr)
     209             : {
     210         977 :     Real64 FlowRate(0);
     211         977 :     if ((OAPtr > 0) && (OAPtr <= state.dataMixedAir->NumOAControllers) && (state.dataEnvrn->StdRhoAir != 0)) {
     212         977 :         FlowRate = state.dataMixedAir->OAController(OAPtr).OAMassFlow / state.dataEnvrn->StdRhoAir;
     213             :     }
     214         977 :     return FlowRate;
     215             : }
     216           0 : Real64 OAGetMinFlowRate(EnergyPlusData &state, int OAPtr)
     217             : {
     218           0 :     Real64 MinFlowRate(0);
     219           0 :     if ((OAPtr > 0) && (OAPtr <= state.dataMixedAir->NumOAControllers)) {
     220           0 :         MinFlowRate = state.dataMixedAir->OAController(OAPtr).MinOA;
     221             :     }
     222           0 :     return MinFlowRate;
     223             : }
     224          84 : void OASetDemandManagerVentilationState(EnergyPlusData &state, int OAPtr, bool aState)
     225             : {
     226          84 :     if ((OAPtr > 0) && (OAPtr <= state.dataMixedAir->NumOAControllers)) {
     227          84 :         state.dataMixedAir->OAController(OAPtr).ManageDemand = aState;
     228             :     }
     229          84 : }
     230          42 : void OASetDemandManagerVentilationFlow(EnergyPlusData &state, int OAPtr, Real64 aFlow)
     231             : {
     232          42 :     if ((OAPtr > 0) && (OAPtr <= state.dataMixedAir->NumOAControllers)) {
     233          42 :         state.dataMixedAir->OAController(OAPtr).DemandLimitFlowRate = aFlow * state.dataEnvrn->StdRhoAir;
     234             :     }
     235          42 : }
     236        1031 : int GetOAController(EnergyPlusData &state, std::string const &OAName)
     237             : {
     238        1031 :     int CurrentOAController(0);
     239       13162 :     for (int i = 1; i <= state.dataMixedAir->NumOAControllers; i++) {
     240       13162 :         if (OAName == state.dataMixedAir->OAController(i).Name) {
     241        1031 :             CurrentOAController = i;
     242        1031 :             break;
     243             :         }
     244             :     }
     245        1031 :     return CurrentOAController;
     246             : }
     247             : 
     248    24268600 : void ManageOutsideAirSystem(EnergyPlusData &state, std::string const &OASysName, bool const FirstHVACIteration, int const AirLoopNum, int &OASysNum)
     249             : {
     250             : 
     251             :     // SUBROUTINE INFORMATION:
     252             :     //       AUTHOR         Fred Buhl
     253             :     //       DATE WRITTEN   Oct 1998
     254             :     //       MODIFIED       na
     255             :     //       RE-ENGINEERED  na
     256             : 
     257             :     // PURPOSE OF THIS SUBROUTINE
     258             :     // Manage the outside air system
     259             : 
     260    24268600 :     if (state.dataMixedAir->GetOASysInputFlag) {
     261           0 :         GetOutsideAirSysInputs(state);
     262           0 :         state.dataMixedAir->GetOASysInputFlag = false;
     263             :     }
     264             : 
     265    24268600 :     if (OASysNum == 0) {
     266        1021 :         OASysNum = UtilityRoutines::FindItemInList(OASysName, state.dataAirLoop->OutsideAirSys);
     267        1021 :         if (OASysNum == 0) {
     268           0 :             ShowFatalError(state, "ManageOutsideAirSystem: AirLoopHVAC:OutdoorAirSystem not found=" + OASysName);
     269             :         }
     270             :     }
     271             : 
     272    24268600 :     InitOutsideAirSys(state, OASysNum, FirstHVACIteration, AirLoopNum);
     273             : 
     274    24268600 :     SimOutsideAirSys(state, OASysNum, FirstHVACIteration, AirLoopNum);
     275    24268600 : }
     276             : 
     277    24335080 : void SimOASysComponents(EnergyPlusData &state, int const OASysNum, bool const FirstHVACIteration, int const AirLoopNum)
     278             : {
     279             :     int CompNum;
     280    24335080 :     auto &CompType = state.dataMixedAir->CompType;
     281    24335080 :     auto &CompName = state.dataMixedAir->CompName;
     282    24335080 :     bool ReSim(false);
     283    24335080 :     bool Sim(true);
     284    24335080 :     bool OAHeatCoil(false);
     285    24335080 :     bool OACoolCoil(false);
     286    24335080 :     bool OAHX(false);
     287             : 
     288    54326732 :     for (CompNum = 1; CompNum <= state.dataAirLoop->OutsideAirSys(OASysNum).NumComponents; ++CompNum) {
     289    29991652 :         CompType = state.dataAirLoop->OutsideAirSys(OASysNum).ComponentType(CompNum);
     290    29991652 :         CompName = state.dataAirLoop->OutsideAirSys(OASysNum).ComponentName(CompNum);
     291    89974956 :         SimOAComponent(state,
     292             :                        CompType,
     293             :                        CompName,
     294    29991652 :                        state.dataAirLoop->OutsideAirSys(OASysNum).ComponentTypeEnum(CompNum),
     295             :                        FirstHVACIteration,
     296    29991652 :                        state.dataAirLoop->OutsideAirSys(OASysNum).ComponentIndex(CompNum),
     297             :                        AirLoopNum,
     298             :                        Sim,
     299             :                        OASysNum,
     300             :                        OAHeatCoil,
     301             :                        OACoolCoil,
     302             :                        OAHX);
     303    29991652 :         if (OAHX) ReSim = true;
     304             :     }
     305             :     // if there were heat exchangers and/or desiccant wheel in the OA path, need to simulate again
     306             :     // in reverse order to propagate the air flow and conditions out the relief air path to the relief air
     307             :     // exit node
     308    24335080 :     if (ReSim) {
     309     1260822 :         for (CompNum = state.dataAirLoop->OutsideAirSys(OASysNum).NumComponents - 1; CompNum >= 1; --CompNum) {
     310      683958 :             CompType = state.dataAirLoop->OutsideAirSys(OASysNum).ComponentType(CompNum);
     311      683958 :             CompName = state.dataAirLoop->OutsideAirSys(OASysNum).ComponentName(CompNum);
     312     2051874 :             SimOAComponent(state,
     313             :                            CompType,
     314             :                            CompName,
     315      683958 :                            state.dataAirLoop->OutsideAirSys(OASysNum).ComponentTypeEnum(CompNum),
     316             :                            FirstHVACIteration,
     317      683958 :                            state.dataAirLoop->OutsideAirSys(OASysNum).ComponentIndex(CompNum),
     318             :                            AirLoopNum,
     319             :                            Sim,
     320             :                            OASysNum,
     321             :                            OAHeatCoil,
     322             :                            OACoolCoil,
     323             :                            OAHX);
     324             :         }
     325             :         // now simulate again propagate current temps back through OA system
     326     1837686 :         for (CompNum = 1; CompNum <= state.dataAirLoop->OutsideAirSys(OASysNum).NumComponents; ++CompNum) {
     327     1260822 :             CompType = state.dataAirLoop->OutsideAirSys(OASysNum).ComponentType(CompNum);
     328     1260822 :             CompName = state.dataAirLoop->OutsideAirSys(OASysNum).ComponentName(CompNum);
     329     3782466 :             SimOAComponent(state,
     330             :                            CompType,
     331             :                            CompName,
     332     1260822 :                            state.dataAirLoop->OutsideAirSys(OASysNum).ComponentTypeEnum(CompNum),
     333             :                            FirstHVACIteration,
     334     1260822 :                            state.dataAirLoop->OutsideAirSys(OASysNum).ComponentIndex(CompNum),
     335             :                            AirLoopNum,
     336             :                            Sim,
     337             :                            OASysNum,
     338             :                            OAHeatCoil,
     339             :                            OACoolCoil,
     340             :                            OAHX);
     341             :         }
     342             :     }
     343    24335080 : }
     344             : 
     345    24268600 : void SimOutsideAirSys(EnergyPlusData &state, int const OASysNum, bool const FirstHVACIteration, int const AirLoopNum)
     346             : {
     347             : 
     348             :     // SUBROUTINE INFORMATION:
     349             :     //       AUTHOR         Fred Buhl
     350             :     //       DATE WRITTEN   Oct 1998
     351             :     //       MODIFIED       na
     352             :     //       RE-ENGINEERED  na
     353             : 
     354             :     // PURPOSE OF THIS SUBROUTINE
     355             :     // Simulate the controllers and components in the outside air system.
     356             : 
     357             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     358             :     int CompNum;
     359             :     // INTEGER :: CtrlNum
     360             :     int OAMixerNum;
     361             :     int OAControllerNum;                           // OA controller index in OAController
     362    24268600 :     auto &CompType = state.dataMixedAir->CompType; // Tuned Made static
     363    24268600 :     auto &CompName = state.dataMixedAir->CompName; // Tuned Made static
     364    24268600 :     bool FatalErrorFlag(false);
     365             : 
     366             :     // SimOutsideAirSys can handle only 1 controller right now.  This must be
     367             :     // an Outside Air Controller.  This is because of the lack of iteration
     368             :     // and convergence control in the following code.
     369             :     //  DO CtrlNum=1,OutsideAirSys(OASysNum)%NumControllers
     370             :     //    CtrlName = OutsideAirSys(OASysNum)%ControllerName(CtrlNum)
     371             :     //    CALL SimOAController(CtrlName,FirstHVACIteration)
     372             :     //  END DO
     373    24268600 :     state.dataSize->CurOASysNum = OASysNum;
     374    24268600 :     auto &CurrentOASystem(state.dataAirLoop->OutsideAirSys(OASysNum));
     375    24268600 :     if (state.dataAirLoop->OutsideAirSys(OASysNum).AirLoopDOASNum == -1) {
     376    24257718 :         SimOAController(state, CurrentOASystem.OAControllerName, CurrentOASystem.OAControllerIndex, FirstHVACIteration, AirLoopNum);
     377             :     }
     378    24268600 :     SimOASysComponents(state, OASysNum, FirstHVACIteration, AirLoopNum);
     379             : 
     380    24268600 :     if (state.dataMixedAir->MyOneTimeErrorFlag(OASysNum)) {
     381        1022 :         if (CurrentOASystem.NumControllers - CurrentOASystem.NumSimpleControllers > 1) {
     382           0 :             ShowWarningError(
     383           0 :                 state, "AirLoopHVAC:OutdoorAirSystem " + CurrentOASystem.Name + " has more than 1 outside air controller; only the 1st will be used");
     384             :         }
     385        2166 :         for (CompNum = 1; CompNum <= CurrentOASystem.NumComponents; ++CompNum) {
     386        1144 :             CompType = CurrentOASystem.ComponentType(CompNum);
     387        1144 :             CompName = CurrentOASystem.ComponentName(CompNum);
     388        1144 :             if (UtilityRoutines::SameString(CompType, "OutdoorAir:Mixer")) {
     389        1021 :                 OAMixerNum = UtilityRoutines::FindItemInList(CompName, state.dataMixedAir->OAMixer);
     390        1021 :                 OAControllerNum = CurrentOASystem.OAControllerIndex;
     391        1021 :                 if (state.dataMixedAir->OAController(OAControllerNum).MixNode != state.dataMixedAir->OAMixer(OAMixerNum).MixNode) {
     392           0 :                     ShowSevereError(state,
     393           0 :                                     "The mixed air node of Controller:OutdoorAir=\"" + state.dataMixedAir->OAController(OAControllerNum).Name + "\"");
     394           0 :                     ShowContinueError(state,
     395           0 :                                       "should be the same node as the mixed air node of OutdoorAir:Mixer=\"" +
     396           0 :                                           state.dataMixedAir->OAMixer(OAMixerNum).Name + "\".");
     397           0 :                     ShowContinueError(state,
     398           0 :                                       "Controller:OutdoorAir mixed air node=\"" +
     399           0 :                                           state.dataLoopNodes->NodeID(state.dataMixedAir->OAController(OAControllerNum).MixNode) + "\".");
     400           0 :                     ShowContinueError(state,
     401           0 :                                       "OutdoorAir:Mixer mixed air node=\"" +
     402           0 :                                           state.dataLoopNodes->NodeID(state.dataMixedAir->OAMixer(OAMixerNum).MixNode) + "\".");
     403           0 :                     FatalErrorFlag = true;
     404             :                 }
     405        1021 :                 if (state.dataMixedAir->OAController(OAControllerNum).RelNode != state.dataMixedAir->OAMixer(OAMixerNum).RelNode) {
     406           0 :                     ShowSevereError(
     407           0 :                         state, "The relief air node of Controller:OutdoorAir=\"" + state.dataMixedAir->OAController(OAControllerNum).Name + "\"");
     408           0 :                     ShowContinueError(state,
     409           0 :                                       "should be the same node as the relief air node of OutdoorAir:Mixer=\"" +
     410           0 :                                           state.dataMixedAir->OAMixer(OAMixerNum).Name + "\".");
     411           0 :                     ShowContinueError(state,
     412           0 :                                       "Controller:OutdoorAir relief air node=\"" +
     413           0 :                                           state.dataLoopNodes->NodeID(state.dataMixedAir->OAController(OAControllerNum).RelNode) + "\".");
     414           0 :                     ShowContinueError(state,
     415           0 :                                       "OutdoorAir:Mixer relief air node=\"" +
     416           0 :                                           state.dataLoopNodes->NodeID(state.dataMixedAir->OAMixer(OAMixerNum).RelNode) + "\".");
     417           0 :                     FatalErrorFlag = true;
     418             :                 }
     419        1021 :                 if (state.dataMixedAir->OAController(OAControllerNum).RetNode != state.dataMixedAir->OAMixer(OAMixerNum).RetNode) {
     420           0 :                     ShowSevereError(
     421           0 :                         state, "The return air node of Controller:OutdoorAir=\"" + state.dataMixedAir->OAController(OAControllerNum).Name + "\"");
     422           0 :                     ShowContinueError(state,
     423           0 :                                       "should be the same node as the return air node of OutdoorAir:Mixer=\"" +
     424           0 :                                           state.dataMixedAir->OAMixer(OAMixerNum).Name + "\".");
     425           0 :                     ShowContinueError(state,
     426           0 :                                       "Controller:OutdoorAir return air node=\"" +
     427           0 :                                           state.dataLoopNodes->NodeID(state.dataMixedAir->OAController(OAControllerNum).RetNode) + "\".");
     428           0 :                     ShowContinueError(state,
     429           0 :                                       "OutdoorAir:Mixer return air node=\"" +
     430           0 :                                           state.dataLoopNodes->NodeID(state.dataMixedAir->OAMixer(OAMixerNum).RetNode) + "\".");
     431           0 :                     FatalErrorFlag = true;
     432             :                 }
     433             :             }
     434             :         }
     435        1022 :         state.dataMixedAir->MyOneTimeErrorFlag(OASysNum) = false;
     436        1022 :         if (FatalErrorFlag) ShowFatalError(state, "Previous severe error(s) cause program termination");
     437             :     }
     438             : 
     439    24268600 :     state.dataSize->CurOASysNum = 0;
     440    24268600 :     if (state.dataAirLoop->OutsideAirSys(OASysNum).AirLoopDOASNum == -1) {
     441    24257718 :         state.dataAirLoop->AirLoopControlInfo(AirLoopNum).OASysComponentsSimulated = true;
     442             :     }
     443    24268600 : }
     444             : 
     445    31938724 : void SimOAComponent(EnergyPlusData &state,
     446             :                     std::string const &CompType,                    // the component type
     447             :                     std::string const &CompName,                    // the component Name
     448             :                     SimAirServingZones::CompType const CompTypeNum, // Component Type -- Integerized for this module
     449             :                     bool const FirstHVACIteration,
     450             :                     int &CompIndex,
     451             :                     int const AirLoopNum, // air loop index for economizer lockout coordination
     452             :                     bool const Sim,       // if TRUE, simulate component; if FALSE, just set the coil exisitence flags
     453             :                     int const OASysNum,   // index to outside air system
     454             :                     bool &OAHeatingCoil,  // TRUE indicates a heating coil has been found
     455             :                     bool &OACoolingCoil,  // TRUE indicates a cooling coil has been found
     456             :                     bool &OAHX            // TRUE indicates a heat exchanger has been found
     457             : )
     458             : {
     459             : 
     460             :     // SUBROUTINE INFORMATION
     461             :     //             AUTHOR:  Russ Taylor, Dan Fisher, Fred Buhl
     462             :     //       DATE WRITTEN:  Oct 1997
     463             :     //           MODIFIED:  Dec 1997 Fred Buhl, D Shirey Feb/Sept 2003
     464             :     //                      Nov 2004 M. J. Witte, GARD Analytics, Inc.
     465             :     //                        Add DXSystem:AirLoop as valid OA system equipment
     466             :     //                        Work supported by ASHRAE research project 1254-RP
     467             :     //      RE-ENGINEERED:  This is new code, not reengineered
     468             : 
     469             :     // PURPOSE OF THIS SUBROUTINE:
     470             :     // Calls the individual air loop component simulation routines
     471             : 
     472             :     // METHODOLOGY EMPLOYED: None
     473             : 
     474             :     // REFERENCES: None
     475             : 
     476             :     // USE Statements
     477             :     // Using/Aliasing
     478             :     using DesiccantDehumidifiers::SimDesiccantDehumidifier;
     479             :     using EvaporativeCoolers::SimEvapCooler;
     480             :     using HeatingCoils::SimulateHeatingCoilComponents;
     481             :     using HeatRecovery::SimHeatRecovery;
     482             :     using Humidifiers::SimHumidifier;
     483             :     using HVACDXHeatPumpSystem::SimDXHeatPumpSystem;
     484             :     using HVACHXAssistedCoolingCoil::SimHXAssistedCoolingCoil;
     485             :     using SimAirServingZones::SolveWaterCoilController;
     486             :     using SteamCoils::SimulateSteamCoilComponents;
     487             :     using TranspiredCollector::SimTranspiredCollector;
     488             :     using UserDefinedComponents::SimCoilUserDefined;
     489             :     // Locals
     490             :     // SUBROUTINE ARGUMENTS:
     491             : 
     492             :     // SUBROUTINE PARAMETER DEFINITIONS: None
     493             : 
     494             :     // INTERFACE BLOCK DEFINITIONS: None
     495             : 
     496             :     // DERIVED TYPE DEFINITIONS: None
     497             : 
     498             :     // SUBROUTINE LOCAL VARIABLE DEFINITIONS
     499             : 
     500    31938724 :     OAHeatingCoil = false;
     501    31938724 :     OACoolingCoil = false;
     502    31938724 :     OAHX = false;
     503             :     Real64 AirloopPLR;
     504             :     int FanOpMode;
     505             : 
     506    31938724 :     if (CompTypeNum == SimAirServingZones::CompType::OAMixer_Num) { // 'OutdoorAir:Mixer'
     507    24903114 :         if (Sim) {
     508    24901062 :             SimOAMixer(state, CompName, FirstHVACIteration, CompIndex);
     509             :         }
     510             : 
     511             :         // Fan Types
     512     7035610 :     } else if (CompTypeNum == SimAirServingZones::CompType::Fan_Simple_CV) { // 'Fan:ConstantVolume'
     513           0 :         if (Sim) {
     514           0 :             Fans::SimulateFanComponents(state, CompName, FirstHVACIteration, CompIndex);
     515             :         }
     516     7035610 :     } else if (CompTypeNum == SimAirServingZones::CompType::Fan_Simple_VAV) { // 'Fan:VariableVolume'
     517       17611 :         if (Sim) {
     518       17609 :             Fans::SimulateFanComponents(state, CompName, FirstHVACIteration, CompIndex);
     519             :         }
     520             : 
     521     7017999 :     } else if (CompTypeNum == SimAirServingZones::CompType::Fan_System_Object) { // 'Fan:SystemModel'
     522       10882 :         if (CompIndex == 0) {                                                  // 0 means has not been filled because of 1-based arrays in old fortran
     523           0 :             CompIndex = HVACFan::getFanObjectVectorIndex(state, CompName) + 1; // + 1 for shift from zero-based vector to 1-based compIndex
     524             :         }
     525       10882 :         if (Sim) {
     526       10882 :             state.dataHVACFan->fanObjs[CompIndex - 1]->simulate(state, _, _, _, _); // vector is 0 based, but CompIndex is 1 based so shift
     527             :         }
     528     7007117 :     } else if (CompTypeNum == SimAirServingZones::CompType::Fan_ComponentModel) { // 'Fan:ComponentModel'
     529           0 :         if (Sim) {
     530           0 :             Fans::SimulateFanComponents(state, CompName, FirstHVACIteration, CompIndex);
     531             :         }
     532             : 
     533             :         // Coil Types
     534     7007117 :     } else if (CompTypeNum == SimAirServingZones::CompType::WaterCoil_Cooling) { // 'Coil:Cooling:Water'
     535     1275051 :         if (Sim) {
     536             :             // get water coil and controller data if not called previously
     537     1274999 :             if (CompIndex == 0) WaterCoils::SimulateWaterCoilComponents(state, CompName, FirstHVACIteration, CompIndex);
     538             :             // iterate on OA sys controller and water coil at the same time
     539     1274999 :             if (!state.dataWaterCoils->WaterCoil(CompIndex).heatRecoveryCoil) {
     540     2517534 :                 SolveWaterCoilController(state,
     541             :                                          FirstHVACIteration,
     542             :                                          AirLoopNum,
     543             :                                          CompName,
     544             :                                          CompIndex,
     545     1258767 :                                          state.dataWaterCoils->WaterCoil(CompIndex).ControllerName,
     546     1258767 :                                          state.dataWaterCoils->WaterCoil(CompIndex).ControllerIndex,
     547             :                                          false);
     548             :                 // set flag to tell HVAC controller it will be simulated only in SolveWaterCoilController()
     549     1258767 :                 state.dataHVACControllers->ControllerProps(state.dataWaterCoils->WaterCoil(CompIndex).ControllerIndex).BypassControllerCalc = true;
     550             :             } else {
     551       16232 :                 WaterCoils::SimulateWaterCoilComponents(state, CompName, FirstHVACIteration, CompIndex);
     552             :             }
     553             :         } else {
     554             :             // This is not working as intended ... don't want to include the HR coil in sizing.
     555             :             // But if the water coil is called to get this index, then the controller is called to set the
     556             :             // controller index and the simulation sizes the controller before the cooling coil.
     557             :             // Pushing this aspect forward to a follow up issue where the
     558             :             // controller index call is moved out of water coils getInput.
     559             :             // if (CompIndex == 0) {
     560             :             //    bool errFound = false;
     561             :             //    CompIndex = WaterCoils::GetWaterCoilIndex(state, CompType, CompName, errFound);
     562             :             //    if (errFound) ShowFatalError(state, "SimOAComponent: Program terminates for preceding reason.");
     563             :             // }
     564             :             // if (!state.dataWaterCoils->WaterCoil(CompIndex).heatRecoveryCoil) OACoolingCoil = true;
     565             :             // should not include heat recovery coils in sizing since heat transfer at peak cooling is minimal.
     566          52 :             OACoolingCoil = true;
     567             :         }
     568     5732066 :     } else if (CompTypeNum == SimAirServingZones::CompType::WaterCoil_SimpleHeat) { // 'Coil:Heating:Water')
     569     1285603 :         if (Sim) {
     570             :             // get water coil and controller data if not called previously
     571     1285549 :             if (CompIndex == 0) WaterCoils::SimulateWaterCoilComponents(state, CompName, FirstHVACIteration, CompIndex);
     572             :             // iterate on OA sys controller and water coil at the same time
     573     2571098 :             SolveWaterCoilController(state,
     574             :                                      FirstHVACIteration,
     575             :                                      AirLoopNum,
     576             :                                      CompName,
     577             :                                      CompIndex,
     578     1285549 :                                      state.dataWaterCoils->WaterCoil(CompIndex).ControllerName,
     579     1285549 :                                      state.dataWaterCoils->WaterCoil(CompIndex).ControllerIndex,
     580             :                                      false);
     581             :             // set flag to tell HVAC controller it will be simulated only in SolveWaterCoilController()
     582     1285549 :             state.dataHVACControllers->ControllerProps(state.dataWaterCoils->WaterCoil(CompIndex).ControllerIndex).BypassControllerCalc = true;
     583             :         }
     584     1285603 :         OAHeatingCoil = true;
     585     4446463 :     } else if (CompTypeNum == SimAirServingZones::CompType::SteamCoil_AirHeat) { // 'Coil:Heating:Steam'
     586           0 :         if (Sim) {
     587           0 :             SimulateSteamCoilComponents(state, CompName, FirstHVACIteration, CompIndex, 0.0);
     588             :         }
     589           0 :         OAHeatingCoil = true;
     590     4446463 :     } else if (CompTypeNum == SimAirServingZones::CompType::WaterCoil_DetailedCool) { // 'Coil:Cooling:Water:DetailedGeometry'
     591           0 :         if (Sim) {
     592             :             // get water coil and controller data if not called previously
     593           0 :             if (CompIndex == 0) WaterCoils::SimulateWaterCoilComponents(state, CompName, FirstHVACIteration, CompIndex);
     594             :             // iterate on OA sys controller and water coil at the same time
     595           0 :             SolveWaterCoilController(state,
     596             :                                      FirstHVACIteration,
     597             :                                      AirLoopNum,
     598             :                                      CompName,
     599             :                                      CompIndex,
     600           0 :                                      state.dataWaterCoils->WaterCoil(CompIndex).ControllerName,
     601           0 :                                      state.dataWaterCoils->WaterCoil(CompIndex).ControllerIndex,
     602             :                                      false);
     603             :             // set flag to tell HVAC controller it will be simulated only in SolveWaterCoilController()
     604           0 :             state.dataHVACControllers->ControllerProps(state.dataWaterCoils->WaterCoil(CompIndex).ControllerIndex).BypassControllerCalc = true;
     605             :         }
     606           0 :         OACoolingCoil = true;
     607     4446463 :     } else if (CompTypeNum == SimAirServingZones::CompType::Coil_ElectricHeat) { // 'Coil:Heating:Electric'
     608       26696 :         if (Sim) {
     609             :             //     stand-alone coils are temperature controlled (do not pass QCoilReq in argument list, QCoilReq overrides temp SP)
     610       26694 :             SimulateHeatingCoilComponents(state, CompName, FirstHVACIteration, _, CompIndex);
     611             :         }
     612       26696 :         OAHeatingCoil = true;
     613     4419767 :     } else if (CompTypeNum == SimAirServingZones::CompType::Coil_GasHeat) { // 'Coil:Heating:Fuel'
     614           0 :         if (Sim) {
     615             :             //     stand-alone coils are temperature controlled (do not pass QCoilReq in argument list, QCoilReq overrides temp SP)
     616           0 :             SimulateHeatingCoilComponents(state, CompName, FirstHVACIteration, _, CompIndex);
     617             :         }
     618           0 :         OAHeatingCoil = true;
     619     4419767 :     } else if (CompTypeNum == SimAirServingZones::CompType::WaterCoil_CoolingHXAsst) { // 'CoilSystem:Cooling:Water:HeatExchangerAssisted'
     620           0 :         if (Sim) {
     621             :             // get water coil and controller data if not called previously
     622           0 :             if (CompIndex == 0)
     623           0 :                 SimHXAssistedCoolingCoil(state, CompName, FirstHVACIteration, CompressorOperation::On, 0.0, CompIndex, ContFanCycCoil);
     624             :             // iterate on OA sys controller and water coil at the same time
     625           0 :             SolveWaterCoilController(state,
     626             :                                      FirstHVACIteration,
     627             :                                      AirLoopNum,
     628             :                                      CompName,
     629             :                                      CompIndex,
     630           0 :                                      state.dataHVACAssistedCC->HXAssistedCoil(CompIndex).ControllerName,
     631           0 :                                      state.dataHVACAssistedCC->HXAssistedCoil(CompIndex).ControllerIndex,
     632             :                                      true);
     633             :             // set flag to tell HVAC controller it will be simulated only in SolveWaterCoilController()
     634           0 :             state.dataHVACControllers->ControllerProps(state.dataHVACAssistedCC->HXAssistedCoil(CompIndex).ControllerIndex).BypassControllerCalc =
     635             :                 true;
     636             :         }
     637           0 :         OACoolingCoil = true;
     638     4419767 :     } else if (CompTypeNum == SimAirServingZones::CompType::DXSystem) { // CoilSystem:Cooling:DX  old 'AirLoopHVAC:UnitaryCoolOnly'
     639        3716 :         if (Sim) {
     640        3714 :             if (state.dataAirLoop->OutsideAirSys(OASysNum).compPointer[CompIndex] == nullptr) {
     641           4 :                 UnitarySystems::UnitarySys thisSys;
     642           2 :                 state.dataAirLoop->OutsideAirSys(OASysNum).compPointer[CompIndex] =
     643           4 :                     thisSys.factory(state, DataHVACGlobals::UnitarySys_AnyCoilType, CompName, false, 0);
     644           2 :                 CompIndex = UnitarySystems::getUnitarySystemIndex(state, CompName) + 1;
     645           2 :                 UnitarySystems::UnitarySys::checkUnitarySysCoilInOASysExists(state, CompName, 0);
     646             :             }
     647        3714 :             bool HeatingActive = false;
     648        3714 :             bool CoolingActive = false;
     649        3714 :             Real64 OAUCoilOutTemp = 0.0;
     650        3714 :             bool ZoneEquipFlag = false;
     651        3714 :             Real64 sensOut = 0.0;
     652        3714 :             Real64 latOut = 0.0;
     653        3714 :             int compNum = CompIndex - 1;
     654        7428 :             state.dataAirLoop->OutsideAirSys(OASysNum).compPointer[compNum]->simulate(state,
     655             :                                                                                       CompName,
     656             :                                                                                       FirstHVACIteration,
     657             :                                                                                       AirLoopNum,
     658             :                                                                                       compNum,
     659             :                                                                                       HeatingActive,
     660             :                                                                                       CoolingActive,
     661             :                                                                                       0,
     662             :                                                                                       OAUCoilOutTemp,
     663             :                                                                                       ZoneEquipFlag,
     664             :                                                                                       sensOut,
     665        3714 :                                                                                       latOut);
     666             :         }
     667        3716 :         OACoolingCoil = true;
     668     4416051 :     } else if (CompTypeNum == SimAirServingZones::CompType::CoilSystemWater) { // "CoilSystem:Cooling:Water"
     669       16234 :         if (state.dataAirLoop->OutsideAirSys(OASysNum).compPointer[CompIndex] == nullptr) {
     670           2 :             UnitarySystems::UnitarySys thisSys;
     671           1 :             state.dataAirLoop->OutsideAirSys(OASysNum).compPointer[CompIndex] =
     672           2 :                 thisSys.factory(state, DataHVACGlobals::UnitarySys_AnyCoilType, CompName, false, 0);
     673           1 :             UnitarySystems::UnitarySys::checkUnitarySysCoilInOASysExists(state, CompName, 0);
     674             :         }
     675       16234 :         if (Sim) {
     676       16232 :             bool HeatingActive = false;
     677       16232 :             bool CoolingActive = false;
     678       16232 :             Real64 OAUCoilOutTemp = 0.0;
     679       16232 :             bool ZoneEquipFlag = false;
     680       16232 :             Real64 sensOut = 0.0;
     681       16232 :             Real64 latOut = 0.0;
     682       32464 :             state.dataAirLoop->OutsideAirSys(OASysNum).compPointer[CompIndex]->simulate(state,
     683             :                                                                                         CompName,
     684             :                                                                                         FirstHVACIteration,
     685             :                                                                                         AirLoopNum,
     686             :                                                                                         CompIndex,
     687             :                                                                                         HeatingActive,
     688             :                                                                                         CoolingActive,
     689             :                                                                                         CompIndex,
     690             :                                                                                         OAUCoilOutTemp,
     691             :                                                                                         ZoneEquipFlag,
     692             :                                                                                         sensOut,
     693       16232 :                                                                                         latOut);
     694             :         }
     695       16234 :         OACoolingCoil = true;
     696     4399817 :     } else if (CompTypeNum == SimAirServingZones::CompType::UnitarySystemModel) { // AirLoopHVAC:UnitarySystem
     697           0 :         if (Sim) {
     698           0 :             bool HeatingActive = false;
     699           0 :             bool CoolingActive = false;
     700           0 :             Real64 OAUCoilOutTemp = 0.0;
     701           0 :             bool ZoneEquipFlag = false;
     702           0 :             Real64 sensOut = 0.0;
     703           0 :             Real64 latOut = 0.0;
     704           0 :             state.dataAirLoop->OutsideAirSys(OASysNum).compPointer[CompIndex]->simulate(state,
     705             :                                                                                         CompName,
     706             :                                                                                         FirstHVACIteration,
     707             :                                                                                         AirLoopNum,
     708             :                                                                                         CompIndex,
     709             :                                                                                         HeatingActive,
     710             :                                                                                         CoolingActive,
     711             :                                                                                         CompIndex,
     712             :                                                                                         OAUCoilOutTemp,
     713             :                                                                                         ZoneEquipFlag,
     714             :                                                                                         sensOut,
     715           0 :                                                                                         latOut);
     716             :         }
     717           0 :         if (state.dataMixedAir->MyOneTimeCheckUnitarySysFlag(OASysNum)) {
     718           0 :             UnitarySystems::UnitarySys::getUnitarySysHeatCoolCoil(state, CompName, OACoolingCoil, OAHeatingCoil, 0);
     719           0 :             UnitarySystems::UnitarySys::checkUnitarySysCoilInOASysExists(state, CompName, 0);
     720           0 :             if (Sim) state.dataMixedAir->MyOneTimeCheckUnitarySysFlag(OASysNum) = false;
     721             :         }
     722     4399817 :     } else if (CompTypeNum == SimAirServingZones::CompType::DXHeatPumpSystem) {
     723           0 :         if (Sim) {
     724           0 :             SimDXHeatPumpSystem(state, CompName, FirstHVACIteration, AirLoopNum, CompIndex);
     725             :         }
     726           0 :         OAHeatingCoil = true;
     727     4399817 :     } else if (CompTypeNum == SimAirServingZones::CompType::CoilUserDefined) {
     728       26786 :         if (Sim) {
     729       26782 :             SimCoilUserDefined(state, CompName, CompIndex, AirLoopNum, OAHeatingCoil, OACoolingCoil);
     730             :         }
     731             :         // Heat recovery
     732     4373031 :     } else if (CompTypeNum ==
     733             :                SimAirServingZones::CompType::HeatXchngr) { // 'HeatExchanger:AirToAir:FlatPlate', 'HeatExchanger:AirToAir:SensibleAndLatent',
     734             :         // 'HeatExchanger:Desiccant:BalancedFlow'
     735     1730644 :         if (Sim) {
     736     1730592 :             if (state.dataAirLoop->OutsideAirSys(OASysNum).AirLoopDOASNum > -1) {
     737           0 :                 AirloopPLR = 1.0;
     738           0 :                 FanOpMode = DataHVACGlobals::ContFanCycCoil;
     739             :             } else {
     740     1730592 :                 if (state.dataAirLoop->AirLoopControlInfo(AirLoopNum).FanOpMode == DataHVACGlobals::CycFanCycCoil) {
     741           0 :                     FanOpMode = DataHVACGlobals::CycFanCycCoil;
     742             :                 } else {
     743     1730592 :                     FanOpMode = DataHVACGlobals::ContFanCycCoil;
     744             :                 }
     745     1730592 :                 if (FanOpMode == DataHVACGlobals::CycFanCycCoil) {
     746             :                     // HX's in the OA system can be troublesome given that the OA flow rate is not necessarily proportional to air loop PLR
     747             :                     // adding that user input for branch flow rate, HX nominal flow rate, OA system min/max flow rate will not necessarily be
     748             :                     // perfectly input, a compromise is used for OA sys HX's as the ratio of flow to max. Issue #4298.
     749             :                     //                    AirloopPLR = AirLoopFlow( AirLoopNum ).FanPLR;
     750           0 :                     AirloopPLR = state.dataMixedAir->OAController(OASysNum).OAMassFlow / state.dataMixedAir->OAController(OASysNum).MaxOAMassFlowRate;
     751             :                 } else {
     752     1730592 :                     AirloopPLR = 1.0;
     753             :                 }
     754             :             }
     755     1730592 :             if (state.dataAirLoop->OutsideAirSys(OASysNum).AirLoopDOASNum > -1) {
     756           0 :                 SimHeatRecovery(state, CompName, FirstHVACIteration, CompIndex, FanOpMode, AirloopPLR, _, _, _, _, _);
     757             :             } else {
     758     5191776 :                 SimHeatRecovery(state,
     759             :                                 CompName,
     760             :                                 FirstHVACIteration,
     761             :                                 CompIndex,
     762             :                                 FanOpMode,
     763             :                                 AirloopPLR,
     764             :                                 _,
     765             :                                 _,
     766             :                                 _,
     767     1730592 :                                 state.dataAirLoop->AirLoopControlInfo(AirLoopNum).HeatRecoveryBypass,
     768     1730592 :                                 state.dataAirLoop->AirLoopControlInfo(AirLoopNum).HighHumCtrlActive);
     769             :             }
     770             :         }
     771     1730644 :         OAHX = true;
     772             : 
     773             :         // Desiccant Dehumidifier
     774     2642387 :     } else if (CompTypeNum == SimAirServingZones::CompType::Desiccant) { // 'Dehumidifier:Desiccant:NoFans'
     775             :         // 'Dehumidifier:Desiccant:System'
     776      246811 :         if (Sim) {
     777      246801 :             SimDesiccantDehumidifier(state, CompName, FirstHVACIteration, CompIndex);
     778             :         }
     779      246811 :         OAHX = true;
     780             : 
     781             :         // Humidifiers
     782     2395576 :     } else if (CompTypeNum == SimAirServingZones::CompType::Humidifier) { // 'Humidifier:Steam:Electric'
     783             :         // 'Humidifier:Steam:Gas'
     784       47789 :         if (Sim) {
     785       47787 :             SimHumidifier(state, CompName, FirstHVACIteration, CompIndex);
     786             :         }
     787             : 
     788             :         // Unglazed Transpired Solar Collector
     789     2347787 :     } else if (CompTypeNum == SimAirServingZones::CompType::Unglazed_SolarCollector) { // 'SolarCollector:UnglazedTranspired'
     790       40693 :         if (Sim) {
     791       40675 :             SimTranspiredCollector(state, CompName, CompIndex);
     792             :         }
     793             : 
     794             :         // Air-based Photovoltaic-thermal flat plate collector
     795     2307094 :     } else if (CompTypeNum == SimAirServingZones::CompType::PVT_AirBased) { // 'SolarCollector:FlatPlate:PhotovoltaicThermal'
     796       45653 :         if (Sim) {
     797       45643 :             if (CompIndex == 0) {
     798           5 :                 CompIndex = PhotovoltaicThermalCollectors::getPVTindexFromName(state, CompName);
     799             :             }
     800       45643 :             PhotovoltaicThermalCollectors::simPVTfromOASys(state, CompIndex, FirstHVACIteration);
     801             :         }
     802             : 
     803             :         // Evaporative Cooler Types
     804     2261441 :     } else if (CompTypeNum ==
     805             :                SimAirServingZones::CompType::EvapCooler) { // 'EvaporativeCooler:Direct:CelDekPad','EvaporativeCooler:Indirect:CelDekPad'
     806             :         // 'EvaporativeCooler:Indirect:WetCoil','EvaporativeCooler:Indirect:ResearchSpecial'
     807     2258255 :         if (Sim) {
     808     2258227 :             SimEvapCooler(state, CompName, CompIndex);
     809             :         }
     810             : 
     811        3186 :     } else if (CompTypeNum == SimAirServingZones::CompType::ZoneVRFasAirLoopEquip) { // 'ZoneHVAC:TerminalUnit:VariableRefrigerantFlow'
     812        3186 :         if (Sim) {
     813        3184 :             int ControlledZoneNum = 0;
     814        3184 :             bool HeatingActive = false;
     815        3184 :             bool CoolingActive = false;
     816        3184 :             int constexpr OAUnitNum = 0;
     817        3184 :             Real64 constexpr OAUCoilOutTemp = 0.0;
     818        3184 :             bool constexpr ZoneEquipment = false;
     819        3184 :             Real64 sysOut = 0.0;
     820        3184 :             Real64 latOut = 0.0;
     821        3184 :             HVACVariableRefrigerantFlow::SimulateVRF(state,
     822             :                                                      CompName,
     823             :                                                      FirstHVACIteration,
     824             :                                                      ControlledZoneNum,
     825             :                                                      CompIndex,
     826             :                                                      HeatingActive,
     827             :                                                      CoolingActive,
     828             :                                                      OAUnitNum,
     829             :                                                      OAUCoilOutTemp,
     830             :                                                      ZoneEquipment,
     831             :                                                      sysOut,
     832             :                                                      latOut);
     833             :         } else {
     834           2 :             HVACVariableRefrigerantFlow::isVRFCoilPresent(state, CompName, OACoolingCoil, OAHeatingCoil);
     835             :         }
     836             : 
     837             :     } else {
     838           0 :         ShowFatalError(state, "Invalid Outside Air Component=" + CompType);
     839             :     }
     840    31938724 : }
     841             : 
     842    43707297 : void SimOAMixer(EnergyPlusData &state, std::string const &CompName, bool const FirstHVACIteration, int &CompIndex)
     843             : {
     844             : 
     845             :     // SUBROUTINE INFORMATION:
     846             :     //       AUTHOR         Fred Buhl
     847             :     //       DATE WRITTEN   Oct 1998
     848             :     //       MODIFIED       na
     849             :     //       RE-ENGINEERED  na
     850             : 
     851             :     // PURPOSE OF THIS SUBROUTINE
     852             :     // Simulate an Outside Air Mixer component
     853             : 
     854             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     855             :     int OAMixerNum;
     856             : 
     857    43707297 :     if (state.dataMixedAir->GetOAMixerInputFlag) {
     858           0 :         GetOAMixerInputs(state);
     859           0 :         state.dataMixedAir->GetOAMixerInputFlag = false;
     860             :     }
     861             : 
     862    43707297 :     if (CompIndex == 0) {
     863        1167 :         OAMixerNum = UtilityRoutines::FindItemInList(CompName, state.dataMixedAir->OAMixer);
     864        1167 :         CompIndex = OAMixerNum;
     865        1167 :         if (OAMixerNum == 0) {
     866           0 :             ShowFatalError(state, "SimOAMixer: OutdoorAir:Mixer not found=" + CompName);
     867             :         }
     868             :     } else {
     869    43706130 :         OAMixerNum = CompIndex;
     870             :     }
     871             : 
     872    43707297 :     InitOAMixer(state, OAMixerNum, FirstHVACIteration);
     873             : 
     874    43707297 :     CalcOAMixer(state, OAMixerNum);
     875             : 
     876    43707297 :     UpdateOAMixer(state, OAMixerNum);
     877             : 
     878    43707297 :     ReportOAMixer(OAMixerNum);
     879    43707297 : }
     880             : 
     881    24821703 : void SimOAController(EnergyPlusData &state, std::string const &CtrlName, int &CtrlIndex, bool const FirstHVACIteration, int const AirLoopNum)
     882             : {
     883             : 
     884             :     // SUBROUTINE INFORMATION:
     885             :     //       AUTHOR         Fred Buhl
     886             :     //       DATE WRITTEN   Oct 1998
     887             :     //       MODIFIED       na
     888             :     //       RE-ENGINEERED  na
     889             : 
     890             :     // PURPOSE OF THIS SUBROUTINE
     891             :     // Simulate an Outside Air Controller component
     892             : 
     893             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     894             :     int OAControllerNum;
     895             : 
     896    24821703 :     if ((state.dataMixedAir->GetOAControllerInputFlag) &&
     897             :         (AirLoopNum > 0)) { // Gets input for object  first time Sim routine is called from an airloop
     898         393 :         GetOAControllerInputs(state);
     899         393 :         state.dataMixedAir->GetOAControllerInputFlag = false;
     900             :     }
     901             : 
     902    24821703 :     if (CtrlIndex == 0) {
     903        1021 :         if (state.dataMixedAir->NumOAControllers > 0) {
     904        1021 :             OAControllerNum = UtilityRoutines::FindItemInList(CtrlName, state.dataMixedAir->OAController);
     905             :         } else {
     906           0 :             OAControllerNum = 0;
     907             :         }
     908        1021 :         CtrlIndex = OAControllerNum;
     909        1021 :         if (OAControllerNum == 0) {
     910           0 :             ShowFatalError(state, "SimOAController: Outside Air Controller not found=" + CtrlName);
     911             :         }
     912             :     } else {
     913    24820682 :         OAControllerNum = CtrlIndex;
     914             :     }
     915             : 
     916    24821703 :     InitOAController(state, OAControllerNum, FirstHVACIteration, AirLoopNum);
     917             : 
     918    24821703 :     state.dataMixedAir->OAController(OAControllerNum).CalcOAController(state, AirLoopNum, FirstHVACIteration);
     919    24821703 :     state.dataMixedAir->OAController(OAControllerNum).UpdateOAController(state);
     920    24821703 : }
     921             : 
     922             : // Get Input Section of the Module
     923             : //******************************************************************************
     924             : 
     925         770 : void GetOutsideAirSysInputs(EnergyPlusData &state)
     926             : {
     927             : 
     928             :     // SUBROUTINE INFORMATION:
     929             :     //       AUTHOR         Fred Buhl
     930             :     //       DATE WRITTEN   Oct 1998
     931             :     //       MODIFIED       na
     932             :     //       RE-ENGINEERED  na
     933             : 
     934             :     // PURPOSE OF THIS SUBROUTINE
     935             :     // Input the Outside Air System data and store it in the OutsideAirSys array.
     936             : 
     937             :     // METHODOLOGY EMPLOYED:
     938             :     // Use the Get routines from the InputProcessor module.
     939             : 
     940             :     // Using/Aliasing
     941             :     using BranchNodeConnections::SetUpCompSets;
     942             :     using BranchNodeConnections::TestCompSet;
     943             : 
     944             :     // Locals
     945             :     // SUBROUTINE PARAMETER DEFINITIONS:
     946             :     static constexpr std::string_view RoutineName("GetOutsideAirSysInputs: "); // include trailing blank space
     947             : 
     948             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     949             : 
     950             :     int NumNums;   // Number of real numbers returned by GetObjectItem
     951             :     int NumAlphas; // Number of alphanumerics returned by GetObjectItem
     952             :     int IOStat;
     953        1540 :     Array1D<Real64> NumArray;
     954        1540 :     Array1D_string AlphArray;
     955             :     int OASysNum;
     956             :     int CompNum;
     957             :     int Item;
     958             :     // unused0909INTEGER :: NumComponents
     959             :     int AlphaNum;
     960        1540 :     std::string ComponentListName;
     961        1540 :     std::string ControllerListName;
     962             :     int NumInList;
     963             :     int InListNum;
     964             :     int ListNum;
     965             :     int NumSimpControllers; // number of Controller:Simple objects in an OA System
     966         770 :     bool ErrorsFound(false);
     967        1540 :     std::string CurrentModuleObject; // Object type for getting and messages
     968        1540 :     Array1D_string cAlphaFields;     // Alpha field names
     969        1540 :     Array1D_string cNumericFields;   // Numeric field names
     970        1540 :     Array1D_bool lAlphaBlanks;       // Logical array, alpha field input BLANK = .TRUE.
     971        1540 :     Array1D_bool lNumericBlanks;     // Logical array, numeric field input BLANK = .TRUE.
     972         770 :     int MaxNums(0);                  // Maximum number of numeric input fields
     973         770 :     int MaxAlphas(0);                // Maximum number of alpha input fields
     974         770 :     int TotalArgs(0);                // Total number of alpha and numeric arguments (max) for a
     975             :     //  certain object in the input file
     976             : 
     977         770 :     if (!state.dataMixedAir->GetOASysInputFlag) return;
     978             : 
     979        1540 :     state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(
     980         770 :         state, CurrentModuleObjects(static_cast<int>(CMO::OASystem)), TotalArgs, NumAlphas, NumNums);
     981         770 :     MaxNums = max(MaxNums, NumNums);
     982         770 :     MaxAlphas = max(MaxAlphas, NumAlphas);
     983        1540 :     state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(
     984         770 :         state, CurrentModuleObjects(static_cast<int>(CMO::AirLoopEqList)), TotalArgs, NumAlphas, NumNums);
     985         770 :     MaxNums = max(MaxNums, NumNums);
     986         770 :     MaxAlphas = max(MaxAlphas, NumAlphas);
     987        1540 :     state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(
     988         770 :         state, CurrentModuleObjects(static_cast<int>(CMO::ControllerList)), TotalArgs, NumAlphas, NumNums);
     989         770 :     MaxNums = max(MaxNums, NumNums);
     990         770 :     MaxAlphas = max(MaxAlphas, NumAlphas);
     991             : 
     992         770 :     AlphArray.allocate(MaxAlphas);
     993         770 :     cAlphaFields.allocate(MaxAlphas);
     994         770 :     NumArray.dimension(MaxNums, 0.0);
     995         770 :     cNumericFields.allocate(MaxNums);
     996         770 :     lAlphaBlanks.dimension(MaxAlphas, true);
     997         770 :     lNumericBlanks.dimension(MaxNums, true);
     998             : 
     999         770 :     CurrentModuleObject = CurrentModuleObjects(static_cast<int>(CMO::ControllerList));
    1000         770 :     state.dataMixedAir->NumControllerLists = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
    1001             : 
    1002         770 :     state.dataMixedAir->ControllerLists.allocate(state.dataMixedAir->NumControllerLists);
    1003             : 
    1004        2212 :     for (Item = 1; Item <= state.dataMixedAir->NumControllerLists; ++Item) {
    1005             : 
    1006             :         // create a reference for convenience
    1007        1442 :         auto &thisControllerList(state.dataMixedAir->ControllerLists(Item));
    1008        1442 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1009             :                                                                  CurrentModuleObject,
    1010             :                                                                  Item,
    1011             :                                                                  AlphArray,
    1012             :                                                                  NumAlphas,
    1013             :                                                                  NumArray,
    1014             :                                                                  NumNums,
    1015             :                                                                  IOStat,
    1016             :                                                                  lNumericBlanks,
    1017             :                                                                  lAlphaBlanks,
    1018             :                                                                  cAlphaFields,
    1019             :                                                                  cNumericFields);
    1020        1442 :         UtilityRoutines::IsNameEmpty(state, AlphArray(1), CurrentModuleObject, ErrorsFound);
    1021        1442 :         thisControllerList.Name = AlphArray(1);
    1022        1442 :         thisControllerList.NumControllers = (NumAlphas - 1) / 2;
    1023        1442 :         thisControllerList.ControllerType.allocate(thisControllerList.NumControllers);
    1024        1442 :         thisControllerList.ControllerName.allocate(thisControllerList.NumControllers);
    1025        1442 :         AlphaNum = 2;
    1026        3290 :         for (CompNum = 1; CompNum <= thisControllerList.NumControllers; ++CompNum) {
    1027        4722 :             if (UtilityRoutines::SameString(AlphArray(AlphaNum), "Controller:WaterCoil") ||
    1028        2874 :                 UtilityRoutines::SameString(AlphArray(AlphaNum), "Controller:OutdoorAir")) {
    1029        1848 :                 thisControllerList.ControllerType(CompNum) = AlphArray(AlphaNum);
    1030        1848 :                 thisControllerList.ControllerName(CompNum) = AlphArray(AlphaNum + 1);
    1031             :                 // loop over all previous controller lists to check if this controllers is also present on previous controllers
    1032        9328 :                 for (int previousListNum = 1; previousListNum < Item; ++previousListNum) {
    1033             :                     // loop over each of the controllers listed for this list
    1034        7480 :                     auto &previousList(state.dataMixedAir->ControllerLists(previousListNum));
    1035       17315 :                     for (int PreviousListControllerNum = 1; PreviousListControllerNum <= previousList.NumControllers; ++PreviousListControllerNum) {
    1036       17335 :                         if ((previousList.ControllerType(PreviousListControllerNum) == thisControllerList.ControllerType(CompNum)) &&
    1037        7500 :                             (previousList.ControllerName(PreviousListControllerNum) == thisControllerList.ControllerName(CompNum))) {
    1038           0 :                             ShowSevereError(state, "Controller instance repeated in multiple " + CurrentModuleObject + " objects");
    1039           0 :                             ShowContinueError(state, "Found in " + CurrentModuleObject + " = " + thisControllerList.Name);
    1040           0 :                             ShowContinueError(state, "Also found in " + CurrentModuleObject + " = " + previousList.Name);
    1041           0 :                             ErrorsFound = true;
    1042             :                         }
    1043             :                     }
    1044             :                 }
    1045             :             } else {
    1046           0 :                 ShowSevereError(state, "For " + CurrentModuleObject + "=\"" + AlphArray(1) + "\" invalid " + cAlphaFields(AlphaNum));
    1047           0 :                 ShowContinueError(state, "...entered=\"" + AlphArray(AlphaNum) + "\", should be Controller:WaterCoil or Controller:OutdoorAir.");
    1048           0 :                 ErrorsFound = true;
    1049             :             }
    1050        1848 :             AlphaNum += 2;
    1051             :         }
    1052             :     }
    1053             : 
    1054         770 :     CurrentModuleObject = CurrentModuleObjects(static_cast<int>(CMO::OASystem));
    1055             : 
    1056         770 :     state.dataAirLoop->NumOASystems = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
    1057             : 
    1058         770 :     state.dataAirLoop->OutsideAirSys.allocate(state.dataAirLoop->NumOASystems);
    1059         770 :     state.dataSize->OASysEqSizing.allocate(state.dataAirLoop->NumOASystems);
    1060         770 :     state.dataMixedAir->ControllerListUniqueNames.reserve(static_cast<unsigned>(state.dataAirLoop->NumOASystems));
    1061         770 :     state.dataMixedAir->MyOneTimeErrorFlag.dimension(state.dataAirLoop->NumOASystems, true);
    1062         770 :     state.dataMixedAir->MyOneTimeCheckUnitarySysFlag.dimension(state.dataAirLoop->NumOASystems, true);
    1063         770 :     state.dataMixedAir->initOASysFlag.dimension(state.dataAirLoop->NumOASystems, true);
    1064             : 
    1065        1797 :     for (OASysNum = 1; OASysNum <= state.dataAirLoop->NumOASystems; ++OASysNum) {
    1066             : 
    1067        1027 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1068             :                                                                  CurrentModuleObject,
    1069             :                                                                  OASysNum,
    1070             :                                                                  AlphArray,
    1071             :                                                                  NumAlphas,
    1072             :                                                                  NumArray,
    1073             :                                                                  NumNums,
    1074             :                                                                  IOStat,
    1075             :                                                                  lNumericBlanks,
    1076             :                                                                  lAlphaBlanks,
    1077             :                                                                  cAlphaFields,
    1078             :                                                                  cNumericFields);
    1079        1027 :         UtilityRoutines::IsNameEmpty(state, AlphArray(1), CurrentModuleObject, ErrorsFound);
    1080        1027 :         state.dataAirLoop->OutsideAirSys(OASysNum).Name = AlphArray(1);
    1081        1027 :         if (!AlphArray(2).empty()) {
    1082        3081 :             GlobalNames::IntraObjUniquenessCheck(
    1083        3081 :                 state, AlphArray(2), CurrentModuleObject, cAlphaFields(2), state.dataMixedAir->ControllerListUniqueNames, ErrorsFound);
    1084             :         }
    1085        1027 :         ControllerListName = AlphArray(2);
    1086        1027 :         state.dataAirLoop->OutsideAirSys(OASysNum).ControllerListName = AlphArray(2);
    1087        1027 :         ComponentListName = AlphArray(3);
    1088        1027 :         state.dataAirLoop->OutsideAirSys(OASysNum).ComponentListName = AlphArray(3);
    1089             : 
    1090        1027 :         TestCompSet(state, CurrentModuleObject, AlphArray(1), "UNDEFINED", "UNDEFINED", "Air Nodes");
    1091             : 
    1092        1027 :         if (!lAlphaBlanks(3)) {
    1093        2054 :             ListNum = state.dataInputProcessing->inputProcessor->getObjectItemNum(
    1094        1027 :                 state, CurrentModuleObjects(static_cast<int>(CMO::AirLoopEqList)), ComponentListName);
    1095        1027 :             if (ListNum > 0) {
    1096        2054 :                 state.dataInputProcessing->inputProcessor->getObjectItem(
    1097        1027 :                     state, CurrentModuleObjects(static_cast<int>(CMO::AirLoopEqList)), ListNum, AlphArray, NumAlphas, NumArray, NumNums, IOStat);
    1098        1027 :                 NumInList = (NumAlphas - 1) / 2;
    1099        1027 :                 state.dataAirLoop->OutsideAirSys(OASysNum).NumComponents = NumInList;
    1100        1027 :                 state.dataAirLoop->OutsideAirSys(OASysNum).ComponentName.allocate(NumInList);
    1101        1027 :                 state.dataAirLoop->OutsideAirSys(OASysNum).ComponentType.allocate(NumInList);
    1102        1027 :                 state.dataAirLoop->OutsideAirSys(OASysNum).ComponentTypeEnum.dimension(NumInList, SimAirServingZones::CompType::Invalid);
    1103        1027 :                 state.dataAirLoop->OutsideAirSys(OASysNum).ComponentIndex.dimension(NumInList, 0);
    1104        1027 :                 state.dataAirLoop->OutsideAirSys(OASysNum).InletNodeNum.dimension(NumInList, 0);
    1105        1027 :                 state.dataAirLoop->OutsideAirSys(OASysNum).OutletNodeNum.dimension(NumInList, 0);
    1106        1027 :                 state.dataAirLoop->OutsideAirSys(OASysNum).compPointer.resize(NumInList + 1, nullptr);
    1107        2176 :                 for (InListNum = 1; InListNum <= NumInList; ++InListNum) {
    1108        1149 :                     state.dataAirLoop->OutsideAirSys(OASysNum).ComponentName(InListNum) = AlphArray(InListNum * 2 + 1);
    1109        1149 :                     state.dataAirLoop->OutsideAirSys(OASysNum).ComponentType(InListNum) = AlphArray(InListNum * 2);
    1110             : 
    1111             :                     // Add equipment to component sets array
    1112        3447 :                     SetUpCompSets(state,
    1113             :                                   CurrentModuleObject,
    1114        1149 :                                   state.dataAirLoop->OutsideAirSys(OASysNum).Name,
    1115        1149 :                                   state.dataAirLoop->OutsideAirSys(OASysNum).ComponentType(InListNum),
    1116        1149 :                                   state.dataAirLoop->OutsideAirSys(OASysNum).ComponentName(InListNum),
    1117             :                                   "UNDEFINED",
    1118        1149 :                                   "UNDEFINED");
    1119             :                 }
    1120             :             } else {
    1121           0 :                 ShowSevereError(
    1122           0 :                     state, CurrentModuleObject + " = \"" + AlphArray(1) + "\" invalid " + cAlphaFields(3) + "=\"" + AlphArray(3) + "\" not found.");
    1123           0 :                 ErrorsFound = true;
    1124             :             }
    1125             :         } else {
    1126           0 :             ShowSevereError(state, CurrentModuleObject + " = \"" + AlphArray(1) + "\" invalid " + cAlphaFields(3) + " is blank and must be entered.");
    1127           0 :             ErrorsFound = true;
    1128             :         }
    1129             : 
    1130        1027 :         ListNum = 0;
    1131        1027 :         NumSimpControllers = 0;
    1132        1027 :         if (!lAlphaBlanks(2)) {
    1133        2054 :             ListNum = state.dataInputProcessing->inputProcessor->getObjectItemNum(
    1134        1027 :                 state, CurrentModuleObjects(static_cast<int>(CMO::ControllerList)), ControllerListName);
    1135        1027 :             if (ListNum > 0) {
    1136        2054 :                 state.dataInputProcessing->inputProcessor->getObjectItem(
    1137        1027 :                     state, CurrentModuleObjects(static_cast<int>(CMO::ControllerList)), ListNum, AlphArray, NumAlphas, NumArray, NumNums, IOStat);
    1138        1027 :                 NumInList = (NumAlphas - 1) / 2;
    1139        1027 :                 state.dataAirLoop->OutsideAirSys(OASysNum).NumControllers = NumInList;
    1140        1027 :                 state.dataAirLoop->OutsideAirSys(OASysNum).ControllerName.allocate(NumInList);
    1141        1027 :                 state.dataAirLoop->OutsideAirSys(OASysNum).ControllerType.allocate(NumInList);
    1142        1027 :                 state.dataAirLoop->OutsideAirSys(OASysNum).ControllerIndex.dimension(NumInList, 0);
    1143        2107 :                 for (InListNum = 1; InListNum <= NumInList; ++InListNum) {
    1144        1080 :                     state.dataAirLoop->OutsideAirSys(OASysNum).ControllerName(InListNum) = AlphArray(InListNum * 2 + 1);
    1145        1080 :                     state.dataAirLoop->OutsideAirSys(OASysNum).ControllerType(InListNum) = AlphArray(InListNum * 2);
    1146        1080 :                     if (!UtilityRoutines::SameString(state.dataAirLoop->OutsideAirSys(OASysNum).ControllerType(InListNum),
    1147        1080 :                                                      CurrentModuleObjects(static_cast<int>(CMO::OAController)))) {
    1148          54 :                         ++NumSimpControllers;
    1149             :                     }
    1150             :                 }
    1151             :             } else {
    1152           0 :                 ShowSevereError(
    1153           0 :                     state, CurrentModuleObject + " = \"" + AlphArray(1) + "\" invalid " + cAlphaFields(2) + "=\"" + AlphArray(2) + "\" not found.");
    1154           0 :                 ErrorsFound = true;
    1155             :             }
    1156             :         } else {
    1157           0 :             if (state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "AirLoopHVAC:DedicatedOutdoorAirSystem") == 0) {
    1158           0 :                 ShowSevereError(state,
    1159           0 :                                 CurrentModuleObject + " = \"" + AlphArray(1) + "\" invalid " + cAlphaFields(2) + " is blank and must be entered.");
    1160           0 :                 ErrorsFound = true;
    1161             :             } else {
    1162           0 :                 ShowWarningError(state,
    1163           0 :                                  CurrentModuleObject + " = \"" + AlphArray(1) + "\": blank " + cAlphaFields(2) +
    1164             :                                      " must be used with AirLoopHVAC:DedicatedOutdoorAirSystem.");
    1165             :             }
    1166             :         }
    1167        1027 :         state.dataAirLoop->OutsideAirSys(OASysNum).ControllerListNum = ListNum;
    1168        1027 :         state.dataAirLoop->OutsideAirSys(OASysNum).NumSimpleControllers = NumSimpControllers;
    1169             :     }
    1170             : 
    1171        1797 :     for (OASysNum = 1; OASysNum <= state.dataAirLoop->NumOASystems; ++OASysNum) {
    1172        2176 :         for (CompNum = 1; CompNum <= state.dataAirLoop->OutsideAirSys(OASysNum).NumComponents; ++CompNum) {
    1173        2298 :             state.dataAirLoop->OutsideAirSys(OASysNum).ComponentTypeEnum(CompNum) = static_cast<SimAirServingZones::CompType>(getEnumerationValue(
    1174        3447 :                 CompTypeNamesUC, UtilityRoutines::MakeUPPERCase(state.dataAirLoop->OutsideAirSys(OASysNum).ComponentType(CompNum))));
    1175        1149 :             if (state.dataAirLoop->OutsideAirSys(OASysNum).ComponentTypeEnum(CompNum) == SimAirServingZones::CompType::Fan_System_Object) {
    1176             :                 // construct fan object
    1177           2 :                 state.dataHVACFan->fanObjs.emplace_back(
    1178           2 :                     new HVACFan::FanSystem(state, state.dataAirLoop->OutsideAirSys(OASysNum).ComponentName(CompNum)));
    1179           1 :                 state.dataAirLoop->OutsideAirSys(OASysNum).ComponentIndex(CompNum) = state.dataHVACFan->fanObjs.size();
    1180        1148 :             } else if (state.dataAirLoop->OutsideAirSys(OASysNum).ComponentTypeEnum(CompNum) == SimAirServingZones::CompType::CoilSystemWater) {
    1181           1 :                 state.dataAirLoop->OutsideAirSys(OASysNum).ComponentIndex(CompNum) = CompNum;
    1182           2 :                 UnitarySystems::UnitarySys thisSys;
    1183           1 :                 state.dataAirLoop->OutsideAirSys(OASysNum).compPointer[CompNum] = thisSys.factory(
    1184           1 :                     state, DataHVACGlobals::UnitarySys_AnyCoilType, state.dataAirLoop->OutsideAirSys(OASysNum).ComponentName(CompNum), false, 0);
    1185        1147 :             } else if (state.dataAirLoop->OutsideAirSys(OASysNum).ComponentTypeEnum(CompNum) == SimAirServingZones::CompType::UnitarySystemModel) {
    1186           0 :                 UnitarySystems::UnitarySys thisSys;
    1187           0 :                 state.dataAirLoop->OutsideAirSys(OASysNum).compPointer[CompNum] = thisSys.factory(
    1188           0 :                     state, DataHVACGlobals::UnitarySys_AnyCoilType, state.dataAirLoop->OutsideAirSys(OASysNum).ComponentName(CompNum), false, 0);
    1189           0 :                 state.dataAirLoop->OutsideAirSys(OASysNum).ComponentIndex(CompNum) =
    1190           0 :                     UnitarySystems::getUnitarySystemIndex(state, state.dataAirLoop->OutsideAirSys(OASysNum).ComponentName(CompNum)) + 1;
    1191        1147 :             } else if (state.dataAirLoop->OutsideAirSys(OASysNum).ComponentTypeEnum(CompNum) == SimAirServingZones::CompType::Invalid) {
    1192          74 :                 std::string thisComp = UtilityRoutines::MakeUPPERCase(state.dataAirLoop->OutsideAirSys(OASysNum).ComponentType(CompNum));
    1193          37 :                 if (thisComp == "HEATEXCHANGER:AIRTOAIR:SENSIBLEANDLATENT" || thisComp == "HEATEXCHANGER:DESICCANT:BALANCEDFLOW") {
    1194          21 :                     state.dataAirLoop->OutsideAirSys(OASysNum).ComponentTypeEnum(CompNum) = SimAirServingZones::CompType::HeatXchngr;
    1195          16 :                 } else if (thisComp == "DEHUMIDIFIER:DESICCANT:SYSTEM") {
    1196           2 :                     state.dataAirLoop->OutsideAirSys(OASysNum).ComponentTypeEnum(CompNum) = SimAirServingZones::CompType::Desiccant;
    1197          56 :                 } else if (thisComp == "EVAPORATIVECOOLER:INDIRECT:CELDEKPAD" || thisComp == "EVAPORATIVECOOLER:INDIRECT:WETCOIL" ||
    1198          36 :                            thisComp == "EVAPORATIVECOOLER:INDIRECT:RESEARCHSPECIAL" || thisComp == "EVAPORATIVECOOLER:DIRECT:RESEARCHSPECIAL") {
    1199          14 :                     state.dataAirLoop->OutsideAirSys(OASysNum).ComponentTypeEnum(CompNum) = SimAirServingZones::CompType::EvapCooler;
    1200           0 :                 } else if (thisComp == "HUMIDIFIER:STEAM:GAS") {
    1201           0 :                     state.dataAirLoop->OutsideAirSys(OASysNum).ComponentTypeEnum(CompNum) = SimAirServingZones::CompType::Humidifier;
    1202             :                 } else {
    1203           0 :                     ShowSevereError(state,
    1204           0 :                                     CurrentModuleObject + " = \"" + AlphArray(1) + "\" invalid Outside Air Component=\"" +
    1205           0 :                                         state.dataAirLoop->OutsideAirSys(OASysNum).ComponentType(CompNum) + "\".");
    1206           0 :                     ErrorsFound = true;
    1207             :                 }
    1208             :             }
    1209             :         }
    1210             : 
    1211             :         // loop through the controllers in the controller list for OA system and save the pointer to the OA controller index
    1212        1029 :         for (int OAControllerNum = 1; OAControllerNum <= state.dataAirLoop->OutsideAirSys(OASysNum).NumControllers; ++OAControllerNum) {
    1213        1028 :             if (UtilityRoutines::SameString(state.dataAirLoop->OutsideAirSys(OASysNum).ControllerType(OAControllerNum),
    1214        1028 :                                             CurrentModuleObjects(static_cast<int>(CMO::OAController)))) {
    1215        2052 :                 state.dataAirLoop->OutsideAirSys(OASysNum).OAControllerName =
    1216        2052 :                     state.dataAirLoop->OutsideAirSys(OASysNum).ControllerName(OAControllerNum);
    1217        1026 :                 break;
    1218             :             }
    1219             :         }
    1220             :     }
    1221             : 
    1222         770 :     if (ErrorsFound) {
    1223           0 :         ShowFatalError(state, std::string{RoutineName} + "Errors found in getting " + CurrentModuleObject + '.');
    1224             :     }
    1225             : 
    1226         770 :     AlphArray.deallocate();
    1227         770 :     cAlphaFields.deallocate();
    1228         770 :     NumArray.deallocate();
    1229         770 :     cNumericFields.deallocate();
    1230         770 :     lAlphaBlanks.deallocate();
    1231         770 :     lNumericBlanks.deallocate();
    1232             : 
    1233         770 :     state.dataMixedAir->GetOASysInputFlag = false;
    1234             : }
    1235             : 
    1236         393 : void GetOAControllerInputs(EnergyPlusData &state)
    1237             : {
    1238             : 
    1239             :     // SUBROUTINE INFORMATION:
    1240             :     //       AUTHOR         Fred Buhl
    1241             :     //       DATE WRITTEN   Oct 1998
    1242             :     //       MODIFIED       Shirey/Raustad FSEC, June 2003, Jan 2004
    1243             :     //                      Mangesh Basarkar, 06/2011: Getting zone OA specifications from Design Specification Object
    1244             :     //                      Tianzhen Hong, 3/2012: getting zone air distribution effectiveness and secondary recirculation
    1245             :     //                       from DesignSpecification:ZoneAirDistribution objects
    1246             : 
    1247             :     // PURPOSE OF THIS SUBROUTINE
    1248             :     // Input the OAController data and store it in the OAController array.
    1249             :     // Input the Ventilation:Mechanical data and store it in the VentilationMechanical array.
    1250             :     //  Condense Ventilation:Mechanical data array to include only unique zones specified for each instance of this object.
    1251             : 
    1252             :     // METHODOLOGY EMPLOYED:
    1253             :     // Use the Get routines from the InputProcessor module.
    1254             : 
    1255             :     // Using/Aliasing
    1256             :     using namespace DataDefineEquip;
    1257             :     using namespace OutputReportPredefined;
    1258             : 
    1259             :     using Curve::GetCurveIndex;
    1260             :     using OutAirNodeManager::CheckOutAirNodeNumber;
    1261             : 
    1262             :     // SUBROUTINE PARAMETER DEFINITIONS:
    1263             :     static constexpr std::string_view RoutineName("GetOAControllerInputs: "); // include trailing blank space
    1264             : 
    1265             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1266             : 
    1267             :     int ZoneNum;         // zone number attached to a given air loop
    1268             :     int NumNums;         // Number of real numbers returned by GetObjectItem
    1269             :     int NumAlphas;       // Number of alphanumerics returned by GetObjectItem
    1270             :     int OutAirNum;       // Number of Controller:OutdoorAir or CONTROLLER:STAND ALONE ERV objects
    1271             :     int OAControllerNum; // Index to Controller:OutdoorAir or CONTROLLER:STAND ALONE ERV objects
    1272             :     int VentMechNum;     // Number of VENTILATION:MECHANICAL objects
    1273             :     int groupNum;        // Index to group in extensible VENTILATION:MECHANICAL object
    1274             :     int IOStat;          // Status of GetObjectItem call
    1275         786 :     Array1D<Real64> NumArray;
    1276         786 :     Array1D_string AlphArray;
    1277         786 :     std::string CurrentModuleObject; // Object type for getting and messages
    1278         786 :     Array1D_string cAlphaFields;     // Alpha field names
    1279         786 :     Array1D_string cNumericFields;   // Numeric field names
    1280         786 :     Array1D_bool lAlphaBlanks;       // Logical array, alpha field input BLANK = .TRUE.
    1281         786 :     Array1D_bool lNumericBlanks;     // Logical array, numeric field input BLANK = .TRUE.
    1282         393 :     bool ErrorsFound(false);         // Flag identifying errors found during get input
    1283             :     int ZoneListNum;                 // Index to Zone List
    1284             :     int MechVentZoneCount;           // Index counter for zones with mechanical ventilation
    1285             :     int NumArg;                      // Number of arguments from GetObjectDefMaxArgs call
    1286             :     int MaxAlphas;                   // Maximum alphas in multiple objects
    1287             :     int MaxNums;                     // Maximum numbers in multiple objects
    1288             : 
    1289             :     int NumGroups; // Number of extensible input groups of the VentilationMechanical object
    1290         393 :     int ObjIndex(0);
    1291         393 :     int EquipListIndex(0);
    1292         393 :     int EquipNum(0);
    1293         393 :     int EquipListNum(0);
    1294         393 :     int ADUNum(0);
    1295             :     int jZone;
    1296             :     int i;
    1297             : 
    1298             :     // Formats
    1299             : 
    1300             :     // First, call other get input routines in this module to make sure data is filled during this routine.
    1301         393 :     if (state.dataMixedAir->GetOASysInputFlag) { // Gets input for object  first time Sim routine is called
    1302           0 :         GetOutsideAirSysInputs(state);
    1303           0 :         state.dataMixedAir->GetOASysInputFlag = false;
    1304             :     }
    1305         393 :     if (state.dataMixedAir->GetOAMixerInputFlag) { // Gets input for object  first time Sim routine is called
    1306           0 :         GetOAMixerInputs(state);
    1307           0 :         state.dataMixedAir->GetOAMixerInputFlag = false;
    1308             :     }
    1309             : 
    1310         393 :     FaultsManager::CheckAndReadFaults(state);
    1311             : 
    1312         786 :     state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(
    1313         393 :         state, CurrentModuleObjects(static_cast<int>(CMO::OAController)), NumArg, NumAlphas, NumNums);
    1314         393 :     MaxAlphas = NumAlphas;
    1315         393 :     MaxNums = NumNums;
    1316         786 :     state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(
    1317         393 :         state, CurrentModuleObjects(static_cast<int>(CMO::ERVController)), NumArg, NumAlphas, NumNums);
    1318         393 :     MaxAlphas = max(MaxAlphas, NumAlphas);
    1319         393 :     MaxNums = max(MaxNums, NumNums);
    1320         786 :     state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(
    1321         393 :         state, CurrentModuleObjects(static_cast<int>(CMO::MechVentilation)), NumArg, NumAlphas, NumNums);
    1322         393 :     MaxAlphas = max(MaxAlphas, NumAlphas);
    1323         393 :     MaxNums = max(MaxNums, NumNums);
    1324             : 
    1325         393 :     AlphArray.allocate(MaxAlphas);
    1326         393 :     NumArray.dimension(MaxNums, 0.0);
    1327         393 :     lAlphaBlanks.dimension(MaxAlphas, true);
    1328         393 :     lNumericBlanks.dimension(MaxNums, true);
    1329         393 :     cAlphaFields.allocate(MaxAlphas);
    1330         393 :     cNumericFields.allocate(MaxNums);
    1331             : 
    1332             :     // Count OAcontrollers and ERVcontrollers and allocate arrays
    1333         393 :     AllocateOAControllers(state);
    1334             : 
    1335             :     // If there are ERV controllers, they have been filled before now NumOAControllers includes the count of NumERVControllers
    1336         393 :     if (state.dataMixedAir->NumOAControllers > state.dataMixedAir->NumERVControllers) {
    1337         393 :         CurrentModuleObject = CurrentModuleObjects(static_cast<int>(CMO::OAController));
    1338         393 :         int currentOAControllerNum = 0;
    1339        1414 :         for (OutAirNum = state.dataMixedAir->NumERVControllers + 1; OutAirNum <= state.dataMixedAir->NumOAControllers; ++OutAirNum) {
    1340        1021 :             ++currentOAControllerNum;
    1341        1021 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1342             :                                                                      CurrentModuleObject,
    1343             :                                                                      currentOAControllerNum,
    1344             :                                                                      AlphArray,
    1345             :                                                                      NumAlphas,
    1346             :                                                                      NumArray,
    1347             :                                                                      NumNums,
    1348             :                                                                      IOStat,
    1349             :                                                                      lNumericBlanks,
    1350             :                                                                      lAlphaBlanks,
    1351             :                                                                      cAlphaFields,
    1352             :                                                                      cNumericFields);
    1353        2042 :             GlobalNames::VerifyUniqueInterObjectName(
    1354        2042 :                 state, state.dataMixedAir->OAControllerUniqueNames, AlphArray(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
    1355             : 
    1356        1021 :             ProcessOAControllerInputs(state,
    1357             :                                       CurrentModuleObject,
    1358             :                                       OutAirNum,
    1359             :                                       AlphArray,
    1360             :                                       NumAlphas,
    1361             :                                       NumArray,
    1362             :                                       NumNums,
    1363             :                                       lNumericBlanks,
    1364             :                                       lAlphaBlanks,
    1365             :                                       cAlphaFields,
    1366             :                                       cNumericFields,
    1367             :                                       ErrorsFound);
    1368             : 
    1369             :             // add applicable faults identifier to avoid string comparison at each time step
    1370             :             //  loop through each fault for each OA controller and determine economizer faultys
    1371        1041 :             for (i = 1; i <= state.dataFaultsMgr->NumFaultyEconomizer; ++i) {
    1372          20 :                 if (state.dataFaultsMgr->FaultsEconomizer(i).ControllerTypeEnum != iController_AirEconomizer) continue;
    1373          20 :                 if (UtilityRoutines::SameString(state.dataMixedAir->OAController(OutAirNum).Name,
    1374          20 :                                                 state.dataFaultsMgr->FaultsEconomizer(i).ControllerName)) {
    1375           5 :                     state.dataFaultsMgr->FaultsEconomizer(i).ControllerID = OutAirNum;
    1376           5 :                     ++state.dataMixedAir->OAController(OutAirNum).NumFaultyEconomizer;
    1377             :                 }
    1378             :             }
    1379             :             //  loop through each fault for each OA controller to determine faulty counts
    1380        1021 :             state.dataMixedAir->OAController(OutAirNum).EconmizerFaultNum.allocate(state.dataMixedAir->OAController(OutAirNum).NumFaultyEconomizer);
    1381        1021 :             if (state.dataMixedAir->OAController(OutAirNum).NumFaultyEconomizer > 0) {
    1382          12 :                 for (int j = 0, i = 1; i <= state.dataFaultsMgr->NumFaultyEconomizer; ++i) {
    1383          10 :                     if (state.dataFaultsMgr->FaultsEconomizer(i).ControllerTypeEnum != iController_AirEconomizer) continue;
    1384          10 :                     if (UtilityRoutines::SameString(state.dataMixedAir->OAController(OutAirNum).Name,
    1385          10 :                                                     state.dataFaultsMgr->FaultsEconomizer(i).ControllerName)) {
    1386           5 :                         state.dataMixedAir->OAController(OutAirNum).EconmizerFaultNum(++j) = i;
    1387             :                     }
    1388             :                 }
    1389             :             }
    1390             :         } // LOOP FOR OutAirNum
    1391             : 
    1392         393 :         if (ErrorsFound) {
    1393           0 :             AlphArray.deallocate();
    1394           0 :             NumArray.deallocate();
    1395           0 :             lNumericBlanks.deallocate();
    1396           0 :             lAlphaBlanks.deallocate();
    1397           0 :             cAlphaFields.deallocate();
    1398           0 :             cNumericFields.deallocate();
    1399           0 :             ShowFatalError(state, std::string{RoutineName} + "Errors found in getting " + CurrentModuleObject + " inputs.");
    1400             :         }
    1401             :     }
    1402             : 
    1403         393 :     state.dataMixedAir->GetOAControllerInputFlag = false;
    1404             : 
    1405             :     // Process Controller:MechanicalVentilation objects
    1406         393 :     CurrentModuleObject = CurrentModuleObjects(static_cast<int>(CMO::MechVentilation));
    1407         393 :     state.dataMixedAir->NumVentMechControllers = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
    1408         393 :     if (state.dataMixedAir->NumVentMechControllers > 0) {
    1409          24 :         state.dataMixedAir->VentilationMechanical.allocate(state.dataMixedAir->NumVentMechControllers);
    1410          76 :         for (VentMechNum = 1; VentMechNum <= state.dataMixedAir->NumVentMechControllers; ++VentMechNum) {
    1411          52 :             auto &thisVentilationMechanical(state.dataMixedAir->VentilationMechanical(VentMechNum));
    1412          52 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1413             :                                                                      CurrentModuleObject,
    1414             :                                                                      VentMechNum,
    1415             :                                                                      AlphArray,
    1416             :                                                                      NumAlphas,
    1417             :                                                                      NumArray,
    1418             :                                                                      NumNums,
    1419             :                                                                      IOStat,
    1420             :                                                                      lNumericBlanks,
    1421             :                                                                      lAlphaBlanks,
    1422             :                                                                      cAlphaFields,
    1423             :                                                                      cNumericFields);
    1424             : 
    1425          52 :             MechVentZoneCount = 0;
    1426             : 
    1427          52 :             NumGroups = (NumAlphas + NumNums - 5) / 3;
    1428          52 :             if (mod((NumAlphas + NumNums - 5), 3) != 0) ++NumGroups;
    1429          52 :             thisVentilationMechanical.Name = AlphArray(1);
    1430             : 
    1431          52 :             UtilityRoutines::IsNameEmpty(state, AlphArray(1), CurrentModuleObject, ErrorsFound);
    1432             : 
    1433          52 :             thisVentilationMechanical.SchName = AlphArray(2);
    1434          52 :             if (lAlphaBlanks(2)) {
    1435           3 :                 thisVentilationMechanical.SchPtr = DataGlobalConstants::ScheduleAlwaysOn;
    1436             :             } else {
    1437          49 :                 thisVentilationMechanical.SchPtr = GetScheduleIndex(state, AlphArray(2)); // convert schedule name to pointer
    1438          49 :                 if (thisVentilationMechanical.SchPtr == 0) {
    1439           0 :                     ShowSevereError(
    1440           0 :                         state, CurrentModuleObject + "=\"" + AlphArray(1) + "\" invalid " + cAlphaFields(2) + "=\"" + AlphArray(2) + "\" not found.");
    1441           0 :                     ErrorsFound = true;
    1442             :                 }
    1443             :             }
    1444             : 
    1445             :             // Adding new flag for DCV
    1446          52 :             if (UtilityRoutines::SameString(AlphArray(3), "Yes")) {
    1447          50 :                 thisVentilationMechanical.DCVFlag = true;
    1448           2 :             } else if (UtilityRoutines::SameString(AlphArray(3), "No") || lAlphaBlanks(3)) {
    1449           2 :                 thisVentilationMechanical.DCVFlag = false;
    1450             :             } else {
    1451           0 :                 ShowSevereError(state,
    1452           0 :                                 CurrentModuleObject + "=\"" + AlphArray(1) + "\" invalid value " + cAlphaFields(3) + "=\"" + AlphArray(3) + "\".");
    1453           0 :                 ShowContinueError(state, "...Valid values are \"Yes\" or \"No\".");
    1454           0 :                 ErrorsFound = true;
    1455             :             }
    1456             : 
    1457             :             // System outdoor air method
    1458          52 :             thisVentilationMechanical.SystemOAMethod =
    1459         104 :                 static_cast<DataSizing::SysOAMethod>(getEnumerationValue(SOAMNamesUC, UtilityRoutines::MakeUPPERCase(AlphArray(4))));
    1460             : 
    1461         103 :             if (thisVentilationMechanical.SystemOAMethod == DataSizing::SysOAMethod::IAQP ||
    1462         101 :                 thisVentilationMechanical.SystemOAMethod == DataSizing::SysOAMethod::ProportionalControlSchOcc ||
    1463         100 :                 thisVentilationMechanical.SystemOAMethod == DataSizing::SysOAMethod::ProportionalControlDesOcc ||
    1464          99 :                 thisVentilationMechanical.SystemOAMethod == DataSizing::SysOAMethod::ProportionalControlDesOARate ||
    1465          49 :                 thisVentilationMechanical.SystemOAMethod == DataSizing::SysOAMethod::IAQPCOM) {
    1466           3 :                 if (!state.dataContaminantBalance->Contaminant.CO2Simulation) {
    1467           0 :                     ShowSevereError(state,
    1468           0 :                                     CurrentModuleObject + "=\"" + AlphArray(1) + "\" valid " + cAlphaFields(2) + "=\"" + AlphArray(2) +
    1469             :                                         "\" requires CO2 simulation.");
    1470           0 :                     ShowContinueError(state, "The choice must be Yes for the field Carbon Dioxide Concentration in ZoneAirContaminantBalance");
    1471           0 :                     ErrorsFound = true;
    1472             :                 }
    1473             :             }
    1474             : 
    1475         103 :             if (thisVentilationMechanical.SystemOAMethod == DataSizing::SysOAMethod::IAQPGC ||
    1476          51 :                 thisVentilationMechanical.SystemOAMethod == DataSizing::SysOAMethod::IAQPCOM) {
    1477           1 :                 if (!state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    1478           0 :                     ShowSevereError(state,
    1479           0 :                                     CurrentModuleObject + "=\"" + AlphArray(1) + "\" valid " + cAlphaFields(2) + "=\"" + AlphArray(2) +
    1480             :                                         "\" requires generic contaminant simulation.");
    1481           0 :                     ShowContinueError(state, "The choice must be Yes for the field Generic Contaminant Concentration in ZoneAirContaminantBalance");
    1482           0 :                     ErrorsFound = true;
    1483             :                 }
    1484             :             }
    1485             : 
    1486          52 :             if (thisVentilationMechanical.SystemOAMethod == DataSizing::SysOAMethod::Invalid) { // If specified incorrectly, show errors
    1487           0 :                 thisVentilationMechanical.SystemOAMethod = DataSizing::SysOAMethod::ZoneSum;
    1488           0 :                 ShowWarningError(state,
    1489           0 :                                  CurrentModuleObject + "=\"" + AlphArray(1) + "\" incorrect specification for " + cAlphaFields(4) +
    1490             :                                      ", the ZoneSum method will be used.");
    1491             :                 // ErrorsFound=.TRUE.
    1492             :             }
    1493             : 
    1494             :             // Zone maximum outdoor air fraction
    1495          52 :             thisVentilationMechanical.ZoneMaxOAFraction = NumArray(1);
    1496             : 
    1497          52 :             state.dataMixedAir->VentMechZoneOrListName.allocate(NumGroups);
    1498          52 :             state.dataMixedAir->DesignSpecOAObjName.allocate(NumGroups);
    1499          52 :             state.dataMixedAir->DesignSpecOAObjIndex.dimension(NumGroups, 0);
    1500          52 :             state.dataMixedAir->DesignSpecZoneADObjName.allocate(NumGroups);
    1501          52 :             state.dataMixedAir->DesignSpecZoneADObjIndex.dimension(NumGroups, 0);
    1502             : 
    1503             :             //   First time through find the total number of zones requiring mechanical ventilation
    1504             :             //   May include duplicate zones. Will check for duplicate zones further down in this subroutine.
    1505         393 :             for (groupNum = 1; groupNum <= NumGroups; ++groupNum) {
    1506         341 :                 state.dataMixedAir->VentMechZoneOrListName(groupNum) = AlphArray((groupNum - 1) * 3 + 5);
    1507             : 
    1508             :                 //     Getting OA details from design specification OA object
    1509         341 :                 if (!lAlphaBlanks((groupNum - 1) * 3 + 6)) {
    1510         341 :                     state.dataMixedAir->DesignSpecOAObjName(groupNum) = AlphArray((groupNum - 1) * 3 + 6);
    1511         341 :                     ObjIndex = UtilityRoutines::FindItemInList(state.dataMixedAir->DesignSpecOAObjName(groupNum), state.dataSize->OARequirements);
    1512         341 :                     state.dataMixedAir->DesignSpecOAObjIndex(groupNum) = ObjIndex;
    1513             : 
    1514         341 :                     if (ObjIndex == 0) {
    1515           0 :                         ShowSevereError(state,
    1516           0 :                                         std::string{RoutineName} + CurrentModuleObject + "=\"" + thisVentilationMechanical.Name + "\", invalid");
    1517           0 :                         ShowContinueError(state,
    1518           0 :                                           "... not found " + cAlphaFields((groupNum - 1) * 3 + 6) + "=\"" +
    1519           0 :                                               state.dataMixedAir->DesignSpecOAObjName(groupNum) + "\".");
    1520           0 :                         ErrorsFound = true;
    1521             :                     }
    1522             :                 }
    1523             : 
    1524             :                 // Get zone air distribution details from design specification Zone Air Distribution object
    1525         341 :                 if (!lAlphaBlanks((groupNum - 1) * 3 + 7)) {
    1526         341 :                     state.dataMixedAir->DesignSpecZoneADObjName(groupNum) = AlphArray((groupNum - 1) * 3 + 7);
    1527         341 :                     ObjIndex =
    1528         341 :                         UtilityRoutines::FindItemInList(state.dataMixedAir->DesignSpecZoneADObjName(groupNum), state.dataSize->ZoneAirDistribution);
    1529         341 :                     state.dataMixedAir->DesignSpecZoneADObjIndex(groupNum) = ObjIndex;
    1530             : 
    1531         341 :                     if (ObjIndex == 0) {
    1532             :                         // Cannot find the design specification Zone Air Distribution object
    1533           0 :                         ShowSevereError(state,
    1534           0 :                                         std::string{RoutineName} + CurrentModuleObject + "=\"" + thisVentilationMechanical.Name + "\", invalid");
    1535           0 :                         ShowContinueError(state,
    1536           0 :                                           "... not found " + cAlphaFields((groupNum - 1) * 3 + 7) + "=\"" +
    1537           0 :                                               state.dataMixedAir->DesignSpecZoneADObjName(groupNum) + "\".");
    1538           0 :                         ErrorsFound = true;
    1539             :                     }
    1540             :                 }
    1541             : 
    1542         341 :                 ZoneNum = UtilityRoutines::FindItemInList(state.dataMixedAir->VentMechZoneOrListName(groupNum), state.dataHeatBal->Zone);
    1543         341 :                 if (ZoneNum > 0) {
    1544         335 :                     ++MechVentZoneCount;
    1545             :                 } else {
    1546           6 :                     ZoneListNum = UtilityRoutines::FindItemInList(state.dataMixedAir->VentMechZoneOrListName(groupNum), state.dataHeatBal->ZoneList);
    1547           6 :                     if (ZoneListNum > 0) {
    1548           6 :                         MechVentZoneCount += state.dataHeatBal->ZoneList(ZoneListNum).NumOfZones;
    1549             :                     } else {
    1550           0 :                         ShowWarningError(
    1551           0 :                             state, CurrentModuleObject + "=\"" + AlphArray(1) + "\" invalid " + cAlphaFields((groupNum - 1) * 3 + 5) + " not found.");
    1552           0 :                         ShowContinueError(
    1553           0 :                             state, "Missing " + cAlphaFields((groupNum - 1) * 3 + 5) + " = " + state.dataMixedAir->VentMechZoneOrListName(groupNum));
    1554           0 :                         ErrorsFound = true;
    1555             :                     }
    1556             :                 }
    1557             :             }
    1558             : 
    1559          52 :             thisVentilationMechanical.NumofVentMechZones = MechVentZoneCount;
    1560             : 
    1561             :             // Now allocate and store unique zone and associated ventilation rate information
    1562          52 :             thisVentilationMechanical.VentMechZone.dimension(MechVentZoneCount, 0);
    1563          52 :             thisVentilationMechanical.VentMechZoneName.dimension(MechVentZoneCount);
    1564          52 :             thisVentilationMechanical.ZoneDesignSpecOAObjName.dimension(MechVentZoneCount);
    1565          52 :             thisVentilationMechanical.ZoneDesignSpecOAObjIndex.dimension(MechVentZoneCount, 0);
    1566          52 :             thisVentilationMechanical.ZoneOAAreaRate.dimension(MechVentZoneCount, 0.0);
    1567          52 :             thisVentilationMechanical.ZoneOAPeopleRate.dimension(MechVentZoneCount, 0.0);
    1568          52 :             thisVentilationMechanical.ZoneOAFlowRate.dimension(MechVentZoneCount, 0.0);
    1569          52 :             thisVentilationMechanical.ZoneOAACHRate.dimension(MechVentZoneCount, 0.0);
    1570          52 :             thisVentilationMechanical.ZoneOAFlowMethod.dimension(MechVentZoneCount);
    1571          52 :             thisVentilationMechanical.ZoneOASchPtr.dimension(MechVentZoneCount, 0);
    1572          52 :             thisVentilationMechanical.OAPropCtlMinRateSchPtr.dimension(MechVentZoneCount, 0);
    1573             : 
    1574             :             // added for new DCV, 2/12/2009
    1575          52 :             thisVentilationMechanical.ZoneADEffCooling.dimension(MechVentZoneCount, 1.0);
    1576             :             // Zone air distribution effectiveness in heating mode
    1577          52 :             thisVentilationMechanical.ZoneADEffHeating.dimension(MechVentZoneCount, 1.0);
    1578             :             // Indices to the zone air distribution effectiveness schedules
    1579          52 :             thisVentilationMechanical.ZoneADEffSchPtr.dimension(MechVentZoneCount, 0);
    1580             :             // Zone air secondary recirculation ratio, added 3/2012
    1581          52 :             thisVentilationMechanical.ZoneSecondaryRecirculation.dimension(MechVentZoneCount, 0.0);
    1582          52 :             thisVentilationMechanical.ZoneDesignSpecADObjName.allocate(MechVentZoneCount);
    1583          52 :             thisVentilationMechanical.ZoneDesignSpecADObjIndex.dimension(MechVentZoneCount, 0);
    1584             : 
    1585          52 :             MechVentZoneCount = 0;
    1586             : 
    1587             :             //   Loop through zone names and list of zone names, remove duplicate zones, and store designspec names and indexes
    1588         393 :             for (groupNum = 1; groupNum <= NumGroups; ++groupNum) {
    1589         341 :                 ZoneNum = UtilityRoutines::FindItemInList(state.dataMixedAir->VentMechZoneOrListName(groupNum), state.dataHeatBal->Zone);
    1590         341 :                 if (ZoneNum > 0) {
    1591         335 :                     if (any_eq(thisVentilationMechanical.VentMechZone, ZoneNum)) {
    1592             :                         //          Disregard duplicate zone names, show warning and do not store data for this zone
    1593           0 :                         ShowWarningError(state,
    1594           0 :                                          "Zone name = " + state.dataMixedAir->VentMechZoneOrListName(groupNum) + " for " + CurrentModuleObject +
    1595           0 :                                              " object = " + thisVentilationMechanical.Name);
    1596           0 :                         ShowContinueError(state, "is specified more than once. The first ventilation values specified for this zone will be used");
    1597           0 :                         ShowContinueError(state, "and the rest will be ignored. Simulation will continue..");
    1598             :                     } else {
    1599             :                         //          Store unique zone names
    1600         335 :                         ++MechVentZoneCount;
    1601         335 :                         thisVentilationMechanical.VentMechZone(MechVentZoneCount) = ZoneNum;
    1602         335 :                         thisVentilationMechanical.VentMechZoneName(MechVentZoneCount) = state.dataHeatBal->Zone(ZoneNum).Name;
    1603             : 
    1604             :                         // Populating new temp array to hold design spec OA object for each zone
    1605         335 :                         if (state.dataMixedAir->DesignSpecOAObjIndex(groupNum) > 0) {
    1606         335 :                             thisVentilationMechanical.ZoneDesignSpecOAObjName(MechVentZoneCount) = state.dataMixedAir->DesignSpecOAObjName(groupNum);
    1607         335 :                             thisVentilationMechanical.ZoneDesignSpecOAObjIndex(MechVentZoneCount) =
    1608         335 :                                 state.dataMixedAir->DesignSpecOAObjIndex(groupNum);
    1609             :                         } else {
    1610           0 :                             if (state.dataGlobal->DoZoneSizing) {
    1611           0 :                                 ObjIndex = UtilityRoutines::FindItemInList(state.dataMixedAir->VentMechZoneOrListName(groupNum),
    1612           0 :                                                                            state.dataSize->ZoneSizingInput,
    1613             :                                                                            &ZoneSizingInputData::ZoneName);
    1614           0 :                                 if (ObjIndex > 0) {
    1615           0 :                                     thisVentilationMechanical.ZoneDesignSpecOAObjName(MechVentZoneCount) =
    1616           0 :                                         state.dataSize->ZoneSizingInput(ObjIndex).DesignSpecOAObjName;
    1617           0 :                                     thisVentilationMechanical.ZoneDesignSpecOAObjIndex(MechVentZoneCount) =
    1618           0 :                                         state.dataSize->ZoneSizingInput(ObjIndex).ZoneDesignSpecOAIndex;
    1619             :                                 }
    1620             :                             }
    1621             :                         }
    1622             :                         // Zone Air Distribution inputs
    1623         335 :                         if (state.dataMixedAir->DesignSpecZoneADObjIndex(groupNum) > 0) {
    1624             :                             // new DCV inputs
    1625         335 :                             thisVentilationMechanical.ZoneDesignSpecADObjName(MechVentZoneCount) =
    1626         335 :                                 state.dataMixedAir->DesignSpecZoneADObjName(groupNum);
    1627         335 :                             thisVentilationMechanical.ZoneDesignSpecADObjIndex(MechVentZoneCount) =
    1628         335 :                                 state.dataMixedAir->DesignSpecZoneADObjIndex(groupNum);
    1629             :                         } else {
    1630           0 :                             if (state.dataGlobal->DoZoneSizing) {
    1631           0 :                                 ObjIndex = UtilityRoutines::FindItemInList(state.dataMixedAir->VentMechZoneOrListName(groupNum),
    1632           0 :                                                                            state.dataSize->ZoneSizingInput,
    1633             :                                                                            &ZoneSizingInputData::ZoneName);
    1634           0 :                                 if (ObjIndex > 0) {
    1635           0 :                                     thisVentilationMechanical.ZoneDesignSpecADObjName(MechVentZoneCount) =
    1636           0 :                                         state.dataSize->ZoneSizingInput(ObjIndex).ZoneAirDistEffObjName;
    1637           0 :                                     thisVentilationMechanical.ZoneDesignSpecADObjIndex(MechVentZoneCount) =
    1638           0 :                                         state.dataSize->ZoneSizingInput(ObjIndex).ZoneAirDistributionIndex;
    1639             :                                 }
    1640             :                             }
    1641             :                         }
    1642             :                     }
    1643             :                 } else {
    1644             :                     //       Not a zone name, must be a zone list
    1645           6 :                     ZoneListNum = UtilityRoutines::FindItemInList(state.dataMixedAir->VentMechZoneOrListName(groupNum), state.dataHeatBal->ZoneList);
    1646           6 :                     if (ZoneListNum > 0) {
    1647          18 :                         for (int ScanZoneListNum = 1; ScanZoneListNum <= state.dataHeatBal->ZoneList(ZoneListNum).NumOfZones; ++ScanZoneListNum) {
    1648          12 :                             ObjIndex = 0;
    1649             :                             // check to make sure zone name is unique (not listed more than once)...
    1650          12 :                             ZoneNum = state.dataHeatBal->ZoneList(ZoneListNum).Zone(ScanZoneListNum);
    1651          12 :                             if (any_eq(thisVentilationMechanical.VentMechZone, ZoneNum)) {
    1652             :                                 //             Disregard duplicate zone names, show warning and do not store data for this zone
    1653           0 :                                 ShowWarningError(state,
    1654           0 :                                                  "Zone name = " + state.dataHeatBal->Zone(ZoneNum).Name +
    1655           0 :                                                      " in ZoneList = " + state.dataMixedAir->VentMechZoneOrListName(groupNum) + " for " +
    1656           0 :                                                      CurrentModuleObject + " object = " + thisVentilationMechanical.Name);
    1657           0 :                                 ShowContinueError(state, "is a duplicate. The first ventilation values specified for this zone will be used ");
    1658           0 :                                 ShowContinueError(state, "and the rest will be ignored. The simulation will continue...");
    1659             :                             } else {
    1660             :                                 //           Store data for each zone name from zone list (duplicate zone names accounted for in
    1661             :                                 //           HeatBalanceManager)
    1662          12 :                                 ++MechVentZoneCount;
    1663          12 :                                 thisVentilationMechanical.VentMechZone(MechVentZoneCount) = ZoneNum;
    1664          12 :                                 thisVentilationMechanical.VentMechZoneName(MechVentZoneCount) = state.dataHeatBal->Zone(ZoneNum).Name;
    1665             :                                 // Populating new temp array to hold design spec OA object for each zone
    1666          12 :                                 if (state.dataMixedAir->DesignSpecOAObjIndex(groupNum) > 0) {
    1667          12 :                                     thisVentilationMechanical.ZoneDesignSpecOAObjName(MechVentZoneCount) =
    1668          12 :                                         state.dataMixedAir->DesignSpecOAObjName(groupNum);
    1669          12 :                                     thisVentilationMechanical.ZoneDesignSpecOAObjIndex(MechVentZoneCount) =
    1670          12 :                                         state.dataMixedAir->DesignSpecOAObjIndex(groupNum);
    1671             :                                 } else {
    1672           0 :                                     if (state.dataGlobal->DoZoneSizing) {
    1673           0 :                                         ObjIndex = UtilityRoutines::FindItemInList(
    1674           0 :                                             state.dataHeatBal->Zone(ZoneNum).Name, state.dataSize->ZoneSizingInput, &ZoneSizingInputData::ZoneName);
    1675           0 :                                         if (ObjIndex > 0) {
    1676           0 :                                             thisVentilationMechanical.ZoneDesignSpecOAObjName(MechVentZoneCount) =
    1677           0 :                                                 state.dataSize->ZoneSizingInput(ObjIndex).DesignSpecOAObjName;
    1678           0 :                                             thisVentilationMechanical.ZoneDesignSpecOAObjIndex(MechVentZoneCount) =
    1679           0 :                                                 state.dataSize->ZoneSizingInput(ObjIndex).ZoneDesignSpecOAIndex;
    1680             :                                         }
    1681             :                                     }
    1682             :                                 }
    1683             : 
    1684          12 :                                 if (state.dataMixedAir->DesignSpecZoneADObjIndex(groupNum) > 0) {
    1685             :                                     // new DCV inputs
    1686          12 :                                     thisVentilationMechanical.ZoneDesignSpecADObjName(MechVentZoneCount) =
    1687          12 :                                         state.dataMixedAir->DesignSpecZoneADObjName(groupNum);
    1688          12 :                                     thisVentilationMechanical.ZoneDesignSpecADObjIndex(MechVentZoneCount) =
    1689          12 :                                         state.dataMixedAir->DesignSpecZoneADObjIndex(groupNum);
    1690             :                                 } else {
    1691           0 :                                     if (state.dataGlobal->DoZoneSizing) {
    1692           0 :                                         ObjIndex = UtilityRoutines::FindItemInList(
    1693           0 :                                             state.dataHeatBal->Zone(ZoneNum).Name, state.dataSize->ZoneSizingInput, &ZoneSizingInputData::ZoneName);
    1694           0 :                                         if (ObjIndex > 0) {
    1695           0 :                                             thisVentilationMechanical.ZoneDesignSpecADObjName(MechVentZoneCount) =
    1696           0 :                                                 state.dataSize->ZoneSizingInput(ObjIndex).ZoneAirDistEffObjName;
    1697           0 :                                             thisVentilationMechanical.ZoneDesignSpecADObjIndex(MechVentZoneCount) =
    1698           0 :                                                 state.dataSize->ZoneSizingInput(ObjIndex).ZoneAirDistributionIndex;
    1699             :                                         }
    1700             :                                     }
    1701             :                                 }
    1702             :                             }
    1703             :                         }
    1704             :                     }
    1705             :                 }
    1706             :             }
    1707             : 
    1708             :             //   Overwrite previous number of zones with number that does not include duplicates
    1709          52 :             thisVentilationMechanical.NumofVentMechZones = MechVentZoneCount;
    1710             : 
    1711             :             // Loop over zones and fill OA and AD specs, if none were found, use defaults
    1712         399 :             for (int ventMechZoneNum = 1; ventMechZoneNum <= MechVentZoneCount; ++ventMechZoneNum) {
    1713         347 :                 int zoneOAReqObjIndex = thisVentilationMechanical.ZoneDesignSpecOAObjIndex(ventMechZoneNum);
    1714         347 :                 if (zoneOAReqObjIndex > 0) {
    1715         347 :                     auto const &curOARequirements(state.dataSize->OARequirements(zoneOAReqObjIndex));
    1716         347 :                     thisVentilationMechanical.ZoneOAAreaRate(ventMechZoneNum) = curOARequirements.OAFlowPerArea;
    1717         347 :                     thisVentilationMechanical.ZoneOAPeopleRate(ventMechZoneNum) = curOARequirements.OAFlowPerPerson;
    1718         347 :                     thisVentilationMechanical.ZoneOAFlowRate(ventMechZoneNum) = curOARequirements.OAFlowPerZone;
    1719         347 :                     thisVentilationMechanical.ZoneOAACHRate(ventMechZoneNum) = curOARequirements.OAFlowACH;
    1720         347 :                     thisVentilationMechanical.ZoneOAFlowMethod(ventMechZoneNum) = curOARequirements.OAFlowMethod;
    1721         347 :                     thisVentilationMechanical.ZoneOASchPtr(ventMechZoneNum) = curOARequirements.OAFlowFracSchPtr;
    1722         347 :                     thisVentilationMechanical.OAPropCtlMinRateSchPtr(ventMechZoneNum) = curOARequirements.OAPropCtlMinRateSchPtr;
    1723         347 :                     if (thisVentilationMechanical.SystemOAMethod == DataSizing::SysOAMethod::ProportionalControlDesOARate) {
    1724           3 :                         if (thisVentilationMechanical.ZoneOAPeopleRate(ventMechZoneNum) == 0.0 &&
    1725           0 :                             thisVentilationMechanical.ZoneOAAreaRate(ventMechZoneNum) == 0.0) {
    1726           0 :                             ShowSevereError(state,
    1727           0 :                                             std::string{RoutineName} + CurrentModuleObject + "=\"" + thisVentilationMechanical.Name +
    1728             :                                                 "\", invalid input with System Outdoor Air Method = ProportionalControlBasedOnDesignOARate.");
    1729           0 :                             ShowContinueError(state,
    1730             :                                               " The values of Outdoor Air Flow per Person and Outdoor Air Flow per Zone Floor Area in the same "
    1731             :                                               "object can not be zero.");
    1732           0 :                             ErrorsFound = true;
    1733             :                         }
    1734             :                     }
    1735             :                 } else { // use defaults
    1736           0 :                     thisVentilationMechanical.ZoneOAAreaRate(ventMechZoneNum) = 0.0;
    1737             :                     // since this is case with no DesSpcOA object, cannot determine the method and default would be Flow/Person which should
    1738             :                     // default to this flow rate
    1739           0 :                     thisVentilationMechanical.ZoneOAPeopleRate(ventMechZoneNum) = 0.00944;
    1740           0 :                     thisVentilationMechanical.ZoneOAFlowRate(ventMechZoneNum) = 0.0;
    1741           0 :                     thisVentilationMechanical.ZoneOAACHRate = 0.0;
    1742           0 :                     thisVentilationMechanical.ZoneOAFlowMethod(ventMechZoneNum) = OAFlowCalcMethod::PerPerson;
    1743           0 :                     thisVentilationMechanical.ZoneOASchPtr(ventMechZoneNum) = DataGlobalConstants::ScheduleAlwaysOn;
    1744           0 :                     ShowWarningError(state, std::string{RoutineName} + CurrentModuleObject + "=\"" + thisVentilationMechanical.Name);
    1745           0 :                     ShowContinueError(state,
    1746           0 :                                       "Cannot locate a matching DesignSpecification:OutdoorAir object for Zone=\"" +
    1747           0 :                                           thisVentilationMechanical.VentMechZoneName(ventMechZoneNum) + "\".");
    1748           0 :                     ShowContinueError(state, "Using default OA of 0.00944 m3/s-person and 0.0 m3/s-m2.");
    1749             :                 }
    1750         347 :                 int zoneAirDistObjIndex = thisVentilationMechanical.ZoneDesignSpecADObjIndex(ventMechZoneNum);
    1751         347 :                 if (zoneAirDistObjIndex > 0) {
    1752         347 :                     auto const &curZoneAirDistribution(state.dataSize->ZoneAirDistribution(zoneAirDistObjIndex));
    1753         347 :                     thisVentilationMechanical.ZoneADEffCooling(ventMechZoneNum) = curZoneAirDistribution.ZoneADEffCooling;
    1754         347 :                     thisVentilationMechanical.ZoneADEffHeating(ventMechZoneNum) = curZoneAirDistribution.ZoneADEffHeating;
    1755         347 :                     thisVentilationMechanical.ZoneADEffSchPtr(ventMechZoneNum) = curZoneAirDistribution.ZoneADEffSchPtr;
    1756         347 :                     thisVentilationMechanical.ZoneSecondaryRecirculation(ventMechZoneNum) = curZoneAirDistribution.ZoneSecondaryRecirculation;
    1757             :                 } else { // use defaults
    1758           0 :                     thisVentilationMechanical.ZoneADEffCooling(ventMechZoneNum) = 1.0;
    1759           0 :                     thisVentilationMechanical.ZoneADEffHeating(ventMechZoneNum) = 1.0;
    1760           0 :                     thisVentilationMechanical.ZoneSecondaryRecirculation(ventMechZoneNum) = 0.0;
    1761           0 :                     ShowWarningError(state, std::string{RoutineName} + CurrentModuleObject + "=\"" + thisVentilationMechanical.Name);
    1762           0 :                     ShowContinueError(state,
    1763           0 :                                       "Cannot locate a matching DesignSpecification:ZoneAirDistribution object for Zone=\"" +
    1764           0 :                                           thisVentilationMechanical.VentMechZoneName(ventMechZoneNum) + "\".");
    1765           0 :                     ShowContinueError(state, "Using default zone air distribution effectiveness of 1.0 for heating and cooling.");
    1766             :                 }
    1767             :             }
    1768          52 :             state.dataMixedAir->VentMechZoneOrListName.deallocate();
    1769          52 :             state.dataMixedAir->DesignSpecOAObjName.deallocate();
    1770          52 :             state.dataMixedAir->DesignSpecOAObjIndex.deallocate();
    1771          52 :             state.dataMixedAir->DesignSpecZoneADObjName.deallocate();
    1772          52 :             state.dataMixedAir->DesignSpecZoneADObjIndex.deallocate();
    1773             :         }
    1774             : 
    1775          76 :         for (VentMechNum = 1; VentMechNum <= state.dataMixedAir->NumVentMechControllers; ++VentMechNum) {
    1776          52 :             auto &thisVentilationMechanical(state.dataMixedAir->VentilationMechanical(VentMechNum));
    1777         399 :             for (jZone = 1; jZone <= thisVentilationMechanical.NumofVentMechZones; ++jZone) {
    1778         347 :                 if (thisVentilationMechanical.SystemOAMethod == DataSizing::SysOAMethod::ProportionalControlSchOcc) {
    1779           3 :                     if (thisVentilationMechanical.ZoneOAACHRate(jZone) > 0.0 || thisVentilationMechanical.ZoneOAFlowRate(jZone) > 0.0) {
    1780           0 :                         ShowWarningError(state,
    1781           0 :                                          CurrentModuleObject + "=\"" + thisVentilationMechanical.Name + "\", inappropriate outdoor air method");
    1782           0 :                         ShowContinueError(state,
    1783           0 :                                           "Inappropriate method for Design Specification Outdoor Air Object Name=\"" +
    1784           0 :                                               thisVentilationMechanical.ZoneDesignSpecOAObjName(jZone) + "\".");
    1785           0 :                         ShowContinueError(state, "For Zone=\"" + thisVentilationMechanical.VentMechZoneName(jZone) + "\".");
    1786           0 :                         ShowContinueError(state,
    1787             :                                           "Since System Outdoor Air Method= ProportionalControlBasedOnOccupancySchedule\", AirChanges/Hour or "
    1788             :                                           "Flow/Zone outdoor air methods are not valid. Simulation continues.... ");
    1789             :                     }
    1790             :                 }
    1791         347 :                 if (thisVentilationMechanical.SystemOAMethod == DataSizing::SysOAMethod::ProportionalControlDesOcc) {
    1792           0 :                     if (thisVentilationMechanical.ZoneOAACHRate(jZone) > 0.0 || thisVentilationMechanical.ZoneOAFlowRate(jZone) > 0.0) {
    1793           0 :                         ShowWarningError(state,
    1794           0 :                                          CurrentModuleObject + "=\"" + thisVentilationMechanical.Name + "\", inappropriate outdoor air method");
    1795           0 :                         ShowContinueError(state,
    1796           0 :                                           "Inappropriate method for Design Specification Outdoor Air Object Name=\"" +
    1797           0 :                                               thisVentilationMechanical.ZoneDesignSpecOAObjName(jZone) + "\".");
    1798           0 :                         ShowContinueError(state, "For Zone=\"" + thisVentilationMechanical.VentMechZoneName(jZone) + "\".");
    1799           0 :                         ShowContinueError(state,
    1800             :                                           "Since System Outdoor Air Method= ProportionalControlBasedOnDesignOccupancy\", AirChanges/Hour or "
    1801             :                                           "Flow/Zone outdoor air methods are not valid. Simulation continues.... ");
    1802             :                     }
    1803             :                 }
    1804             : 
    1805             :                 // Error check to see if a single duct air terminal is assigned to a zone that has zone secondary recirculation
    1806         347 :                 if (thisVentilationMechanical.ZoneSecondaryRecirculation(jZone) > 0.0) {
    1807           5 :                     ZoneNum = thisVentilationMechanical.VentMechZone(jZone);
    1808           5 :                     if (ZoneNum > 0) {
    1809           5 :                         EquipListIndex = state.dataZoneEquip->ZoneEquipConfig(ZoneNum).EquipListIndex;
    1810           5 :                         if (EquipListIndex > 0) {
    1811          15 :                             for (EquipListNum = 1; EquipListNum <= state.dataZoneEquip->NumOfZoneEquipLists; ++EquipListNum) {
    1812          15 :                                 if (EquipListNum == EquipListIndex) {
    1813           5 :                                     for (EquipNum = 1; EquipNum <= state.dataZoneEquip->ZoneEquipList(EquipListNum).NumOfEquipTypes; ++EquipNum) {
    1814           5 :                                         if (UtilityRoutines::SameString(state.dataZoneEquip->ZoneEquipList(EquipListNum).EquipType(EquipNum),
    1815           5 :                                                                         "ZONEHVAC:AIRDISTRIBUTIONUNIT")) {
    1816          15 :                                             for (ADUNum = 1; ADUNum <= (int)state.dataDefineEquipment->AirDistUnit.size(); ++ADUNum) {
    1817          15 :                                                 if (UtilityRoutines::SameString(state.dataZoneEquip->ZoneEquipList(EquipListNum).EquipName(EquipNum),
    1818          15 :                                                                                 state.dataDefineEquipment->AirDistUnit(ADUNum).Name)) {
    1819          10 :                                                     if ((state.dataDefineEquipment->AirDistUnit(ADUNum).EquipTypeEnum(EquipNum) ==
    1820           1 :                                                          DataDefineEquip::ZnAirLoopEquipType::SingleDuctVAVReheat) ||
    1821           1 :                                                         (state.dataDefineEquipment->AirDistUnit(ADUNum).EquipTypeEnum(EquipNum) ==
    1822           1 :                                                          DataDefineEquip::ZnAirLoopEquipType::SingleDuctConstVolNoReheat) ||
    1823           1 :                                                         (state.dataDefineEquipment->AirDistUnit(ADUNum).EquipTypeEnum(EquipNum) ==
    1824           1 :                                                          DataDefineEquip::ZnAirLoopEquipType::SingleDuctConstVolReheat) ||
    1825           1 :                                                         (state.dataDefineEquipment->AirDistUnit(ADUNum).EquipTypeEnum(EquipNum) ==
    1826           1 :                                                          DataDefineEquip::ZnAirLoopEquipType::SingleDuctVAVNoReheat) ||
    1827           1 :                                                         (state.dataDefineEquipment->AirDistUnit(ADUNum).EquipTypeEnum(EquipNum) ==
    1828           1 :                                                          DataDefineEquip::ZnAirLoopEquipType::SingleDuctVAVReheatVSFan) ||
    1829           1 :                                                         (state.dataDefineEquipment->AirDistUnit(ADUNum).EquipTypeEnum(EquipNum) ==
    1830           1 :                                                          DataDefineEquip::ZnAirLoopEquipType::SingleDuctCBVAVReheat) ||
    1831           1 :                                                         (state.dataDefineEquipment->AirDistUnit(ADUNum).EquipTypeEnum(EquipNum) ==
    1832           1 :                                                          DataDefineEquip::ZnAirLoopEquipType::SingleDuctCBVAVNoReheat) ||
    1833           1 :                                                         (state.dataDefineEquipment->AirDistUnit(ADUNum).EquipTypeEnum(EquipNum) ==
    1834           1 :                                                          DataDefineEquip::ZnAirLoopEquipType::SingleDuctConstVolCooledBeam) ||
    1835           1 :                                                         (state.dataDefineEquipment->AirDistUnit(ADUNum).EquipTypeEnum(EquipNum) ==
    1836           6 :                                                          DataDefineEquip::ZnAirLoopEquipType::SingleDuctConstVolFourPipeBeam) ||
    1837           1 :                                                         (state.dataDefineEquipment->AirDistUnit(ADUNum).EquipTypeEnum(EquipNum) ==
    1838             :                                                          DataDefineEquip::ZnAirLoopEquipType::DualDuctVAVOutdoorAir)) {
    1839          12 :                                                         ShowWarningError(state,
    1840           8 :                                                                          CurrentModuleObject + "=\"" + thisVentilationMechanical.Name +
    1841             :                                                                              "\", inappropriate use of Zone secondary recirculation");
    1842           4 :                                                         ShowContinueError(state,
    1843             :                                                                           "A zone secondary recirculation fraction is specified for zone served by ");
    1844          12 :                                                         ShowContinueError(state,
    1845           8 :                                                                           "...terminal unit \"" +
    1846          12 :                                                                               state.dataDefineEquipment->AirDistUnit(ADUNum).Name +
    1847             :                                                                               "\" , that indicates a single path system");
    1848          12 :                                                         ShowContinueError(state,
    1849           8 :                                                                           "For Zone=\"" + thisVentilationMechanical.VentMechZoneName(jZone) + "\".");
    1850           4 :                                                         ShowContinueError(state, "...The zone secondary recirculation for that zone was set to 0.0");
    1851           4 :                                                         thisVentilationMechanical.ZoneSecondaryRecirculation(jZone) = 0.0;
    1852             :                                                     }
    1853           5 :                                                     goto EquipLoop_exit;
    1854             :                                                 }
    1855             :                                             }
    1856             :                                         }
    1857             :                                     }
    1858             :                                 }
    1859             :                             }
    1860           0 :                         EquipLoop_exit:;
    1861             :                         }
    1862             :                     }
    1863             :                 }
    1864         347 :                 if (thisVentilationMechanical.ZoneDesignSpecOAObjName(jZone).empty()) {
    1865           0 :                     ShowSevereError(state,
    1866           0 :                                     CurrentModuleObject + "=\"" + thisVentilationMechanical.Name +
    1867             :                                         "\", Design Specification Outdoor Air Object Name blank");
    1868           0 :                     ShowContinueError(state, "For Zone=\"" + thisVentilationMechanical.VentMechZoneName(jZone) + "\".");
    1869           0 :                     ShowContinueError(state, "This field either needs to be filled in in this object or Sizing:Zone object.");
    1870           0 :                     ShowContinueError(state, "For this run, default values for these fields will be used.");
    1871             :                 }
    1872         347 :                 if (thisVentilationMechanical.ZoneOAPeopleRate(jZone) <= 0.0 && thisVentilationMechanical.DCVFlag) {
    1873           2 :                     ShowWarningError(state, CurrentModuleObject + "=\"" + thisVentilationMechanical.Name + "\", Zone OA/person rate");
    1874           2 :                     ShowContinueError(state, "For Zone=\"" + thisVentilationMechanical.VentMechZoneName(jZone) + "\".");
    1875           6 :                     ShowContinueError(state,
    1876           4 :                                       "Zone outside air per person rate not set in Design Specification Outdoor Air Object=\"" +
    1877           6 :                                           thisVentilationMechanical.ZoneDesignSpecOAObjName(jZone) + "\".");
    1878             :                 }
    1879             : 
    1880         347 :                 if (thisVentilationMechanical.ZoneOAAreaRate(jZone) < 0.0) {
    1881           0 :                     ShowSevereError(state, CurrentModuleObject + "=\"" + thisVentilationMechanical.Name + "\", invalid Outdoor Air flow per area");
    1882           0 :                     ShowContinueError(state, "For Zone=\"" + thisVentilationMechanical.VentMechZoneName(jZone) + "\".");
    1883           0 :                     ShowContinueError(state,
    1884           0 :                                       "invalid Outdoor Air flow per area specified in object=\"" +
    1885           0 :                                           thisVentilationMechanical.ZoneDesignSpecOAObjName(jZone) + "\". Value must be >= 0.0.");
    1886           0 :                     ErrorsFound = true;
    1887             :                 }
    1888         347 :                 if (thisVentilationMechanical.ZoneOAPeopleRate(jZone) < 0.0) {
    1889           0 :                     ShowSevereError(state, CurrentModuleObject + "=\"" + thisVentilationMechanical.Name + "\", invalid Outdoor Air flow per person");
    1890           0 :                     ShowContinueError(state, "For Zone=\"" + thisVentilationMechanical.VentMechZoneName(jZone) + "\".");
    1891           0 :                     ShowContinueError(state,
    1892           0 :                                       "invalid Outdoor Air flow per person specified in object \"" +
    1893           0 :                                           thisVentilationMechanical.ZoneDesignSpecOAObjName(jZone) + "\". Value must be >= 0.0.");
    1894           0 :                     ErrorsFound = true;
    1895             :                 }
    1896             :             }
    1897             :         }
    1898             : 
    1899             :         // Link OA controller object with mechanical ventilation object
    1900         111 :         for (OAControllerNum = 1; OAControllerNum <= state.dataMixedAir->NumOAControllers; ++OAControllerNum) {
    1901         174 :             state.dataMixedAir->OAController(OAControllerNum).VentMechObjectNum = UtilityRoutines::FindItemInList(
    1902         174 :                 state.dataMixedAir->OAController(OAControllerNum).VentilationMechanicalName, state.dataMixedAir->VentilationMechanical);
    1903         122 :             if (state.dataMixedAir->OAController(OAControllerNum).VentMechObjectNum == 0 &&
    1904          35 :                 !state.dataMixedAir->OAController(OAControllerNum).VentilationMechanicalName.empty()) {
    1905           0 :                 ShowSevereError(state,
    1906           0 :                                 CurrentModuleObject + "=\"" + state.dataMixedAir->OAController(OAControllerNum).VentilationMechanicalName +
    1907             :                                     "\", non-match to Controller:OutdoorAir");
    1908           0 :                 ShowContinueError(state,
    1909           0 :                                   "Invalid specified in Controller:OutdoorAir object = " + state.dataMixedAir->OAController(OAControllerNum).Name);
    1910           0 :                 ShowContinueError(state,
    1911           0 :                                   CurrentModuleObject + " object name must match the " + CurrentModuleObject +
    1912             :                                       " object name specified in Controller:OutdoorAir.");
    1913           0 :                 ErrorsFound = true;
    1914             :             }
    1915             :         }
    1916             : 
    1917             :         // write to .eio file
    1918             :         static constexpr std::string_view Format_700(
    1919             :             "!<Controller:MechanicalVentilation>,Name,Availability Schedule Name,Demand Controlled Ventilation "
    1920             :             "{Yes/No},System Outdoor Air Method,Zone Maximum Outdoor Air Fraction,Number of Zones,Zone Name,DSOA "
    1921             :             "Name,DSZAD Name");
    1922          24 :         print(state.files.eio, "{}\n", Format_700);
    1923          76 :         for (VentMechNum = 1; VentMechNum <= state.dataMixedAir->NumVentMechControllers; ++VentMechNum) {
    1924         156 :             print(state.files.eio,
    1925             :                   " Controller:MechanicalVentilation,{},{},",
    1926          52 :                   state.dataMixedAir->VentilationMechanical(VentMechNum).Name,
    1927         104 :                   state.dataMixedAir->VentilationMechanical(VentMechNum).SchName);
    1928             : 
    1929          52 :             if (state.dataMixedAir->VentilationMechanical(VentMechNum).DCVFlag) {
    1930          50 :                 print(state.files.eio, "Yes,");
    1931             :             } else {
    1932           2 :                 print(state.files.eio, "No,");
    1933             :             }
    1934             : 
    1935          52 :             if (state.dataMixedAir->VentilationMechanical(VentMechNum).SystemOAMethod != DataSizing::SysOAMethod::Invalid) {
    1936          52 :                 print(state.files.eio, printSysOAMethod[static_cast<int>(state.dataMixedAir->VentilationMechanical(VentMechNum).SystemOAMethod)]);
    1937             :             } else {
    1938           0 :                 print(state.files.eio, "Invalid/Unknown,");
    1939             :             }
    1940             : 
    1941          52 :             print(state.files.eio, "{:.2R},", state.dataMixedAir->VentilationMechanical(VentMechNum).ZoneMaxOAFraction);
    1942          52 :             print(state.files.eio, "{},", state.dataMixedAir->VentilationMechanical(VentMechNum).NumofVentMechZones);
    1943             : 
    1944         399 :             for (jZone = 1; jZone <= state.dataMixedAir->VentilationMechanical(VentMechNum).NumofVentMechZones; ++jZone) {
    1945         347 :                 if (jZone < state.dataMixedAir->VentilationMechanical(VentMechNum).NumofVentMechZones) {
    1946        1180 :                     print(state.files.eio,
    1947             :                           "{},{},{},",
    1948         295 :                           state.dataHeatBal->Zone(state.dataMixedAir->VentilationMechanical(VentMechNum).VentMechZone(jZone)).Name,
    1949         295 :                           state.dataMixedAir->VentilationMechanical(VentMechNum).ZoneDesignSpecOAObjName(jZone),
    1950         590 :                           state.dataMixedAir->VentilationMechanical(VentMechNum).ZoneDesignSpecADObjName(jZone));
    1951             :                 } else {
    1952         208 :                     print(state.files.eio,
    1953             :                           "{},{},{}\n",
    1954          52 :                           state.dataHeatBal->Zone(state.dataMixedAir->VentilationMechanical(VentMechNum).VentMechZone(jZone)).Name,
    1955          52 :                           state.dataMixedAir->VentilationMechanical(VentMechNum).ZoneDesignSpecOAObjName(jZone),
    1956         104 :                           state.dataMixedAir->VentilationMechanical(VentMechNum).ZoneDesignSpecADObjName(jZone));
    1957             :                 }
    1958             :             }
    1959             :         }
    1960             : 
    1961             :     } // Number of Mechanical Ventilation Objects > 0
    1962             : 
    1963         393 :     AlphArray.deallocate();
    1964         393 :     NumArray.deallocate();
    1965         393 :     lNumericBlanks.deallocate();
    1966         393 :     lAlphaBlanks.deallocate();
    1967         393 :     cAlphaFields.deallocate();
    1968         393 :     cNumericFields.deallocate();
    1969             : 
    1970         393 :     if (ErrorsFound) {
    1971           0 :         ShowFatalError(state, std::string{RoutineName} + "Errors found when getting " + CurrentModuleObject + " inputs.");
    1972             :     }
    1973         393 : }
    1974             : 
    1975         396 : void AllocateOAControllers(EnergyPlusData &state)
    1976             : {
    1977             : 
    1978             :     // PURPOSE OF THIS SUBROUTINE:
    1979             :     // Allocate the OA controller arrays which are shared by Controller:OutdoorAir and ZoneHVAC:EnergyRecoveryVentilator:Controller
    1980             : 
    1981         396 :     if (state.dataMixedAir->AllocateOAControllersFlag) {
    1982         394 :         state.dataMixedAir->NumOAControllers =
    1983         394 :             state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObjects(static_cast<int>(CMO::OAController)));
    1984         394 :         state.dataMixedAir->NumERVControllers =
    1985         394 :             state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObjects(static_cast<int>(CMO::ERVController)));
    1986         394 :         state.dataMixedAir->NumOAControllers += state.dataMixedAir->NumERVControllers;
    1987         394 :         state.dataMixedAir->OAController.allocate(state.dataMixedAir->NumOAControllers);
    1988         394 :         state.dataMixedAir->OAControllerUniqueNames.reserve(static_cast<unsigned>(state.dataMixedAir->NumOAControllers));
    1989         394 :         state.dataMixedAir->AllocateOAControllersFlag = false;
    1990             :     }
    1991         396 : }
    1992             : 
    1993         435 : void GetOAMixerInputs(EnergyPlusData &state)
    1994             : {
    1995             : 
    1996             :     // SUBROUTINE INFORMATION:
    1997             :     //       AUTHOR         Fred Buhl
    1998             :     //       DATE WRITTEN   Oct 1998
    1999             :     //       MODIFIED       na
    2000             :     //       RE-ENGINEERED  na
    2001             : 
    2002             :     // PURPOSE OF THIS SUBROUTINE
    2003             :     // Input the OAMixer data and store it in the OAMixer array.
    2004             : 
    2005             :     // METHODOLOGY EMPLOYED:
    2006             :     // Use the Get routines from the InputProcessor module.
    2007             : 
    2008             :     // Using/Aliasing
    2009             :     using BranchNodeConnections::TestCompSet;
    2010             :     using NodeInputManager::GetOnlySingleNode;
    2011             : 
    2012             :     // Locals
    2013             :     // SUBROUTINE PARAMETER DEFINITIONS:
    2014             :     static constexpr std::string_view RoutineName("GetOAMixerInputs: "); // include trailing blank space
    2015             : 
    2016             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2017             : 
    2018             :     int NumNums;   // Number of REAL(r64) numbers returned by GetObjectItem
    2019             :     int NumAlphas; // Number of alphanumerics returned by GetObjectItem
    2020             :     int NumArg;    // Number of arguments from GetObjectDefMaxArgs call
    2021             :     int OutAirNum;
    2022             :     int IOStat;
    2023         870 :     Array1D<Real64> NumArray;        // array that holds numeric input values
    2024         870 :     Array1D_string AlphArray;        // array that holds alpha input values
    2025         870 :     std::string CurrentModuleObject; // Object type for getting and messages
    2026         870 :     Array1D_string cAlphaFields;     // Alpha field names
    2027         870 :     Array1D_string cNumericFields;   // Numeric field names
    2028         870 :     Array1D_bool lAlphaBlanks;       // Logical array, alpha field input BLANK = .TRUE.
    2029         870 :     Array1D_bool lNumericBlanks;     // Logical array, numeric field input BLANK = .TRUE.
    2030         435 :     bool ErrorsFound(false);
    2031             : 
    2032         435 :     if (!state.dataMixedAir->GetOAMixerInputFlag) return;
    2033             : 
    2034         870 :     state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(
    2035         435 :         state, CurrentModuleObjects(static_cast<int>(CMO::OAMixer)), NumArg, NumAlphas, NumNums);
    2036             : 
    2037         435 :     AlphArray.allocate(NumAlphas);
    2038         435 :     NumArray.dimension(NumNums, 0.0);
    2039         435 :     lNumericBlanks.dimension(NumNums, true);
    2040         435 :     lAlphaBlanks.dimension(NumAlphas, true);
    2041         435 :     cAlphaFields.allocate(NumAlphas);
    2042         435 :     cNumericFields.allocate(NumNums);
    2043             : 
    2044         435 :     CurrentModuleObject = CurrentModuleObjects(static_cast<int>(CMO::OAMixer));
    2045             : 
    2046         435 :     state.dataMixedAir->NumOAMixers = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
    2047             : 
    2048         435 :     if (state.dataMixedAir->NumOAMixers > 0) {
    2049             : 
    2050         435 :         state.dataMixedAir->OAMixer.allocate(state.dataMixedAir->NumOAMixers);
    2051             : 
    2052        1774 :         for (OutAirNum = 1; OutAirNum <= state.dataMixedAir->NumOAMixers; ++OutAirNum) {
    2053        1339 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    2054             :                                                                      CurrentModuleObject,
    2055             :                                                                      OutAirNum,
    2056             :                                                                      AlphArray,
    2057             :                                                                      NumAlphas,
    2058             :                                                                      NumArray,
    2059             :                                                                      NumNums,
    2060             :                                                                      IOStat,
    2061             :                                                                      lNumericBlanks,
    2062             :                                                                      lAlphaBlanks,
    2063             :                                                                      cAlphaFields,
    2064             :                                                                      cNumericFields);
    2065        1339 :             UtilityRoutines::IsNameEmpty(state, AlphArray(1), CurrentModuleObject, ErrorsFound);
    2066             : 
    2067        1339 :             state.dataMixedAir->OAMixer(OutAirNum).Name = AlphArray(1);
    2068        1339 :             state.dataMixedAir->OAMixer(OutAirNum).MixNode = GetOnlySingleNode(state,
    2069        1339 :                                                                                AlphArray(2),
    2070             :                                                                                ErrorsFound,
    2071             :                                                                                DataLoopNode::ConnectionObjectType::OutdoorAirMixer,
    2072        1339 :                                                                                AlphArray(1),
    2073             :                                                                                DataLoopNode::NodeFluidType::Air,
    2074             :                                                                                DataLoopNode::ConnectionType::Outlet,
    2075             :                                                                                NodeInputManager::CompFluidStream::Primary,
    2076        1339 :                                                                                ObjectIsNotParent);
    2077             :             //  Set connection type to 'Inlet', because this is not necessarily directly from
    2078             :             //  outside air.  Outside Air Inlet Node List will set the connection to outside air
    2079        1339 :             state.dataMixedAir->OAMixer(OutAirNum).InletNode = GetOnlySingleNode(state,
    2080        1339 :                                                                                  AlphArray(3),
    2081             :                                                                                  ErrorsFound,
    2082             :                                                                                  DataLoopNode::ConnectionObjectType::OutdoorAirMixer,
    2083        1339 :                                                                                  AlphArray(1),
    2084             :                                                                                  DataLoopNode::NodeFluidType::Air,
    2085             :                                                                                  DataLoopNode::ConnectionType::Inlet,
    2086             :                                                                                  NodeInputManager::CompFluidStream::Primary,
    2087        1339 :                                                                                  ObjectIsNotParent);
    2088        1339 :             state.dataMixedAir->OAMixer(OutAirNum).RelNode = GetOnlySingleNode(state,
    2089        1339 :                                                                                AlphArray(4),
    2090             :                                                                                ErrorsFound,
    2091             :                                                                                DataLoopNode::ConnectionObjectType::OutdoorAirMixer,
    2092        1339 :                                                                                AlphArray(1),
    2093             :                                                                                DataLoopNode::NodeFluidType::Air,
    2094             :                                                                                DataLoopNode::ConnectionType::ReliefAir,
    2095             :                                                                                NodeInputManager::CompFluidStream::Primary,
    2096        1339 :                                                                                ObjectIsNotParent);
    2097        1339 :             state.dataMixedAir->OAMixer(OutAirNum).RetNode = GetOnlySingleNode(state,
    2098        1339 :                                                                                AlphArray(5),
    2099             :                                                                                ErrorsFound,
    2100             :                                                                                DataLoopNode::ConnectionObjectType::OutdoorAirMixer,
    2101        1339 :                                                                                AlphArray(1),
    2102             :                                                                                DataLoopNode::NodeFluidType::Air,
    2103             :                                                                                DataLoopNode::ConnectionType::Inlet,
    2104             :                                                                                NodeInputManager::CompFluidStream::Primary,
    2105        1339 :                                                                                ObjectIsNotParent);
    2106             :             // Check for dupes in the four nodes.
    2107        1339 :             if (state.dataMixedAir->OAMixer(OutAirNum).MixNode == state.dataMixedAir->OAMixer(OutAirNum).InletNode) {
    2108           0 :                 ShowSevereError(state,
    2109           0 :                                 CurrentModuleObject + " = " + state.dataMixedAir->OAMixer(OutAirNum).Name + ' ' + cAlphaFields(3) + " = " +
    2110           0 :                                     state.dataLoopNodes->NodeID(state.dataMixedAir->OAMixer(OutAirNum).InletNode) + " duplicates the " +
    2111           0 :                                     cAlphaFields(2) + '.');
    2112           0 :                 ErrorsFound = true;
    2113        1339 :             } else if (state.dataMixedAir->OAMixer(OutAirNum).MixNode == state.dataMixedAir->OAMixer(OutAirNum).RelNode) {
    2114           0 :                 ShowSevereError(state,
    2115           0 :                                 CurrentModuleObject + " = " + state.dataMixedAir->OAMixer(OutAirNum).Name + ' ' + cAlphaFields(4) + " = " +
    2116           0 :                                     state.dataLoopNodes->NodeID(state.dataMixedAir->OAMixer(OutAirNum).RelNode) + " duplicates the " +
    2117           0 :                                     cAlphaFields(2) + '.');
    2118           0 :                 ErrorsFound = true;
    2119        1339 :             } else if (state.dataMixedAir->OAMixer(OutAirNum).MixNode == state.dataMixedAir->OAMixer(OutAirNum).RetNode) {
    2120           0 :                 ShowSevereError(state,
    2121           0 :                                 CurrentModuleObject + " = " + state.dataMixedAir->OAMixer(OutAirNum).Name + ' ' + cAlphaFields(5) + " = " +
    2122           0 :                                     state.dataLoopNodes->NodeID(state.dataMixedAir->OAMixer(OutAirNum).RetNode) + " duplicates the " +
    2123           0 :                                     cAlphaFields(2) + '.');
    2124           0 :                 ErrorsFound = true;
    2125             :             }
    2126             : 
    2127        1339 :             if (state.dataMixedAir->OAMixer(OutAirNum).InletNode == state.dataMixedAir->OAMixer(OutAirNum).RelNode) {
    2128           0 :                 ShowSevereError(state,
    2129           0 :                                 CurrentModuleObject + " = " + state.dataMixedAir->OAMixer(OutAirNum).Name + ' ' + cAlphaFields(4) + " = " +
    2130           0 :                                     state.dataLoopNodes->NodeID(state.dataMixedAir->OAMixer(OutAirNum).RelNode) + " duplicates the " +
    2131           0 :                                     cAlphaFields(3) + '.');
    2132           0 :                 ErrorsFound = true;
    2133        1339 :             } else if (state.dataMixedAir->OAMixer(OutAirNum).InletNode == state.dataMixedAir->OAMixer(OutAirNum).RetNode) {
    2134           0 :                 ShowSevereError(state,
    2135           0 :                                 CurrentModuleObject + " = " + state.dataMixedAir->OAMixer(OutAirNum).Name + ' ' + cAlphaFields(5) + " = " +
    2136           0 :                                     state.dataLoopNodes->NodeID(state.dataMixedAir->OAMixer(OutAirNum).RetNode) + " duplicates the " +
    2137           0 :                                     cAlphaFields(3) + '.');
    2138           0 :                 ErrorsFound = true;
    2139             :             }
    2140             : 
    2141        1339 :             if (state.dataMixedAir->OAMixer(OutAirNum).RelNode == state.dataMixedAir->OAMixer(OutAirNum).RetNode) {
    2142           0 :                 ShowSevereError(state,
    2143           0 :                                 CurrentModuleObject + " = " + state.dataMixedAir->OAMixer(OutAirNum).Name + ' ' + cAlphaFields(5) + " = " +
    2144           0 :                                     state.dataLoopNodes->NodeID(state.dataMixedAir->OAMixer(OutAirNum).RetNode) + " duplicates the " +
    2145           0 :                                     cAlphaFields(4) + '.');
    2146           0 :                 ErrorsFound = true;
    2147             :             }
    2148             : 
    2149        1339 :             TestCompSet(state, CurrentModuleObject, state.dataMixedAir->OAMixer(OutAirNum).Name, AlphArray(3), AlphArray(2), "Air Nodes");
    2150             :         }
    2151             :     }
    2152             : 
    2153         435 :     if (ErrorsFound) {
    2154           0 :         ShowFatalError(state, std::string{RoutineName} + "Errors found in getting " + CurrentModuleObject);
    2155             :     }
    2156             : 
    2157         435 :     state.dataMixedAir->GetOAMixerInputFlag = false;
    2158             : }
    2159             : 
    2160        1021 : void ProcessOAControllerInputs(EnergyPlusData &state,
    2161             :                                std::string const &CurrentModuleObject,
    2162             :                                int const OutAirNum,
    2163             :                                Array1D_string const &AlphArray,
    2164             :                                int &NumAlphas,
    2165             :                                Array1D<Real64> const &NumArray,
    2166             :                                int &NumNums,
    2167             :                                Array1D_bool const &lNumericBlanks, // Unused
    2168             :                                Array1D_bool const &lAlphaBlanks,
    2169             :                                Array1D_string const &cAlphaFields,
    2170             :                                Array1D_string const &cNumericFields, // Unused
    2171             :                                bool &ErrorsFound                     // If errors found in input
    2172             : )
    2173             : {
    2174             : 
    2175             :     // SUBROUTINE INFORMATION:
    2176             :     //       AUTHOR         Fred Buhl
    2177             :     //       DATE WRITTEN   Oct 1998
    2178             :     //       MODIFIED       Shirey/Raustad FSEC, June 2003, Jan 2004
    2179             :     //                      Mangesh Basarkar, 06/2011: Getting zone OA specifications from Design Specification Object
    2180             :     //                      Tianzhen Hong, 3/2012: getting zone air distribution effectiveness and secondary recirculation
    2181             :     //                       from DesignSpecification:ZoneAirDistribution objects
    2182             :     //       RE-ENGINEERED  MJW: Split out processing controller:outdoorair input to facilitate unit testing, Feb 2015
    2183             : 
    2184             :     // PURPOSE OF THIS SUBROUTINE
    2185             :     // Input the OAController data and store it in the OAController array.
    2186             : 
    2187             :     // METHODOLOGY EMPLOYED:
    2188             : 
    2189             :     // Using/Aliasing
    2190             :     using namespace DataDefineEquip;
    2191             :     using Curve::GetCurveIndex;
    2192             :     using NodeInputManager::GetOnlySingleNode;
    2193             :     using namespace OutputReportPredefined;
    2194             : 
    2195             :     using OutAirNodeManager::CheckOutAirNodeNumber;
    2196             : 
    2197             :     using SetPointManager::GetMixedAirNumWithCoilFreezingCheck;
    2198             : 
    2199             :     // SUBROUTINE PARAMETER DEFINITIONS:
    2200             :     static constexpr std::string_view RoutineName("GetOAControllerInputs: "); // include trailing blank space
    2201             : 
    2202             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2203             : 
    2204             :     int OAControllerNum;   // Index to Controller:OutdoorAir or CONTROLLER:STAND ALONE ERV objects
    2205             :     int ControlledZoneNum; // Index to controlled zones
    2206             :     bool AirNodeFound;     // Used to determine if control zone is valid
    2207             :     bool AirLoopFound;     // Used to determine if control zone is served by furnace air loop
    2208             :     int BranchNum;         // Used to determine if control zone is served by furnace air loop
    2209             :     int CompNum;           // Used to determine if control zone is served by furnace air loop
    2210             :     int HStatZoneNum;      // Used to determine if control zone has a humidistat object
    2211             :     int OASysNum;          // Used to find OA System index for OA Controller
    2212             :     int OASysIndex;        // Index to OA System
    2213             :     bool OASysFound;       // OA Controller found OA System index
    2214             :     Real64 OAFlowRatio;    // Ratio of minimum OA flow rate to maximum OA flow rate
    2215             : 
    2216        1021 :     state.dataMixedAir->OAController(OutAirNum).Name = AlphArray(1);
    2217        1021 :     state.dataMixedAir->OAController(OutAirNum).ControllerType = CurrentModuleObject;
    2218        1021 :     state.dataMixedAir->OAController(OutAirNum).ControllerType_Num = MixedAirControllerType::ControllerOutsideAir;
    2219        1021 :     state.dataMixedAir->OAController(OutAirNum).MaxOA = NumArray(2);
    2220        1021 :     state.dataMixedAir->OAController(OutAirNum).MinOA = NumArray(1);
    2221        1021 :     state.dataMixedAir->OAController(OutAirNum).MixNode = GetOnlySingleNode(state,
    2222        1021 :                                                                             AlphArray(4),
    2223             :                                                                             ErrorsFound,
    2224             :                                                                             DataLoopNode::ConnectionObjectType::ControllerOutdoorAir,
    2225        1021 :                                                                             AlphArray(1),
    2226             :                                                                             DataLoopNode::NodeFluidType::Air,
    2227             :                                                                             DataLoopNode::ConnectionType::Sensor,
    2228             :                                                                             NodeInputManager::CompFluidStream::Primary,
    2229        1021 :                                                                             ObjectIsNotParent);
    2230        1021 :     state.dataMixedAir->OAController(OutAirNum).OANode = GetOnlySingleNode(state,
    2231        1021 :                                                                            AlphArray(5),
    2232             :                                                                            ErrorsFound,
    2233             :                                                                            DataLoopNode::ConnectionObjectType::ControllerOutdoorAir,
    2234        1021 :                                                                            AlphArray(1),
    2235             :                                                                            DataLoopNode::NodeFluidType::Air,
    2236             :                                                                            DataLoopNode::ConnectionType::Actuator,
    2237             :                                                                            NodeInputManager::CompFluidStream::Primary,
    2238        1021 :                                                                            ObjectIsNotParent);
    2239        1021 :     if (!CheckOutAirNodeNumber(state, state.dataMixedAir->OAController(OutAirNum).OANode)) {
    2240           0 :         ShowWarningError(
    2241           0 :             state, CurrentModuleObject + "=\"" + AlphArray(1) + "\": " + cAlphaFields(5) + "=\"" + AlphArray(5) + "\" is not an OutdoorAir:Node.");
    2242           0 :         ShowContinueError(state, "Confirm that this is the intended source for the outdoor air stream.");
    2243             :     }
    2244        1021 :     if (UtilityRoutines::SameString(AlphArray(6), "NoEconomizer")) {
    2245         507 :         state.dataMixedAir->OAController(OutAirNum).Econo = EconoOp::NoEconomizer;
    2246         514 :     } else if (UtilityRoutines::SameString(AlphArray(6), "FixedDryBulb")) {
    2247         123 :         state.dataMixedAir->OAController(OutAirNum).Econo = EconoOp::FixedDryBulb;
    2248         391 :     } else if (UtilityRoutines::SameString(AlphArray(6), "FixedEnthalpy")) {
    2249           0 :         state.dataMixedAir->OAController(OutAirNum).Econo = EconoOp::FixedEnthalpy;
    2250         391 :     } else if (UtilityRoutines::SameString(AlphArray(6), "FixedDewPointAndDryBulb")) {
    2251           0 :         state.dataMixedAir->OAController(OutAirNum).Econo = EconoOp::FixedDewPointAndDryBulb;
    2252         391 :     } else if (UtilityRoutines::SameString(AlphArray(6), "DifferentialDryBulb")) {
    2253         366 :         state.dataMixedAir->OAController(OutAirNum).Econo = EconoOp::DifferentialDryBulb;
    2254          25 :     } else if (UtilityRoutines::SameString(AlphArray(6), "DifferentialEnthalpy")) {
    2255          18 :         state.dataMixedAir->OAController(OutAirNum).Econo = EconoOp::DifferentialEnthalpy;
    2256           7 :     } else if (UtilityRoutines::SameString(AlphArray(6), "DifferentialDryBulbAndEnthalpy")) {
    2257           0 :         state.dataMixedAir->OAController(OutAirNum).Econo = EconoOp::DifferentialDryBulbAndEnthalpy;
    2258           7 :     } else if (UtilityRoutines::SameString(AlphArray(6), "ElectronicEnthalpy")) {
    2259           7 :         state.dataMixedAir->OAController(OutAirNum).Econo = EconoOp::ElectronicEnthalpy;
    2260             :     } else {
    2261           0 :         ShowSevereError(state, CurrentModuleObject + "=\"" + AlphArray(1) + "\" invalid " + cAlphaFields(6) + "=\"" + AlphArray(6) + "\" value.");
    2262           0 :         ErrorsFound = true;
    2263             :     }
    2264             :     // Bypass choice - Added by Amit for new feature implementation
    2265        1021 :     if (UtilityRoutines::SameString(AlphArray(7), "ModulateFlow")) {
    2266        1005 :         state.dataMixedAir->OAController(OutAirNum).EconBypass = false;
    2267          16 :     } else if (UtilityRoutines::SameString(AlphArray(7), "MinimumFlowWithBypass")) {
    2268          16 :         state.dataMixedAir->OAController(OutAirNum).EconBypass = true;
    2269             :     } else {
    2270           0 :         ShowSevereError(state, CurrentModuleObject + "=\"" + AlphArray(1) + "\" invalid " + cAlphaFields(7) + "=\"" + AlphArray(7) + "\" value.");
    2271           0 :         ErrorsFound = true;
    2272             :     }
    2273             : 
    2274        1021 :     if (UtilityRoutines::SameString(AlphArray(9), "NoLockout")) {
    2275         784 :         state.dataMixedAir->OAController(OutAirNum).Lockout = LockoutType::NoLockoutPossible;
    2276         237 :     } else if (UtilityRoutines::SameString(AlphArray(9), "LockoutWithHeating")) {
    2277         196 :         state.dataMixedAir->OAController(OutAirNum).Lockout = LockoutType::LockoutWithHeatingPossible;
    2278          41 :     } else if (UtilityRoutines::SameString(AlphArray(9), "LockoutWithCompressor")) {
    2279          41 :         state.dataMixedAir->OAController(OutAirNum).Lockout = LockoutType::LockoutWithCompressorPossible;
    2280             :     } else {
    2281           0 :         ShowSevereError(state, CurrentModuleObject + "=\"" + AlphArray(1) + "\" invalid " + cAlphaFields(9) + "=\"" + AlphArray(9) + "\" value.");
    2282           0 :         ErrorsFound = true;
    2283             :     }
    2284        1021 :     if (UtilityRoutines::SameString(AlphArray(10), "FixedMinimum")) {
    2285         981 :         state.dataMixedAir->OAController(OutAirNum).FixedMin = true;
    2286             :     } else {
    2287          40 :         state.dataMixedAir->OAController(OutAirNum).FixedMin = false;
    2288             :     }
    2289        1021 :     if (lNumericBlanks(3)) {
    2290         291 :         state.dataMixedAir->OAController(OutAirNum).TempLim = BlankNumeric;
    2291             :     } else {
    2292         730 :         state.dataMixedAir->OAController(OutAirNum).TempLim = NumArray(3);
    2293             :     }
    2294             : 
    2295        1021 :     if (lNumericBlanks(4)) {
    2296         634 :         state.dataMixedAir->OAController(OutAirNum).EnthLim = BlankNumeric;
    2297             :     } else {
    2298         387 :         state.dataMixedAir->OAController(OutAirNum).EnthLim = NumArray(4);
    2299             :     }
    2300        1021 :     if (lNumericBlanks(5)) {
    2301        1006 :         state.dataMixedAir->OAController(OutAirNum).DPTempLim = BlankNumeric;
    2302             :     } else {
    2303          15 :         state.dataMixedAir->OAController(OutAirNum).DPTempLim = NumArray(5);
    2304             :     }
    2305             : 
    2306        1021 :     if (lNumericBlanks(6)) {
    2307         357 :         state.dataMixedAir->OAController(OutAirNum).TempLowLim = BlankNumeric;
    2308             :     } else {
    2309         664 :         state.dataMixedAir->OAController(OutAirNum).TempLowLim = NumArray(6);
    2310             :     }
    2311             : 
    2312        1021 :     if (!lAlphaBlanks(8)) {
    2313           7 :         state.dataMixedAir->OAController(OutAirNum).EnthalpyCurvePtr = GetCurveIndex(state, AlphArray(8)); // convert curve name to number
    2314           7 :         if (state.dataMixedAir->OAController(OutAirNum).EnthalpyCurvePtr == 0) {
    2315           0 :             ShowSevereError(state,
    2316           0 :                             CurrentModuleObject + "=\"" + AlphArray(1) + "\" invalid " + cAlphaFields(8) + "=\"" + AlphArray(8) + "\" not found.");
    2317           0 :             ErrorsFound = true;
    2318             :         } else {
    2319             :             // Verify Curve Object, only legal types are Quadratic and Cubic
    2320          21 :             ErrorsFound |= Curve::CheckCurveDims(state,
    2321           7 :                                                  state.dataMixedAir->OAController(OutAirNum).EnthalpyCurvePtr, // Curve index
    2322             :                                                  {1},                                                          // Valid dimensions
    2323             :                                                  RoutineName,                                                  // Routine name
    2324             :                                                  CurrentModuleObject,                                          // Object Type
    2325           7 :                                                  state.dataMixedAir->OAController(OutAirNum).Name,             // Object Name
    2326           7 :                                                  cAlphaFields(8));                                             // Field Name
    2327             :         }
    2328             :     }
    2329             : 
    2330        1021 :     state.dataMixedAir->OAController(OutAirNum).RelNode = GetOnlySingleNode(state,
    2331        1021 :                                                                             AlphArray(2),
    2332             :                                                                             ErrorsFound,
    2333             :                                                                             DataLoopNode::ConnectionObjectType::ControllerOutdoorAir,
    2334        1021 :                                                                             AlphArray(1),
    2335             :                                                                             DataLoopNode::NodeFluidType::Air,
    2336             :                                                                             DataLoopNode::ConnectionType::Actuator,
    2337             :                                                                             NodeInputManager::CompFluidStream::Primary,
    2338        1021 :                                                                             ObjectIsNotParent);
    2339        1021 :     state.dataMixedAir->OAController(OutAirNum).RetNode = GetOnlySingleNode(state,
    2340        1021 :                                                                             AlphArray(3),
    2341             :                                                                             ErrorsFound,
    2342             :                                                                             DataLoopNode::ConnectionObjectType::ControllerOutdoorAir,
    2343        1021 :                                                                             AlphArray(1),
    2344             :                                                                             DataLoopNode::NodeFluidType::Air,
    2345             :                                                                             DataLoopNode::ConnectionType::Sensor,
    2346             :                                                                             NodeInputManager::CompFluidStream::Primary,
    2347        1021 :                                                                             ObjectIsNotParent);
    2348        1021 :     state.dataMixedAir->OAController(OutAirNum).MinOASch = AlphArray(11);
    2349        1021 :     state.dataMixedAir->OAController(OutAirNum).MinOASchPtr = GetScheduleIndex(state, AlphArray(11));
    2350        1021 :     if (state.dataMixedAir->OAController(OutAirNum).MinOASchPtr == 0 && (!lAlphaBlanks(11))) {
    2351           0 :         ShowSevereError(state,
    2352           0 :                         CurrentModuleObject + "=\"" + AlphArray(1) + "\" invalid " + cAlphaFields(11) + "=\"" + AlphArray(11) + "\" not found.");
    2353           0 :         ErrorsFound = true;
    2354             :     }
    2355             : 
    2356             :     // Changed by Amit for new feature implementation
    2357        1021 :     state.dataMixedAir->OAController(OutAirNum).MinOAflowSch = AlphArray(12);
    2358        1021 :     state.dataMixedAir->OAController(OutAirNum).MinOAflowSchPtr = GetScheduleIndex(state, AlphArray(12));
    2359        1021 :     if (state.dataMixedAir->OAController(OutAirNum).MinOAflowSchPtr == 0 && (!lAlphaBlanks(12))) {
    2360           0 :         ShowSevereError(state,
    2361           0 :                         CurrentModuleObject + "=\"" + AlphArray(1) + "\" invalid " + cAlphaFields(12) + "=\"" + AlphArray(12) + "\" not found.");
    2362           0 :         ErrorsFound = true;
    2363             :     }
    2364             : 
    2365        1021 :     state.dataMixedAir->OAController(OutAirNum).MaxOAflowSch = AlphArray(13);
    2366        1021 :     state.dataMixedAir->OAController(OutAirNum).MaxOAflowSchPtr = GetScheduleIndex(state, AlphArray(13));
    2367        1021 :     if (state.dataMixedAir->OAController(OutAirNum).MaxOAflowSchPtr == 0 && (!lAlphaBlanks(13))) {
    2368           0 :         ShowSevereError(state,
    2369           0 :                         CurrentModuleObject + "=\"" + AlphArray(1) + "\" invalid " + cAlphaFields(13) + "=\"" + AlphArray(13) + "\" not found.");
    2370           0 :         ErrorsFound = true;
    2371             :     }
    2372        1021 :     state.dataMixedAir->OAController(OutAirNum).VentilationMechanicalName = AlphArray(14);
    2373             : 
    2374             :     //   Check for a time of day economizer control schedule
    2375        1021 :     state.dataMixedAir->OAController(OutAirNum).EconomizerOASchedPtr = GetScheduleIndex(state, AlphArray(15));
    2376             : 
    2377             :     //   High humidity control option can be used with any economizer flag
    2378        1021 :     if (UtilityRoutines::SameString(AlphArray(16), "Yes")) {
    2379             : 
    2380           6 :         state.dataMixedAir->OAController(OutAirNum).HumidistatZoneNum = UtilityRoutines::FindItemInList(AlphArray(17), state.dataHeatBal->Zone);
    2381             : 
    2382             :         // Get the node number for the zone with the humidistat
    2383           6 :         if (state.dataMixedAir->OAController(OutAirNum).HumidistatZoneNum > 0) {
    2384           6 :             AirNodeFound = false;
    2385           6 :             AirLoopFound = false;
    2386           6 :             OASysFound = false;
    2387          25 :             for (ControlledZoneNum = 1; ControlledZoneNum <= state.dataGlobal->NumOfZones; ++ControlledZoneNum) {
    2388          19 :                 if (ControlledZoneNum != state.dataMixedAir->OAController(OutAirNum).HumidistatZoneNum) continue;
    2389             :                 //           Find the controlled zone number for the specified humidistat location
    2390           6 :                 state.dataMixedAir->OAController(OutAirNum).NodeNumofHumidistatZone =
    2391           6 :                     state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).ZoneNode;
    2392             :                 //           Determine which OA System uses this OA Controller
    2393           6 :                 OASysIndex = 0;
    2394           6 :                 for (OASysNum = 1; OASysNum <= state.dataAirLoop->NumOASystems; ++OASysNum) {
    2395           6 :                     for (OAControllerNum = 1; OAControllerNum <= state.dataAirLoop->OutsideAirSys(OASysNum).NumControllers; ++OAControllerNum) {
    2396          12 :                         if (!UtilityRoutines::SameString(state.dataAirLoop->OutsideAirSys(OASysNum).ControllerType(OAControllerNum),
    2397          12 :                                                          CurrentModuleObject) ||
    2398           6 :                             !UtilityRoutines::SameString(state.dataAirLoop->OutsideAirSys(OASysNum).ControllerName(OAControllerNum),
    2399           6 :                                                          state.dataMixedAir->OAController(OutAirNum).Name))
    2400           0 :                             continue;
    2401           6 :                         OASysIndex = OASysNum;
    2402           6 :                         OASysFound = true;
    2403           6 :                         break;
    2404             :                     }
    2405           6 :                     if (OASysFound) break;
    2406             :                 }
    2407             :                 //           Determine if controller is on air loop served by the humidistat location specified
    2408          12 :                 for (int zoneInNode = 1; zoneInNode <= state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).NumInletNodes; ++zoneInNode) {
    2409           6 :                     int AirLoopNumber = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).InletNodeAirLoopNum(zoneInNode);
    2410          12 :                     if (AirLoopNumber > 0 && OASysIndex > 0) {
    2411           6 :                         for (BranchNum = 1; BranchNum <= state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).NumBranches; ++BranchNum) {
    2412           6 :                             for (CompNum = 1; CompNum <= state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).Branch(BranchNum).TotalComponents;
    2413             :                                  ++CompNum) {
    2414          18 :                                 if (!UtilityRoutines::SameString(
    2415           6 :                                         state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).Branch(BranchNum).Comp(CompNum).Name,
    2416          18 :                                         state.dataAirLoop->OutsideAirSys(OASysIndex).Name) ||
    2417          12 :                                     !UtilityRoutines::SameString(
    2418           6 :                                         state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).Branch(BranchNum).Comp(CompNum).TypeOf,
    2419           6 :                                         "AirLoopHVAC:OutdoorAirSystem"))
    2420           0 :                                     continue;
    2421           6 :                                 AirLoopFound = true;
    2422           6 :                                 break;
    2423             :                             }
    2424           6 :                             if (AirLoopFound) break;
    2425             :                         }
    2426           6 :                         for (HStatZoneNum = 1; HStatZoneNum <= state.dataZoneCtrls->NumHumidityControlZones; ++HStatZoneNum) {
    2427          12 :                             if (state.dataZoneCtrls->HumidityControlZone(HStatZoneNum).ActualZoneNum !=
    2428           6 :                                 state.dataMixedAir->OAController(OutAirNum).HumidistatZoneNum)
    2429           0 :                                 continue;
    2430           6 :                             AirNodeFound = true;
    2431           6 :                             break;
    2432             :                         }
    2433             :                     } else {
    2434           0 :                         if (OASysIndex == 0) {
    2435           0 :                             ShowSevereError(state,
    2436           0 :                                             "Did not find an AirLoopHVAC:OutdoorAirSystem for " +
    2437           0 :                                                 state.dataMixedAir->OAController(OutAirNum).ControllerType + " = \"" +
    2438           0 :                                                 state.dataMixedAir->OAController(OutAirNum).Name + "\"");
    2439           0 :                             ErrorsFound = true;
    2440             :                         }
    2441             :                     }
    2442             :                 }
    2443             :             }
    2444           6 :             if (!AirNodeFound) {
    2445           0 :                 ShowSevereError(state,
    2446           0 :                                 "Did not find Air Node (Zone with Humidistat), " + state.dataMixedAir->OAController(OutAirNum).ControllerType +
    2447           0 :                                     " = \"" + state.dataMixedAir->OAController(OutAirNum).Name + "\"");
    2448           0 :                 ShowContinueError(state, "Specified " + cAlphaFields(17) + " = " + AlphArray(17));
    2449           0 :                 ShowContinueError(state,
    2450             :                                   "Both a ZoneHVAC:EquipmentConnections object and a ZoneControl:Humidistat object must be specified for this zone.");
    2451           0 :                 ErrorsFound = true;
    2452             :             }
    2453           6 :             if (!AirLoopFound) {
    2454           0 :                 ShowSevereError(state,
    2455           0 :                                 "Did not find correct Primary Air Loop for " + state.dataMixedAir->OAController(OutAirNum).ControllerType + " = \"" +
    2456           0 :                                     state.dataMixedAir->OAController(OutAirNum).Name + "\"");
    2457           0 :                 ShowContinueError(state, cAlphaFields(17) + " = " + AlphArray(17) + " is not served by this Primary Air Loop equipment.");
    2458           0 :                 ErrorsFound = true;
    2459             :             }
    2460             :         } else {
    2461           0 :             ShowSevereError(state,
    2462           0 :                             "Did not find Air Node (Zone with Humidistat), " + state.dataMixedAir->OAController(OutAirNum).ControllerType + " = \"" +
    2463           0 :                                 state.dataMixedAir->OAController(OutAirNum).Name + "\"");
    2464           0 :             ShowContinueError(state, "Specified " + cAlphaFields(17) + " = " + AlphArray(17));
    2465           0 :             ShowContinueError(state,
    2466             :                               "Both a ZoneHVAC:EquipmentConnections object and a ZoneControl:Humidistat object must be specified for this zone.");
    2467           0 :             ErrorsFound = true;
    2468             :         }
    2469             : 
    2470           6 :         state.dataMixedAir->OAController(OutAirNum).HighRHOAFlowRatio = NumArray(7);
    2471           6 :         if (state.dataMixedAir->OAController(OutAirNum).HighRHOAFlowRatio <= 0.0 && NumNums > 6) {
    2472           0 :             ShowWarningError(state, CurrentModuleObject + " \"" + state.dataMixedAir->OAController(OutAirNum).Name + "\"");
    2473           0 :             ShowContinueError(state, ' ' + cNumericFields(7) + " must be greater than 0.");
    2474           0 :             ShowContinueError(state, ' ' + cNumericFields(7) + " is reset to 1 and the simulation continues.");
    2475           0 :             state.dataMixedAir->OAController(OutAirNum).HighRHOAFlowRatio = 1.0;
    2476             :         }
    2477             : 
    2478           6 :         if (UtilityRoutines::SameString(AlphArray(16), "Yes") && state.dataMixedAir->OAController(OutAirNum).FixedMin) {
    2479           6 :             if (state.dataMixedAir->OAController(OutAirNum).MaxOA > 0.0 && state.dataMixedAir->OAController(OutAirNum).MinOA != AutoSize) {
    2480           5 :                 OAFlowRatio = state.dataMixedAir->OAController(OutAirNum).MinOA / state.dataMixedAir->OAController(OutAirNum).MaxOA;
    2481           5 :                 if (state.dataMixedAir->OAController(OutAirNum).HighRHOAFlowRatio < OAFlowRatio) {
    2482           0 :                     ShowWarningError(state, CurrentModuleObject + " \"" + state.dataMixedAir->OAController(OutAirNum).Name + "\"");
    2483           0 :                     ShowContinueError(state, "... A fixed minimum outside air flow rate and high humidity control have been specified.");
    2484           0 :                     ShowContinueError(state,
    2485           0 :                                       "... The " + cNumericFields(7) +
    2486             :                                           " is less than the ratio of the outside air controllers minimum to maximum outside air flow rate.");
    2487           0 :                     ShowContinueError(
    2488           0 :                         state, format("... Controller {} = {:.4T} m3/s.", cNumericFields(1), state.dataMixedAir->OAController(OutAirNum).MinOA));
    2489           0 :                     ShowContinueError(
    2490           0 :                         state, format("... Controller {} = {:.4T} m3/s.", cNumericFields(2), state.dataMixedAir->OAController(OutAirNum).MaxOA));
    2491           0 :                     ShowContinueError(state, format("... Controller minimum to maximum flow ratio = {:.4T}.", OAFlowRatio));
    2492           0 :                     ShowContinueError(state,
    2493           0 :                                       format("... {} = {:.4T}.", cNumericFields(7), state.dataMixedAir->OAController(OutAirNum).HighRHOAFlowRatio));
    2494             :                 }
    2495             :             }
    2496             :         }
    2497             : 
    2498           6 :         if (NumAlphas >= 18) {
    2499           6 :             if (UtilityRoutines::SameString(AlphArray(18), "Yes")) {
    2500           6 :                 state.dataMixedAir->OAController(OutAirNum).ModifyDuringHighOAMoisture = false;
    2501           0 :             } else if (UtilityRoutines::SameString(AlphArray(18), "No")) {
    2502           0 :                 state.dataMixedAir->OAController(OutAirNum).ModifyDuringHighOAMoisture = true;
    2503             :             } else {
    2504           0 :                 ShowSevereError(state, CurrentModuleObject + " \"" + state.dataMixedAir->OAController(OutAirNum).Name + "\", invalid field value");
    2505           0 :                 ShowContinueError(state, "..." + cAlphaFields(18) + "=\"" + AlphArray(18) + "\" - valid values are \"Yes\" or \"No\".");
    2506           0 :                 ErrorsFound = true;
    2507             :             }
    2508             :         } else {
    2509           0 :             if (state.dataMixedAir->OAController(OutAirNum).Econo == EconoOp::NoEconomizer) {
    2510           0 :                 state.dataMixedAir->OAController(OutAirNum).ModifyDuringHighOAMoisture = true;
    2511             :             } else {
    2512           0 :                 state.dataMixedAir->OAController(OutAirNum).ModifyDuringHighOAMoisture = false;
    2513           0 :                 ShowWarningError(state, CurrentModuleObject + " \"" + state.dataMixedAir->OAController(OutAirNum).Name + "\", missing field value");
    2514           0 :                 ShowContinueError(state, "..." + cAlphaFields(18) + " will default to Yes when " + cAlphaFields(16) + "= \"Yes\"");
    2515             :             }
    2516             :         }
    2517             : 
    2518        1015 :     } else if (UtilityRoutines::SameString(AlphArray(16), "No") || lAlphaBlanks(16)) {
    2519        1015 :         if (NumAlphas >= 18) {
    2520         121 :             if (!UtilityRoutines::SameString(AlphArray(18), "Yes") && !UtilityRoutines::SameString(AlphArray(18), "No")) {
    2521           0 :                 ShowSevereError(state, CurrentModuleObject + " \"" + state.dataMixedAir->OAController(OutAirNum).Name + "\", invalid field value");
    2522           0 :                 ShowContinueError(state, "..." + cAlphaFields(18) + "=\"" + AlphArray(18) + "\" - valid values are \"Yes\" or \"No\".");
    2523           0 :                 ErrorsFound = true;
    2524             :             }
    2525             :         }
    2526             :     } else { // Invalid field 16
    2527           0 :         ShowSevereError(state, CurrentModuleObject + " \"" + state.dataMixedAir->OAController(OutAirNum).Name + "\", invalid field value");
    2528           0 :         ShowContinueError(state, "..." + cAlphaFields(16) + "=\"" + AlphArray(16) + "\" - valid values are \"Yes\" or \"No\".");
    2529           0 :         ErrorsFound = true;
    2530           0 :         if (NumAlphas >= 18) {
    2531           0 :             if (!UtilityRoutines::SameString(AlphArray(18), "Yes") && !UtilityRoutines::SameString(AlphArray(18), "No")) {
    2532           0 :                 ShowSevereError(state, CurrentModuleObject + " \"" + state.dataMixedAir->OAController(OutAirNum).Name + "\", invalid field value");
    2533           0 :                 ShowContinueError(state, "..." + cAlphaFields(18) + "=\"" + AlphArray(18) + "\" - valid values are \"Yes\" or \"No\".");
    2534           0 :                 ErrorsFound = true;
    2535             :             }
    2536             :         }
    2537             :     }
    2538             : 
    2539        1021 :     if (NumAlphas > 18) {
    2540         120 :         if (!lAlphaBlanks(19)) {
    2541         120 :             if (UtilityRoutines::SameString(AlphArray(19), "BypassWhenWithinEconomizerLimits")) {
    2542         103 :                 state.dataMixedAir->OAController(OutAirNum).HeatRecoveryBypassControlType = BypassWhenWithinEconomizerLimits;
    2543          17 :             } else if (UtilityRoutines::SameString(AlphArray(19), "BypassWhenOAFlowGreaterThanMinimum")) {
    2544          17 :                 state.dataMixedAir->OAController(OutAirNum).HeatRecoveryBypassControlType = BypassWhenOAFlowGreaterThanMinimum;
    2545             :             } else {
    2546           0 :                 ShowWarningError(state,
    2547           0 :                                  CurrentModuleObject + "=\"" + AlphArray(1) + "\" invalid " + cAlphaFields(19) + "=\"" + AlphArray(19) + "\".");
    2548           0 :                 ShowContinueError(state, "...assuming \"BypassWhenWithinEconomizerLimits\" and the simulation continues.");
    2549           0 :                 state.dataMixedAir->OAController(OutAirNum).HeatRecoveryBypassControlType = BypassWhenWithinEconomizerLimits;
    2550             :             }
    2551             :         }
    2552             :     }
    2553             : 
    2554        1021 :     if (UtilityRoutines::SameString(AlphArray(16), "Yes") && state.dataMixedAir->OAController(OutAirNum).Econo == EconoOp::NoEconomizer) {
    2555           0 :         ShowWarningError(
    2556           0 :             state, state.dataMixedAir->OAController(OutAirNum).ControllerType + " \"" + state.dataMixedAir->OAController(OutAirNum).Name + "\"");
    2557           0 :         ShowContinueError(state, "...Economizer operation must be enabled when " + cAlphaFields(16) + " is set to YES.");
    2558           0 :         ShowContinueError(state, "...The high humidity control option will be disabled and the simulation continues.");
    2559             :     }
    2560             : 
    2561        1021 :     state.dataMixedAir->OAController(OutAirNum).MixedAirSPMNum =
    2562        1021 :         GetMixedAirNumWithCoilFreezingCheck(state, state.dataMixedAir->OAController(OutAirNum).MixNode);
    2563        1021 : }
    2564             : 
    2565             : // End of Get Input subroutines for the Module
    2566             : //******************************************************************************
    2567             : 
    2568             : // Beginning Initialization Section of the Module
    2569             : //******************************************************************************
    2570             : 
    2571    24268600 : void InitOutsideAirSys(EnergyPlusData &state, int const(OASysNum), bool const FirstHVACIteration, int const AirLoopNum)
    2572             : {
    2573             : 
    2574             :     // SUBROUTINE INFORMATION:
    2575             :     //       AUTHOR         Fred Buhl
    2576             :     //       DATE WRITTEN   Oct 1998
    2577             :     //       MODIFIED       na
    2578             :     //       RE-ENGINEERED  na
    2579             : 
    2580             :     // PURPOSE OF THIS SUBROUTINE
    2581             :     // Initialize the OutsideAirSys data structure
    2582             : 
    2583             :     // METHODOLOGY EMPLOYED:
    2584             : 
    2585             :     // REFERENCES:
    2586             : 
    2587             :     // Using/Aliasing
    2588             :     using namespace DataLoopNode;
    2589             : 
    2590             :     // Locals
    2591             :     // SUBROUTINE ARGUMENT DEFINITIONS
    2592             : 
    2593             :     // SUBROUTINE PARAMETER DEFINITIONS:
    2594             : 
    2595             :     // INTERFACE BLOCK SPECIFICATIONS
    2596             :     // na
    2597             : 
    2598             :     // DERIVED TYPE DEFINITIONS
    2599             :     // na
    2600             : 
    2601             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2602             : 
    2603             :     //        if ( BeginEnvrnFlag && FirstHVACIteration ) {
    2604             :     //        }
    2605             : 
    2606             :     //        if ( BeginDayFlag ) {
    2607             :     //        }
    2608             : 
    2609    24268600 :     if (state.dataAirLoop->OutsideAirSys(OASysNum).AirLoopDOASNum > -1) return;
    2610             : 
    2611    24257718 :     if (state.dataMixedAir->initOASysFlag(OASysNum)) {
    2612        1021 :         state.dataAirLoop->AirLoopControlInfo(AirLoopNum).OASysNum = OASysNum;
    2613        1021 :         state.dataMixedAir->initOASysFlag(OASysNum) = false;
    2614             :     }
    2615             : 
    2616             :     // Each time step
    2617             :     if (FirstHVACIteration) {
    2618             :     }
    2619             : 
    2620             :     // Each iteration
    2621             : }
    2622             : 
    2623    24821703 : void InitOAController(EnergyPlusData &state, int const OAControllerNum, bool const FirstHVACIteration, int const AirLoopNum)
    2624             : {
    2625             : 
    2626             :     // SUBROUTINE INFORMATION:
    2627             :     //       AUTHOR         Fred Buhl
    2628             :     //       DATE WRITTEN   Oct 1998
    2629             :     //       MODIFIED       Shirey/Raustad FSEC, June/Aug 2003, Feb 2004
    2630             :     //                      Tianzhen Hong, Feb 2009 for DCV
    2631             :     //                      Tianzhen Hong, Aug 2013 for economizer faults
    2632             : 
    2633             :     // PURPOSE OF THIS SUBROUTINE
    2634             :     // Initialize the OAController data structure with input node data
    2635             : 
    2636             :     using namespace DataLoopNode;
    2637             :     using Psychrometrics::PsyRhoAirFnPbTdbW;
    2638             : 
    2639             :     using namespace OutputReportPredefined;
    2640             :     using EMSManager::CheckIfNodeSetPointManagedByEMS;
    2641             : 
    2642    24821703 :     auto &OAControllerMyOneTimeFlag = state.dataMixedAir->OAControllerMyOneTimeFlag; // One-time initialization flag
    2643    24821703 :     auto &OAControllerMyEnvrnFlag = state.dataMixedAir->OAControllerMyEnvrnFlag;     // One-time initialization flag
    2644    24821703 :     auto &OAControllerMySizeFlag = state.dataMixedAir->OAControllerMySizeFlag;       // One-time initialization flag
    2645    24821703 :     auto &MechVentCheckFlag = state.dataMixedAir->MechVentCheckFlag;                 // One-time initialization flag
    2646             :     bool FoundZone;               // Logical determines if ZONE object is accounted for in VENTILATION:MECHANICAL object
    2647             :     bool FoundAreaZone;           // Logical determines if ZONE object is accounted for in VENTILATION:MECHANICAL object
    2648             :     bool FoundPeopleZone;         // Logical determines if ZONE object is accounted for in VENTILATION:MECHANICAL object
    2649             :     bool OASysFound;              // Logical determines if OA system found
    2650             :     bool AirLoopFound;            // Logical determines if primary air loop found
    2651             :     bool ErrorsFound;             // Errors found getting input
    2652             :     Real64 RhoAirStdInit;         // Standard air density
    2653             :     Real64 TotalPeopleOAFlow;     // Total outside air required for PEOPLE objects served by this OA controller
    2654             :     int MixedAirNode;             // Controller:OutdoorAir mixed air node
    2655             :     int AirLoopZoneInfoZoneNum;   // Index to AirLoopZoneInfo structure
    2656             :     int NumZone;                  // Zone number in AirLoopZoneInfo structure
    2657             :     int PeopleNum;                // Index to PEOPLE objects
    2658             :     int NumMechVentZone;          // Index to number of zones in VentilationMechanical structure
    2659             :     int TempMechVentArrayCounter; // Temporary array counter
    2660             :     int thisOASys;                // Temporary array counter
    2661             :     int thisNumForMixer;          // Temporary array counter
    2662             :     int thisMixerIndex;           // Temporary array counter
    2663             :     int OASysNum;                 // Temporary array counter
    2664             :     int found;                    // Temporary index to equipment
    2665             :     int OANode;                   // OA node index
    2666             :     int VentMechObjectNum;        // Temporary variable
    2667             :     int OAControllerLoop;         // Index to OA controller in an OA system
    2668             :     int OAControllerLoop2;        // Index to OA controller in an OA system
    2669             :     int thisAirLoop;              // Temporary array counter
    2670             :     int BranchNum;                // Temporary array counter
    2671             :     int CompNum;                  // Temporary array counter
    2672    49643406 :     std::string equipName;        // Temporary equipment name
    2673    49643406 :     std::string airloopName;      // Temporary equipment name
    2674    49643406 :     std::string zoneName;
    2675             :     int jZone;
    2676             : 
    2677             :     Real64 rSchVal;
    2678             :     Real64 rOffset;
    2679             :     int i;
    2680             :     EconoOp iEco;
    2681             : 
    2682    24821703 :     ErrorsFound = false;
    2683    24821703 :     OANode = 0;
    2684             : 
    2685    24821703 :     auto &thisOAController(state.dataMixedAir->OAController(OAControllerNum));
    2686             : 
    2687    24821703 :     if (state.dataMixedAir->InitOAControllerOneTimeFlag) {
    2688         394 :         OAControllerMyOneTimeFlag.dimension(state.dataMixedAir->NumOAControllers, true);
    2689         394 :         OAControllerMyEnvrnFlag.dimension(state.dataMixedAir->NumOAControllers, true);
    2690         394 :         OAControllerMySizeFlag.dimension(state.dataMixedAir->NumOAControllers, true);
    2691         394 :         MechVentCheckFlag.dimension(state.dataMixedAir->NumOAControllers, true);
    2692         394 :         state.dataMixedAir->InitOAControllerSetPointCheckFlag.dimension(state.dataMixedAir->NumOAControllers, true);
    2693         394 :         state.dataMixedAir->InitOAControllerOneTimeFlag = false;
    2694             :     }
    2695    24821703 :     if (OAControllerMyOneTimeFlag(OAControllerNum)) {
    2696             :         // Determine Inlet node index for OAController, not a user input for controller, but is obtained from OutsideAirSys and OAMixer
    2697        1125 :         switch (thisOAController.ControllerType_Num) {
    2698        1021 :         case MixedAirControllerType::ControllerOutsideAir: {
    2699        1021 :             thisOASys = 0;
    2700        6280 :             for (OASysNum = 1; OASysNum <= state.dataAirLoop->NumOASystems; ++OASysNum) {
    2701             :                 // find which OAsys has this controller
    2702       12560 :                 found = UtilityRoutines::FindItemInList(thisOAController.Name,
    2703        6280 :                                                         state.dataAirLoop->OutsideAirSys(OASysNum).ControllerName,
    2704        6280 :                                                         isize(state.dataAirLoop->OutsideAirSys(OASysNum).ControllerName));
    2705        6280 :                 if (found != 0) {
    2706        1021 :                     thisOASys = OASysNum;
    2707        1021 :                     state.dataAirLoop->OutsideAirSys(thisOASys).OAControllerIndex = GetOAController(state, thisOAController.Name);
    2708        1021 :                     break; // we found it
    2709             :                 }
    2710             :             }
    2711        1021 :             if (thisOASys == 0) {
    2712           0 :                 ShowSevereError(state, "InitOAController: Did not find OAController=\"" + thisOAController.Name + "\".");
    2713           0 :                 ShowContinueError(state, "in list of valid OA Controllers.");
    2714           0 :                 ErrorsFound = true;
    2715             :             }
    2716        2042 :             thisNumForMixer = UtilityRoutines::FindItem(CurrentModuleObjects(static_cast<int>(CMO::OAMixer)),
    2717        1021 :                                                         state.dataAirLoop->OutsideAirSys(thisOASys).ComponentType,
    2718        1021 :                                                         isize(state.dataAirLoop->OutsideAirSys(thisOASys).ComponentType));
    2719        1021 :             if (thisNumForMixer != 0) {
    2720        1021 :                 equipName = state.dataAirLoop->OutsideAirSys(thisOASys).ComponentName(thisNumForMixer);
    2721        1021 :                 thisMixerIndex = UtilityRoutines::FindItemInList(equipName, state.dataMixedAir->OAMixer);
    2722        1021 :                 if (thisMixerIndex != 0) {
    2723        1021 :                     thisOAController.InletNode = state.dataMixedAir->OAMixer(thisMixerIndex).InletNode;
    2724             :                 } else {
    2725           0 :                     ShowSevereError(state, "InitOAController: Did not find OAMixer=\"" + equipName + "\".");
    2726           0 :                     ShowContinueError(state, "in list of valid OA Mixers.");
    2727           0 :                     ErrorsFound = true;
    2728             :                 }
    2729             :             } else {
    2730           0 :                 ShowSevereError(state, "InitOAController: Did not find OutdoorAir:Mixer Component=\"OutdoorAir:Mixer\".");
    2731           0 :                 ShowContinueError(state, "in list of valid OA Components.");
    2732           0 :                 ErrorsFound = true;
    2733             :             }
    2734             : 
    2735        1021 :             if (thisOAController.InletNode == 0) { // throw an error
    2736           0 :                 ShowSevereError(state,
    2737           0 :                                 "InitOAController: Failed to find proper inlet node for OutdoorAir:Mixer and Controller = " + thisOAController.Name);
    2738           0 :                 ErrorsFound = true;
    2739             :             }
    2740        1021 :         } break;
    2741         104 :         case MixedAirControllerType::ControllerStandAloneERV: {
    2742             :             // set the inlet node to also equal the OA node because this is a special controller for economizing stand alone ERV
    2743             :             // with the assumption that equipment is bypassed....
    2744         104 :             thisOAController.InletNode = thisOAController.OANode;
    2745         104 :         } break;
    2746           0 :         default: {
    2747           0 :             ShowSevereError(state, "InitOAController: Failed to find ControllerType: " + thisOAController.ControllerType);
    2748           0 :             ErrorsFound = true;
    2749           0 :         } break;
    2750             :         }
    2751             : 
    2752        1125 :         OAControllerMyOneTimeFlag(OAControllerNum) = false;
    2753             :     }
    2754             : 
    2755    74474805 :     if (!state.dataGlobal->SysSizingCalc && state.dataMixedAir->InitOAControllerSetPointCheckFlag(OAControllerNum) &&
    2756    24835411 :         state.dataHVACGlobal->DoSetPointTest && !FirstHVACIteration) {
    2757        1125 :         MixedAirNode = thisOAController.MixNode;
    2758        1125 :         if (MixedAirNode > 0) {
    2759             :             //      IF (OAController(OAControllerNum)%Econo == 1 .AND. .NOT. AirLoopControlInfo(AirLoopNum)%CyclingFan) THEN
    2760        1021 :             if (thisOAController.Econo > EconoOp::NoEconomizer && state.dataAirLoop->AirLoopControlInfo(AirLoopNum).AnyContFan) {
    2761         480 :                 if (state.dataLoopNodes->Node(MixedAirNode).TempSetPoint == SensedNodeFlagValue) {
    2762          16 :                     if (!state.dataGlobal->AnyEnergyManagementSystemInModel) {
    2763           0 :                         ShowSevereError(state, "MixedAir: Missing temperature setpoint for economizer controller " + thisOAController.Name);
    2764           0 :                         ShowSevereError(state, "Node Referenced (by Controller)=" + state.dataLoopNodes->NodeID(MixedAirNode));
    2765           0 :                         ShowContinueError(
    2766             :                             state, "  use a Setpoint Manager with Control Variable = \"Temperature\" to establish a setpoint at the mixed air node.");
    2767           0 :                         state.dataHVACGlobal->SetPointErrorFlag = true;
    2768             :                     } else {
    2769             :                         // add call to check node in EMS
    2770          16 :                         CheckIfNodeSetPointManagedByEMS(
    2771          16 :                             state, MixedAirNode, EMSManager::SPControlType::TemperatureSetPoint, state.dataHVACGlobal->SetPointErrorFlag);
    2772          16 :                         if (state.dataHVACGlobal->SetPointErrorFlag) {
    2773           0 :                             ShowSevereError(state, "MixedAir: Missing temperature setpoint for economizer controller " + thisOAController.Name);
    2774           0 :                             ShowSevereError(state, "Node Referenced (by Controller)=" + state.dataLoopNodes->NodeID(MixedAirNode));
    2775           0 :                             ShowContinueError(state,
    2776             :                                               "  use a Setpoint Manager with Control Variable = \"Temperature\" to establish a setpoint at the "
    2777             :                                               "mixed air node.");
    2778           0 :                             ShowContinueError(state, "Or add EMS Actuator to provide temperature setpoint at this node");
    2779             :                         }
    2780             :                     }
    2781             :                 }
    2782             :             }
    2783             :         }
    2784             : 
    2785        1125 :         state.dataMixedAir->InitOAControllerSetPointCheckFlag(OAControllerNum) = false;
    2786             :     }
    2787             : 
    2788    24821703 :     if (!state.dataGlobal->SysSizingCalc && OAControllerMySizeFlag(OAControllerNum)) {
    2789        1125 :         thisOAController.SizeOAController(state);
    2790        1125 :         if (AirLoopNum > 0) {
    2791        1021 :             state.dataAirLoop->AirLoopControlInfo(AirLoopNum).OACtrlNum = OAControllerNum;
    2792        1021 :             state.dataAirLoop->AirLoopControlInfo(AirLoopNum).OACtrlName = thisOAController.Name;
    2793        1021 :             if (thisOAController.Lockout == LockoutType::LockoutWithHeatingPossible) {
    2794         196 :                 state.dataAirLoop->AirLoopControlInfo(AirLoopNum).CanLockoutEconoWithHeating = true;
    2795         196 :                 state.dataAirLoop->AirLoopControlInfo(AirLoopNum).CanLockoutEconoWithCompressor = false;
    2796         196 :                 state.dataAirLoop->AirLoopControlInfo(AirLoopNum).CanNotLockoutEcono = false;
    2797         825 :             } else if (thisOAController.Lockout == LockoutType::LockoutWithCompressorPossible) {
    2798          41 :                 state.dataAirLoop->AirLoopControlInfo(AirLoopNum).CanLockoutEconoWithHeating = false;
    2799          41 :                 state.dataAirLoop->AirLoopControlInfo(AirLoopNum).CanLockoutEconoWithCompressor = true;
    2800          41 :                 state.dataAirLoop->AirLoopControlInfo(AirLoopNum).CanNotLockoutEcono = false;
    2801             :             } else {
    2802         784 :                 state.dataAirLoop->AirLoopControlInfo(AirLoopNum).CanLockoutEconoWithHeating = false;
    2803         784 :                 state.dataAirLoop->AirLoopControlInfo(AirLoopNum).CanLockoutEconoWithCompressor = false;
    2804         784 :                 state.dataAirLoop->AirLoopControlInfo(AirLoopNum).CanNotLockoutEcono = true;
    2805             :             }
    2806             :         }
    2807        1125 :         if ((thisOAController.MaxOA - thisOAController.MinOA) < -SmallAirVolFlow) {
    2808           0 :             ShowSevereError(state, "For Controller:OutdoorAir: " + thisOAController.Name);
    2809           0 :             ShowContinueError(state,
    2810           0 :                               format("  maximum outdoor air flow rate ({:.4R}) < minimum outdoor air flow rate ({:.4R})",
    2811             :                                      thisOAController.MaxOA,
    2812           0 :                                      thisOAController.MinOA));
    2813           0 :             ShowContinueError(state,
    2814             :                               "  To set the minimum outside air flow rate use the \"Design (minimum) outdoor air flow rate\" field in the "
    2815             :                               "Sizing:System object");
    2816           0 :             ErrorsFound = true;
    2817             :         }
    2818             : 
    2819        1125 :         if (AirLoopNum > 0) {
    2820        1021 :             Real64 DesSupplyVolFlowRate = state.dataAirLoop->AirLoopFlow(AirLoopNum).DesSupply / state.dataEnvrn->StdRhoAir;
    2821        1021 :             if ((thisOAController.MinOA - DesSupplyVolFlowRate) > 0.0001) {
    2822           0 :                 ShowWarningError(state,
    2823           0 :                                  "InitOAController: Minimum Outdoor Air Flow Rate for Controller:OutdoorAir=" + thisOAController.Name +
    2824           0 :                                      " is greater than Design Supply Air Flow Rate for AirLoopHVAC=" +
    2825           0 :                                      state.dataAirSystemsData->PrimaryAirSystems(AirLoopNum).Name + ".");
    2826           0 :                 ShowContinueError(state,
    2827           0 :                                   format("...Minimum Outdoor Air Flow Rate={:.6R} will be reset to loop Design Supply Air Flow Rate={:.6R}",
    2828             :                                          thisOAController.MinOA,
    2829           0 :                                          DesSupplyVolFlowRate));
    2830           0 :                 thisOAController.MinOA = DesSupplyVolFlowRate;
    2831        1021 :             } else if ((thisOAController.MinOA - DesSupplyVolFlowRate) > 0.0) {
    2832             :                 // If difference is tiny, reset silently
    2833           0 :                 thisOAController.MinOA = DesSupplyVolFlowRate;
    2834             :             }
    2835        1021 :             if ((thisOAController.MaxOA - DesSupplyVolFlowRate) > 0.0001) {
    2836           0 :                 ShowWarningError(state,
    2837           0 :                                  "InitOAController: Maximum Outdoor Air Flow Rate for Controller:OutdoorAir=" + thisOAController.Name +
    2838           0 :                                      " is greater than Design Supply Air Flow Rate for AirLoopHVAC=" +
    2839           0 :                                      state.dataAirSystemsData->PrimaryAirSystems(AirLoopNum).Name + ".");
    2840           0 :                 ShowContinueError(state,
    2841           0 :                                   format("...Maximum Outdoor Air Flow Rate={:.6R} will be reset to loop Design Supply Air Flow Rate={:.6R}",
    2842             :                                          thisOAController.MaxOA,
    2843           0 :                                          DesSupplyVolFlowRate));
    2844           0 :                 thisOAController.MaxOA = DesSupplyVolFlowRate;
    2845        1021 :             } else if ((thisOAController.MaxOA - DesSupplyVolFlowRate) > 0.0) {
    2846             :                 // If difference is tiny, reset silently
    2847           9 :                 thisOAController.MaxOA = DesSupplyVolFlowRate;
    2848             :             }
    2849             : 
    2850             :             // Check if system has a Sizing:System object and a sizing run has been done
    2851        1021 :             bool SizingDesRunThisAirSys = false;
    2852        1021 :             CheckThisAirSystemForSizing(state, AirLoopNum, SizingDesRunThisAirSys);
    2853             : 
    2854             :             // Get design outdoor air flow rate
    2855        1021 :             if (SizingDesRunThisAirSys && thisOAController.VentMechObjectNum > 0) {
    2856          46 :                 state.dataMixedAir->VentilationMechanical(thisOAController.VentMechObjectNum).SysDesOA =
    2857          46 :                     state.dataSize->FinalSysSizing(AirLoopNum).DesOutAirVolFlow;
    2858             :             }
    2859             :         }
    2860             : 
    2861        1125 :         OAControllerMySizeFlag(OAControllerNum) = false;
    2862             :     }
    2863             : 
    2864    24821703 :     if (state.dataGlobal->BeginEnvrnFlag && OAControllerMyEnvrnFlag(OAControllerNum)) {
    2865        7204 :         OANode = thisOAController.OANode;
    2866        7204 :         RhoAirStdInit = state.dataEnvrn->StdRhoAir;
    2867        7204 :         thisOAController.MinOAMassFlowRate = thisOAController.MinOA * RhoAirStdInit;
    2868        7204 :         thisOAController.MaxOAMassFlowRate = thisOAController.MaxOA * RhoAirStdInit;
    2869        7204 :         OAControllerMyEnvrnFlag(OAControllerNum) = false;
    2870        7204 :         state.dataLoopNodes->Node(OANode).MassFlowRateMax = thisOAController.MaxOAMassFlowRate;
    2871             : 
    2872             :         // predefined reporting
    2873        7204 :         if (thisOAController.Econo > EconoOp::NoEconomizer) {
    2874        3517 :             equipName = thisOAController.Name;
    2875             :             // 90.1 descriptor for economizer controls
    2876             :             // Changed by Amit for New Feature implementation
    2877        3517 :             if (thisOAController.Econo == EconoOp::DifferentialEnthalpy) {
    2878         118 :                 PreDefTableEntry(state, state.dataOutRptPredefined->pdchEcoKind, equipName, "DifferentialEnthalpy");
    2879        3399 :             } else if (thisOAController.Econo == EconoOp::DifferentialDryBulb) {
    2880        2612 :                 PreDefTableEntry(state, state.dataOutRptPredefined->pdchEcoKind, equipName, "DifferentialDryBulb");
    2881         787 :             } else if (thisOAController.Econo == EconoOp::FixedEnthalpy) {
    2882           0 :                 PreDefTableEntry(state, state.dataOutRptPredefined->pdchEcoKind, equipName, "FixedEnthalpy");
    2883         787 :             } else if (thisOAController.Econo == EconoOp::FixedDryBulb) {
    2884         740 :                 PreDefTableEntry(state, state.dataOutRptPredefined->pdchEcoKind, equipName, "FixedDryBulb");
    2885             :             } else {
    2886          47 :                 PreDefTableEntry(state, state.dataOutRptPredefined->pdchEcoKind, equipName, "Other");
    2887             :             }
    2888             : 
    2889        3517 :             PreDefTableEntry(state, state.dataOutRptPredefined->pdchEcoMinOA, equipName, thisOAController.MinOA);
    2890        3517 :             PreDefTableEntry(state, state.dataOutRptPredefined->pdchEcoMaxOA, equipName, thisOAController.MaxOA);
    2891             :             // EnergyPlus input echos for economizer controls
    2892             :             // Chnged by Amit for new feature implementation
    2893        3517 :             if (thisOAController.Econo == EconoOp::DifferentialDryBulb) {
    2894        2612 :                 PreDefTableEntry(state, state.dataOutRptPredefined->pdchEcoRetTemp, equipName, "Yes");
    2895             :             } else {
    2896         905 :                 PreDefTableEntry(state, state.dataOutRptPredefined->pdchEcoRetTemp, equipName, "No");
    2897             :             }
    2898        3517 :             if (thisOAController.Econo == EconoOp::DifferentialEnthalpy) {
    2899         118 :                 PreDefTableEntry(state, state.dataOutRptPredefined->pdchEcoRetTemp, equipName, "Yes");
    2900             :             } else {
    2901        3399 :                 PreDefTableEntry(state, state.dataOutRptPredefined->pdchEcoRetTemp, equipName, "No");
    2902             :             }
    2903        3517 :             if (thisOAController.Econo == EconoOp::FixedDryBulb) {
    2904         740 :                 PreDefTableEntry(state, state.dataOutRptPredefined->pdchEcoRetTemp, equipName, thisOAController.TempLim);
    2905             :             } else {
    2906        2777 :                 PreDefTableEntry(state, state.dataOutRptPredefined->pdchEcoRetTemp, equipName, "-");
    2907             :             }
    2908        3517 :             if (thisOAController.Econo == EconoOp::FixedEnthalpy) {
    2909           0 :                 PreDefTableEntry(state, state.dataOutRptPredefined->pdchEcoRetTemp, equipName, thisOAController.EnthLim);
    2910             :             } else {
    2911        3517 :                 PreDefTableEntry(state, state.dataOutRptPredefined->pdchEcoRetTemp, equipName, "-");
    2912             :             }
    2913             :         }
    2914             :     }
    2915             : 
    2916    24821703 :     if (!state.dataGlobal->BeginEnvrnFlag) {
    2917    24740261 :         OAControllerMyEnvrnFlag(OAControllerNum) = true;
    2918             :     }
    2919             : 
    2920    24821703 :     VentMechObjectNum = thisOAController.VentMechObjectNum;
    2921    24821703 :     if (MechVentCheckFlag(OAControllerNum)) {
    2922             :         // Make these checks only once at the beginning of the simulation
    2923             : 
    2924             :         // Make sure all air loop zones and air loop zones with people objects are covered by mechanical ventilation
    2925             :         // Issue a warning only if the zone is not accounted for in the associated mechanical ventilation object
    2926        1125 :         if (VentMechObjectNum > 0) {
    2927          52 :             auto &vent_mech(state.dataMixedAir->VentilationMechanical(VentMechObjectNum));
    2928             : 
    2929             :             // Make sure all zones with mechanical ventilation are on the correct air loop
    2930          52 :             TempMechVentArrayCounter = 0;
    2931         399 :             for (NumMechVentZone = 1; NumMechVentZone <= vent_mech.NumofVentMechZones; ++NumMechVentZone) {
    2932         347 :                 int ZoneNum = vent_mech.VentMechZone(NumMechVentZone);
    2933         347 :                 auto const &zone(state.dataHeatBal->Zone(ZoneNum));
    2934         347 :                 FoundZone = false;
    2935             : 
    2936        3200 :                 for (AirLoopZoneInfoZoneNum = 1; AirLoopZoneInfoZoneNum <= state.dataAirLoop->AirLoopZoneInfo(AirLoopNum).NumZones;
    2937             :                      ++AirLoopZoneInfoZoneNum) {
    2938        3200 :                     NumZone = state.dataAirLoop->AirLoopZoneInfo(AirLoopNum).ActualZoneNumber(AirLoopZoneInfoZoneNum);
    2939        3200 :                     if (ZoneNum == NumZone) {
    2940         347 :                         FoundZone = true;
    2941         347 :                         ++TempMechVentArrayCounter;
    2942         347 :                         if (TempMechVentArrayCounter < NumMechVentZone) { // Copy to lower index
    2943           0 :                             vent_mech.VentMechZone(TempMechVentArrayCounter) = vent_mech.VentMechZone(NumMechVentZone);
    2944           0 :                             vent_mech.ZoneOAAreaRate(TempMechVentArrayCounter) = vent_mech.ZoneOAAreaRate(NumMechVentZone);
    2945           0 :                             vent_mech.ZoneOAPeopleRate(TempMechVentArrayCounter) = vent_mech.ZoneOAPeopleRate(NumMechVentZone);
    2946           0 :                             vent_mech.ZoneOAFlowRate(TempMechVentArrayCounter) = vent_mech.ZoneOAFlowRate(NumMechVentZone);
    2947           0 :                             vent_mech.ZoneOAACHRate(TempMechVentArrayCounter) = vent_mech.ZoneOAACHRate(NumMechVentZone);
    2948           0 :                             vent_mech.ZoneOAFlowMethod(TempMechVentArrayCounter) = vent_mech.ZoneOAFlowMethod(NumMechVentZone);
    2949           0 :                             vent_mech.ZoneOASchPtr(TempMechVentArrayCounter) = vent_mech.ZoneOASchPtr(NumMechVentZone);
    2950           0 :                             vent_mech.ZoneDesignSpecOAObjIndex(TempMechVentArrayCounter) = vent_mech.ZoneDesignSpecOAObjIndex(NumMechVentZone);
    2951           0 :                             vent_mech.ZoneDesignSpecOAObjName(TempMechVentArrayCounter) = vent_mech.ZoneDesignSpecOAObjName(NumMechVentZone);
    2952             : 
    2953             :                             // new DCV
    2954           0 :                             vent_mech.ZoneADEffCooling(TempMechVentArrayCounter) = vent_mech.ZoneADEffCooling(NumMechVentZone);
    2955           0 :                             vent_mech.ZoneADEffHeating(TempMechVentArrayCounter) = vent_mech.ZoneADEffHeating(NumMechVentZone);
    2956           0 :                             vent_mech.ZoneADEffSchPtr(TempMechVentArrayCounter) = vent_mech.ZoneADEffSchPtr(NumMechVentZone);
    2957             :                         }
    2958             : 
    2959             :                         // Sum outside air per unit floor area for each mechanical ventilation object only once per simulation
    2960         347 :                         vent_mech.TotAreaOAFlow += zone.FloorArea * zone.Multiplier * zone.ListMultiplier * vent_mech.ZoneOAAreaRate(NumMechVentZone);
    2961         347 :                         vent_mech.TotZoneOAFlow += zone.Multiplier * zone.ListMultiplier * vent_mech.ZoneOAFlowRate(NumMechVentZone);
    2962         347 :                         vent_mech.TotZoneOAACH +=
    2963         347 :                             zone.Multiplier * zone.ListMultiplier * (vent_mech.ZoneOAACHRate(NumMechVentZone) * zone.Volume / 3600.0);
    2964         347 :                         break;
    2965             :                     }
    2966             :                 }
    2967         347 :                 if (!FoundZone) {
    2968           0 :                     ShowWarningError(state,
    2969           0 :                                      "Zone name = " + zone.Name + " in " + CurrentModuleObjects(static_cast<int>(CMO::MechVentilation)) +
    2970           0 :                                          " object name = " + thisOAController.VentilationMechanicalName +
    2971           0 :                                          " is not on the same air loop as Controller:OutdoorAir = " + thisOAController.Name);
    2972           0 :                     ShowContinueError(state, "This zone will not be used and the simulation will continue...");
    2973             :                 }
    2974             :             }
    2975             : 
    2976             :             // Shrink final arrays to conserve environment space
    2977          52 :             if (TempMechVentArrayCounter < vent_mech.NumofVentMechZones) {
    2978           0 :                 vent_mech.VentMechZone.redimension(TempMechVentArrayCounter);
    2979           0 :                 vent_mech.ZoneOAAreaRate.redimension(TempMechVentArrayCounter);
    2980           0 :                 vent_mech.ZoneOAPeopleRate.redimension(TempMechVentArrayCounter);
    2981           0 :                 vent_mech.ZoneOAFlowRate.redimension(TempMechVentArrayCounter);
    2982           0 :                 vent_mech.ZoneOAACHRate.redimension(TempMechVentArrayCounter);
    2983           0 :                 vent_mech.ZoneOAFlowMethod.redimension(TempMechVentArrayCounter);
    2984           0 :                 vent_mech.ZoneOASchPtr.redimension(TempMechVentArrayCounter);
    2985           0 :                 vent_mech.ZoneDesignSpecOAObjIndex.redimension(TempMechVentArrayCounter);
    2986           0 :                 vent_mech.ZoneDesignSpecOAObjName.redimension(TempMechVentArrayCounter);
    2987             : 
    2988           0 :                 vent_mech.ZoneADEffCooling.redimension(TempMechVentArrayCounter);
    2989           0 :                 vent_mech.ZoneADEffHeating.redimension(TempMechVentArrayCounter);
    2990           0 :                 vent_mech.ZoneADEffSchPtr.redimension(TempMechVentArrayCounter);
    2991             : 
    2992           0 :                 vent_mech.NumofVentMechZones = TempMechVentArrayCounter;
    2993             :             }
    2994             : 
    2995             :             // predefined report
    2996         399 :             for (jZone = 1; jZone <= vent_mech.NumofVentMechZones; ++jZone) {
    2997         347 :                 zoneName = state.dataHeatBal->Zone(vent_mech.VentMechZone(jZone)).Name;
    2998         347 :                 PreDefTableEntry(state, state.dataOutRptPredefined->pdchDCVventMechName, zoneName, vent_mech.Name);
    2999         347 :                 PreDefTableEntry(state, state.dataOutRptPredefined->pdchDCVperPerson, zoneName, vent_mech.ZoneOAPeopleRate(jZone), 6);
    3000         347 :                 PreDefTableEntry(state, state.dataOutRptPredefined->pdchDCVperArea, zoneName, vent_mech.ZoneOAAreaRate(jZone), 6);
    3001         347 :                 PreDefTableEntry(state, state.dataOutRptPredefined->pdchDCVperZone, zoneName, vent_mech.ZoneOAFlowRate(jZone), 6);
    3002         347 :                 PreDefTableEntry(state, state.dataOutRptPredefined->pdchDCVperACH, zoneName, vent_mech.ZoneOAACHRate(jZone), 6);
    3003         694 :                 PreDefTableEntry(state,
    3004         347 :                                  state.dataOutRptPredefined->pdchDCVMethod,
    3005             :                                  zoneName,
    3006         347 :                                  OAFlowCalcMethodNames[static_cast<int>(vent_mech.ZoneOAFlowMethod(jZone))]);
    3007         347 :                 if (vent_mech.ZoneOASchPtr(jZone) > 0) {
    3008           2 :                     PreDefTableEntry(
    3009           3 :                         state, state.dataOutRptPredefined->pdchDCVOASchName, zoneName, GetScheduleName(state, vent_mech.ZoneOASchPtr(jZone)));
    3010             :                 } else {
    3011         346 :                     PreDefTableEntry(state, state.dataOutRptPredefined->pdchDCVOASchName, zoneName, "");
    3012             :                 }
    3013             : 
    3014             :                 // added for new DCV inputs
    3015         347 :                 if (vent_mech.ZoneADEffSchPtr(jZone) > 0) {
    3016           5 :                     PreDefTableEntry(state, state.dataOutRptPredefined->pdchDCVZoneADEffCooling, zoneName, "");
    3017           5 :                     PreDefTableEntry(state, state.dataOutRptPredefined->pdchDCVZoneADEffHeating, zoneName, "");
    3018          10 :                     PreDefTableEntry(state,
    3019           5 :                                      state.dataOutRptPredefined->pdchDCVZoneADEffSchName,
    3020             :                                      zoneName,
    3021          10 :                                      GetScheduleName(state, vent_mech.ZoneADEffSchPtr(jZone)));
    3022             :                 } else {
    3023         342 :                     PreDefTableEntry(state, state.dataOutRptPredefined->pdchDCVZoneADEffCooling, zoneName, vent_mech.ZoneADEffCooling(jZone), 2);
    3024         342 :                     PreDefTableEntry(state, state.dataOutRptPredefined->pdchDCVZoneADEffHeating, zoneName, vent_mech.ZoneADEffHeating(jZone), 2);
    3025         342 :                     PreDefTableEntry(state, state.dataOutRptPredefined->pdchDCVZoneADEffSchName, zoneName, "");
    3026             :                 }
    3027             :             }
    3028             : 
    3029             :             // Check to see if any zones on an air loop are not accounted for by a mechanical ventilation object
    3030         399 :             for (AirLoopZoneInfoZoneNum = 1; AirLoopZoneInfoZoneNum <= state.dataAirLoop->AirLoopZoneInfo(AirLoopNum).NumZones;
    3031             :                  ++AirLoopZoneInfoZoneNum) {
    3032         347 :                 NumZone = state.dataAirLoop->AirLoopZoneInfo(AirLoopNum).ActualZoneNumber(AirLoopZoneInfoZoneNum);
    3033         347 :                 FoundAreaZone = false;
    3034         347 :                 FoundPeopleZone = false;
    3035        3200 :                 for (NumMechVentZone = 1; NumMechVentZone <= vent_mech.NumofVentMechZones; ++NumMechVentZone) {
    3036        3200 :                     int ZoneNum = vent_mech.VentMechZone(NumMechVentZone);
    3037        3200 :                     if (ZoneNum == NumZone) {
    3038         347 :                         FoundAreaZone = true;
    3039         347 :                         if (vent_mech.ZoneOAPeopleRate(NumMechVentZone) > 0.0) {
    3040         336 :                             FoundPeopleZone = true;
    3041             :                         }
    3042         347 :                         break;
    3043             :                     }
    3044             :                 }
    3045         347 :                 if (!FoundAreaZone) {
    3046           0 :                     ShowWarningError(state,
    3047           0 :                                      "Zone name = " + state.dataHeatBal->Zone(NumZone).Name + " is not accounted for by " +
    3048           0 :                                          CurrentModuleObjects(static_cast<int>(CMO::MechVentilation)) +
    3049           0 :                                          " object name = " + thisOAController.VentilationMechanicalName);
    3050           0 :                     ShowContinueError(state, "Ventilation per unit floor area has not been specified for this zone, which is connected to");
    3051           0 :                     ShowContinueError(state,
    3052           0 :                                       "the air loop served by Controller:OutdoorAir = " + thisOAController.Name + ". Simulation will continue...");
    3053             :                 }
    3054         347 :                 if (!FoundPeopleZone) {
    3055             :                     // Loop through people objects to see if this zone has a people object and only then show a warning
    3056         257 :                     for (PeopleNum = 1; PeopleNum <= state.dataHeatBal->TotPeople; ++PeopleNum) {
    3057         246 :                         if (state.dataHeatBal->People(PeopleNum).ZonePtr == NumZone) {
    3058           7 :                             if (!FoundAreaZone) {
    3059           0 :                                 ShowWarningError(state,
    3060           0 :                                                  "PEOPLE object for zone = " + state.dataHeatBal->Zone(NumZone).Name + " is not accounted for by " +
    3061           0 :                                                      CurrentModuleObjects(static_cast<int>(CMO::MechVentilation)) +
    3062           0 :                                                      " object name = " + thisOAController.VentilationMechanicalName);
    3063           0 :                                 ShowContinueError(state,
    3064           0 :                                                   "A \"PEOPLE\" object has been specified in the idf for this zone, but it is not included in this " +
    3065           0 :                                                       CurrentModuleObjects(static_cast<int>(CMO::MechVentilation)) + " Object.");
    3066           0 :                                 ShowContinueError(state,
    3067           0 :                                                   "Check " + CurrentModuleObjects(static_cast<int>(CMO::MechVentilation)) +
    3068             :                                                       " object. Simulation will continue.");
    3069             :                             }
    3070             :                         }
    3071             :                     }
    3072             :                 } else { // People > 0, check to make sure there is a people statement in the zone
    3073         336 :                     FoundAreaZone = false;
    3074        7247 :                     for (PeopleNum = 1; PeopleNum <= state.dataHeatBal->TotPeople; ++PeopleNum) {
    3075        7203 :                         if (state.dataHeatBal->People(PeopleNum).ZonePtr != NumZone) continue;
    3076         292 :                         FoundAreaZone = true;
    3077         292 :                         break;
    3078             :                     }
    3079         336 :                     if (!FoundAreaZone) {
    3080         132 :                         ShowWarningError(state,
    3081          88 :                                          CurrentModuleObjects(static_cast<int>(CMO::MechVentilation)) + " = \"" +
    3082         132 :                                              thisOAController.VentilationMechanicalName + "\", Zone=\"" + state.dataHeatBal->Zone(NumZone).Name +
    3083             :                                              "\".");
    3084          44 :                         ShowContinueError(state,
    3085             :                                           "No \"PEOPLE\" object has been specified in the idf for this zone, but the ventilation rate is > 0 in "
    3086             :                                           "this Controller:MechanicalVentilation Object.");
    3087          44 :                         ShowContinueError(state, "Check ventilation rate in Controller:MechanicalVentilation object.  Simulation will continue.");
    3088             :                     }
    3089             :                 }
    3090             :             }
    3091             :         }
    3092             : 
    3093        1125 :         MechVentCheckFlag(OAControllerNum) = false;
    3094             :     }
    3095             :     //****
    3096             : 
    3097             :     // Perform a one time initialization of AirloopHVAC OA System report variables
    3098             :     // If AirloopHVAC objects are used, NumPrimaryAirSys > 0 and the initialization proceeds and then sets
    3099             :     // SetUpAirLoopHVACVariables to .FALSE. so this is never done again and only the first IF is checked
    3100             :     // each time through Init. If for some reason the primary air system have not yet been read in, this
    3101             :     // code waits for the air loop data to be available before performing the report variable initialization.
    3102             :     // If AirloopHVAC objects are not used, NumPrimaryAirSys is always equal to 0 and only these
    3103             :     // two IF statements are checked each time through Init (e.g., if StandAloneERV controllers are used
    3104             :     // without AirloopHVAC objects).
    3105    24821703 :     if (state.dataMixedAir->InitOAControllerSetUpAirLoopHVACVariables) {
    3106        7771 :         if (AirLoopNum > 0) {
    3107             :             // Added code to report (TH, 10/20/2008):
    3108             :             //   air economizer status (1 = on, 0 = off or does not exist), and
    3109             :             //   actual and minimum outside air fraction (0 to 1)
    3110        1516 :             for (OAControllerLoop = 1; OAControllerLoop <= state.dataMixedAir->NumOAControllers; ++OAControllerLoop) {
    3111        1123 :                 auto &loopOAController(state.dataMixedAir->OAController(OAControllerLoop));
    3112             : 
    3113             :                 // Find the outside air system that has the OA controller
    3114        1123 :                 if (loopOAController.ControllerType_Num == MixedAirControllerType::ControllerStandAloneERV) continue; // ERV controller not on airloop
    3115        1021 :                 OASysFound = false;
    3116        1021 :                 thisOASys = 0;
    3117        6280 :                 for (OASysNum = 1; OASysNum <= state.dataAirLoop->NumOASystems; ++OASysNum) {
    3118       11541 :                     for (OAControllerLoop2 = 1; OAControllerLoop2 <= state.dataAirLoop->OutsideAirSys(OASysNum).NumControllers; ++OAControllerLoop2) {
    3119        6282 :                         if (UtilityRoutines::SameString(state.dataAirLoop->OutsideAirSys(OASysNum).ControllerName(OAControllerLoop2),
    3120             :                                                         loopOAController.Name)) {
    3121        1021 :                             thisOASys = OASysNum;
    3122        1021 :                             OASysFound = true;
    3123        1021 :                             break;
    3124             :                         }
    3125             :                     }
    3126        6280 :                     if (OASysFound) break;
    3127             :                 }
    3128             : 
    3129        1021 :                 if (thisOASys <= 0) {
    3130             :                     // Check outside air system name
    3131           0 :                     ShowWarningError(state, "Cannot find the AirLoopHVAC:OutdoorAirSystem for the OA Controller: " + thisOAController.Name);
    3132           0 :                     AirLoopFound = false;
    3133             :                 } else {
    3134             :                     // Find the primary air loop that has the outside air system
    3135        1021 :                     AirLoopFound = false;
    3136        6280 :                     for (thisAirLoop = 1; thisAirLoop <= state.dataHVACGlobal->NumPrimaryAirSys; ++thisAirLoop) {
    3137       11542 :                         for (BranchNum = 1; BranchNum <= state.dataAirSystemsData->PrimaryAirSystems(thisAirLoop).NumBranches; ++BranchNum) {
    3138       19084 :                             for (CompNum = 1; CompNum <= state.dataAirSystemsData->PrimaryAirSystems(thisAirLoop).Branch(BranchNum).TotalComponents;
    3139             :                                  ++CompNum) {
    3140       41466 :                                 if (!UtilityRoutines::SameString(
    3141       13822 :                                         state.dataAirSystemsData->PrimaryAirSystems(thisAirLoop).Branch(BranchNum).Comp(CompNum).Name,
    3142       28665 :                                         state.dataAirLoop->OutsideAirSys(thisOASys).Name) ||
    3143       14843 :                                     !UtilityRoutines::SameString(
    3144        1021 :                                         state.dataAirSystemsData->PrimaryAirSystems(thisAirLoop).Branch(BranchNum).Comp(CompNum).TypeOf,
    3145        1021 :                                         "AirLoopHVAC:OutdoorAirSystem"))
    3146       12801 :                                     continue;
    3147        1021 :                                 AirLoopFound = true;
    3148        1021 :                                 break;
    3149             :                             }
    3150        6283 :                             if (AirLoopFound) break;
    3151             :                         }
    3152        6280 :                         if (AirLoopFound) break;
    3153             :                     }
    3154             :                 }
    3155             :                 // Check primary air loop name
    3156        1021 :                 if (AirLoopFound && thisAirLoop > 0) {
    3157        1021 :                     airloopName = state.dataAirSystemsData->PrimaryAirSystems(thisAirLoop).Name; // OutsideAirSys(OASysIndex)%Name
    3158             :                 } else {
    3159           0 :                     ShowWarningError(state, "Cannot find the primary air loop for the OA Controller: " + thisOAController.Name);
    3160           0 :                     airloopName = "AirLoop not found";
    3161             :                 }
    3162             : 
    3163             :                 //    Note use of OAControllerLoop here to keep DO Loop index separate from InitOAController local variable
    3164             :                 // CurrentModuleObject='AirLoopHVAC'
    3165        2042 :                 SetupOutputVariable(state,
    3166             :                                     "Air System Outdoor Air Economizer Status",
    3167             :                                     OutputProcessor::Unit::None,
    3168             :                                     loopOAController.EconomizerStatus,
    3169             :                                     OutputProcessor::SOVTimeStepType::System,
    3170             :                                     OutputProcessor::SOVStoreType::Average,
    3171        1021 :                                     airloopName);
    3172             : 
    3173        2042 :                 SetupOutputVariable(state,
    3174             :                                     "Air System Outdoor Air Heat Recovery Bypass Status",
    3175             :                                     OutputProcessor::Unit::None,
    3176             :                                     loopOAController.HeatRecoveryBypassStatus,
    3177             :                                     OutputProcessor::SOVTimeStepType::System,
    3178             :                                     OutputProcessor::SOVStoreType::Average,
    3179        1021 :                                     airloopName);
    3180             : 
    3181        2042 :                 SetupOutputVariable(state,
    3182             :                                     "Air System Outdoor Air Heat Recovery Bypass Heating Coil Activity Status",
    3183             :                                     OutputProcessor::Unit::None,
    3184             :                                     loopOAController.HRHeatingCoilActive,
    3185             :                                     OutputProcessor::SOVTimeStepType::System,
    3186             :                                     OutputProcessor::SOVStoreType::Average,
    3187        1021 :                                     airloopName);
    3188        2042 :                 SetupOutputVariable(state,
    3189             :                                     "Air System Outdoor Air Heat Recovery Bypass Minimum Outdoor Air Mixed Air Temperature",
    3190             :                                     OutputProcessor::Unit::C,
    3191             :                                     loopOAController.MixedAirTempAtMinOAFlow,
    3192             :                                     OutputProcessor::SOVTimeStepType::System,
    3193             :                                     OutputProcessor::SOVStoreType::Average,
    3194        1021 :                                     airloopName);
    3195             : 
    3196        2042 :                 SetupOutputVariable(state,
    3197             :                                     "Air System Outdoor Air High Humidity Control Status",
    3198             :                                     OutputProcessor::Unit::None,
    3199             :                                     loopOAController.HighHumCtrlStatus,
    3200             :                                     OutputProcessor::SOVTimeStepType::System,
    3201             :                                     OutputProcessor::SOVStoreType::Average,
    3202        1021 :                                     airloopName);
    3203             : 
    3204        2042 :                 SetupOutputVariable(state,
    3205             :                                     "Air System Outdoor Air Limiting Factor",
    3206             :                                     OutputProcessor::Unit::None,
    3207             :                                     loopOAController.OALimitingFactor,
    3208             :                                     OutputProcessor::SOVTimeStepType::System,
    3209             :                                     OutputProcessor::SOVStoreType::Average,
    3210        1021 :                                     airloopName);
    3211             : 
    3212        2042 :                 SetupOutputVariable(state,
    3213             :                                     "Air System Outdoor Air Flow Fraction",
    3214             :                                     OutputProcessor::Unit::None,
    3215             :                                     loopOAController.OAFractionRpt,
    3216             :                                     OutputProcessor::SOVTimeStepType::System,
    3217             :                                     OutputProcessor::SOVStoreType::Average,
    3218        1021 :                                     airloopName);
    3219             : 
    3220        2042 :                 SetupOutputVariable(state,
    3221             :                                     "Air System Outdoor Air Minimum Flow Fraction",
    3222             :                                     OutputProcessor::Unit::None,
    3223             :                                     loopOAController.MinOAFracLimit,
    3224             :                                     OutputProcessor::SOVTimeStepType::System,
    3225             :                                     OutputProcessor::SOVStoreType::Average,
    3226        1021 :                                     airloopName);
    3227             : 
    3228        2042 :                 SetupOutputVariable(state,
    3229             :                                     "Air System Outdoor Air Mass Flow Rate",
    3230             :                                     OutputProcessor::Unit::kg_s,
    3231             :                                     loopOAController.OAMassFlow,
    3232             :                                     OutputProcessor::SOVTimeStepType::System,
    3233             :                                     OutputProcessor::SOVStoreType::Average,
    3234        1021 :                                     airloopName);
    3235             : 
    3236        2042 :                 SetupOutputVariable(state,
    3237             :                                     "Air System Mixed Air Mass Flow Rate",
    3238             :                                     OutputProcessor::Unit::kg_s,
    3239             :                                     loopOAController.MixMassFlow,
    3240             :                                     OutputProcessor::SOVTimeStepType::System,
    3241             :                                     OutputProcessor::SOVStoreType::Average,
    3242        1021 :                                     airloopName);
    3243             : 
    3244        2042 :                 SetupOutputVariable(state,
    3245             :                                     "Air System Relief Air Heat Transfer Rate",
    3246             :                                     OutputProcessor::Unit::W,
    3247             :                                     loopOAController.RelTotalLossRate,
    3248             :                                     OutputProcessor::SOVTimeStepType::System,
    3249             :                                     OutputProcessor::SOVStoreType::Average,
    3250        1021 :                                     airloopName);
    3251             : 
    3252        2042 :                 SetupOutputVariable(state,
    3253             :                                     "Air System Relief Air Sensible Heat Transfer Rate",
    3254             :                                     OutputProcessor::Unit::W,
    3255             :                                     loopOAController.RelSensiLossRate,
    3256             :                                     OutputProcessor::SOVTimeStepType::System,
    3257             :                                     OutputProcessor::SOVStoreType::Average,
    3258        1021 :                                     airloopName);
    3259             : 
    3260        2042 :                 SetupOutputVariable(state,
    3261             :                                     "Air System Relief Air Latent Heat Transfer Rate",
    3262             :                                     OutputProcessor::Unit::W,
    3263             :                                     loopOAController.RelLatentLossRate,
    3264             :                                     OutputProcessor::SOVTimeStepType::System,
    3265             :                                     OutputProcessor::SOVStoreType::Average,
    3266        1021 :                                     airloopName);
    3267             : 
    3268        1021 :                 if (loopOAController.MixedAirSPMNum > 0) {
    3269           2 :                     SetupOutputVariable(state,
    3270             :                                         "Air System Outdoor Air Maximum Flow Fraction",
    3271             :                                         OutputProcessor::Unit::None,
    3272             :                                         loopOAController.MaxOAFracBySetPoint,
    3273             :                                         OutputProcessor::SOVTimeStepType::System,
    3274             :                                         OutputProcessor::SOVStoreType::Average,
    3275           1 :                                         airloopName);
    3276             :                 }
    3277             : 
    3278        1021 :                 if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
    3279         969 :                     SetupEMSInternalVariable(
    3280         646 :                         state, "Outdoor Air Controller Maximum Mass Flow Rate", loopOAController.Name, "[kg/s]", loopOAController.MaxOAMassFlowRate);
    3281         969 :                     SetupEMSInternalVariable(
    3282         646 :                         state, "Outdoor Air Controller Minimum Mass Flow Rate", loopOAController.Name, "[kg/s]", loopOAController.MinOAMassFlowRate);
    3283         969 :                     SetupEMSActuator(state,
    3284             :                                      "Outdoor Air Controller",
    3285             :                                      loopOAController.Name,
    3286             :                                      "Air Mass Flow Rate",
    3287             :                                      "[kg/s]",
    3288             :                                      loopOAController.EMSOverrideOARate,
    3289         646 :                                      loopOAController.EMSOARateValue);
    3290             :                 }
    3291             : 
    3292        1021 :                 VentMechObjectNum = loopOAController.VentMechObjectNum;
    3293        1021 :                 if (VentMechObjectNum > 0 && thisAirLoop > 0) {
    3294         104 :                     SetupOutputVariable(state,
    3295             :                                         "Air System Outdoor Air Mechanical Ventilation Requested Mass Flow Rate",
    3296             :                                         OutputProcessor::Unit::kg_s,
    3297             :                                         loopOAController.MechVentOAMassFlowRequest,
    3298             :                                         OutputProcessor::SOVTimeStepType::System,
    3299             :                                         OutputProcessor::SOVStoreType::Average,
    3300          52 :                                         airloopName);
    3301          52 :                     if (!state.dataMixedAir->VentilationMechanical(VentMechObjectNum).DCVFlag) {
    3302           2 :                         state.dataAirLoop->AirLoopControlInfo(thisAirLoop).AirLoopDCVFlag = false;
    3303             :                     }
    3304             :                 }
    3305             :             }
    3306             : 
    3307         393 :             state.dataMixedAir->InitOAControllerSetUpAirLoopHVACVariables = false;
    3308             :         }
    3309             :     }
    3310             : 
    3311             :     // Each time step
    3312    24821703 :     if (FirstHVACIteration) {
    3313             :         // Mixed air setpoint. Set by a setpoint manager.
    3314     8606988 :         if (thisOAController.ControllerType_Num == MixedAirControllerType::ControllerOutsideAir) {
    3315     8461036 :             if (state.dataLoopNodes->Node(thisOAController.MixNode).TempSetPoint > SensedNodeFlagValue) {
    3316     7613497 :                 thisOAController.MixSetTemp = state.dataLoopNodes->Node(thisOAController.MixNode).TempSetPoint;
    3317             :             } else {
    3318      847539 :                 thisOAController.MixSetTemp = thisOAController.TempLowLim;
    3319             :             }
    3320             : 
    3321     8461036 :             TotalPeopleOAFlow = 0.0;
    3322     8461036 :             if (VentMechObjectNum != 0) {
    3323      343560 :                 auto &vent_mech(state.dataMixedAir->VentilationMechanical(VentMechObjectNum));
    3324     2825748 :                 for (int ZoneIndex = 1; ZoneIndex <= vent_mech.NumofVentMechZones; ++ZoneIndex) {
    3325     2482188 :                     int ZoneNum = vent_mech.VentMechZone(ZoneIndex);
    3326             : 
    3327             :                     // ZoneIntGain(ZoneNum)%NOFOCC is the number of occupants of a zone at each time step, already counting the occupant schedule
    3328     2482188 :                     OAFlowCalcMethod OAFlowMethod = vent_mech.ZoneOAFlowMethod(ZoneIndex);
    3329     2482188 :                     if (OAFlowMethod == OAFlowCalcMethod::PerPerson || OAFlowMethod == OAFlowCalcMethod::Sum ||
    3330             :                         OAFlowMethod == OAFlowCalcMethod::Max) {
    3331     7446564 :                         TotalPeopleOAFlow += state.dataHeatBal->ZoneIntGain(ZoneNum).NOFOCC * state.dataHeatBal->Zone(ZoneNum).Multiplier *
    3332     7446564 :                                              state.dataHeatBal->Zone(ZoneNum).ListMultiplier * vent_mech.ZoneOAPeopleRate(ZoneIndex) *
    3333     2482188 :                                              GetCurrentScheduleValue(state, vent_mech.ZoneOASchPtr(ZoneIndex));
    3334             :                     }
    3335             :                 }
    3336      343560 :                 vent_mech.TotPeopleOAFlow = TotalPeopleOAFlow;
    3337             :             }
    3338             :         } else {
    3339             :             // Stand Alone ERV does not require a termperature setpoint schedule, make setpoint equal to lower economizer limit
    3340      145952 :             thisOAController.MixSetTemp = thisOAController.TempLowLim;
    3341             :         }
    3342             :     }
    3343             : 
    3344             :     // Each iteration
    3345             : 
    3346    24821703 :     if (thisOAController.ControllerType_Num == MixedAirControllerType::ControllerOutsideAir) {
    3347             :         // zone exhaust mass flow is saved in AirLoopFlow%ZoneExhaust
    3348             :         // the zone exhaust mass flow that is said to be balanced by simple air flows is saved in AirLoopFlow%ZoneExhaustBalanced
    3349    24257718 :         if (AirLoopNum > 0) {
    3350    24257718 :             thisOAController.ExhMassFlow =
    3351    24257718 :                 max(0.0, state.dataAirLoop->AirLoopFlow(AirLoopNum).SupFlow - state.dataAirLoop->AirLoopFlow(AirLoopNum).SysRetFlow);
    3352    24257718 :             state.dataAirLoop->AirLoopControlInfo(AirLoopNum).ZoneExhMassFlow = thisOAController.ExhMassFlow;
    3353    24257718 :             if (state.dataAirLoop->AirLoopControlInfo(AirLoopNum).LoopFlowRateSet && !FirstHVACIteration) {
    3354             :                 // if flow rate has been specified by a manager, set it to the specified value
    3355       21240 :                 thisOAController.MixMassFlow =
    3356       21240 :                     state.dataAirLoop->AirLoopFlow(AirLoopNum).ReqSupplyFrac * state.dataAirLoop->AirLoopFlow(AirLoopNum).DesSupply;
    3357             :             } else {
    3358    24236478 :                 thisOAController.MixMassFlow = state.dataLoopNodes->Node(thisOAController.RetNode).MassFlowRate + thisOAController.ExhMassFlow;
    3359             : 
    3360             :                 // The following was commented out after discussion on PR 7382, it can be reopened for discussion anytime
    3361             :                 // found this equation results in flow that exceeds the design flow rate when there is exhaust flow rate is greater than
    3362             :                 // the design supply air flow rate. Capped the mixed air flow rate at design supply air flow rate, issue #77379
    3363             :                 // thisOAController.MixMassFlow = Node(thisOAController.RetNode).MassFlowRate + thisOAController.ExhMassFlow;
    3364             :                 // thisOAController.MixMassFlow =
    3365             :                 //     min(Node(thisOAController.RetNode).MassFlowRate + thisOAController.ExhMassFlow, AirLoopFlow(AirLoopNum).DesSupply);
    3366             :             }
    3367             :         } else {
    3368           0 :             thisOAController.ExhMassFlow = 0.0;
    3369           0 :             thisOAController.MixMassFlow = state.dataLoopNodes->Node(thisOAController.RetNode).MassFlowRate;
    3370             :         }
    3371    24257718 :         if (state.dataLoopNodes->Node(thisOAController.MixNode).MassFlowRateMaxAvail <= 0.0) {
    3372     1781680 :             thisOAController.MixMassFlow = 0.0;
    3373             :         }
    3374             :     } else {
    3375             :         // Mixed and exhaust flow rates are passed through to model CONTROLLER:STAND ALONE ERV in SimOAController
    3376      563985 :         thisOAController.OAMassFlow = thisOAController.MaxOAMassFlowRate;
    3377      563985 :         thisOAController.MixMassFlow = thisOAController.MaxOAMassFlowRate;
    3378      563985 :         thisOAController.ExhMassFlow = state.dataLoopNodes->Node(thisOAController.RetNode).MassFlowRate;
    3379             :     }
    3380    24821703 :     thisOAController.ExhMassFlow = max(thisOAController.ExhMassFlow, 0.0);
    3381             : 
    3382             :     // Outside air values
    3383    24821703 :     thisOAController.OATemp = state.dataLoopNodes->Node(thisOAController.OANode).Temp;
    3384    24821703 :     thisOAController.OAEnth = state.dataLoopNodes->Node(thisOAController.OANode).Enthalpy;
    3385    24821703 :     thisOAController.OAPress = state.dataLoopNodes->Node(thisOAController.OANode).Press;
    3386    24821703 :     thisOAController.OAHumRat = state.dataLoopNodes->Node(thisOAController.OANode).HumRat;
    3387             : 
    3388             :     // Inlet air values (on OA input side)
    3389    24821703 :     thisOAController.InletTemp = state.dataLoopNodes->Node(thisOAController.InletNode).Temp;
    3390    24821703 :     thisOAController.InletEnth = state.dataLoopNodes->Node(thisOAController.InletNode).Enthalpy;
    3391    24821703 :     thisOAController.InletPress = state.dataLoopNodes->Node(thisOAController.InletNode).Press;
    3392    24821703 :     thisOAController.InletHumRat = state.dataLoopNodes->Node(thisOAController.InletNode).HumRat;
    3393             : 
    3394             :     // Return air values
    3395    24821703 :     thisOAController.RetTemp = state.dataLoopNodes->Node(thisOAController.RetNode).Temp;
    3396    24821703 :     thisOAController.RetEnth = state.dataLoopNodes->Node(thisOAController.RetNode).Enthalpy;
    3397             : 
    3398             :     // Check sensors faults for the air economizer
    3399    24821703 :     iEco = thisOAController.Econo;
    3400    24821703 :     if (state.dataFaultsMgr->AnyFaultsInModel && (iEco != EconoOp::NoEconomizer)) {
    3401             :         int j; // index to economizer faults
    3402     1744681 :         for (i = 1; i <= thisOAController.NumFaultyEconomizer; ++i) {
    3403      241001 :             j = thisOAController.EconmizerFaultNum(i);
    3404      241001 :             if (GetCurrentScheduleValue(state, state.dataFaultsMgr->FaultsEconomizer(j).AvaiSchedPtr) > 0.0) {
    3405      241001 :                 rSchVal = 1.0;
    3406      241001 :                 if (state.dataFaultsMgr->FaultsEconomizer(j).SeveritySchedPtr > 0) {
    3407       47025 :                     rSchVal = GetCurrentScheduleValue(state, state.dataFaultsMgr->FaultsEconomizer(j).SeveritySchedPtr);
    3408             :                 }
    3409             :             } else {
    3410             :                 // no fault
    3411           0 :                 continue;
    3412             :             }
    3413             : 
    3414      241001 :             rOffset = rSchVal * state.dataFaultsMgr->FaultsEconomizer(j).Offset;
    3415             : 
    3416      241001 :             if (std::abs(rOffset) < 0.000000001) continue;
    3417             : 
    3418             :             // ECONOMIZER - outdoor air dry-bulb temperature sensor offset
    3419      232646 :             switch (iEco) {
    3420      232646 :             case EconoOp::FixedDryBulb:
    3421             :             case EconoOp::DifferentialDryBulb:
    3422             :             case EconoOp::FixedDewPointAndDryBulb:
    3423             :             case EconoOp::ElectronicEnthalpy:
    3424             :             case EconoOp::DifferentialDryBulbAndEnthalpy: {
    3425      232646 :                 if (state.dataFaultsMgr->FaultsEconomizer(j).FaultTypeEnum == Fault::TemperatureSensorOffset_OutdoorAir) {
    3426             :                     // FaultModel:TemperatureSensorOffset:OutdoorAir
    3427       38670 :                     thisOAController.OATemp += rOffset;
    3428       38670 :                     thisOAController.InletTemp += rOffset;
    3429             :                 }
    3430      232646 :             } break;
    3431           0 :             default:
    3432           0 :                 break;
    3433             :             }
    3434             : 
    3435             :             // ECONOMIZER - outdoor air humidity ratio sensor offset. really needed ???
    3436      232646 :             switch (iEco) {
    3437           0 :             case EconoOp::FixedDewPointAndDryBulb:
    3438             :             case EconoOp::ElectronicEnthalpy: {
    3439           0 :                 if (state.dataFaultsMgr->FaultsEconomizer(j).FaultTypeEnum == Fault::HumiditySensorOffset_OutdoorAir) {
    3440             :                     // FaultModel:HumiditySensorOffset:OutdoorAir
    3441           0 :                     thisOAController.OAHumRat += rOffset;
    3442           0 :                     thisOAController.InletHumRat += rOffset;
    3443             :                 }
    3444           0 :             } break;
    3445      232646 :             default:
    3446      232646 :                 break;
    3447             :             }
    3448             : 
    3449             :             // ECONOMIZER - outdoor air enthalpy sensor offset
    3450      232646 :             switch (iEco) {
    3451           0 :             case EconoOp::FixedEnthalpy:
    3452             :             case EconoOp::ElectronicEnthalpy:
    3453             :             case EconoOp::DifferentialDryBulbAndEnthalpy: {
    3454           0 :                 if (state.dataFaultsMgr->FaultsEconomizer(j).FaultTypeEnum == Fault::EnthalpySensorOffset_OutdoorAir) {
    3455             :                     // FaultModel:EnthalpySensorOffset:OutdoorAir
    3456           0 :                     thisOAController.OAEnth += rOffset;
    3457           0 :                     thisOAController.InletEnth += rOffset;
    3458             :                 }
    3459           0 :             } break;
    3460      232646 :             default:
    3461      232646 :                 break;
    3462             :             }
    3463             : 
    3464             :             // ECONOMIZER - return air dry-bulb temperature sensor offset
    3465      232646 :             switch (iEco) {
    3466      232646 :             case EconoOp::DifferentialDryBulb:
    3467             :             case EconoOp::DifferentialDryBulbAndEnthalpy: {
    3468      232646 :                 if (state.dataFaultsMgr->FaultsEconomizer(j).FaultTypeEnum == Fault::TemperatureSensorOffset_ReturnAir) {
    3469             :                     // FaultModel:TemperatureSensorOffset:ReturnAir
    3470       49963 :                     thisOAController.RetTemp += rOffset;
    3471             :                 }
    3472      232646 :             } break;
    3473           0 :             default:
    3474           0 :                 break;
    3475             :             }
    3476             : 
    3477             :             // ECONOMIZER - return air enthalpy sensor offset
    3478      232646 :             switch (iEco) {
    3479           0 :             case EconoOp::ElectronicEnthalpy:
    3480             :             case EconoOp::DifferentialDryBulbAndEnthalpy: {
    3481           0 :                 if (state.dataFaultsMgr->FaultsEconomizer(j).FaultTypeEnum == Fault::EnthalpySensorOffset_ReturnAir) {
    3482             :                     // FaultModel:EnthalpySensorOffset:ReturnAir
    3483           0 :                     thisOAController.RetEnth += rOffset;
    3484             :                 }
    3485           0 :             } break;
    3486      232646 :             default:
    3487      232646 :                 break;
    3488             :             }
    3489             :         }
    3490             :     }
    3491             : 
    3492    24821703 :     if (ErrorsFound) {
    3493           0 :         ShowFatalError(state, "Error in " + CurrentModuleObjects(static_cast<int>(CMO::OAController)) + "; program terminated");
    3494             :     }
    3495    24821703 : } // namespace MixedAir
    3496             : 
    3497    43707297 : void InitOAMixer(EnergyPlusData &state, int const OAMixerNum, bool const FirstHVACIteration)
    3498             : {
    3499             : 
    3500             :     // SUBROUTINE INFORMATION:
    3501             :     //       AUTHOR         Fred Buhl
    3502             :     //       DATE WRITTEN   Oct 1998
    3503             :     //       MODIFIED       na
    3504             :     //       RE-ENGINEERED  na
    3505             : 
    3506             :     // PURPOSE OF THIS SUBROUTINE
    3507             :     // Initialize the OAMixer data structure with input node data
    3508             : 
    3509             :     // METHODOLOGY EMPLOYED:
    3510             : 
    3511             :     // REFERENCES:
    3512             : 
    3513             :     // Using/Aliasing
    3514             :     using namespace DataLoopNode;
    3515             : 
    3516             :     // Locals
    3517             :     // SUBROUTINE ARGUMENT DEFINITIONS
    3518             : 
    3519             :     // SUBROUTINE PARAMETER DEFINITIONS:
    3520             : 
    3521             :     // INTERFACE BLOCK SPECIFICATIONS
    3522             :     // na
    3523             : 
    3524             :     // DERIVED TYPE DEFINITIONS
    3525             :     // na
    3526             : 
    3527             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    3528             :     int RetNode;
    3529             :     int InletNode;
    3530             :     int RelNode;
    3531             : 
    3532    43707297 :     RetNode = state.dataMixedAir->OAMixer(OAMixerNum).RetNode;
    3533    43707297 :     InletNode = state.dataMixedAir->OAMixer(OAMixerNum).InletNode;
    3534    43707297 :     RelNode = state.dataMixedAir->OAMixer(OAMixerNum).RelNode;
    3535             : 
    3536    43707297 :     if (state.dataGlobal->BeginEnvrnFlag && FirstHVACIteration) {
    3537             :     }
    3538             : 
    3539    43707297 :     if (state.dataGlobal->BeginDayFlag) {
    3540             :     }
    3541             : 
    3542             :     if (FirstHVACIteration) {
    3543             :     }
    3544             : 
    3545             :     // Each iteration
    3546             : 
    3547             :     // Return air stream data
    3548    43707297 :     state.dataMixedAir->OAMixer(OAMixerNum).RetTemp = state.dataLoopNodes->Node(RetNode).Temp;
    3549    43707297 :     state.dataMixedAir->OAMixer(OAMixerNum).RetHumRat = state.dataLoopNodes->Node(RetNode).HumRat;
    3550    43707297 :     state.dataMixedAir->OAMixer(OAMixerNum).RetEnthalpy = state.dataLoopNodes->Node(RetNode).Enthalpy;
    3551    43707297 :     state.dataMixedAir->OAMixer(OAMixerNum).RetPressure = state.dataLoopNodes->Node(RetNode).Press;
    3552    43707297 :     state.dataMixedAir->OAMixer(OAMixerNum).RetMassFlowRate = state.dataLoopNodes->Node(RetNode).MassFlowRate;
    3553             :     // Outside air stream data
    3554    43707297 :     state.dataMixedAir->OAMixer(OAMixerNum).OATemp = state.dataLoopNodes->Node(InletNode).Temp;
    3555    43707297 :     state.dataMixedAir->OAMixer(OAMixerNum).OAHumRat = state.dataLoopNodes->Node(InletNode).HumRat;
    3556    43707297 :     state.dataMixedAir->OAMixer(OAMixerNum).OAEnthalpy = state.dataLoopNodes->Node(InletNode).Enthalpy;
    3557    43707297 :     state.dataMixedAir->OAMixer(OAMixerNum).OAPressure = state.dataLoopNodes->Node(InletNode).Press;
    3558    43707297 :     state.dataMixedAir->OAMixer(OAMixerNum).OAMassFlowRate = state.dataLoopNodes->Node(InletNode).MassFlowRate;
    3559             :     // Relief air data
    3560    43707297 :     state.dataMixedAir->OAMixer(OAMixerNum).RelMassFlowRate = state.dataLoopNodes->Node(RelNode).MassFlowRate;
    3561    43707297 : }
    3562             : 
    3563             : // End of Initialization Section of the Module
    3564             : //******************************************************************************
    3565             : 
    3566             : // Beginning Calculation Section of the Module
    3567             : //******************************************************************************
    3568             : 
    3569    24821703 : void OAControllerProps::CalcOAController(EnergyPlusData &state, int const AirLoopNum, bool const FirstHVACIteration)
    3570             : {
    3571             : 
    3572             :     // SUBROUTINE INFORMATION:
    3573             :     //       AUTHOR         Fred Buhl
    3574             :     //       DATE WRITTEN   Oct 1998
    3575             :     //       MODIFIED       Shirey/Raustad FSEC, June 2003
    3576             :     //                      Tianzhen Hong, Feb 2009 for new DCV
    3577             :     //                      Brent Griffith ,EMS override of OA rate
    3578             :     //                      Mangesh Basarkar, 06/2011: Modifying outside air calculation based on DCV flag
    3579             :     //                      Chandan Sharma, FSEC, 25Aug 2011 - Added ProportionalControl
    3580             :     //                           to enhance CO2 based DCV control
    3581             :     //                      Tianzhen Hong, March 2012, zone maximum OA fraction - a TRACE feature
    3582             :     //                      Tianzhen Hong, March 2012, multi-path VRP based on ASHRAE 62.1-2010
    3583             :     //       RE-ENGINEERED  na
    3584             : 
    3585             :     // PURPOSE OF THIS SUBROUTINE
    3586             :     // Determine the outside air flow
    3587             : 
    3588             :     // METHODOLOGY EMPLOYED:
    3589             : 
    3590             :     // REFERENCES:
    3591             :     // DOE-2.1E Supplement pages 3.97 - 3.100
    3592             :     // BLAST User Reference pages 183 - 186
    3593             :     // ASHRAE Standard 62.1-2010
    3594             : 
    3595             :     // Using/Aliasing
    3596             :     using Curve::CurveValue;
    3597             : 
    3598             :     // Locals
    3599             :     // SUBROUTINE ARGUMENT DEFINITIONS
    3600             : 
    3601             :     // SUBROUTINE PARAMETER DEFINITIONS:
    3602             :     static constexpr std::string_view RoutineName("CalcOAController: ");
    3603             : 
    3604             :     // INTERFACE BLOCK SPECIFICATIONS
    3605             :     // na
    3606             : 
    3607             :     // DERIVED TYPE DEFINITIONS
    3608             :     // na
    3609             : 
    3610             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    3611             :     Real64 OutAirMinFrac; // Local variable used to calculate min OA fraction
    3612             : 
    3613             :     Real64 MechVentOutsideAirMinFrac;     // fraction of OA specified by mechanical ventilation object
    3614             :     Real64 MechVentOAMassFlow;            // outside air mass flow rate calculated by mechanical ventilation object [kg/s]
    3615             :     Real64 MinOASchedVal;                 // value of the minimum outside air schedule
    3616             :     Real64 OASignal;                      // Outside air flow rate fraction (0.0 to 1.0)
    3617             :     bool AirLoopCyclingFan;               // Type of air loop fan (TRUE if Fan:OnOff)
    3618             :     bool HighHumidityOperationFlag;       // TRUE if zone humidistat senses a high humidity condition
    3619             :     Real64 RecircTemp;                    // - return air temp, used for custom economizer control calculation
    3620             :     Real64 MixedAirTempAtMinOAFlow;       // - mixed air temperature at min flow rate, used for custom economizer control calculation
    3621             :     Real64 RecircMassFlowRateAtMinOAFlow; // recirc air mass flow rate at min OA, used for custom economizer control calculation
    3622             :     Real64 ReliefMassFlowAtMinOA;         // relief air mass flow rate at min OA, used for custom economizer control calculation
    3623    24821703 :     Real64 SysSA(0.0);                    // System supply air mass flow rate [kg/s]
    3624    24821703 :     MinOASchedVal = 1.0;
    3625             : 
    3626    24821703 :     if (AirLoopNum > 0) {
    3627    24257718 :         AirLoopCyclingFan = (state.dataAirLoop->AirLoopControlInfo(AirLoopNum).FanOpMode == CycFanCycCoil);
    3628             :     } else {
    3629      563985 :         AirLoopCyclingFan = false;
    3630             :     }
    3631             : 
    3632    24821703 :     this->OALimitingFactor = limitFactorNone; // oa controller limiting factor
    3633             : 
    3634             :     // Check for no flow
    3635    24821703 :     if (this->MixMassFlow <= SmallMassFlow) {
    3636             : 
    3637     1809228 :         this->OAMassFlow = 0.0;     // outside air mass flow rate
    3638     1809228 :         this->RelMassFlow = 0.0;    // relief air mass flow rate
    3639     1809228 :         this->MixMassFlow = 0.0;    // mixed air mass flow rate
    3640     1809228 :         this->MinOAFracLimit = 0.0; // minimum OA fraction limit
    3641             : 
    3642     1809228 :         this->EconomizerStatus = 0;                                                    // economizer status for reporting
    3643     1809228 :         this->HeatRecoveryBypassStatus = 0;                                            // HR bypass status for reporting
    3644     1809228 :         this->HRHeatingCoilActive = 0;                                                 // resets report variable
    3645     1809228 :         this->MixedAirTempAtMinOAFlow = state.dataLoopNodes->Node(this->RetNode).Temp; // track return T
    3646     1809228 :         this->HighHumCtrlStatus = 0;                                                   // high humdity control status for reporting
    3647     1809228 :         this->OAFractionRpt = 0.0;                                                     // actual OA fraction for reporting
    3648             : 
    3649     1809228 :         this->EconoActive = false;       // DataAirLoop variable (OA Controllers)
    3650     1809228 :         this->HighHumCtrlActive = false; // DataAirLoop variable (OA Controllers)
    3651             : 
    3652             :         // also reset air loop data for use by other routines
    3653     1809228 :         if (AirLoopNum > 0) {
    3654     1809126 :             auto &curAirLoopControlInfo(state.dataAirLoop->AirLoopControlInfo(AirLoopNum));
    3655     1809126 :             auto &curAirLoopFlow(state.dataAirLoop->AirLoopFlow(AirLoopNum));
    3656             : 
    3657     1809126 :             curAirLoopControlInfo.EconoActive = false;        // DataAirLoop variable (AirloopHVAC)
    3658     1809126 :             curAirLoopControlInfo.HeatRecoveryBypass = false; // DataAirLoop variable (AirloopHVAC)
    3659     1809126 :             curAirLoopControlInfo.HighHumCtrlActive = false;  // DataAirLoop variable (AirloopHVAC)
    3660     1809126 :             curAirLoopControlInfo.ResimAirLoopFlag = false;   // DataAirLoop variable (AirloopHVAC)
    3661     1809126 :             curAirLoopFlow.OAFrac = 0.0;                      // DataAirLoop variable (AirloopHVAC)
    3662     1809126 :             curAirLoopFlow.OAMinFrac = 0.0;                   // DataAirLoop variable (AirloopHVAC)
    3663     1809126 :             curAirLoopFlow.MinOutAir = 0.0;
    3664     1809126 :             curAirLoopFlow.OAFlow = 0.0;
    3665             :         }
    3666             : 
    3667     3618456 :         return;
    3668             :     }
    3669             : 
    3670             :     // set OutAirMinFrac
    3671    23012475 :     if (AirLoopNum > 0) {
    3672    22448592 :         auto &curAirLoopFlow(state.dataAirLoop->AirLoopFlow(AirLoopNum));
    3673             : 
    3674    22448592 :         if (curAirLoopFlow.DesSupply >= SmallAirVolFlow) {
    3675    22448592 :             OutAirMinFrac = this->MinOAMassFlowRate / curAirLoopFlow.DesSupply;
    3676             :         } else {
    3677           0 :             OutAirMinFrac = 0.0;
    3678             :         }
    3679             :     } else {
    3680      563883 :         if (this->MaxOA >= SmallAirVolFlow) {
    3681      563883 :             OutAirMinFrac = this->MinOA / this->MaxOA;
    3682             :         } else {
    3683           0 :             OutAirMinFrac = 0.0;
    3684             :         }
    3685             :     }
    3686    23012475 :     if (this->MinOASchPtr > 0) {
    3687    21740148 :         MinOASchedVal = GetCurrentScheduleValue(state, this->MinOASchPtr);
    3688    21740148 :         MinOASchedVal = min(max(MinOASchedVal, 0.0), 1.0);
    3689    21740148 :         OutAirMinFrac *= MinOASchedVal;
    3690    21740148 :         this->OALimitingFactor = limitFactorLimits;
    3691             :     }
    3692             : 
    3693             :     // Get mechanical ventilation
    3694    23012475 :     MechVentOAMassFlow = 0.0;
    3695    23012475 :     MechVentOutsideAirMinFrac = 0.0;
    3696    23012475 :     if (AirLoopNum > 0 && this->VentMechObjectNum != 0) {
    3697     1211670 :         auto &curAirLoopControlInfo(state.dataAirLoop->AirLoopControlInfo(AirLoopNum));
    3698     1211670 :         auto &curAirLoopFlow(state.dataAirLoop->AirLoopFlow(AirLoopNum));
    3699             : 
    3700             :         // Get system supply air flow rate
    3701     1211670 :         if (curAirLoopControlInfo.LoopFlowRateSet) {
    3702             :             // if flow rate has been specified by a manager, set it to the specified value
    3703             :             // DesSupply and SupFlow are mass flow rate in kg/s
    3704           0 :             SysSA = curAirLoopFlow.ReqSupplyFrac * curAirLoopFlow.DesSupply;
    3705             :         } else {
    3706     1211670 :             SysSA = curAirLoopFlow.SupFlow;
    3707             :         }
    3708             : 
    3709     1211670 :         state.dataMixedAir->VentilationMechanical(this->VentMechObjectNum).CalcMechVentController(state, SysSA, MechVentOAMassFlow);
    3710     1211670 :         MechVentOutsideAirMinFrac = MechVentOAMassFlow / curAirLoopFlow.DesSupply;
    3711     1211670 :         if (curAirLoopFlow.FanPLR > 0.0) {
    3712     1210685 :             MechVentOutsideAirMinFrac *= curAirLoopFlow.FanPLR;
    3713     1210685 :             MechVentOAMassFlow *= curAirLoopFlow.FanPLR;
    3714             :         }
    3715             :     }
    3716    23012475 :     this->MechVentOAMassFlowRequest = MechVentOAMassFlow;
    3717             :     //****** use greater of Mechanical Ventilation Outside Air fraction and OutAirMinFrac
    3718    23012475 :     if ((MechVentOutsideAirMinFrac > 0.0) && (OutAirMinFrac > MechVentOutsideAirMinFrac)) {
    3719           0 :         if (!state.dataGlobal->WarmupFlag) {
    3720           0 :             if (this->CountMechVentFrac == 0) {
    3721           0 :                 ++this->CountMechVentFrac;
    3722           0 :                 ShowWarningError(state,
    3723           0 :                                  std::string{RoutineName} +
    3724           0 :                                      "Minimum OA fraction > Mechanical Ventilation Controller request for Controller:OutdoorAir=" + this->Name +
    3725             :                                      ", Min OA fraction is used.");
    3726           0 :                 ShowContinueError(state,
    3727             :                                   "This may be overriding desired ventilation controls. Check inputs for Minimum Outdoor Air Flow Rate, Minimum "
    3728             :                                   "Outdoor Air Schedule Name and Controller:MechanicalVentilation");
    3729           0 :                 ShowContinueErrorTimeStamp(
    3730           0 :                     state, format("Minimum OA fraction = {:.4R}, Mech Vent OA fraction = {:.4R}", OutAirMinFrac, MechVentOutsideAirMinFrac));
    3731             :             } else {
    3732           0 :                 ShowRecurringWarningErrorAtEnd(state,
    3733           0 :                                                "Controller:OutdoorAir=\"" + this->Name +
    3734             :                                                    "\": Min OA fraction > Mechanical ventilation OA fraction, continues...",
    3735             :                                                this->IndexMechVentFrac,
    3736             :                                                OutAirMinFrac,
    3737             :                                                OutAirMinFrac);
    3738             :             }
    3739             :         }
    3740             :     }
    3741    23012475 :     if (MechVentOutsideAirMinFrac > OutAirMinFrac) {
    3742      830782 :         OutAirMinFrac = MechVentOutsideAirMinFrac;
    3743      830782 :         this->OALimitingFactor = limitFactorDCV;
    3744             :     }
    3745             : 
    3746    23012475 :     OutAirMinFrac = min(max(OutAirMinFrac, 0.0), 1.0);
    3747             : 
    3748             :     // At this point, OutAirMinFrac is still based on AirLoopFlow.DesSupply
    3749    23012475 :     if (AirLoopNum > 0) {
    3750    22448592 :         auto &curAirLoopFlow(state.dataAirLoop->AirLoopFlow(AirLoopNum));
    3751             : 
    3752    22448592 :         curAirLoopFlow.MinOutAir = OutAirMinFrac * curAirLoopFlow.DesSupply;
    3753             : 
    3754             :         // calculate mixed air temp at min OA flow rate
    3755    22448592 :         ReliefMassFlowAtMinOA = max(curAirLoopFlow.MinOutAir - this->ExhMassFlow, 0.0);
    3756    22448592 :         RecircMassFlowRateAtMinOAFlow = max(state.dataLoopNodes->Node(this->RetNode).MassFlowRate - ReliefMassFlowAtMinOA, 0.0);
    3757    22448592 :         if ((RecircMassFlowRateAtMinOAFlow + curAirLoopFlow.MinOutAir) > 0.0) {
    3758    22436986 :             RecircTemp = state.dataLoopNodes->Node(this->RetNode).Temp;
    3759    22436986 :             MixedAirTempAtMinOAFlow =
    3760    22436986 :                 (RecircMassFlowRateAtMinOAFlow * RecircTemp + curAirLoopFlow.MinOutAir * state.dataLoopNodes->Node(this->OANode).Temp) /
    3761    22436986 :                 (RecircMassFlowRateAtMinOAFlow + curAirLoopFlow.MinOutAir);
    3762             :         } else {
    3763       11606 :             MixedAirTempAtMinOAFlow = state.dataLoopNodes->Node(this->RetNode).Temp;
    3764             :         }
    3765    22448592 :         this->MixedAirTempAtMinOAFlow = MixedAirTempAtMinOAFlow;
    3766             :     }
    3767             : 
    3768             :     // Economizer
    3769    23012475 :     this->CalcOAEconomizer(state, AirLoopNum, OutAirMinFrac, OASignal, HighHumidityOperationFlag, FirstHVACIteration);
    3770             : 
    3771    23012475 :     this->OAMassFlow = OASignal * this->MixMassFlow;
    3772             : 
    3773             :     // Do not allow OA to be below Ventilation:Mechanical flow rate or above mixed mass flow rate
    3774    23012475 :     if (AirLoopNum > 0 && VentMechObjectNum != 0) {
    3775     1211670 :         if (MechVentOAMassFlow > this->OAMassFlow) {
    3776      564704 :             this->OAMassFlow = min(MechVentOAMassFlow, this->MixMassFlow);
    3777             :         }
    3778             :     }
    3779             : 
    3780             :     // Do not allow OA to be below Exh for controller:outside air
    3781    23012475 :     if (this->ControllerType_Num == MixedAirControllerType::ControllerOutsideAir) {
    3782    22448592 :         if (this->ExhMassFlow > this->OAMassFlow) {
    3783      504541 :             this->OAMassFlow = this->ExhMassFlow;
    3784      504541 :             this->OALimitingFactor = limitFactorExhaust;
    3785             :         }
    3786             :     }
    3787             : 
    3788             :     // if fixed minimum, don't let go below min OA
    3789    23012475 :     if (this->FixedMin) {
    3790             :         // cycling fans allow "average" min OA to be below minimum
    3791    22095811 :         if (!AirLoopCyclingFan) {
    3792    19862215 :             Real64 minOASchedMassFlowRate = this->MinOAMassFlowRate * MinOASchedVal;
    3793    19862215 :             if (minOASchedMassFlowRate > this->OAMassFlow) {
    3794     7313053 :                 this->OAMassFlow = minOASchedMassFlowRate;
    3795     7313053 :                 this->OALimitingFactor = limitFactorLimits;
    3796             :             }
    3797             :         }
    3798             :     }
    3799             : 
    3800             :     // Apply Minimum Fraction of Outdoor Air Schedule
    3801    23012475 :     if (this->MinOAflowSchPtr > 0) {
    3802     1323839 :         Real64 MinOAflowfracVal = GetCurrentScheduleValue(state, this->MinOAflowSchPtr);
    3803     1323839 :         MinOAflowfracVal = min(max(MinOAflowfracVal, 0.0), 1.0);
    3804     1323839 :         OutAirMinFrac = max(MinOAflowfracVal, OutAirMinFrac);
    3805     1323839 :         Real64 minOAFracMassFlowRate = this->MixMassFlow * MinOAflowfracVal;
    3806     1323839 :         if (minOAFracMassFlowRate > this->OAMassFlow) {
    3807      740224 :             this->OAMassFlow = minOAFracMassFlowRate;
    3808      740224 :             this->OALimitingFactor = limitFactorLimits;
    3809             :         }
    3810             :     }
    3811             : 
    3812             :     // Apply Maximum Fraction of Outdoor Air Schedule
    3813    23012475 :     Real64 currentMaxOAMassFlowRate = this->MaxOAMassFlowRate;
    3814    23012475 :     if (this->MaxOAflowSchPtr > 0) {
    3815     1130563 :         Real64 MaxOAflowfracVal = GetCurrentScheduleValue(state, this->MaxOAflowSchPtr);
    3816     1130563 :         MaxOAflowfracVal = min(max(MaxOAflowfracVal, 0.0), 1.0);
    3817     1130563 :         currentMaxOAMassFlowRate = min(this->MaxOAMassFlowRate, this->MixMassFlow * MaxOAflowfracVal);
    3818     1130563 :         OutAirMinFrac = min(MaxOAflowfracVal, OutAirMinFrac);
    3819     1130563 :         if (currentMaxOAMassFlowRate < this->OAMassFlow) {
    3820       31059 :             this->OAMassFlow = currentMaxOAMassFlowRate;
    3821       31059 :             this->OALimitingFactor = limitFactorLimits;
    3822             :         }
    3823             :     }
    3824             : 
    3825             :     // Don't let the OA flow be > than the max OA limit. OA for high humidity control is allowed to be greater than max OA.
    3826             :     // Night Ventilation has priority and may override an OASignal > 1 high humidity condition with OASignal = 1
    3827    23012475 :     if (HighHumidityOperationFlag) {
    3828         394 :         Real64 maxOAMassFlow = this->MaxOAMassFlowRate * max(1.0, OASignal);
    3829         394 :         if (maxOAMassFlow < this->OAMassFlow) {
    3830           0 :             this->OAMassFlow = maxOAMassFlow;
    3831           0 :             this->OALimitingFactor = limitFactorLimits;
    3832             :         }
    3833             :     } else {
    3834    23012081 :         if (this->MaxOAMassFlowRate < this->OAMassFlow) {
    3835      116276 :             this->OAMassFlow = this->MaxOAMassFlowRate;
    3836      116276 :             this->OALimitingFactor = limitFactorLimits;
    3837             :         }
    3838             :     }
    3839             : 
    3840    23012475 :     if (!state.dataGlobal->WarmupFlag && !state.dataGlobal->DoingSizing && (this->ManageDemand) && (this->OAMassFlow > this->DemandLimitFlowRate)) {
    3841        3973 :         this->OAMassFlow = this->DemandLimitFlowRate;
    3842        3973 :         this->OALimitingFactor = limitFactorDemandLimit;
    3843             :     }
    3844    23012475 :     if (this->EMSOverrideOARate) {
    3845           0 :         this->OAMassFlow = this->EMSOARateValue;
    3846           0 :         this->OALimitingFactor = limitFactorEMS;
    3847             :     }
    3848             : 
    3849             :     // Don't let OA flow be > mixed air flow.
    3850             :     // Seems if RAB (return air bypass) that this should be don't let OA flow be > design supply flow but that causes other issues
    3851    23012475 :     if (this->MixMassFlow < this->OAMassFlow) {
    3852      233157 :         this->OAMassFlow = this->MixMassFlow;
    3853      233157 :         this->OALimitingFactor = limitFactorMixedAir;
    3854             :     }
    3855             : 
    3856             :     // save the min outside air flow fraction and max outside air mass flow rate
    3857    23012475 :     if (AirLoopNum > 0) {
    3858    22448592 :         auto &curAirLoopControlInfo(state.dataAirLoop->AirLoopControlInfo(AirLoopNum));
    3859    22448592 :         auto &curAirLoopFlow(state.dataAirLoop->AirLoopFlow(AirLoopNum));
    3860             : 
    3861    22448592 :         curAirLoopFlow.OAMinFrac = OutAirMinFrac;
    3862    22448592 :         if (this->FixedMin) {
    3863    22095811 :             curAirLoopFlow.MinOutAir = min(OutAirMinFrac * curAirLoopFlow.DesSupply, this->MixMassFlow);
    3864             :         } else {
    3865      352781 :             curAirLoopFlow.MinOutAir = OutAirMinFrac * this->MixMassFlow;
    3866             :         }
    3867    22448592 :         if (this->MixMassFlow > 0.0) {
    3868    22448592 :             curAirLoopFlow.OAFrac = this->OAMassFlow / this->MixMassFlow;
    3869    22448592 :             curAirLoopFlow.OAFlow = this->OAMassFlow;
    3870             :         } else {
    3871           0 :             curAirLoopFlow.OAFrac = 0.0;
    3872           0 :             curAirLoopFlow.OAFlow = 0.0;
    3873             :         }
    3874    22448592 :         this->MinOAFracLimit = OutAirMinFrac;
    3875    22448592 :         if (HighHumidityOperationFlag && OASignal > 1.0) {
    3876          62 :             curAirLoopFlow.MaxOutAir = this->MaxOAMassFlowRate * OASignal;
    3877             :         } else {
    3878    22448530 :             curAirLoopFlow.MaxOutAir = currentMaxOAMassFlowRate;
    3879             :         }
    3880             : 
    3881             :         // MJW - Not sure if this is necessary but keeping it for now
    3882    22448592 :         if (curAirLoopControlInfo.HeatingActiveFlag && curAirLoopControlInfo.EconomizerFlowLocked) {
    3883             :             // The airloop needs to be simulated again so that the heating coil & HX can be resimulated
    3884      970490 :             if (curAirLoopControlInfo.HeatRecoveryResimFlag && curAirLoopControlInfo.OASysComponentsSimulated) {
    3885       43098 :                 curAirLoopControlInfo.ResimAirLoopFlag = true;
    3886       43098 :                 curAirLoopControlInfo.HeatRecoveryResimFlag = false;
    3887       43098 :                 curAirLoopControlInfo.HeatRecoveryResimFlag2 = true;
    3888             :                 // on the first iteration, air loop heating coils have not be simulated so HeatingCoilActive=FALSE
    3889             :                 // on the second iteration, the heating coils could have been on, but logic tests here could deactivate heating coil
    3890             :                 // reset heating coil active status and HX since logic tests may turn off heating coil
    3891             :                 // the ResimAirLoopFlag will force another iteration and things should line up on subsequent iterations
    3892       43098 :                 curAirLoopControlInfo.HeatingActiveFlag = false;
    3893       43098 :                 this->HRHeatingCoilActive = 0;
    3894       43098 :                 curAirLoopControlInfo.HeatRecoveryBypass = true;
    3895       43098 :                 this->HeatRecoveryBypassStatus = 1;
    3896      442147 :             } else if (curAirLoopControlInfo.HeatRecoveryResimFlag2) {
    3897       43084 :                 curAirLoopControlInfo.ResimAirLoopFlag = true;
    3898       43084 :                 curAirLoopControlInfo.HeatRecoveryResimFlag2 = false;
    3899             :             } else {
    3900      399063 :                 curAirLoopControlInfo.ResimAirLoopFlag = false;
    3901             :             }
    3902    21963347 :         } else if (curAirLoopControlInfo.HeatingActiveFlag) {
    3903     2748734 :             this->HRHeatingCoilActive = 1;
    3904             :         } else {
    3905    19214613 :             this->HRHeatingCoilActive = 0;
    3906             :         }
    3907             : 
    3908             :     } // if (AirLoopNum > 0)
    3909             : 
    3910             :     // Set the relief air flow rate (must be done last to account for changes in OAMassFlow
    3911    23012475 :     this->RelMassFlow = max(this->OAMassFlow - this->ExhMassFlow, 0.0);
    3912             : 
    3913             :     // Save OA fraction for reporting
    3914    23012475 :     if (this->MixMassFlow > 0) {
    3915    23012475 :         this->OAFractionRpt = this->OAMassFlow / this->MixMassFlow;
    3916             :     } else {
    3917           0 :         if (this->OAMassFlow > 0) {
    3918           0 :             this->OAFractionRpt = OASignal;
    3919             :         } else {
    3920           0 :             this->OAFractionRpt = 0.0;
    3921             :         }
    3922             :     }
    3923    23012475 :     this->RelTemp = this->RetTemp;
    3924    23012475 :     this->RelEnth = this->RetEnth;
    3925    23012475 :     this->RelSensiLossRate =
    3926    23012475 :         this->RelMassFlow * Psychrometrics::PsyCpAirFnW(state.dataEnvrn->OutHumRat) * (this->RelTemp - state.dataEnvrn->OutDryBulbTemp);
    3927    23012475 :     this->RelTotalLossRate = this->RelMassFlow * (this->RelEnth - state.dataEnvrn->OutEnthalpy);
    3928    23012475 :     this->RelLatentLossRate = this->RelTotalLossRate - this->RelSensiLossRate;
    3929             : }
    3930             : 
    3931     1211670 : void VentilationMechanicalProps::CalcMechVentController(
    3932             :     EnergyPlusData &state,
    3933             :     Real64 &SysSA,             // System supply air mass flow rate [kg/s]
    3934             :     Real64 &MechVentOAMassFlow // outside air mass flow rate calculated by mechanical ventilation object [kg/s]
    3935             : )
    3936             : {
    3937             :     using Psychrometrics::PsyRhoAirFnPbTdbW;
    3938             : 
    3939             :     static constexpr std::string_view RoutineName("CalcMechVentController: ");
    3940     1211670 :     static std::string const &CurrentModuleObject(CurrentModuleObjects(static_cast<int>(CMO::MechVentilation)));
    3941             : 
    3942             :     // new local variables for DCV
    3943     1211670 :     std::array<Real64, static_cast<int>(DataSizing::OAFlowCalcMethod::Num)> ZoneOACalc{
    3944             :         0.0};         // Zone OA flow rate based on each calculation method [m3/s]
    3945             :     Real64 ZoneOABZ;  // Zone breathing-zone OA flow rate [m3/s]
    3946             :     Real64 ZoneOAMin; // Minimum Zone OA flow rate when the zone is unoccupied (i.e. ZoneOAPeople = 0)
    3947             :     // used for "ProportionalControl" System outdoor air method
    3948             :     Real64 ZoneOAMax; // Maximum Zone OA flow rate (ZoneOAPeople + ZoneOACalc[static_cast<int>(DataSizing::OAFlowCalcMethod::PerArea)])
    3949             :     // used for "ProportionalControl" System outdoor air method
    3950             :     Real64 ZoneOA;        // Zone OA flow rate [m3/s]
    3951             :     Real64 ZoneOAFrac;    // Zone OA fraction (as a fraction of actual supply air flow rate)
    3952             :     Real64 ZoneEz;        // Zone air distribution effectiveness
    3953             :     Real64 ZoneSA;        // Zone supply air flow rate
    3954             :     Real64 ZonePA;        // Zone primary air flow rate
    3955             :     Real64 SysOAuc;       // System uncorrected OA flow rate
    3956             :     Real64 SysOA;         // System supply OA volume flow rate [m3/s]
    3957             :     Real64 SysOAMassFlow; // System supply OA mass flow rate [kg/s]
    3958             :     Real64 SysEv;         // System ventilation efficiency
    3959             :     Real64 NodeTemp;      // node temperature
    3960             :     Real64 NodeHumRat;    // node humidity ratio
    3961             :     Real64 MassFlowRate;  // Temporary variable
    3962             :     Real64 ZoneLoad;      // Zone loads
    3963     2423340 :     std::string ZoneName; // Zone name
    3964             :     int OAIndex;          // index to design specification outdoor air objects
    3965             :     int PeopleNum;
    3966             :     Real64 ZoneMaxCO2;                // Breathing-zone CO2 concentartion
    3967             :     Real64 ZoneMinCO2;                // Minimum CO2 concentration in zone
    3968             :     Real64 ZoneContamControllerSched; // Schedule value for ZoneControl:ContaminantController
    3969             :     Real64 CO2PeopleGeneration;       // CO2 generation from people at design level
    3970             : 
    3971             :     int PriNode;   // primary node of zone terminal unit
    3972             :     int InletNode; // outlet node of zone terminal unit
    3973             : 
    3974     1211670 :     ZoneMaxCO2 = 0.0;
    3975     1211670 :     ZoneMinCO2 = 0.0;
    3976     1211670 :     ZoneOAMin = 0.0;
    3977     1211670 :     ZoneOAMax = 0.0;
    3978     1211670 :     ZoneContamControllerSched = 0.0;
    3979     1211670 :     MechVentOAMassFlow = 0.0;
    3980             : 
    3981             :     // Apply mechanical ventilation only when it is available/allowed
    3982     1211670 :     if (GetCurrentScheduleValue(state, this->SchPtr) > 0) {
    3983      937404 :         if (this->SystemOAMethod == DataSizing::SysOAMethod::IAQP) {
    3984             :             // IAQP for CO2 control
    3985        6176 :             SysOAMassFlow = 0.0;
    3986       24704 :             for (int ZoneIndex = 1; ZoneIndex <= this->NumofVentMechZones; ++ZoneIndex) {
    3987       18528 :                 int ZoneNum = this->VentMechZone(ZoneIndex);
    3988       37056 :                 SysOAMassFlow += state.dataContaminantBalance->ZoneSysContDemand(ZoneNum).OutputRequiredToCO2SP *
    3989       18528 :                                  GetCurrentScheduleValue(state, this->ZoneOASchPtr(ZoneIndex));
    3990             :             }
    3991        6176 :             MechVentOAMassFlow = SysOAMassFlow;
    3992      931228 :         } else if (this->SystemOAMethod == DataSizing::SysOAMethod::IAQPGC) {
    3993             :             // IAQP for generic contaminant control
    3994        7228 :             SysOAMassFlow = 0.0;
    3995       28912 :             for (int ZoneIndex = 1; ZoneIndex <= this->NumofVentMechZones; ++ZoneIndex) {
    3996       21684 :                 int ZoneNum = this->VentMechZone(ZoneIndex);
    3997       43368 :                 SysOAMassFlow += state.dataContaminantBalance->ZoneSysContDemand(ZoneNum).OutputRequiredToGCSP *
    3998       21684 :                                  GetCurrentScheduleValue(state, this->ZoneOASchPtr(ZoneIndex));
    3999             :             }
    4000        7228 :             MechVentOAMassFlow = SysOAMassFlow;
    4001      924000 :         } else if (this->SystemOAMethod == DataSizing::SysOAMethod::IAQPCOM) {
    4002             :             // IAQP for both CO2 and generic contaminant control
    4003           0 :             SysOAMassFlow = 0.0;
    4004           0 :             for (int ZoneIndex = 1; ZoneIndex <= this->NumofVentMechZones; ++ZoneIndex) {
    4005           0 :                 int ZoneNum = this->VentMechZone(ZoneIndex);
    4006           0 :                 SysOAMassFlow += state.dataContaminantBalance->ZoneSysContDemand(ZoneNum).OutputRequiredToCO2SP *
    4007           0 :                                  GetCurrentScheduleValue(state, this->ZoneOASchPtr(ZoneIndex));
    4008             :             }
    4009           0 :             MechVentOAMassFlow = SysOAMassFlow;
    4010           0 :             SysOAMassFlow = 0.0;
    4011           0 :             for (int ZoneIndex = 1; ZoneIndex <= this->NumofVentMechZones; ++ZoneIndex) {
    4012           0 :                 int ZoneNum = this->VentMechZone(ZoneIndex);
    4013           0 :                 SysOAMassFlow += state.dataContaminantBalance->ZoneSysContDemand(ZoneNum).OutputRequiredToGCSP *
    4014           0 :                                  GetCurrentScheduleValue(state, this->ZoneOASchPtr(ZoneIndex));
    4015             :             }
    4016           0 :             MechVentOAMassFlow = max(SysOAMassFlow, MechVentOAMassFlow);
    4017             :         } else {
    4018             :             // for system OA methods: Zone_Sum, VRP, CO2 methods
    4019             :             // new code for DCV method complying with the VRP defined in ASHRAE Standard 62.1-2010
    4020             : 
    4021             :             // Loop through each zone first to calc uncorrected system OA flow rate
    4022      924000 :             SysOAuc = 0.0;
    4023      924000 :             SysOA = 0.0;
    4024     7691481 :             for (int ZoneIndex = 1; ZoneIndex <= this->NumofVentMechZones; ++ZoneIndex) {
    4025     6767481 :                 int ZoneNum = this->VentMechZone(ZoneIndex);
    4026     6767481 :                 auto const &curZone(state.dataHeatBal->Zone(ZoneNum));
    4027     6767481 :                 Real64 curZoneOASchValue = GetCurrentScheduleValue(state, this->ZoneOASchPtr(ZoneIndex));
    4028             : 
    4029             :                 // Calc the zone OA flow rate based on the people component
    4030             :                 // ZoneIntGain(ZoneNum)%NOFOCC is the number of occupants of a zone at each time step, already counting the occupant schedule
    4031             :                 //  Checking DCV flag before calculating zone OA per person
    4032     6767481 :                 if (this->DCVFlag && this->SystemOAMethod != DataSizing::SysOAMethod::ProportionalControlDesOcc) {
    4033    16905264 :                     ZoneOACalc[static_cast<int>(DataSizing::OAFlowCalcMethod::PerPerson)] = state.dataHeatBal->ZoneIntGain(ZoneNum).NOFOCC *
    4034    16905264 :                                                                                             curZone.Multiplier * curZone.ListMultiplier *
    4035    11270176 :                                                                                             this->ZoneOAPeopleRate(ZoneIndex) * curZoneOASchValue;
    4036             :                 } else {
    4037     1132393 :                     ZoneOACalc[static_cast<int>(DataSizing::OAFlowCalcMethod::PerPerson)] =
    4038     1132393 :                         curZone.TotOccupants * curZone.Multiplier * curZone.ListMultiplier * this->ZoneOAPeopleRate(ZoneIndex) * curZoneOASchValue;
    4039             :                 }
    4040             : 
    4041             :                 // Calc the zone OA flow rate based on the floor area component
    4042     6767481 :                 ZoneOACalc[static_cast<int>(DataSizing::OAFlowCalcMethod::PerArea)] =
    4043     6767481 :                     curZone.FloorArea * curZone.Multiplier * curZone.ListMultiplier * this->ZoneOAAreaRate(ZoneIndex) * curZoneOASchValue;
    4044     6767481 :                 ZoneOACalc[static_cast<int>(DataSizing::OAFlowCalcMethod::PerZone)] =
    4045     6767481 :                     curZone.Multiplier * curZone.ListMultiplier * this->ZoneOAFlowRate(ZoneIndex) * curZoneOASchValue;
    4046     6767481 :                 ZoneOACalc[static_cast<int>(DataSizing::OAFlowCalcMethod::ACH)] =
    4047     6767481 :                     curZone.Multiplier * curZone.ListMultiplier * (this->ZoneOAACHRate(ZoneIndex) * curZone.Volume) * curZoneOASchValue / 3600.0;
    4048     6767481 :                 ZoneOACalc[static_cast<int>(DataSizing::OAFlowCalcMethod::Sum)] =
    4049    13534962 :                     ZoneOACalc[static_cast<int>(DataSizing::OAFlowCalcMethod::PerPerson)] +
    4050    13534962 :                     ZoneOACalc[static_cast<int>(DataSizing::OAFlowCalcMethod::PerArea)] +
    4051    13534962 :                     ZoneOACalc[static_cast<int>(DataSizing::OAFlowCalcMethod::PerZone)] +
    4052     6767481 :                     ZoneOACalc[static_cast<int>(DataSizing::OAFlowCalcMethod::ACH)];
    4053     6767481 :                 ZoneOACalc[static_cast<int>(DataSizing::OAFlowCalcMethod::Max)] =
    4054    20302443 :                     max(ZoneOACalc[static_cast<int>(DataSizing::OAFlowCalcMethod::PerPerson)],
    4055     6767481 :                         ZoneOACalc[static_cast<int>(DataSizing::OAFlowCalcMethod::PerArea)],
    4056     6767481 :                         ZoneOACalc[static_cast<int>(DataSizing::OAFlowCalcMethod::PerZone)],
    4057     6767481 :                         ZoneOACalc[static_cast<int>(DataSizing::OAFlowCalcMethod::ACH)]);
    4058             : 
    4059             :                 // Calc the breathing-zone OA flow rate
    4060     6767481 :                 OAIndex = this->ZoneDesignSpecOAObjIndex(ZoneIndex);
    4061     6767481 :                 if (OAIndex > 0) {
    4062     6767481 :                     ZoneOABZ = ZoneOACalc[static_cast<int>(state.dataSize->OARequirements(OAIndex).OAFlowMethod)];
    4063             :                 } else {
    4064           0 :                     ZoneOABZ = ZoneOACalc[static_cast<int>(DataSizing::OAFlowCalcMethod::PerPerson)];
    4065             :                 }
    4066             : 
    4067     6767481 :                 if (this->SystemOAMethod == DataSizing::SysOAMethod::ZoneSum) {
    4068             :                     // Sum the zone OA flow rates and done
    4069      605311 :                     SysOA += ZoneOABZ;
    4070             :                 } else {
    4071             :                     // Calc the uncorrected system OA flow rate - VRP and ProportionalControl
    4072     6162170 :                     SysOAuc += ZoneOABZ;
    4073             :                 }
    4074             :             }
    4075             : 
    4076             :             // get system supply air flow rate
    4077     1743634 :             if (this->SystemOAMethod == DataSizing::SysOAMethod::VRP || this->SystemOAMethod == DataSizing::SysOAMethod::ProportionalControlSchOcc ||
    4078     1639268 :                 this->SystemOAMethod == DataSizing::SysOAMethod::ProportionalControlDesOcc ||
    4079     1633080 :                 this->SystemOAMethod == DataSizing::SysOAMethod::ProportionalControlDesOARate ||
    4080      813446 :                 this->SystemOAMethod == DataSizing::SysOAMethod::VRPL) {
    4081             : 
    4082             :                 // System supply air flow rate is always greater than or equal the system outdoor air flow rate
    4083      780873 :                 if ((SysSA > 0.0) && (SysSA < (SysOAuc * state.dataEnvrn->StdRhoAir))) SysSA = SysOAuc * state.dataEnvrn->StdRhoAir;
    4084             : 
    4085             :                 // calc Xs - average outdoor air fraction
    4086      780873 :                 if (SysSA > 0.0) {
    4087      770578 :                     Xs = (SysOAuc * state.dataEnvrn->StdRhoAir) / SysSA;
    4088             :                 } else {
    4089       10295 :                     Xs = 0.0;
    4090             :                 }
    4091             : 
    4092             :                 // Loop through each zone again
    4093      780873 :                 SysEv = 2.0; // starting with a big fraction
    4094     6943043 :                 for (int ZoneIndex = 1; ZoneIndex <= this->NumofVentMechZones; ++ZoneIndex) {
    4095     6162170 :                     int ZoneNum = this->VentMechZone(ZoneIndex);
    4096     6162170 :                     int ZoneEquipConfigNum = ZoneNum; // correspondence - 1:1 of ZoneEquipConfig to Zone index
    4097     6162170 :                     ZoneEz = 0.0;
    4098             : 
    4099             :                     // Assign references
    4100     6162170 :                     auto &curZone(state.dataHeatBal->Zone(ZoneNum));
    4101     6162170 :                     auto &curZoneEquipConfig(state.dataZoneEquip->ZoneEquipConfig(ZoneEquipConfigNum));
    4102     6162170 :                     auto &curZoneSysEnergyDemand(state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneEquipConfigNum));
    4103     6162170 :                     ZoneName = curZone.Name;
    4104     6162170 :                     Real64 curZoneOASchValue = GetCurrentScheduleValue(state, this->ZoneOASchPtr(ZoneIndex));
    4105             : 
    4106             :                     // Calc the zone OA flow rate based on the people component
    4107             :                     // ZoneIntGain(ZoneNum)%NOFOCC is the number of occupants of a zone at each time step, already counting the occupant schedule
    4108             :                     //  Checking DCV flag before calculating zone OA per person
    4109     6162170 :                     if (this->DCVFlag && this->SystemOAMethod != DataSizing::SysOAMethod::ProportionalControlDesOcc) {
    4110    15719226 :                         ZoneOACalc[static_cast<int>(DataSizing::OAFlowCalcMethod::PerPerson)] = state.dataHeatBal->ZoneIntGain(ZoneNum).NOFOCC *
    4111    15719226 :                                                                                                 curZone.Multiplier * curZone.ListMultiplier *
    4112    10479484 :                                                                                                 this->ZoneOAPeopleRate(ZoneIndex) * curZoneOASchValue;
    4113             :                     } else {
    4114     2767284 :                         ZoneOACalc[static_cast<int>(DataSizing::OAFlowCalcMethod::PerPerson)] = curZone.TotOccupants * curZone.Multiplier *
    4115     1844856 :                                                                                                 curZone.ListMultiplier *
    4116     1844856 :                                                                                                 this->ZoneOAPeopleRate(ZoneIndex) * curZoneOASchValue;
    4117      922428 :                         CO2PeopleGeneration = 0.0;
    4118      922428 :                         if (this->SystemOAMethod == DataSizing::SysOAMethod::ProportionalControlDesOcc) {
    4119             :                             // Accumulate CO2 generation from people at design occupancy and current activity level
    4120           0 :                             for (PeopleNum = 1; PeopleNum <= state.dataHeatBal->TotPeople; ++PeopleNum) {
    4121           0 :                                 if (state.dataHeatBal->People(PeopleNum).ZonePtr != ZoneNum) continue;
    4122           0 :                                 CO2PeopleGeneration += state.dataHeatBal->People(PeopleNum).NumberOfPeople *
    4123           0 :                                                        state.dataHeatBal->People(PeopleNum).CO2RateFactor *
    4124           0 :                                                        GetCurrentScheduleValue(state, state.dataHeatBal->People(PeopleNum).ActivityLevelPtr);
    4125             :                             }
    4126             :                         }
    4127             :                     }
    4128             : 
    4129             :                     // Calc the zone OA flow rate based on the floor area component
    4130     6162170 :                     ZoneOACalc[static_cast<int>(DataSizing::OAFlowCalcMethod::PerArea)] =
    4131     6162170 :                         curZone.FloorArea * curZone.Multiplier * curZone.ListMultiplier * this->ZoneOAAreaRate(ZoneIndex) * curZoneOASchValue;
    4132     6162170 :                     ZoneOACalc[static_cast<int>(DataSizing::OAFlowCalcMethod::PerZone)] =
    4133     6162170 :                         curZone.Multiplier * curZone.ListMultiplier * this->ZoneOAFlowRate(ZoneIndex) * curZoneOASchValue;
    4134     6162170 :                     ZoneOACalc[static_cast<int>(DataSizing::OAFlowCalcMethod::ACH)] =
    4135     6162170 :                         curZone.Multiplier * curZone.ListMultiplier * (this->ZoneOAACHRate(ZoneIndex) * curZone.Volume) * curZoneOASchValue / 3600.0;
    4136             : 
    4137             :                     // Calc the breathing-zone OA flow rate
    4138     6162170 :                     OAIndex = this->ZoneDesignSpecOAObjIndex(ZoneIndex);
    4139     6162170 :                     if (OAIndex > 0) {
    4140     6162170 :                         std::array<Real64, static_cast<int>(OAFlowCalcMethod::Num)> BZOAFlowRate{
    4141     6162170 :                             ZoneOACalc[static_cast<int>(DataSizing::OAFlowCalcMethod::PerPerson)],
    4142     6162170 :                             ZoneOACalc[static_cast<int>(DataSizing::OAFlowCalcMethod::PerZone)],
    4143     6162170 :                             ZoneOACalc[static_cast<int>(DataSizing::OAFlowCalcMethod::PerArea)],
    4144     6162170 :                             ZoneOACalc[static_cast<int>(DataSizing::OAFlowCalcMethod::ACH)],
    4145    12324340 :                             ZoneOACalc[static_cast<int>(DataSizing::OAFlowCalcMethod::PerPerson)] +
    4146    12324340 :                                 ZoneOACalc[static_cast<int>(DataSizing::OAFlowCalcMethod::PerArea)] +
    4147    12324340 :                                 ZoneOACalc[static_cast<int>(DataSizing::OAFlowCalcMethod::PerZone)] +
    4148     6162170 :                                 ZoneOACalc[static_cast<int>(DataSizing::OAFlowCalcMethod::ACH)],
    4149    18486510 :                             max(ZoneOACalc[static_cast<int>(DataSizing::OAFlowCalcMethod::PerPerson)],
    4150     6162170 :                                 ZoneOACalc[static_cast<int>(DataSizing::OAFlowCalcMethod::PerArea)],
    4151     6162170 :                                 ZoneOACalc[static_cast<int>(DataSizing::OAFlowCalcMethod::PerZone)],
    4152     6162170 :                                 ZoneOACalc[static_cast<int>(DataSizing::OAFlowCalcMethod::ACH)]),
    4153             :                             0.0,
    4154             :                             0.0,
    4155    36973020 :                             0.0};
    4156             : 
    4157     6162170 :                         ZoneOABZ = BZOAFlowRate[static_cast<int>(state.dataSize->OARequirements(OAIndex).OAFlowMethod)];
    4158             :                     }
    4159             : 
    4160             :                     // use the ventilation rate procedure in ASHRAE Standard 62.1-2007
    4161             :                     // Calc the zone supplied OA flow rate counting the zone air distribution effectiveness
    4162             :                     //  First check whether the zone air distribution effectiveness schedule exists, if yes uses it;
    4163             :                     //   otherwise uses the inputs of zone distribution effectiveness in cooling mode or heating mode
    4164     6162170 :                     int ADEffSchPtr = this->ZoneADEffSchPtr(ZoneIndex);
    4165     6162170 :                     if (ADEffSchPtr > 0) {
    4166             :                         // Get schedule value for the zone air distribution effectiveness
    4167       18564 :                         ZoneEz = GetCurrentScheduleValue(state, ADEffSchPtr);
    4168             :                     } else {
    4169     6143606 :                         ZoneLoad = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).TotalOutputRequired;
    4170             : 
    4171             :                         // Zone in cooling mode
    4172     6143606 :                         if (ZoneLoad < 0.0) ZoneEz = this->ZoneADEffCooling(ZoneIndex);
    4173             : 
    4174             :                         // Zone in heating mode
    4175     6143606 :                         if (ZoneLoad > 0.0) ZoneEz = this->ZoneADEffHeating(ZoneIndex);
    4176             :                     }
    4177     6162170 :                     if (ZoneEz <= 0.0) {
    4178             :                         // Enforce defaults
    4179      550500 :                         ZoneEz = 1.0;
    4180             :                     }
    4181             : 
    4182             :                     // Calc zone supply OA flow rate
    4183     6162170 :                     if (this->SystemOAMethod == DataSizing::SysOAMethod::VRP || this->SystemOAMethod == DataSizing::SysOAMethod::VRPL) {
    4184             :                         // the VRP case
    4185     6125042 :                         ZoneOA = ZoneOABZ / ZoneEz;
    4186             : 
    4187       55692 :                     } else if (this->SystemOAMethod == DataSizing::SysOAMethod::ProportionalControlSchOcc ||
    4188       37128 :                                this->SystemOAMethod == DataSizing::SysOAMethod::ProportionalControlDesOcc ||
    4189       18564 :                                this->SystemOAMethod == DataSizing::SysOAMethod::ProportionalControlDesOARate) {
    4190             :                         // Check whether "Carbon Dioxide Control Availability Schedule" for ZoneControl:ContaminantController is specified
    4191       37128 :                         if (curZone.ZoneContamControllerSchedIndex > 0.0) {
    4192             :                             // Check the availability schedule value for ZoneControl:ContaminantController
    4193       12376 :                             ZoneContamControllerSched = GetCurrentScheduleValue(state, curZone.ZoneContamControllerSchedIndex);
    4194       12376 :                             if (ZoneContamControllerSched > 0.0) {
    4195       12376 :                                 ZoneOAMin = ZoneOACalc[static_cast<int>(DataSizing::OAFlowCalcMethod::PerArea)] / ZoneEz;
    4196       37128 :                                 ZoneOAMax = (ZoneOACalc[static_cast<int>(DataSizing::OAFlowCalcMethod::PerArea)] +
    4197       24752 :                                              ZoneOACalc[static_cast<int>(DataSizing::OAFlowCalcMethod::PerPerson)]) /
    4198             :                                             ZoneEz;
    4199       12376 :                                 if (this->SystemOAMethod == DataSizing::SysOAMethod::ProportionalControlDesOARate) {
    4200        6188 :                                     ZoneOAMax = ZoneOABZ / ZoneEz;
    4201        6188 :                                     if (this->OAPropCtlMinRateSchPtr(ZoneIndex) > 0) {
    4202           0 :                                         ZoneOAMin = ZoneOAMax * GetCurrentScheduleValue(state, this->OAPropCtlMinRateSchPtr(ZoneIndex));
    4203             :                                     } else {
    4204        6188 :                                         ZoneOAMin = ZoneOAMax;
    4205             :                                     }
    4206        6188 :                                     if (ZoneOAMax < ZoneOAMin) {
    4207           0 :                                         ZoneOAMin = ZoneOAMax;
    4208           0 :                                         ++this->OAMaxMinLimitErrorCount;
    4209           0 :                                         if (this->OAMaxMinLimitErrorCount < 2) {
    4210           0 :                                             ShowSevereError(state, std::string{RoutineName} + CurrentModuleObject + " = \"" + this->Name + "\".");
    4211           0 :                                             ShowContinueError(
    4212             :                                                 state,
    4213           0 :                                                 format("For System Outdoor Air Method = ProportionalControlBasedOnDesignOARate, maximum zone "
    4214             :                                                        "outdoor air rate ({:.4R}), is not greater than minimum zone outdoor air rate ({:.4R}).",
    4215             :                                                        ZoneOAMax,
    4216           0 :                                                        ZoneOAMin));
    4217           0 :                                             ShowContinueError(state,
    4218             :                                                               " The minimum zone outdoor air rate is set to the maximum zone outdoor air rate. "
    4219             :                                                               "Simulation continues...");
    4220           0 :                                             ShowContinueErrorTimeStamp(state, "");
    4221             :                                         } else {
    4222           0 :                                             ShowRecurringWarningErrorAtEnd(
    4223             :                                                 state,
    4224           0 :                                                 CurrentModuleObject + " = \"" + this->Name +
    4225             :                                                     "\", For System Outdoor Air Method = ProportionalControlBasedOnDesignOARate, maximum zone "
    4226             :                                                     "outdoor air rate is not greater than minimum zone outdoor air rate. Error continues...",
    4227             :                                                 this->OAMaxMinLimitErrorIndex);
    4228             :                                         }
    4229             :                                     }
    4230             :                                 }
    4231             : 
    4232       12376 :                                 if (ZoneOACalc[static_cast<int>(DataSizing::OAFlowCalcMethod::PerPerson)] > 0.0) {
    4233        5824 :                                     if (state.dataContaminantBalance->ZoneCO2GainFromPeople(ZoneNum) > 0.0) {
    4234        5824 :                                         if (curZone.ZoneMinCO2SchedIndex > 0.0) {
    4235             :                                             // Take the schedule value of "Minimum Carbon Dioxide Concentration Schedule Name"
    4236             :                                             // in the ZoneControl:ContaminantController
    4237        2912 :                                             ZoneMinCO2 = GetCurrentScheduleValue(state, curZone.ZoneMinCO2SchedIndex);
    4238             :                                         } else {
    4239        2912 :                                             ZoneMinCO2 = state.dataContaminantBalance->OutdoorCO2;
    4240             :                                         }
    4241             : 
    4242             :                                         // Calculate zone maximum target CO2 concentration in PPM
    4243        5824 :                                         if (this->SystemOAMethod == DataSizing::SysOAMethod::ProportionalControlDesOcc) {
    4244           0 :                                             ZoneMaxCO2 = state.dataContaminantBalance->OutdoorCO2 +
    4245           0 :                                                          (CO2PeopleGeneration * curZone.Multiplier * curZone.ListMultiplier * 1.0e6) / ZoneOAMax;
    4246        5824 :                                         } else if (curZone.ZoneMaxCO2SchedIndex > 0.0) {
    4247        2912 :                                             ZoneMaxCO2 = GetCurrentScheduleValue(state, curZone.ZoneMaxCO2SchedIndex);
    4248             :                                         } else {
    4249        5824 :                                             ZoneMaxCO2 = state.dataContaminantBalance->OutdoorCO2 +
    4250        5824 :                                                          (state.dataContaminantBalance->ZoneCO2GainFromPeople(ZoneNum) * curZone.Multiplier *
    4251        5824 :                                                           curZone.ListMultiplier * 1.0e6) /
    4252             :                                                              ZoneOAMax;
    4253             :                                         }
    4254             : 
    4255        5824 :                                         if (ZoneMaxCO2 <= ZoneMinCO2) {
    4256           0 :                                             ++this->CO2MaxMinLimitErrorCount;
    4257           0 :                                             if (this->SystemOAMethod == DataSizing::SysOAMethod::ProportionalControlSchOcc) {
    4258           0 :                                                 if (this->CO2MaxMinLimitErrorCount < 2) {
    4259           0 :                                                     ShowSevereError(state,
    4260           0 :                                                                     std::string{RoutineName} + CurrentModuleObject + " = \"" + this->Name + "\".");
    4261           0 :                                                     ShowContinueError(
    4262             :                                                         state,
    4263           0 :                                                         format("For System Outdoor Air Method = ProportionalControlBasedOnOccupancySchedule, "
    4264             :                                                                "maximum target CO2 concentration ({:.2R}), is not greater than minimum target "
    4265             :                                                                "CO2 concentration ({:.2R}).",
    4266             :                                                                ZoneMaxCO2,
    4267           0 :                                                                ZoneMinCO2));
    4268           0 :                                                     ShowContinueError(state,
    4269             :                                                                       "\"ProportionalControlBasedOnOccupancySchedule\" will not be modeled. "
    4270             :                                                                       "Default \"Standard62.1VentilationRateProcedure\" will be modeled. Simulation "
    4271             :                                                                       "continues...");
    4272           0 :                                                     ShowContinueErrorTimeStamp(state, "");
    4273             :                                                 } else {
    4274           0 :                                                     ShowRecurringWarningErrorAtEnd(state,
    4275           0 :                                                                                    CurrentModuleObject + " = \"" + this->Name +
    4276             :                                                                                        "\", For System Outdoor Air Method = "
    4277             :                                                                                        "ProportionalControlBasedOnOccupancySchedule, maximum "
    4278             :                                                                                        "target CO2 concentration is not greater than minimum "
    4279             :                                                                                        "target CO2 concentration. Error continues...",
    4280             :                                                                                    this->CO2MaxMinLimitErrorIndex);
    4281             :                                                 }
    4282             :                                             }
    4283           0 :                                             if (this->SystemOAMethod == DataSizing::SysOAMethod::ProportionalControlDesOcc) {
    4284           0 :                                                 if (this->CO2MaxMinLimitErrorCount < 2) {
    4285           0 :                                                     ShowSevereError(state,
    4286           0 :                                                                     std::string{RoutineName} + CurrentModuleObject + " = \"" + this->Name + "\".");
    4287           0 :                                                     ShowContinueError(
    4288             :                                                         state,
    4289           0 :                                                         format("For System Outdoor Air Method = ProportionalControlBasedOnDesignOccupancy, "
    4290             :                                                                "maximum target CO2 concentration ({:.2R}), is not greater than minimum target "
    4291             :                                                                "CO2 concentration ({:.2R}).",
    4292             :                                                                ZoneMaxCO2,
    4293           0 :                                                                ZoneMinCO2));
    4294           0 :                                                     ShowContinueError(state,
    4295             :                                                                       "\"ProportionalControlBasedOnDesignOccupancy\" will not be modeled. "
    4296             :                                                                       "Default \"Standard62.1VentilationRateProcedure\" will be modeled. Simulation "
    4297             :                                                                       "continues...");
    4298           0 :                                                     ShowContinueErrorTimeStamp(state, "");
    4299             :                                                 } else {
    4300           0 :                                                     ShowRecurringWarningErrorAtEnd(state,
    4301           0 :                                                                                    CurrentModuleObject + " = \"" + this->Name +
    4302             :                                                                                        "\", For System Outdoor Air Method = "
    4303             :                                                                                        "ProportionalControlBasedOnDesignOccupancy, maximum "
    4304             :                                                                                        "target CO2 concentration is not greater than minimum "
    4305             :                                                                                        "target CO2 concentration. Error continues...",
    4306             :                                                                                    this->CO2MaxMinLimitErrorIndex);
    4307             :                                                 }
    4308             :                                             }
    4309           0 :                                             if (this->SystemOAMethod == DataSizing::SysOAMethod::ProportionalControlDesOARate) {
    4310           0 :                                                 if (this->CO2MaxMinLimitErrorCount < 2) {
    4311           0 :                                                     ShowSevereError(state,
    4312           0 :                                                                     std::string{RoutineName} + CurrentModuleObject + " = \"" + this->Name + "\".");
    4313           0 :                                                     ShowContinueError(
    4314             :                                                         state,
    4315           0 :                                                         format("For System Outdoor Air Method = ProportionalControlBasedOnDesignOARate, maximum "
    4316             :                                                                "target CO2 concentration ({:.2R}), is not greater than minimum target CO2 "
    4317             :                                                                "concentration ({:.2R}).",
    4318             :                                                                ZoneMaxCO2,
    4319           0 :                                                                ZoneMinCO2));
    4320           0 :                                                     ShowContinueError(
    4321             :                                                         state,
    4322             :                                                         "\"ProportionalControlBasedOnDesignOARate\" will not be modeled. Default "
    4323             :                                                         "\"Standard62.1VentilationRateProcedure\" will be modeled. Simulation continues...");
    4324           0 :                                                     ShowContinueErrorTimeStamp(state, "");
    4325             :                                                 } else {
    4326           0 :                                                     ShowRecurringWarningErrorAtEnd(state,
    4327           0 :                                                                                    CurrentModuleObject + " = \"" + this->Name +
    4328             :                                                                                        "\", For System Outdoor Air Method = "
    4329             :                                                                                        "ProportionalControlBasedOnDesignOARate, maximum target "
    4330             :                                                                                        "CO2 concentration is not greater than minimum target CO2 "
    4331             :                                                                                        "concentration. Error continues...",
    4332             :                                                                                    this->CO2MaxMinLimitErrorIndex);
    4333             :                                                 }
    4334             :                                             }
    4335             : 
    4336           0 :                                             ZoneOA = ZoneOABZ / ZoneEz;
    4337             :                                         } else {
    4338             : 
    4339        5824 :                                             if (state.dataContaminantBalance->ZoneAirCO2(ZoneNum) <= ZoneMinCO2) {
    4340             :                                                 // Zone air CO2 concentration is less than minimum zone CO2 concentration, set the Zone OA flow
    4341             :                                                 // rate to minimum Zone OA flow rate when the zone is unoccupied
    4342           0 :                                                 ZoneOA = ZoneOAMin;
    4343        5824 :                                             } else if (state.dataContaminantBalance->ZoneAirCO2(ZoneNum) >= ZoneMaxCO2) {
    4344             :                                                 // Zone air CO2 concentration is greater than maximum zone CO2 concentration, set the Zone OA flow
    4345             :                                                 // rate to maximum Zone OA flow rate (i.e.
    4346             :                                                 // ZoneOACalc[static_cast<int>(DataSizing::OAFlowCalcMethod::PerArea)] + ZoneOAPeople)
    4347        1156 :                                                 ZoneOA = ZoneOAMax;
    4348             :                                             } else {
    4349             :                                                 // Zone air CO2 concentration is between maximum and minimum limits of zone CO2 concentration,
    4350             :                                                 // set Zone OA flow rate by proportionally adjusting between ZoneOAMin and ZoneOAMax
    4351        4668 :                                                 ZoneOA = ZoneOAMin +
    4352        9336 :                                                          (ZoneOAMax - ZoneOAMin) * ((state.dataContaminantBalance->ZoneAirCO2(ZoneNum) - ZoneMinCO2) /
    4353        4668 :                                                                                     (ZoneMaxCO2 - ZoneMinCO2));
    4354             :                                             }
    4355             :                                         }
    4356             :                                     } else {
    4357           0 :                                         if (state.dataGlobal->DisplayExtraWarnings) {
    4358           0 :                                             ++this->CO2GainErrorCount;
    4359           0 :                                             if (this->SystemOAMethod == DataSizing::SysOAMethod::ProportionalControlSchOcc) {
    4360           0 :                                                 if (this->CO2GainErrorCount < 2) {
    4361           0 :                                                     ShowSevereError(state,
    4362           0 :                                                                     std::string{RoutineName} + CurrentModuleObject + " = \"" + this->Name + "\".");
    4363           0 :                                                     ShowContinueError(state,
    4364             :                                                                       "For System Outdoor Air Method = "
    4365             :                                                                       "ProportionalControlBasedOnOccupancySchedule, CO2 generation from people "
    4366           0 :                                                                       "is not greater than zero. Occurs in Zone =\"" +
    4367           0 :                                                                           curZone.Name + "\". ");
    4368           0 :                                                     ShowContinueError(state,
    4369             :                                                                       "\"ProportionalControlBasedOnOccupancySchedule\" will not be modeled. "
    4370             :                                                                       "Default \"Standard62.1VentilationRateProcedure\" will be modeled. Simulation "
    4371             :                                                                       "continues...");
    4372           0 :                                                     ShowContinueErrorTimeStamp(state, "");
    4373             :                                                 } else {
    4374           0 :                                                     ShowRecurringWarningErrorAtEnd(
    4375             :                                                         state,
    4376           0 :                                                         CurrentModuleObject + " = \"" + this->Name +
    4377             :                                                             "\", For System Outdoor Air Method = ProportionalControlBasedOnOccupancySchedule, "
    4378             :                                                             "CO2 generation from people is not greater than zero. Error continues...",
    4379             :                                                         this->CO2GainErrorIndex);
    4380             :                                                 }
    4381             :                                             }
    4382           0 :                                             if (this->SystemOAMethod == DataSizing::SysOAMethod::ProportionalControlDesOcc) {
    4383           0 :                                                 if (this->CO2GainErrorCount < 2) {
    4384           0 :                                                     ShowSevereError(state,
    4385           0 :                                                                     std::string{RoutineName} + CurrentModuleObject + " = \"" + this->Name + "\".");
    4386           0 :                                                     ShowContinueError(state,
    4387             :                                                                       "For System Outdoor Air Method = "
    4388             :                                                                       "ProportionalControlBasedOnDesignOccupancy, CO2 generation from people is "
    4389           0 :                                                                       "not greater than zero. Occurs in Zone =\"" +
    4390           0 :                                                                           curZone.Name + "\". ");
    4391           0 :                                                     ShowContinueError(state,
    4392             :                                                                       "\"ProportionalControlBasedOnDesignOccupancy\" will not be modeled. "
    4393             :                                                                       "Default \"Standard62.1VentilationRateProcedure\" will be modeled. Simulation "
    4394             :                                                                       "continues...");
    4395           0 :                                                     ShowContinueErrorTimeStamp(state, "");
    4396             :                                                 } else {
    4397           0 :                                                     ShowRecurringWarningErrorAtEnd(
    4398             :                                                         state,
    4399           0 :                                                         CurrentModuleObject + " = \"" + this->Name +
    4400             :                                                             "\", For System Outdoor Air Method = ProportionalControlBasedOnDesignOccupancy, CO2 "
    4401             :                                                             "generation from people is not greater than zero. Error continues...",
    4402             :                                                         this->CO2GainErrorIndex);
    4403             :                                                 }
    4404             :                                             }
    4405             :                                         }
    4406           0 :                                         ZoneOA = ZoneOABZ / ZoneEz;
    4407             :                                     }
    4408             :                                 } else {
    4409             :                                     // ZoneOACalc[static_cast<int>(DataSizing::OAFlowCalcMethod::PerPerson)] is less than or equal to zero
    4410        6552 :                                     ZoneOA = ZoneOABZ / ZoneEz;
    4411             :                                 }
    4412             :                             } else {
    4413             :                                 // ZoneControl:ContaminantController is scheduled off (not available)
    4414           0 :                                 ZoneOA = ZoneOABZ / ZoneEz;
    4415             :                             }
    4416             :                         } else {
    4417             :                             // "Carbon Dioxide Control Availability Schedule" for ZoneControl:ContaminantController not found
    4418       24752 :                             ZoneOA = ZoneOABZ / ZoneEz;
    4419             :                         }
    4420       37128 :                         SysOA = SysOA + ZoneOA;
    4421             :                     }
    4422             : 
    4423             :                     // Get the zone supply air flow rate
    4424     6162170 :                     ZoneSA = 0.0;
    4425     6162170 :                     ZonePA = 0.0;
    4426     6162170 :                     Ep = 1.0;
    4427     6162170 :                     if (ZoneEquipConfigNum > 0) {
    4428    12324340 :                         for (int InNodeIndex = 1; InNodeIndex <= curZoneEquipConfig.NumInletNodes; ++InNodeIndex) {
    4429             :                             // Assume primary air is always stored at the AirDistUnitCool (cooling deck if dual duct)
    4430     6162170 :                             PriNode = curZoneEquipConfig.AirDistUnitCool(InNodeIndex).InNode;
    4431     6162170 :                             if (PriNode > 0) {
    4432     6162170 :                                 NodeTemp = state.dataLoopNodes->Node(PriNode).Temp;
    4433     6162170 :                                 NodeHumRat = state.dataLoopNodes->Node(PriNode).HumRat;
    4434     6162170 :                                 MassFlowRate = state.dataLoopNodes->Node(PriNode).MassFlowRate;
    4435             :                             } else {
    4436           0 :                                 MassFlowRate = 0.0;
    4437             :                             }
    4438             :                             // total primary air to terminal units of the zone
    4439     6162170 :                             if (MassFlowRate > 0.0)
    4440     6110663 :                                 ZonePA += MassFlowRate / PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, NodeTemp, NodeHumRat);
    4441             : 
    4442             :                             // or InletNode = ZoneEquipConfig(ZoneEquipConfigNum)%AirDistUnitCool(InNodeIndex)%OutNode
    4443     6162170 :                             InletNode = curZoneEquipConfig.InletNode(InNodeIndex);
    4444     6162170 :                             if (InletNode > 0) {
    4445     6162170 :                                 NodeTemp = state.dataLoopNodes->Node(InletNode).Temp;
    4446     6162170 :                                 NodeHumRat = state.dataLoopNodes->Node(InletNode).HumRat; // ZoneAirHumRat(ZoneNum)
    4447     6162170 :                                 MassFlowRate = state.dataLoopNodes->Node(InletNode).MassFlowRate;
    4448             :                             } else {
    4449           0 :                                 MassFlowRate = 0.0;
    4450             :                             }
    4451             :                             // total supply air to the zone
    4452     6162170 :                             if (MassFlowRate > 0.0)
    4453     6113987 :                                 ZoneSA += MassFlowRate / PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, NodeTemp, NodeHumRat);
    4454             :                         }
    4455             : 
    4456             :                         // calc zone primary air fraction
    4457     6162170 :                         if (ZoneSA > 0.0) Ep = ZonePA / ZoneSA;
    4458     6162170 :                         if (Ep > 1.0) Ep = 1.0;
    4459             :                     }
    4460             : 
    4461             :                     // Calc the zone OA fraction = Zone OA flow rate / Zone supply air flow rate
    4462     6162170 :                     if (ZoneSA > 0.0) {
    4463     6113987 :                         ZoneOAFrac = ZoneOA / ZoneSA;
    4464             :                         // Zone OA fraction cannot be more than 1
    4465     6113987 :                         if (ZoneOAFrac > 1.0) ZoneOAFrac = 1.0;
    4466             :                     } else {
    4467       48183 :                         ZoneOAFrac = 0.0;
    4468             :                     }
    4469             : 
    4470             :                     // added for TRACE - zone maximum OA fraction - calculate the adjustment factor for the TU/zone supply air flow
    4471             :                     // only for VRP system OA method
    4472     6162170 :                     curZoneSysEnergyDemand.SupplyAirAdjustFactor = 1.0;
    4473             : 
    4474     6162170 :                     if (this->SystemOAMethod == DataSizing::SysOAMethod::VRP || this->SystemOAMethod == DataSizing::SysOAMethod::VRPL) {
    4475     6125042 :                         if (ZoneOAFrac > this->ZoneMaxOAFraction) {
    4476           0 :                             if (this->ZoneMaxOAFraction > 0.0) {
    4477           0 :                                 curZoneSysEnergyDemand.SupplyAirAdjustFactor = ZoneOAFrac / this->ZoneMaxOAFraction;
    4478             :                             } else {
    4479           0 :                                 curZoneSysEnergyDemand.SupplyAirAdjustFactor = 1.0;
    4480             :                             }
    4481             : 
    4482             :                             // cap zone OA fraction at the maximum specified
    4483           0 :                             ZoneOAFrac = this->ZoneMaxOAFraction;
    4484             :                         }
    4485             :                     }
    4486             : 
    4487             :                     // Zone air secondary recirculation fraction
    4488     6162170 :                     Er = this->ZoneSecondaryRecirculation(ZoneIndex);
    4489     6162170 :                     if (Er > 0.0) {
    4490             :                         // multi-path ventilation system using VRP
    4491       19630 :                         Fa = Ep + (1.0 - Ep) * Er;
    4492       19630 :                         Fb = Ep;
    4493       19630 :                         Fc = 1.0 - (1.0 - ZoneEz) * (1.0 - Er) * (1.0 - Ep);
    4494             : 
    4495             :                         // Calc zone ventilation efficiency
    4496       19630 :                         if (Fa > 0.0) {
    4497       19630 :                             Evz = 1.0 + Xs * Fb / Fa - ZoneOAFrac * Ep * Fc / Fa;
    4498             :                         } else {
    4499           0 :                             Evz = 1.0;
    4500             :                         }
    4501             :                     } else {
    4502             :                         // single-path ventilation system
    4503     6142540 :                         Evz = 1.0 + Xs - ZoneOAFrac;
    4504             :                     }
    4505             : 
    4506             :                     // calc system ventilation efficiency = Minimum of zone ventilation efficiency
    4507     6162170 :                     if (Evz < 0.0) Evz = 0.0;
    4508     6162170 :                     if (Evz < SysEv) SysEv = Evz;
    4509             : 
    4510             :                 } // zone loop
    4511             : 
    4512             :                 // Calc the system supply OA flow rate counting the system ventilation efficiency
    4513      780873 :                 if (SysEv <= 0.0) SysEv = 1.0;
    4514             : 
    4515             :                 // Calc system outdoor air requirement
    4516     1555558 :                 if (this->SystemOAMethod == DataSizing::SysOAMethod::ProportionalControlSchOcc ||
    4517     1549370 :                     this->SystemOAMethod == DataSizing::SysOAMethod::ProportionalControlDesOcc ||
    4518      774685 :                     this->SystemOAMethod == DataSizing::SysOAMethod::ProportionalControlDesOARate) {
    4519       12376 :                     SysOA = SysOA / SysEv;
    4520      768497 :                 } else if (this->SystemOAMethod == DataSizing::SysOAMethod::VRPL && this->SysDesOA > 0.0) {
    4521             :                     // Limit system OA to design OA minimum flow rate, as per ASHRAE Guideline 36-2018 Section 5.16.3.1
    4522             :                     // If no system sizing run is done (i.e. no Sizing:System) the design outdoor air flow rate is not known
    4523      670319 :                     SysOA = min(SysOAuc / SysEv, this->SysDesOA);
    4524             :                 } else {
    4525       98178 :                     SysOA = SysOAuc / SysEv;
    4526             :                 }
    4527             :             }
    4528             : 
    4529             :             // Finally calc the system supply OA mass flow rate
    4530      924000 :             MechVentOAMassFlow = SysOA * state.dataEnvrn->StdRhoAir;
    4531             :         }
    4532             : 
    4533             :     } else {
    4534      274266 :         MechVentOAMassFlow = 0.0;
    4535             :     }
    4536     1211670 : }
    4537             : 
    4538    23012475 : void OAControllerProps::CalcOAEconomizer(EnergyPlusData &state,
    4539             :                                          int const AirLoopNum,
    4540             :                                          Real64 const OutAirMinFrac,
    4541             :                                          Real64 &OASignal,
    4542             :                                          bool &HighHumidityOperationFlag,
    4543             :                                          bool const FirstHVACIteration)
    4544             : {
    4545             :     using General::SolveRoot;
    4546             :     using SetPointManager::GetCoilFreezingCheckFlag;
    4547             : 
    4548    23012475 :     int constexpr MaxIte(500);             // Maximum number of iterations
    4549    23012475 :     Real64 constexpr Acc(0.0001);          // Accuracy of result
    4550             :     bool AirLoopEconoLockout;              // Economizer lockout flag
    4551             :     bool AirLoopNightVent;                 // Night Ventilation flag for air loop
    4552             :     bool EconomizerOperationFlag;          // TRUE if OA economizer is active
    4553             :     Real64 EconomizerAirFlowScheduleValue; // value of economizer operation schedule (push-button type control schedule)
    4554             :     Real64 MaximumOAFracBySetPoint;        // The maximum OA fraction due to freezing cooling coil check
    4555             :     Real64 OutAirSignal;                   // Used to set OA mass flow rate
    4556             :     int SolFla;                            // Flag of solver
    4557             :     Real64 lowFlowResiduum;                // result of low OA flow calculation (Tmixedair_sp - Tmixedair)
    4558             :     Real64 highFlowResiduum;               // result of high OA flow calculation (Tmixedair_sp - Tmixedair)
    4559             :     Real64 minOAFrac;
    4560             : 
    4561    23012475 :     if (AirLoopNum > 0) {
    4562             :         // Check lockout with heating for any airloop - will lockout economizer even on airloops without a unitary system
    4563    22448592 :         if (this->Lockout == LockoutType::LockoutWithHeatingPossible) {
    4564             :             // For all system types (even ones that don't set AirLoopEconoLockout) lock out economizer if unfavorable for heating
    4565     3994185 :             if (state.dataAirLoop->AirLoopControlInfo(AirLoopNum).CheckHeatRecoveryBypassStatus &&
    4566      568422 :                 state.dataAirLoop->AirLoopControlInfo(AirLoopNum).OASysComponentsSimulated) {
    4567             : 
    4568      270574 :                 if (this->MixedAirTempAtMinOAFlow <= state.dataLoopNodes->Node(this->MixNode).TempSetPoint) {
    4569       76834 :                     state.dataAirLoop->AirLoopControlInfo(AirLoopNum).EconomizerFlowLocked = true;
    4570             :                     // this->OAMassFlow = AirLoopFlow( AirLoopNum ).MinOutAir;
    4571             :                     // AirLoopFlow( AirLoopNum ).OAFrac = this->OAMassFlow / this->MixMassFlow;
    4572       76834 :                     state.dataAirLoop->AirLoopControlInfo(AirLoopNum).EconoLockout = true;
    4573       76834 :                     EconomizerOperationFlag = false;
    4574             :                 } else {
    4575      193740 :                     state.dataAirLoop->AirLoopControlInfo(AirLoopNum).EconomizerFlowLocked = false;
    4576      193740 :                     this->HRHeatingCoilActive = 0;
    4577             :                 }
    4578      270574 :                 state.dataAirLoop->AirLoopControlInfo(AirLoopNum).CheckHeatRecoveryBypassStatus = false;
    4579             :             }
    4580             :         }
    4581             :     }
    4582             : 
    4583    23012475 :     if (AirLoopNum > 0) {
    4584    22448592 :         AirLoopEconoLockout = state.dataAirLoop->AirLoopControlInfo(AirLoopNum).EconoLockout;
    4585    22448592 :         AirLoopNightVent = state.dataAirLoop->AirLoopControlInfo(AirLoopNum).NightVent;
    4586             :     } else {
    4587      563883 :         AirLoopEconoLockout = false;
    4588      563883 :         AirLoopNightVent = false;
    4589             :     }
    4590             : 
    4591             :     // Define an outside air signal
    4592    23012475 :     if (this->MixedAirSPMNum > 0) {
    4593       10154 :         this->CoolCoilFreezeCheck = GetCoilFreezingCheckFlag(state, this->MixedAirSPMNum);
    4594             :     } else {
    4595    23002321 :         this->CoolCoilFreezeCheck = false;
    4596             :     }
    4597             : 
    4598    23012475 :     if (std::abs(this->RetTemp - this->InletTemp) > SmallTempDiff) {
    4599    23012050 :         OutAirSignal = (this->RetTemp - this->MixSetTemp) / (this->RetTemp - this->InletTemp);
    4600    23012050 :         if (this->CoolCoilFreezeCheck) {
    4601           0 :             this->MaxOAFracBySetPoint = 0.0;
    4602           0 :             MaximumOAFracBySetPoint = OutAirSignal;
    4603             :         }
    4604             :     } else {
    4605         425 :         if (this->RetTemp - this->MixSetTemp < 0.0) {
    4606         175 :             if (this->RetTemp - this->InletTemp >= 0.0) {
    4607         109 :                 OutAirSignal = -1.0;
    4608             :             } else {
    4609          66 :                 OutAirSignal = 1.0;
    4610             :             }
    4611             :         } else {
    4612         250 :             if (this->RetTemp - this->InletTemp >= 0.0) {
    4613         234 :                 OutAirSignal = 1.0;
    4614             :             } else {
    4615          16 :                 OutAirSignal = -1.0;
    4616             :             }
    4617             :         }
    4618             :     }
    4619    23012475 :     OutAirSignal = min(max(OutAirSignal, OutAirMinFrac), 1.0);
    4620             : 
    4621             :     // If no economizer, set to minimum and disable economizer and high humidity control
    4622    23012475 :     if (this->Econo == EconoOp::NoEconomizer) {
    4623     7951550 :         OutAirSignal = OutAirMinFrac;
    4624     7951550 :         EconomizerOperationFlag = false;
    4625     7951550 :         EconomizerAirFlowScheduleValue = 0.0;
    4626     7951550 :         HighHumidityOperationFlag = false;
    4627    15060925 :     } else if (this->MaxOA < SmallAirVolFlow) {
    4628           0 :         OutAirSignal = OutAirMinFrac;
    4629           0 :         EconomizerOperationFlag = false;
    4630           0 :         EconomizerAirFlowScheduleValue = 0.0;
    4631           0 :         HighHumidityOperationFlag = false;
    4632    15060925 :     } else if (AirLoopEconoLockout) {
    4633      468278 :         OutAirSignal = OutAirMinFrac;
    4634      468278 :         EconomizerOperationFlag = false;
    4635      468278 :         EconomizerAirFlowScheduleValue = 0.0;
    4636      468278 :         HighHumidityOperationFlag = false;
    4637             :     } else {
    4638             :         // Changed by Amit for new implementation
    4639             :         // Otherwise do the limit checks
    4640    14592647 :         EconomizerOperationFlag = true;
    4641             :         // Outside air temp greater than mix air setpoint
    4642    14592647 :         if (this->InletTemp > this->MixSetTemp) {
    4643    10797729 :             OutAirSignal = 1.0;
    4644             :         }
    4645             :         // Return air temp limit
    4646    14592647 :         if (this->Econo == EconoOp::DifferentialDryBulb) {
    4647    11438118 :             if (this->InletTemp > this->RetTemp) {
    4648     4346662 :                 OutAirSignal = OutAirMinFrac;
    4649     4346662 :                 EconomizerOperationFlag = false;
    4650             :             }
    4651    11438118 :             this->Checksetpoints(state, OutAirMinFrac, OutAirSignal, EconomizerOperationFlag);
    4652             :         }
    4653             :         // Return air enthalpy limit
    4654    14592647 :         if (this->Econo == EconoOp::DifferentialEnthalpy) {
    4655      657767 :             if (this->InletEnth > this->RetEnth) {
    4656      437692 :                 OutAirSignal = OutAirMinFrac;
    4657      437692 :                 EconomizerOperationFlag = false;
    4658             :             }
    4659      657767 :             this->Checksetpoints(state, OutAirMinFrac, OutAirSignal, EconomizerOperationFlag);
    4660             :         }
    4661             :         // Outside air temperature limit
    4662    14592647 :         if (this->Econo == EconoOp::FixedDryBulb) {
    4663     2434923 :             this->Checksetpoints(state, OutAirMinFrac, OutAirSignal, EconomizerOperationFlag);
    4664             :         }
    4665             :         // Fixed Enthalpy limit
    4666    14592647 :         if (this->Econo == EconoOp::FixedEnthalpy) {
    4667           0 :             this->Checksetpoints(state, OutAirMinFrac, OutAirSignal, EconomizerOperationFlag);
    4668             :         }
    4669             :         // FIXED DEW POINT AND DRY BULB TEMPERATURE STRATEGY
    4670    14592647 :         if (this->Econo == EconoOp::FixedDewPointAndDryBulb) {
    4671           0 :             this->Checksetpoints(state, OutAirMinFrac, OutAirSignal, EconomizerOperationFlag);
    4672             :         }
    4673             :         // ELECRONIC ENTHALPY, HUMIDITY RATIO CURVE
    4674    14592647 :         if (this->Econo == EconoOp::ElectronicEnthalpy) {
    4675       61839 :             this->Checksetpoints(state, OutAirMinFrac, OutAirSignal, EconomizerOperationFlag);
    4676             :         }
    4677             :         // Differential dry bulb and enthalpy strategy
    4678    14592647 :         if (this->Econo == EconoOp::DifferentialDryBulbAndEnthalpy) {
    4679           0 :             if (this->InletTemp > this->RetTemp) {
    4680           0 :                 OutAirSignal = OutAirMinFrac;
    4681           0 :                 EconomizerOperationFlag = false;
    4682             :             }
    4683           0 :             if (this->InletEnth > this->RetEnth) {
    4684           0 :                 OutAirSignal = OutAirMinFrac;
    4685           0 :                 EconomizerOperationFlag = false;
    4686             :             }
    4687           0 :             this->Checksetpoints(state, OutAirMinFrac, OutAirSignal, EconomizerOperationFlag);
    4688             :         }
    4689             : 
    4690    14592647 :         if (this->TempLowLim != BlankNumeric && this->OATemp < this->TempLowLim) {
    4691      953766 :             OutAirSignal = OutAirMinFrac;
    4692      953766 :             EconomizerOperationFlag = false;
    4693             :         }
    4694             :         // Increase air flow for humidity control
    4695             :         // (HumidistatZoneNum is greater than 0 IF High Humidity Control Flag = YES, checked in GetInput)
    4696    14592647 :         if (this->HumidistatZoneNum > 0) {
    4697             :             //   IF humidistat senses a moisture load check to see if modifying air flow is appropriate, otherwise disable modified air flow
    4698       58527 :             if (state.dataZoneEnergyDemand->ZoneSysMoistureDemand(this->HumidistatZoneNum).TotalOutputRequired < 0.0) {
    4699             :                 //     IF OAController is not allowed to modify air flow during high outdoor humrat condition, then disable modified air flow
    4700             :                 //     if indoor humrat is less than or equal to outdoor humrat
    4701       41300 :                 if (!this->ModifyDuringHighOAMoisture &&
    4702       20650 :                     (state.dataLoopNodes->Node(this->NodeNumofHumidistatZone).HumRat - this->OAHumRat) <= DataHVACGlobals::SmallHumRatDiff) {
    4703       20256 :                     HighHumidityOperationFlag = false;
    4704             :                 } else {
    4705         394 :                     HighHumidityOperationFlag = true;
    4706             :                 }
    4707             :             } else {
    4708       37877 :                 HighHumidityOperationFlag = false;
    4709             :             }
    4710             :         } else {
    4711    14534120 :             HighHumidityOperationFlag = false;
    4712             :         }
    4713             : 
    4714             :         // Check time of day economizer schedule, enable economizer if schedule value > 0
    4715    14592647 :         EconomizerAirFlowScheduleValue = 0.0;
    4716    14592647 :         if (this->EconomizerOASchedPtr > 0) {
    4717       62012 :             EconomizerAirFlowScheduleValue = GetCurrentScheduleValue(state, this->EconomizerOASchedPtr);
    4718       62012 :             if (EconomizerAirFlowScheduleValue > 0.0) {
    4719         852 :                 EconomizerOperationFlag = true;
    4720         852 :                 OutAirSignal = 1.0;
    4721             :             }
    4722             :         }
    4723             :     }
    4724             : 
    4725             :     // OutAirSignal will not give exactly the correct mixed air temperature (equal to the setpoint) since
    4726             :     // it was calculated using the approximate method of sensible energy balance. Now we have to get the
    4727             :     // accurate result using a full mass, enthalpy and moisture balance and iteration.
    4728    24284196 :     if (OutAirSignal > OutAirMinFrac && OutAirSignal < 1.0 && this->MixMassFlow > VerySmallMassFlow &&
    4729     2543442 :         this->ControllerType_Num == MixedAirControllerType::ControllerOutsideAir && !AirLoopNightVent) {
    4730             : 
    4731     1271721 :         if (AirLoopNum > 0) {
    4732             : 
    4733     1271721 :             if (state.dataAirLoop->OutsideAirSys(state.dataAirLoop->AirLoopControlInfo(AirLoopNum).OASysNum).NumComponents == 1) {
    4734             :                 // no need to simulate OA System if only a mixer is used in the OutsideAirSystem
    4735             : 
    4736    63999964 :                 auto f = [&state, this](Real64 const OASignal) {
    4737     4571426 :                     Real64 const OAMassFlowRate = OASignal * this->MixMassFlow;
    4738     4571426 :                     Real64 const RecircMassFlowRate = max(this->MixMassFlow - OAMassFlowRate, 0.0);
    4739     9142852 :                     Real64 const RecircEnth = state.dataLoopNodes->Node(this->RetNode).Enthalpy;
    4740     9142852 :                     Real64 const RecircHumRat = state.dataLoopNodes->Node(this->RetNode).HumRat;
    4741             :                     Real64 const MixEnth =
    4742    18285704 :                         (RecircMassFlowRate * RecircEnth + OAMassFlowRate * state.dataLoopNodes->Node(this->OANode).Enthalpy) / this->MixMassFlow;
    4743             :                     Real64 const MixHumRat =
    4744    18285704 :                         (RecircMassFlowRate * RecircHumRat + OAMassFlowRate * state.dataLoopNodes->Node(this->OANode).HumRat) / this->MixMassFlow;
    4745     4571426 :                     Real64 const MixTemp = Psychrometrics::PsyTdbFnHW(MixEnth, MixHumRat);
    4746     9142852 :                     return state.dataLoopNodes->Node(this->MixNode).TempSetPoint - MixTemp;
    4747     1259483 :                 };
    4748             : 
    4749     1259483 :                 General::SolveRoot(state, Acc, MaxIte, SolFla, OASignal, f, OutAirMinFrac, 1.0);
    4750     1259483 :                 if (SolFla < 0) {
    4751         834 :                     OASignal = OutAirSignal;
    4752             :                 }
    4753             : 
    4754             :             } else {
    4755             : 
    4756             :                 // simulate OA System if equipment exists other than the mixer (e.g., heating/cooling coil, HX, ect.)
    4757             : 
    4758             :                 // 1 - check min OA flow result
    4759       12238 :                 if (this->FixedMin) {
    4760       12238 :                     state.dataLoopNodes->Node(this->OANode).MassFlowRate =
    4761       12238 :                         min(max(this->ExhMassFlow, OutAirMinFrac * state.dataAirLoop->AirLoopFlow(AirLoopNum).DesSupply),
    4762       12238 :                             state.dataLoopNodes->Node(this->MixNode).MassFlowRate);
    4763       12238 :                     state.dataLoopNodes->Node(this->RelNode).MassFlowRate =
    4764       12238 :                         max(state.dataLoopNodes->Node(this->OANode).MassFlowRate - this->ExhMassFlow, 0.0);
    4765             :                     // save actual OA flow frac for use as min value for RegulaFalsi call
    4766       12238 :                     minOAFrac = max(OutAirMinFrac, state.dataLoopNodes->Node(this->OANode).MassFlowRate / this->MixMassFlow);
    4767             :                 } else {
    4768           0 :                     state.dataLoopNodes->Node(this->OANode).MassFlowRate =
    4769           0 :                         max(this->ExhMassFlow, OutAirMinFrac * state.dataLoopNodes->Node(this->MixNode).MassFlowRate);
    4770           0 :                     state.dataLoopNodes->Node(this->RelNode).MassFlowRate =
    4771           0 :                         max(state.dataLoopNodes->Node(this->OANode).MassFlowRate - this->ExhMassFlow, 0.0);
    4772             :                     // save actual OA flow frac for use as min value for RegulaFalsi call
    4773           0 :                     minOAFrac = max(OutAirMinFrac, state.dataLoopNodes->Node(this->OANode).MassFlowRate / this->MixMassFlow);
    4774             :                 }
    4775       12238 :                 SimOASysComponents(state, state.dataAirLoop->AirLoopControlInfo(AirLoopNum).OASysNum, FirstHVACIteration, AirLoopNum);
    4776       12238 :                 lowFlowResiduum = state.dataLoopNodes->Node(this->MixNode).TempSetPoint - state.dataLoopNodes->Node(this->MixNode).Temp;
    4777             : 
    4778             :                 // 2 - check max OA flow result
    4779       12238 :                 state.dataLoopNodes->Node(this->OANode).MassFlowRate = max(this->ExhMassFlow, state.dataLoopNodes->Node(this->MixNode).MassFlowRate);
    4780       12238 :                 state.dataLoopNodes->Node(this->RelNode).MassFlowRate =
    4781       12238 :                     max(state.dataLoopNodes->Node(this->OANode).MassFlowRate - this->ExhMassFlow, 0.0);
    4782       12238 :                 SimOASysComponents(state, state.dataAirLoop->AirLoopControlInfo(AirLoopNum).OASysNum, FirstHVACIteration, AirLoopNum);
    4783       12238 :                 highFlowResiduum = state.dataLoopNodes->Node(this->MixNode).TempSetPoint - state.dataLoopNodes->Node(this->MixNode).Temp;
    4784             : 
    4785             :                 // 3 - test to ensure RegulaFalsi can find an answer
    4786       12238 :                 if ((sign(lowFlowResiduum) == sign(highFlowResiduum))) {
    4787         766 :                     OASignal = OutAirSignal;
    4788             :                 } else {
    4789             :                     // 4 - find result
    4790             : 
    4791      630060 :                     auto f = [&state, this, FirstHVACIteration, AirLoopNum](Real64 const OASignal) {
    4792       42004 :                         Real64 const MixMassFlowRate = this->MixMassFlow;
    4793       84008 :                         int const OASysNum = state.dataAirLoop->AirLoopControlInfo(AirLoopNum).OASysNum;
    4794       84008 :                         Real64 localExhMassFlow = state.dataAirLoop->AirLoopControlInfo(AirLoopNum).ZoneExhMassFlow;
    4795       42004 :                         Real64 const OAMassFlowRate = max(localExhMassFlow, OASignal * MixMassFlowRate);
    4796      126012 :                         state.dataLoopNodes->Node(this->OANode).MassFlowRate = OAMassFlowRate; // set OA node mass flow rate
    4797       84008 :                         state.dataLoopNodes->Node(this->RelNode).MassFlowRate =
    4798       42004 :                             max(OAMassFlowRate - localExhMassFlow, 0.0); // set relief node mass flow rate to maintain mixer continuity calcs
    4799       84008 :                         SimOASysComponents(state, OASysNum, FirstHVACIteration, AirLoopNum);
    4800      168016 :                         return state.dataLoopNodes->Node(this->MixNode).TempSetPoint - state.dataLoopNodes->Node(this->MixNode).Temp;
    4801       11472 :                     };
    4802             : 
    4803       11472 :                     SolveRoot(state, (Acc / 10.0), MaxIte, SolFla, OASignal, f, minOAFrac, 1.0);
    4804       11472 :                     if (SolFla < 0) { // if RegulaFalsi fails to find a solution, returns -1 or -2, set to existing OutAirSignal
    4805         267 :                         OASignal = OutAirSignal;
    4806             :                     }
    4807             :                 }
    4808             :             }
    4809             : 
    4810             :         } else {
    4811             : 
    4812           0 :             auto f = [&state, this](Real64 const OASignal) {
    4813           0 :                 Real64 const MixMassFlowRate = this->MixMassFlow;
    4814           0 :                 Real64 OAMassFlowRate = OASignal * MixMassFlowRate;
    4815           0 :                 Real64 RecircMassFlowRate = max(MixMassFlowRate - OAMassFlowRate, 0.0);
    4816           0 :                 Real64 RecircEnth = state.dataLoopNodes->Node(this->RetNode).Enthalpy;
    4817           0 :                 Real64 RecircHumRat = state.dataLoopNodes->Node(this->RetNode).HumRat;
    4818             :                 Real64 MixEnth =
    4819           0 :                     (RecircMassFlowRate * RecircEnth + OAMassFlowRate * state.dataLoopNodes->Node(this->OANode).Enthalpy) / MixMassFlowRate;
    4820             :                 Real64 MixHumRat =
    4821           0 :                     (RecircMassFlowRate * RecircHumRat + OAMassFlowRate * state.dataLoopNodes->Node(this->OANode).HumRat) / MixMassFlowRate;
    4822           0 :                 Real64 MixTemp = Psychrometrics::PsyTdbFnHW(MixEnth, MixHumRat);
    4823           0 :                 return state.dataLoopNodes->Node(this->MixNode).TempSetPoint - MixTemp;
    4824           0 :             };
    4825             : 
    4826           0 :             SolveRoot(state, Acc, MaxIte, SolFla, OASignal, f, OutAirMinFrac, 1.0);
    4827           0 :             if (SolFla < 0) {
    4828           0 :                 OASignal = OutAirSignal;
    4829             :             }
    4830     1271721 :         }
    4831             : 
    4832             :     } else {
    4833    21740754 :         OASignal = OutAirSignal;
    4834             :     }
    4835             : 
    4836             :     // Economizer choice "Bypass" forces minimum OA except when high humidity air flow is active based on indoor RH
    4837    23012475 :     if (this->EconBypass && EconomizerAirFlowScheduleValue == 0.0) {
    4838      694763 :         OASignal = OutAirMinFrac;
    4839             :     }
    4840             : 
    4841             :     // Set outdoor air signal based on OA flow ratio if high humidity air flow is enabled
    4842    23012475 :     if (HighHumidityOperationFlag) {
    4843         394 :         if (this->MixMassFlow > 0.0) {
    4844             :             //   calculate the actual ratio of outside air to mixed air so the magnitude of OA during high humidity control is correct
    4845         394 :             OASignal = max(OutAirMinFrac, (this->HighRHOAFlowRatio * this->MaxOAMassFlowRate / this->MixMassFlow));
    4846         394 :             this->OALimitingFactor = limitFactorHighHum;
    4847             :         }
    4848             :     }
    4849             : 
    4850    23012475 :     if (this->CoolCoilFreezeCheck) {
    4851           0 :         MaximumOAFracBySetPoint = min(max(MaximumOAFracBySetPoint, 0.0), 1.0);
    4852           0 :         this->MaxOAFracBySetPoint = MaximumOAFracBySetPoint;
    4853             : 
    4854             :         // This should not be messing with OutAirMinFrac, freeze protection should only limit economizer operation
    4855             :         // if (MaximumOAFracBySetPoint < OutAirMinFrac) {
    4856             :         // OutAirMinFrac = MaximumOAFracBySetPoint;
    4857             :         //    if (AirLoopNum > 0) AirLoopFlow(AirLoopNum).MinOutAir = OutAirMinFrac * this->MixMassFlow;
    4858             :         //}
    4859           0 :         if (MaximumOAFracBySetPoint < OASignal) {
    4860           0 :             OASignal = MaximumOAFracBySetPoint;
    4861           0 :             this->OALimitingFactor = limitFactorLimits;
    4862             :         }
    4863           0 :         if (OutAirMinFrac > OASignal) {
    4864           0 :             OASignal = OutAirMinFrac;
    4865           0 :             this->OALimitingFactor = limitFactorLimits;
    4866             :         }
    4867             :     }
    4868             : 
    4869    23012475 :     if (AirLoopNum > 0) {
    4870             : 
    4871             :         // Set the air loop economizer and high humidity control flags.
    4872    22448592 :         state.dataAirLoop->AirLoopControlInfo(AirLoopNum).EconoActive = EconomizerOperationFlag;
    4873    22448592 :         state.dataAirLoop->AirLoopControlInfo(AirLoopNum).HighHumCtrlActive = HighHumidityOperationFlag;
    4874    22448592 :         if (state.dataAirLoop->AirLoopControlInfo(AirLoopNum).EconomizerFlowLocked) {
    4875      773113 :             this->OAMassFlow = state.dataAirLoop->AirLoopFlow(AirLoopNum).MinOutAir;
    4876      773113 :             state.dataAirLoop->AirLoopFlow(AirLoopNum).OAFrac = this->OAMassFlow / this->MixMassFlow;
    4877      773113 :             state.dataAirLoop->AirLoopFlow(AirLoopNum).OAFlow = this->OAMassFlow;
    4878             :         }
    4879             : 
    4880             :         // Check heat exchanger bypass control
    4881    22448592 :         state.dataAirLoop->AirLoopControlInfo(AirLoopNum).HeatRecoveryBypass = false;
    4882    22448592 :         this->HeatRecoveryBypassStatus = 0;
    4883    22448592 :         if (EconomizerOperationFlag) {
    4884     4626885 :             if (this->HeatRecoveryBypassControlType == BypassWhenWithinEconomizerLimits) {
    4885     4401395 :                 state.dataAirLoop->AirLoopControlInfo(AirLoopNum).HeatRecoveryBypass = true;
    4886     4401395 :                 this->HeatRecoveryBypassStatus = 1;
    4887      225490 :             } else if (this->HeatRecoveryBypassControlType == BypassWhenOAFlowGreaterThanMinimum) {
    4888      225490 :                 Real64 OAMassFlowMin = OutAirMinFrac * state.dataAirLoop->AirLoopFlow(AirLoopNum).DesSupply;
    4889      225490 :                 Real64 OAMassFlowActual = OASignal * this->MixMassFlow;
    4890      225490 :                 Real64 reasonablySmallMassFlow = 1e-6;
    4891      225490 :                 if (OAMassFlowActual > (OAMassFlowMin + reasonablySmallMassFlow)) {
    4892      143578 :                     state.dataAirLoop->AirLoopControlInfo(AirLoopNum).HeatRecoveryBypass = true;
    4893      143578 :                     this->HeatRecoveryBypassStatus = 1;
    4894             :                 }
    4895             :             }
    4896             :         }
    4897             :     }
    4898             : 
    4899             :     // Set economizer report variable and status flag
    4900    23012475 :     if (this->Econo == EconoOp::NoEconomizer) {
    4901             :         // No economizer
    4902     7951550 :         this->EconomizerStatus = 0;
    4903     7951550 :         this->EconoActive = false;
    4904             :     } else {
    4905             :         // With economizer.
    4906    15060925 :         if (EconomizerOperationFlag) {
    4907             :             // Economizer is enabled
    4908     4627737 :             this->EconomizerStatus = 1;
    4909     4627737 :             this->EconoActive = true;
    4910     4627737 :             if ((OASignal > OutAirMinFrac) && !HighHumidityOperationFlag) {
    4911     3281389 :                 this->OALimitingFactor = limitFactorEconomizer;
    4912             :             }
    4913             :         } else {
    4914             :             // Economizer is disabled
    4915    10433188 :             this->EconomizerStatus = 0;
    4916    10433188 :             this->EconoActive = false;
    4917             :         }
    4918             :     }
    4919             : 
    4920             :     // Night ventilation control overrides economizer and high humidity control.
    4921    23012475 :     if (AirLoopNightVent) {
    4922           0 :         OASignal = 1.0;
    4923           0 :         this->OALimitingFactor = limitFactorNightVent;
    4924             :     }
    4925             : 
    4926             :     // Set high humidity control report variable and status flag
    4927    23012475 :     if (HighHumidityOperationFlag) {
    4928         394 :         this->HighHumCtrlStatus = 1;
    4929         394 :         this->HighHumCtrlActive = true;
    4930             :     } else {
    4931    23012081 :         this->HighHumCtrlStatus = 0;
    4932    23012081 :         this->HighHumCtrlActive = false;
    4933             :     }
    4934    23012475 : }
    4935    43707297 : void CalcOAMixer(EnergyPlusData &state, int const OAMixerNum)
    4936             : {
    4937             : 
    4938             :     // SUBROUTINE INFORMATION:
    4939             :     //       AUTHOR         Fred Buhl
    4940             :     //       DATE WRITTEN   Oct 1998
    4941             :     //       MODIFIED       na
    4942             :     //       RE-ENGINEERED  na
    4943             : 
    4944             :     // PURPOSE OF THIS SUBROUTINE
    4945             :     // Calculate the mixed air flow and conditions
    4946             : 
    4947             :     // METHODOLOGY EMPLOYED:
    4948             : 
    4949             :     // REFERENCES:
    4950             : 
    4951             :     // Using/Aliasing
    4952             :     using Psychrometrics::PsyTdbFnHW;
    4953             : 
    4954             :     // Locals
    4955             :     // SUBROUTINE ARGUMENT DEFINITIONS
    4956             : 
    4957             :     // SUBROUTINE PARAMETER DEFINITIONS:
    4958             : 
    4959             :     // INTERFACE BLOCK SPECIFICATIONS
    4960             :     // na
    4961             : 
    4962             :     // DERIVED TYPE DEFINITIONS
    4963             :     // na
    4964             : 
    4965             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    4966             :     Real64 RecircMassFlowRate;
    4967             :     Real64 RecircPressure;
    4968             :     Real64 RecircEnthalpy;
    4969             :     Real64 RecircHumRat;
    4970             : 
    4971             :     // Define a recirculation mass flow rate
    4972    43707297 :     RecircMassFlowRate = state.dataMixedAir->OAMixer(OAMixerNum).RetMassFlowRate - state.dataMixedAir->OAMixer(OAMixerNum).RelMassFlowRate;
    4973             :     // In certain low flow conditions the return air mass flow rate can be below the outside air value established
    4974             :     //  by the user.  This check will ensure that this condition does not result in unphysical air properties.
    4975    43707297 :     if (RecircMassFlowRate < 0.0) {
    4976      112153 :         RecircMassFlowRate = 0.0;
    4977      112153 :         state.dataMixedAir->OAMixer(OAMixerNum).RelMassFlowRate = state.dataMixedAir->OAMixer(OAMixerNum).RetMassFlowRate;
    4978             :     }
    4979             : 
    4980             :     // Pass through the return air conditions to the relief air stream.  The return air is "split" to
    4981             :     // the relief air and the recirculation air.
    4982    43707297 :     state.dataMixedAir->OAMixer(OAMixerNum).RelTemp = state.dataMixedAir->OAMixer(OAMixerNum).RetTemp;
    4983    43707297 :     state.dataMixedAir->OAMixer(OAMixerNum).RelHumRat = state.dataMixedAir->OAMixer(OAMixerNum).RetHumRat;
    4984    43707297 :     state.dataMixedAir->OAMixer(OAMixerNum).RelEnthalpy = state.dataMixedAir->OAMixer(OAMixerNum).RetEnthalpy;
    4985    43707297 :     state.dataMixedAir->OAMixer(OAMixerNum).RelPressure = state.dataMixedAir->OAMixer(OAMixerNum).RetPressure;
    4986    43707297 :     RecircPressure = state.dataMixedAir->OAMixer(OAMixerNum).RetPressure;
    4987    43707297 :     RecircEnthalpy = state.dataMixedAir->OAMixer(OAMixerNum).RetEnthalpy;
    4988    43707297 :     RecircHumRat = state.dataMixedAir->OAMixer(OAMixerNum).RetHumRat;
    4989             :     // The recirculation air and the outside air are mixed to form the mixed air stream
    4990    43707297 :     state.dataMixedAir->OAMixer(OAMixerNum).MixMassFlowRate = state.dataMixedAir->OAMixer(OAMixerNum).OAMassFlowRate + RecircMassFlowRate;
    4991             :     // Check for zero flow
    4992    43707297 :     if (state.dataMixedAir->OAMixer(OAMixerNum).MixMassFlowRate <= VerySmallMassFlow) {
    4993     4589260 :         state.dataMixedAir->OAMixer(OAMixerNum).MixEnthalpy = state.dataMixedAir->OAMixer(OAMixerNum).RetEnthalpy;
    4994     4589260 :         state.dataMixedAir->OAMixer(OAMixerNum).MixHumRat = state.dataMixedAir->OAMixer(OAMixerNum).RetHumRat;
    4995     4589260 :         state.dataMixedAir->OAMixer(OAMixerNum).MixPressure = state.dataMixedAir->OAMixer(OAMixerNum).RetPressure;
    4996     4589260 :         state.dataMixedAir->OAMixer(OAMixerNum).MixTemp = state.dataMixedAir->OAMixer(OAMixerNum).RetTemp;
    4997     4589260 :         return;
    4998             :     }
    4999             : 
    5000    39118037 :     state.dataMixedAir->OAMixer(OAMixerNum).MixEnthalpy =
    5001    78236074 :         (RecircMassFlowRate * RecircEnthalpy +
    5002    78236074 :          state.dataMixedAir->OAMixer(OAMixerNum).OAMassFlowRate * state.dataMixedAir->OAMixer(OAMixerNum).OAEnthalpy) /
    5003    39118037 :         state.dataMixedAir->OAMixer(OAMixerNum).MixMassFlowRate;
    5004   117354111 :     state.dataMixedAir->OAMixer(OAMixerNum).MixHumRat = (RecircMassFlowRate * RecircHumRat + state.dataMixedAir->OAMixer(OAMixerNum).OAMassFlowRate *
    5005    78236074 :                                                                                                  state.dataMixedAir->OAMixer(OAMixerNum).OAHumRat) /
    5006    39118037 :                                                         state.dataMixedAir->OAMixer(OAMixerNum).MixMassFlowRate;
    5007    39118037 :     state.dataMixedAir->OAMixer(OAMixerNum).MixPressure =
    5008    78236074 :         (RecircMassFlowRate * RecircPressure +
    5009    78236074 :          state.dataMixedAir->OAMixer(OAMixerNum).OAMassFlowRate * state.dataMixedAir->OAMixer(OAMixerNum).OAPressure) /
    5010    39118037 :         state.dataMixedAir->OAMixer(OAMixerNum).MixMassFlowRate;
    5011             :     // Mixed air temperature is calculated from the mixed air enthalpy and humidity ratio.
    5012    39118037 :     state.dataMixedAir->OAMixer(OAMixerNum).MixTemp =
    5013    39118037 :         PsyTdbFnHW(state.dataMixedAir->OAMixer(OAMixerNum).MixEnthalpy, state.dataMixedAir->OAMixer(OAMixerNum).MixHumRat);
    5014             : }
    5015             : 
    5016             : // End of Calculation/Simulation Section of the Module
    5017             : //******************************************************************************
    5018             : 
    5019             : // Beginning Sizing Section of the Module
    5020             : //******************************************************************************
    5021             : 
    5022        1125 : void OAControllerProps::SizeOAController(EnergyPlusData &state)
    5023             : {
    5024             : 
    5025             :     // SUBROUTINE INFORMATION:
    5026             :     //       AUTHOR         Fred Buhl
    5027             :     //       DATE WRITTEN   September 2001
    5028             :     //       MODIFIED       na
    5029             :     //       RE-ENGINEERED  na
    5030             : 
    5031             :     // PURPOSE OF THIS SUBROUTINE:
    5032             :     // This subroutine is for sizing OAController Components for which flow rates have not been
    5033             :     // specified in the input.
    5034             : 
    5035             :     // METHODOLOGY EMPLOYED:
    5036             :     // Obtains flow rates from the zone or system sizing arrays.
    5037             : 
    5038             :     // Using/Aliasing
    5039             : 
    5040             :     using HVACHXAssistedCoolingCoil::GetHXCoilType;
    5041             :     using HVACHXAssistedCoolingCoil::GetHXDXCoilName;
    5042             :     using WaterCoils::SetCoilDesFlow;
    5043             : 
    5044             :     // SUBROUTINE PARAMETER DEFINITIONS:
    5045        1125 :     static std::string const &CurrentModuleObject(CurrentModuleObjects(static_cast<int>(CMO::OAController)));
    5046             : 
    5047             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    5048             :     Real64 OAFlowRatio;   // Used for error checking
    5049        2250 :     std::string CompType; // Component type
    5050        2250 :     std::string CompName; // Component name
    5051        2250 :     std::string CoilName;
    5052        2250 :     std::string CoilType;
    5053             :     int CompNum;
    5054             :     bool ErrorsFound;
    5055             : 
    5056        1125 :     ErrorsFound = false;
    5057        1125 :     if (this->MaxOA == AutoSize) {
    5058             : 
    5059         876 :         if (state.dataSize->CurSysNum > 0) {
    5060             : 
    5061         876 :             switch (this->ControllerType_Num) {
    5062         876 :             case MixedAirControllerType::ControllerOutsideAir: {
    5063         876 :                 CheckSysSizing(state, CurrentModuleObject, this->Name);
    5064         876 :                 switch (state.dataSize->CurDuctType) {
    5065           0 :                 case DataHVACGlobals::AirDuctType::Cooling: {
    5066           0 :                     this->MaxOA = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesCoolVolFlow;
    5067           0 :                 } break;
    5068           1 :                 case DataHVACGlobals::AirDuctType::Heating: {
    5069           1 :                     this->MaxOA = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesHeatVolFlow;
    5070           1 :                 } break;
    5071         875 :                 case DataHVACGlobals::AirDuctType::Main:
    5072             :                 case DataHVACGlobals::AirDuctType::Other:
    5073             :                 default: {
    5074         875 :                     this->MaxOA = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesMainVolFlow;
    5075         875 :                 } break;
    5076             :                 }
    5077         876 :             } break;
    5078           0 :             case MixedAirControllerType::ControllerStandAloneERV: {
    5079           0 :             } break;
    5080           0 :             default:
    5081           0 :                 break;
    5082             :             }
    5083             : 
    5084           0 :         } else if (state.dataSize->CurZoneEqNum > 0) {
    5085             : 
    5086           0 :             switch (this->ControllerType_Num) {
    5087           0 :             case MixedAirControllerType::ControllerOutsideAir: {
    5088           0 :                 CheckZoneSizing(state, CurrentModuleObject, this->Name);
    5089           0 :                 this->MaxOA = max(state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).DesCoolVolFlow,
    5090           0 :                                   state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).DesHeatVolFlow);
    5091           0 :             } break;
    5092           0 :             case MixedAirControllerType::ControllerStandAloneERV: {
    5093           0 :             } break;
    5094           0 :             default:
    5095           0 :                 break;
    5096             :             }
    5097             :         }
    5098             : 
    5099         876 :         if (this->MaxOA < SmallAirVolFlow) {
    5100           0 :             this->MaxOA = 0.0;
    5101             :         }
    5102             : 
    5103         876 :         BaseSizer::reportSizerOutput(state, CurrentModuleObject, this->Name, "Maximum Outdoor Air Flow Rate [m3/s]", this->MaxOA);
    5104             :     }
    5105             : 
    5106        1125 :     if (this->MinOA == AutoSize) {
    5107             : 
    5108         813 :         if (state.dataSize->CurSysNum > 0) {
    5109             : 
    5110         813 :             CheckSysSizing(state, CurrentModuleObject, this->Name);
    5111         813 :             if (state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesOutAirVolFlow >= SmallAirVolFlow) {
    5112         803 :                 this->MinOA = min(state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesOutAirVolFlow, this->MaxOA);
    5113             :             } else {
    5114          10 :                 this->MinOA = 0.0;
    5115             :             }
    5116             :         }
    5117             : 
    5118         813 :         BaseSizer::reportSizerOutput(state, CurrentModuleObject, this->Name, "Minimum Outdoor Air Flow Rate [m3/s]", this->MinOA);
    5119             : 
    5120         813 :         if (this->HumidistatZoneNum > 0 && this->FixedMin) {
    5121           1 :             if (this->MaxOA > 0.0) {
    5122           1 :                 OAFlowRatio = this->MinOA / this->MaxOA;
    5123           1 :                 if (this->HighRHOAFlowRatio < OAFlowRatio) {
    5124           0 :                     ShowWarningError(state, CurrentModuleObject + " \"" + this->Name + "\"");
    5125           0 :                     ShowContinueError(state, "... A fixed minimum outdoor air flow rate and high humidity control have been specified.");
    5126           0 :                     ShowContinueError(state,
    5127             :                                       "... The High Humidity Outdoor Air Flow Ratio is less than the ratio of the outdoor air controllers "
    5128             :                                       "minimum to maximum outside air flow rate.");
    5129           0 :                     ShowContinueError(state, format("... Controller minimum flow rate = {:.4T} m3/s.", this->MinOA));
    5130           0 :                     ShowContinueError(state, format("... Controller maximum flow rate = {:.4T} m3/s.", this->MaxOA));
    5131           0 :                     ShowContinueError(state, format("... Controller minimum to maximum flow ratio = {:.4T}.", OAFlowRatio));
    5132           0 :                     ShowContinueError(state, format("... High humidity control flow ratio = {:.4T}.", this->HighRHOAFlowRatio));
    5133             :                 }
    5134             :             }
    5135             :         }
    5136             :     }
    5137             :     // If there is an outside air system, loop over components in the OA system; pass the design air flow rate
    5138             :     // to the coil components that don't have design air flow as an input.
    5139        1125 :     if (state.dataSize->CurOASysNum > 0) {
    5140        2162 :         for (CompNum = 1; CompNum <= state.dataAirLoop->OutsideAirSys(state.dataSize->CurOASysNum).NumComponents; ++CompNum) {
    5141        1141 :             CompType = state.dataAirLoop->OutsideAirSys(state.dataSize->CurOASysNum).ComponentType(CompNum);
    5142        1141 :             CompName = state.dataAirLoop->OutsideAirSys(state.dataSize->CurOASysNum).ComponentName(CompNum);
    5143        3423 :             if (UtilityRoutines::SameString(CompType, "COIL:COOLING:WATER:DETAILEDGEOMETRY") ||
    5144        3396 :                 UtilityRoutines::SameString(CompType, "COIL:HEATING:WATER") ||
    5145        2255 :                 UtilityRoutines::SameString(CompType, "COILSYSTEM:COOLING:WATER:HEATEXCHANGERASSISTED")) {
    5146          27 :                 if (UtilityRoutines::SameString(CompType, "COILSYSTEM:COOLING:WATER:HEATEXCHANGERASSISTED")) {
    5147           0 :                     CoilName = GetHXDXCoilName(state, CompType, CompName, ErrorsFound);
    5148           0 :                     CoilType = GetHXCoilType(state, CompType, CompName, ErrorsFound);
    5149             :                 } else {
    5150          27 :                     CoilName = CompName;
    5151          27 :                     CoilType = CompType;
    5152             :                 }
    5153          27 :                 SetCoilDesFlow(state, CoilType, CoilName, this->MinOA, ErrorsFound);
    5154             :             }
    5155             :         } // End of component loop
    5156             :     }
    5157        1125 :     if (ErrorsFound) {
    5158           0 :         ShowFatalError(state, "Preceding sizing errors cause program termination");
    5159             :     }
    5160        1125 : }
    5161             : 
    5162             : // End of Sizing Section of the Module
    5163             : //******************************************************************************
    5164             : 
    5165             : // Beginning Update/Reporting Section of the Module
    5166             : //******************************************************************************
    5167             : 
    5168    24821703 : void OAControllerProps::UpdateOAController(EnergyPlusData &state)
    5169             : {
    5170             : 
    5171             :     // SUBROUTINE INFORMATION:
    5172             :     //       AUTHOR         Fred Buhl
    5173             :     //       DATE WRITTEN   Oct 1998
    5174             :     //       MODIFIED       Shirey/Raustad FSEC, June 2003
    5175             :     //       RE-ENGINEERED  na
    5176             : 
    5177             :     // PURPOSE OF THIS SUBROUTINE
    5178             :     // Move the results of CalcOAController to the affected nodes
    5179             : 
    5180             :     // METHODOLOGY EMPLOYED:
    5181             : 
    5182             :     // REFERENCES:
    5183             : 
    5184             :     // Using/Aliasing
    5185             :     using namespace DataLoopNode;
    5186             :     // Locals
    5187             :     // SUBROUTINE ARGUMENT DEFINITIONS
    5188             : 
    5189             :     // SUBROUTINE PARAMETER DEFINITIONS:
    5190             : 
    5191             :     // INTERFACE BLOCK SPECIFICATIONS
    5192             :     // na
    5193             : 
    5194             :     // DERIVED TYPE DEFINITIONS
    5195             :     // na
    5196             : 
    5197             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    5198             :     int OutAirNodeNum;
    5199             :     int InletAirNodeNum;
    5200             :     int RelAirNodeNum;
    5201             :     int RetAirNodeNum;
    5202             : 
    5203    24821703 :     OutAirNodeNum = this->OANode;
    5204    24821703 :     InletAirNodeNum = this->InletNode;
    5205    24821703 :     RelAirNodeNum = this->RelNode;
    5206    24821703 :     RetAirNodeNum = this->RetNode;
    5207             : 
    5208    24821703 :     if (this->ControllerType_Num == MixedAirControllerType::ControllerOutsideAir) {
    5209             :         // The outside air controller sets the outside air flow rate and the relief air flow rate
    5210    24263372 :         if (!state.dataGlobal->WarmupFlag && !state.dataGlobal->DoingSizing && (this->ManageDemand) &&
    5211        5654 :             (this->OAMassFlow > this->DemandLimitFlowRate)) {
    5212           0 :             state.dataLoopNodes->Node(OutAirNodeNum).MassFlowRate = this->DemandLimitFlowRate;
    5213           0 :             state.dataLoopNodes->Node(InletAirNodeNum).MassFlowRate = this->DemandLimitFlowRate;
    5214           0 :             state.dataLoopNodes->Node(OutAirNodeNum).MassFlowRateMaxAvail = this->DemandLimitFlowRate;
    5215             :         } else {
    5216    24257718 :             state.dataLoopNodes->Node(OutAirNodeNum).MassFlowRate = this->OAMassFlow;
    5217    24257718 :             state.dataLoopNodes->Node(InletAirNodeNum).MassFlowRate = this->OAMassFlow;
    5218    24257718 :             state.dataLoopNodes->Node(OutAirNodeNum).MassFlowRateMaxAvail = this->OAMassFlow;
    5219             :         }
    5220    24257718 :         state.dataLoopNodes->Node(RelAirNodeNum).MassFlowRate = this->RelMassFlow;
    5221             :     } else {
    5222             :         // The ERV controller sets the supply and secondary inlet node information for the Stand Alone ERV
    5223             :         // Currently, the Stand Alone ERV only has constant air flows (supply and exhaust), and these are
    5224             :         // already set in HVACStandAloneERV.cc (subroutine init). Therefore, these flow assignments below are
    5225             :         // currently redundant but may be useful in the future as mass flow rates can vary based on the controller signal.
    5226      563985 :         if (!state.dataGlobal->WarmupFlag && !state.dataGlobal->DoingSizing && (this->ManageDemand) &&
    5227           0 :             (this->OAMassFlow > this->DemandLimitFlowRate)) {
    5228           0 :             state.dataLoopNodes->Node(OutAirNodeNum).MassFlowRate = this->DemandLimitFlowRate;
    5229           0 :             state.dataLoopNodes->Node(OutAirNodeNum).MassFlowRateMaxAvail = this->DemandLimitFlowRate;
    5230             :         } else {
    5231      563985 :             state.dataLoopNodes->Node(OutAirNodeNum).MassFlowRate = this->OAMassFlow;
    5232      563985 :             state.dataLoopNodes->Node(OutAirNodeNum).MassFlowRateMaxAvail = this->OAMassFlow;
    5233             :         }
    5234      563985 :         state.dataLoopNodes->Node(RetAirNodeNum).MassFlowRate = state.dataLoopNodes->Node(this->RetNode).MassFlowRate;
    5235      563985 :         state.dataLoopNodes->Node(RetAirNodeNum).MassFlowRateMaxAvail = state.dataLoopNodes->Node(this->RetNode).MassFlowRate;
    5236             :     }
    5237    24821703 : }
    5238             : 
    5239    43707297 : void UpdateOAMixer(EnergyPlusData &state, int const OAMixerNum)
    5240             : {
    5241             : 
    5242             :     // SUBROUTINE INFORMATION:
    5243             :     //       AUTHOR         Fred Buhl
    5244             :     //       DATE WRITTEN   Oct 1998
    5245             :     //       MODIFIED       na
    5246             :     //       RE-ENGINEERED  na
    5247             : 
    5248             :     // PURPOSE OF THIS SUBROUTINE
    5249             :     // Move the results of CalcOAMixer to the affected nodes
    5250             : 
    5251             :     // METHODOLOGY EMPLOYED:
    5252             : 
    5253             :     // REFERENCES:
    5254             : 
    5255             :     // Using/Aliasing
    5256             :     using namespace DataLoopNode;
    5257             : 
    5258             :     // Locals
    5259             :     // SUBROUTINE ARGUMENT DEFINITIONS
    5260             : 
    5261             :     // SUBROUTINE PARAMETER DEFINITIONS:
    5262             : 
    5263             :     // INTERFACE BLOCK SPECIFICATIONS
    5264             :     // na
    5265             : 
    5266             :     // DERIVED TYPE DEFINITIONS
    5267             :     // na
    5268             : 
    5269             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    5270             :     int MixNode;
    5271             :     int RelNode;
    5272             :     int RetNode;
    5273             : 
    5274    43707297 :     MixNode = state.dataMixedAir->OAMixer(OAMixerNum).MixNode;
    5275    43707297 :     RelNode = state.dataMixedAir->OAMixer(OAMixerNum).RelNode;
    5276    43707297 :     RetNode = state.dataMixedAir->OAMixer(OAMixerNum).RetNode;
    5277             :     // Move mixed air data to the mixed air node
    5278    43707297 :     state.dataLoopNodes->Node(MixNode).MassFlowRate = state.dataMixedAir->OAMixer(OAMixerNum).MixMassFlowRate;
    5279    43707297 :     state.dataLoopNodes->Node(MixNode).Temp = state.dataMixedAir->OAMixer(OAMixerNum).MixTemp;
    5280    43707297 :     state.dataLoopNodes->Node(MixNode).HumRat = state.dataMixedAir->OAMixer(OAMixerNum).MixHumRat;
    5281    43707297 :     state.dataLoopNodes->Node(MixNode).Enthalpy = state.dataMixedAir->OAMixer(OAMixerNum).MixEnthalpy;
    5282    43707297 :     state.dataLoopNodes->Node(MixNode).Press = state.dataMixedAir->OAMixer(OAMixerNum).MixPressure;
    5283    43707297 :     state.dataLoopNodes->Node(MixNode).MassFlowRateMaxAvail = state.dataMixedAir->OAMixer(OAMixerNum).MixMassFlowRate;
    5284             :     // Move the relief air data to the relief air node
    5285    43707297 :     state.dataLoopNodes->Node(RelNode).MassFlowRate = state.dataMixedAir->OAMixer(OAMixerNum).RelMassFlowRate;
    5286    43707297 :     state.dataLoopNodes->Node(RelNode).Temp = state.dataMixedAir->OAMixer(OAMixerNum).RelTemp;
    5287    43707297 :     state.dataLoopNodes->Node(RelNode).HumRat = state.dataMixedAir->OAMixer(OAMixerNum).RelHumRat;
    5288    43707297 :     state.dataLoopNodes->Node(RelNode).Enthalpy = state.dataMixedAir->OAMixer(OAMixerNum).RelEnthalpy;
    5289    43707297 :     state.dataLoopNodes->Node(RelNode).Press = state.dataMixedAir->OAMixer(OAMixerNum).RelPressure;
    5290    43707297 :     state.dataLoopNodes->Node(RelNode).MassFlowRateMaxAvail = state.dataMixedAir->OAMixer(OAMixerNum).RelMassFlowRate;
    5291             : 
    5292    43707297 :     if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    5293       66288 :         state.dataLoopNodes->Node(RelNode).CO2 = state.dataLoopNodes->Node(RetNode).CO2;
    5294       66288 :         if (state.dataMixedAir->OAMixer(OAMixerNum).MixMassFlowRate <= VerySmallMassFlow) {
    5295        5646 :             state.dataLoopNodes->Node(MixNode).CO2 = state.dataLoopNodes->Node(RetNode).CO2;
    5296             :         } else {
    5297       60642 :             state.dataLoopNodes->Node(MixNode).CO2 =
    5298      121284 :                 ((state.dataLoopNodes->Node(RetNode).MassFlowRate - state.dataLoopNodes->Node(RelNode).MassFlowRate) *
    5299      121284 :                      state.dataLoopNodes->Node(RetNode).CO2 +
    5300      121284 :                  state.dataMixedAir->OAMixer(OAMixerNum).OAMassFlowRate * state.dataContaminantBalance->OutdoorCO2) /
    5301       60642 :                 state.dataMixedAir->OAMixer(OAMixerNum).MixMassFlowRate;
    5302             :         }
    5303             :     }
    5304             : 
    5305    43707297 :     if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    5306       18233 :         state.dataLoopNodes->Node(RelNode).GenContam = state.dataLoopNodes->Node(RetNode).GenContam;
    5307       18233 :         if (state.dataMixedAir->OAMixer(OAMixerNum).MixMassFlowRate <= VerySmallMassFlow) {
    5308        1971 :             state.dataLoopNodes->Node(MixNode).GenContam = state.dataLoopNodes->Node(RetNode).GenContam;
    5309             :         } else {
    5310       16262 :             state.dataLoopNodes->Node(MixNode).GenContam =
    5311       32524 :                 ((state.dataLoopNodes->Node(RetNode).MassFlowRate - state.dataLoopNodes->Node(RelNode).MassFlowRate) *
    5312       32524 :                      state.dataLoopNodes->Node(RetNode).GenContam +
    5313       32524 :                  state.dataMixedAir->OAMixer(OAMixerNum).OAMassFlowRate * state.dataContaminantBalance->OutdoorGC) /
    5314       16262 :                 state.dataMixedAir->OAMixer(OAMixerNum).MixMassFlowRate;
    5315             :         }
    5316             :     }
    5317    43707297 : }
    5318             : 
    5319    43707297 : void ReportOAMixer([[maybe_unused]] int const OAMixerNum) // unused1208
    5320             : {
    5321             : 
    5322             :     // SUBROUTINE ARGUMENT DEFINITIONS
    5323    43707297 : }
    5324             : 
    5325             : // End of Sizing Section of the Module
    5326             : //******************************************************************************
    5327             : 
    5328             : // Beginning Utility Section of the Module
    5329             : //******************************************************************************
    5330             : 
    5331         607 : Array1D_int GetOAMixerNodeNumbers(EnergyPlusData &state,
    5332             :                                   std::string const &OAMixerName, // must match OA mixer names for the OA mixer type
    5333             :                                   bool &ErrorsFound               // set to true if problem
    5334             : )
    5335             : {
    5336             : 
    5337             :     // FUNCTION INFORMATION:
    5338             :     //       AUTHOR         Richard Raustad
    5339             :     //       DATE WRITTEN   June 2006
    5340             :     //       MODIFIED       na
    5341             :     //       RE-ENGINEERED  na
    5342             : 
    5343             :     // PURPOSE OF THIS FUNCTION:
    5344             :     // This function looks up the given OA mixer and returns the node numbers.  If
    5345             :     // incorrect OA mixer name is given, ErrorsFound is returned as true
    5346             :     // as zero.
    5347             : 
    5348             :     // Return value
    5349         607 :     Array1D_int OANodeNumbers(4); // return OA mixer nodes
    5350             : 
    5351             :     // FUNCTION LOCAL VARIABLE DECLARATIONS:
    5352             :     int WhichOAMixer;
    5353             : 
    5354             :     // Obtains and Allocates OA mixer related parameters from input file
    5355         607 :     if (state.dataMixedAir->GetOAMixerInputFlag) { // First time subroutine has been entered
    5356          36 :         GetOAMixerInputs(state);
    5357          36 :         state.dataMixedAir->GetOAMixerInputFlag = false;
    5358             :     }
    5359             : 
    5360         607 :     WhichOAMixer = UtilityRoutines::FindItemInList(OAMixerName, state.dataMixedAir->OAMixer);
    5361         607 :     if (WhichOAMixer != 0) {
    5362         607 :         OANodeNumbers(1) = state.dataMixedAir->OAMixer(WhichOAMixer).InletNode;
    5363         607 :         OANodeNumbers(2) = state.dataMixedAir->OAMixer(WhichOAMixer).RelNode;
    5364         607 :         OANodeNumbers(3) = state.dataMixedAir->OAMixer(WhichOAMixer).RetNode;
    5365         607 :         OANodeNumbers(4) = state.dataMixedAir->OAMixer(WhichOAMixer).MixNode;
    5366             :     }
    5367             : 
    5368         607 :     if (WhichOAMixer == 0) {
    5369           0 :         ShowSevereError(state, "GetOAMixerNodeNumbers: Could not find OA Mixer = \"" + OAMixerName + "\"");
    5370           0 :         ErrorsFound = true;
    5371           0 :         OANodeNumbers = 0;
    5372             :     }
    5373             : 
    5374         607 :     return OANodeNumbers;
    5375             : }
    5376             : 
    5377          30 : int GetNumOAMixers(EnergyPlusData &state)
    5378             : {
    5379             : 
    5380             :     // FUNCTION INFORMATION:
    5381             :     //       AUTHOR         Linda Lawrie
    5382             :     //       DATE WRITTEN   October 2006
    5383             :     //       MODIFIED       na
    5384             :     //       RE-ENGINEERED  na
    5385             : 
    5386             :     // PURPOSE OF THIS FUNCTION:
    5387             :     // After making sure get input is done, the number of OA mixers is returned.
    5388             : 
    5389             :     // METHODOLOGY EMPLOYED:
    5390             :     // na
    5391             : 
    5392             :     // REFERENCES:
    5393             :     // na
    5394             : 
    5395             :     // USE STATEMENTS:
    5396             :     // na
    5397             : 
    5398             :     // Return value
    5399             :     int NumberOfOAMixers;
    5400             : 
    5401             :     // Locals
    5402             :     // FUNCTION ARGUMENT DEFINITIONS:
    5403             : 
    5404             :     // FUNCTION PARAMETER DEFINITIONS:
    5405             :     // na
    5406             : 
    5407             :     // INTERFACE BLOCK SPECIFICATIONS:
    5408             :     // na
    5409             : 
    5410             :     // DERIVED TYPE DEFINITIONS:
    5411             :     // na
    5412             : 
    5413             :     // FUNCTION LOCAL VARIABLE DECLARATIONS:
    5414             :     // na
    5415             : 
    5416          30 :     if (state.dataMixedAir->GetOAMixerInputFlag) { // First time subroutine has been entered
    5417           0 :         GetOAMixerInputs(state);
    5418           0 :         state.dataMixedAir->GetOAMixerInputFlag = false;
    5419             :     }
    5420             : 
    5421          30 :     NumberOfOAMixers = state.dataMixedAir->NumOAMixers;
    5422             : 
    5423          30 :     return NumberOfOAMixers;
    5424             : }
    5425             : 
    5426           0 : int GetNumOAControllers(EnergyPlusData &state)
    5427             : {
    5428             : 
    5429             :     // FUNCTION INFORMATION:
    5430             :     //       AUTHOR         Linda Lawrie
    5431             :     //       DATE WRITTEN   October 2006
    5432             :     //       MODIFIED       na
    5433             :     //       RE-ENGINEERED  na
    5434             : 
    5435             :     // PURPOSE OF THIS FUNCTION:
    5436             :     // After making sure get input is done, the number of OA Controllers is returned.
    5437             : 
    5438             :     // METHODOLOGY EMPLOYED:
    5439             :     // na
    5440             : 
    5441             :     // REFERENCES:
    5442             :     // na
    5443             : 
    5444             :     // USE STATEMENTS:
    5445             :     // na
    5446             : 
    5447             :     // Return value
    5448             :     int NumberOfOAControllers;
    5449             : 
    5450             :     // Locals
    5451             :     // FUNCTION ARGUMENT DEFINITIONS:
    5452             : 
    5453             :     // FUNCTION PARAMETER DEFINITIONS:
    5454             :     // na
    5455             : 
    5456             :     // INTERFACE BLOCK SPECIFICATIONS:
    5457             :     // na
    5458             : 
    5459             :     // DERIVED TYPE DEFINITIONS:
    5460             :     // na
    5461             : 
    5462             :     // FUNCTION LOCAL VARIABLE DECLARATIONS:
    5463             :     // na
    5464             : 
    5465           0 :     if (state.dataMixedAir->AllocateOAControllersFlag) {
    5466             :         // Make sure OAControllers are allocated
    5467           0 :         AllocateOAControllers(state);
    5468             :     }
    5469             : 
    5470           0 :     NumberOfOAControllers = state.dataMixedAir->NumOAControllers;
    5471             : 
    5472           0 :     return NumberOfOAControllers;
    5473             : }
    5474             : 
    5475          15 : int GetOAMixerReliefNodeNumber(EnergyPlusData &state, int const OAMixerNum) // Which Mixer
    5476             : {
    5477             : 
    5478             :     // FUNCTION INFORMATION:
    5479             :     //       AUTHOR         Linda Lawrie
    5480             :     //       DATE WRITTEN   October 2006
    5481             :     //       MODIFIED       na
    5482             :     //       RE-ENGINEERED  na
    5483             : 
    5484             :     // PURPOSE OF THIS FUNCTION:
    5485             :     // After making sure get input is done, the relief node number of indicated
    5486             :     // mixer is returned.
    5487             : 
    5488             :     // METHODOLOGY EMPLOYED:
    5489             :     // na
    5490             : 
    5491             :     // REFERENCES:
    5492             :     // na
    5493             : 
    5494             :     // Using/Aliasing
    5495             : 
    5496             :     // Return value
    5497             :     int ReliefNodeNumber; // Relief Node Number
    5498             : 
    5499             :     // Locals
    5500             :     // FUNCTION ARGUMENT DEFINITIONS:
    5501             : 
    5502             :     // FUNCTION PARAMETER DEFINITIONS:
    5503             :     // na
    5504             : 
    5505             :     // INTERFACE BLOCK SPECIFICATIONS:
    5506             :     // na
    5507             : 
    5508             :     // DERIVED TYPE DEFINITIONS:
    5509             :     // na
    5510             : 
    5511             :     // FUNCTION LOCAL VARIABLE DECLARATIONS:
    5512             :     // na
    5513             : 
    5514          15 :     if (state.dataMixedAir->GetOAMixerInputFlag) { // First time subroutine has been entered
    5515           0 :         GetOAMixerInputs(state);
    5516           0 :         state.dataMixedAir->GetOAMixerInputFlag = false;
    5517             :     }
    5518             : 
    5519          15 :     if (OAMixerNum > state.dataMixedAir->NumOAMixers) {
    5520           0 :         ShowFatalError(state,
    5521           0 :                        format("GetOAMixerReliefNodeNumber: Requested Mixer #={}, which is > number of OA Mixers={}",
    5522             :                               OAMixerNum,
    5523           0 :                               state.dataMixedAir->NumOAMixers));
    5524             :     }
    5525             : 
    5526          15 :     ReliefNodeNumber = state.dataMixedAir->OAMixer(OAMixerNum).RelNode;
    5527             : 
    5528          15 :     return ReliefNodeNumber;
    5529             : }
    5530             : 
    5531        1026 : int GetOASysControllerListIndex(EnergyPlusData &state, int const OASysNumber) // OA Sys Number
    5532             : {
    5533             : 
    5534             :     // FUNCTION INFORMATION:
    5535             :     //       AUTHOR         Fred Buhl
    5536             :     //       DATE WRITTEN   April 2007
    5537             :     //       MODIFIED       na
    5538             :     //       RE-ENGINEERED  na
    5539             : 
    5540             :     // PURPOSE OF THIS FUNCTION:
    5541             :     // After making sure get input is done, the Controller List index of the indicated
    5542             :     // OA System is returned.
    5543             : 
    5544             :     // METHODOLOGY EMPLOYED:
    5545             :     // na
    5546             : 
    5547             :     // REFERENCES:
    5548             :     // na
    5549             : 
    5550             :     // USE STATEMENTS:
    5551             : 
    5552             :     // Return value
    5553             :     int OASysControllerListNum; // OA Sys Controller List index
    5554             : 
    5555             :     // Locals
    5556             :     // FUNCTION ARGUMENT DEFINITIONS:
    5557             : 
    5558             :     // FUNCTION PARAMETER DEFINITIONS:
    5559             :     // na
    5560             : 
    5561             :     // INTERFACE BLOCK SPECIFICATIONS:
    5562             :     // na
    5563             : 
    5564             :     // DERIVED TYPE DEFINITIONS:
    5565             :     // na
    5566             : 
    5567             :     // FUNCTION LOCAL VARIABLE DECLARATIONS:
    5568             :     // na
    5569             : 
    5570        1026 :     if (state.dataMixedAir->GetOASysInputFlag) {
    5571           0 :         GetOutsideAirSysInputs(state);
    5572           0 :         state.dataMixedAir->GetOASysInputFlag = false;
    5573             :     }
    5574             : 
    5575        1026 :     OASysControllerListNum = state.dataAirLoop->OutsideAirSys(OASysNumber).ControllerListNum;
    5576             : 
    5577        1026 :     return OASysControllerListNum;
    5578             : }
    5579             : 
    5580        1026 : int GetOASysNumSimpControllers(EnergyPlusData &state, int const OASysNumber) // OA Sys Number
    5581             : {
    5582             : 
    5583             :     // FUNCTION INFORMATION:
    5584             :     //       AUTHOR         Fred Buhl
    5585             :     //       DATE WRITTEN   April 2007
    5586             :     //       MODIFIED       na
    5587             :     //       RE-ENGINEERED  na
    5588             : 
    5589             :     // PURPOSE OF THIS FUNCTION:
    5590             :     // After making sure get input is done, the number of Controller:Simple objects in the
    5591             :     // OA System is returned.
    5592             : 
    5593             :     // METHODOLOGY EMPLOYED:
    5594             :     // na
    5595             : 
    5596             :     // REFERENCES:
    5597             :     // na
    5598             : 
    5599             :     // USE STATEMENTS:
    5600             : 
    5601             :     // Return value
    5602             :     int OASysNumSimpControllers; // number of Controller:Simple objects in this OA System
    5603             : 
    5604             :     // Locals
    5605             :     // FUNCTION ARGUMENT DEFINITIONS:
    5606             : 
    5607             :     // FUNCTION PARAMETER DEFINITIONS:
    5608             :     // na
    5609             : 
    5610             :     // INTERFACE BLOCK SPECIFICATIONS:
    5611             :     // na
    5612             : 
    5613             :     // DERIVED TYPE DEFINITIONS:
    5614             :     // na
    5615             : 
    5616             :     // FUNCTION LOCAL VARIABLE DECLARATIONS:
    5617             :     // na
    5618             : 
    5619        1026 :     if (state.dataMixedAir->GetOASysInputFlag) {
    5620           0 :         GetOutsideAirSysInputs(state);
    5621           0 :         state.dataMixedAir->GetOASysInputFlag = false;
    5622             :     }
    5623             : 
    5624        1026 :     OASysNumSimpControllers = state.dataAirLoop->OutsideAirSys(OASysNumber).NumSimpleControllers;
    5625             : 
    5626        1026 :     return OASysNumSimpControllers;
    5627             : }
    5628             : 
    5629        1026 : int GetOASysNumHeatingCoils(EnergyPlusData &state, int const OASysNumber) // OA Sys Number
    5630             : {
    5631             : 
    5632             :     // FUNCTION INFORMATION:
    5633             :     //       AUTHOR         Fred Buhl
    5634             :     //       DATE WRITTEN   May 2007
    5635             :     //       MODIFIED       na
    5636             :     //       RE-ENGINEERED  na
    5637             : 
    5638             :     // PURPOSE OF THIS FUNCTION:
    5639             :     // After making sure get input is done, the number of heating coils in the
    5640             :     // OA System is returned.
    5641             : 
    5642             :     // METHODOLOGY EMPLOYED:
    5643             :     // na
    5644             : 
    5645             :     // REFERENCES:
    5646             :     // na
    5647             : 
    5648             :     // USE STATEMENTS:
    5649             : 
    5650             :     // Return value
    5651             :     int NumHeatingCoils; // number of heating coils in this OA System
    5652             : 
    5653             :     // Locals
    5654             :     // FUNCTION ARGUMENT DEFINITIONS:
    5655             : 
    5656             :     // FUNCTION PARAMETER DEFINITIONS:
    5657             :     // na
    5658             : 
    5659             :     // INTERFACE BLOCK SPECIFICATIONS:
    5660             :     // na
    5661             : 
    5662             :     // DERIVED TYPE DEFINITIONS:
    5663             :     // na
    5664             : 
    5665             :     // FUNCTION LOCAL VARIABLE DECLARATIONS:
    5666        2052 :     std::string CompType;
    5667        2052 :     std::string CompName;
    5668        1026 :     bool Sim(false);
    5669        1026 :     bool FirstHVACIteration(false);
    5670        1026 :     bool OAHeatingCoil(false);
    5671        1026 :     bool OACoolingCoil(false);
    5672             :     int CompNum;
    5673        1026 :     int AirLoopNum(0);
    5674        1026 :     bool OAHX(false);
    5675             : 
    5676        1026 :     if (state.dataMixedAir->GetOASysInputFlag) {
    5677           0 :         GetOutsideAirSysInputs(state);
    5678           0 :         state.dataMixedAir->GetOASysInputFlag = false;
    5679             :     }
    5680             : 
    5681        1026 :     NumHeatingCoils = 0;
    5682        2172 :     for (CompNum = 1; CompNum <= state.dataAirLoop->OutsideAirSys(OASysNumber).NumComponents; ++CompNum) {
    5683        1146 :         CompType = state.dataAirLoop->OutsideAirSys(OASysNumber).ComponentType(CompNum);
    5684        1146 :         CompName = state.dataAirLoop->OutsideAirSys(OASysNumber).ComponentName(CompNum);
    5685        3438 :         SimOAComponent(state,
    5686             :                        CompType,
    5687             :                        CompName,
    5688        1146 :                        state.dataAirLoop->OutsideAirSys(OASysNumber).ComponentTypeEnum(CompNum),
    5689             :                        FirstHVACIteration,
    5690        1146 :                        state.dataAirLoop->OutsideAirSys(OASysNumber).ComponentIndex(CompNum),
    5691             :                        AirLoopNum,
    5692             :                        Sim,
    5693             :                        OASysNumber,
    5694             :                        OAHeatingCoil,
    5695             :                        OACoolingCoil,
    5696             :                        OAHX);
    5697        1146 :         if (OAHeatingCoil) {
    5698          29 :             ++NumHeatingCoils;
    5699             :         }
    5700             :     }
    5701             : 
    5702        2052 :     return NumHeatingCoils;
    5703             : }
    5704             : 
    5705        1026 : int GetOASysNumHXs(EnergyPlusData &state, int const OASysNumber)
    5706             : {
    5707             : 
    5708             :     // FUNCTION INFORMATION:
    5709             :     //       AUTHOR         Fred Buhl, Rongpeng Zhang
    5710             :     //       DATE WRITTEN   Oct. 2015
    5711             :     //       MODIFIED       na
    5712             :     //       RE-ENGINEERED  na
    5713             : 
    5714             :     // PURPOSE OF THIS FUNCTION:
    5715             :     // After making sure get input is done, the number of heat recovery exchangers in the
    5716             :     // OA System is returned.
    5717             : 
    5718             :     // METHODOLOGY EMPLOYED:
    5719             :     // na
    5720             : 
    5721             :     // REFERENCES:
    5722             :     // na
    5723             : 
    5724             :     // USE STATEMENTS:
    5725             : 
    5726             :     // Return value
    5727             :     int NumHX; // number of heat exchangers in this OA System
    5728             : 
    5729             :     // Locals
    5730             :     // FUNCTION ARGUMENT DEFINITIONS:
    5731             : 
    5732             :     // FUNCTION PARAMETER DEFINITIONS:
    5733             :     // na
    5734             : 
    5735             :     // INTERFACE BLOCK SPECIFICATIONS:
    5736             :     // na
    5737             : 
    5738             :     // DERIVED TYPE DEFINITIONS:
    5739             :     // na
    5740             : 
    5741             :     // FUNCTION LOCAL VARIABLE DECLARATIONS:
    5742             :     int CompNum;
    5743             :     int CompNum_end;
    5744             : 
    5745        1026 :     if (state.dataMixedAir->GetOASysInputFlag) {
    5746           0 :         GetOutsideAirSysInputs(state);
    5747           0 :         state.dataMixedAir->GetOASysInputFlag = false;
    5748             :     }
    5749             : 
    5750        1026 :     NumHX = 0;
    5751             : 
    5752        1026 :     auto const &componentType_Num = state.dataAirLoop->OutsideAirSys(OASysNumber).ComponentTypeEnum;
    5753        2172 :     for (CompNum = 1, CompNum_end = state.dataAirLoop->OutsideAirSys(OASysNumber).NumComponents; CompNum <= CompNum_end; ++CompNum) {
    5754        1146 :         SimAirServingZones::CompType const componentTypeNum = componentType_Num(CompNum);
    5755        1146 :         if (SimAirServingZones::CompType::HeatXchngr == componentTypeNum || SimAirServingZones::CompType::Desiccant == componentTypeNum) {
    5756          31 :             ++NumHX;
    5757             :         }
    5758             :     }
    5759             : 
    5760        1026 :     return NumHX;
    5761             : }
    5762             : 
    5763        1026 : int GetOASysNumCoolingCoils(EnergyPlusData &state, int const OASysNumber) // OA Sys Number
    5764             : {
    5765             : 
    5766             :     // FUNCTION INFORMATION:
    5767             :     //       AUTHOR         Fred Buhl
    5768             :     //       DATE WRITTEN   May 2007
    5769             :     //       MODIFIED       na
    5770             :     //       RE-ENGINEERED  na
    5771             : 
    5772             :     // PURPOSE OF THIS FUNCTION:
    5773             :     // After making sure get input is done, the number of cooling coils in the
    5774             :     // OA System is returned.
    5775             : 
    5776             :     // METHODOLOGY EMPLOYED:
    5777             :     // na
    5778             : 
    5779             :     // REFERENCES:
    5780             :     // na
    5781             : 
    5782             :     // USE STATEMENTS:
    5783             : 
    5784             :     // Return value
    5785             :     int NumCoolingCoils; // number of cooling coils in this OA System
    5786             : 
    5787             :     // Locals
    5788             :     // FUNCTION ARGUMENT DEFINITIONS:
    5789             : 
    5790             :     // FUNCTION PARAMETER DEFINITIONS:
    5791             :     // na
    5792             : 
    5793             :     // INTERFACE BLOCK SPECIFICATIONS:
    5794             :     // na
    5795             : 
    5796             :     // DERIVED TYPE DEFINITIONS:
    5797             :     // na
    5798             : 
    5799             :     // FUNCTION LOCAL VARIABLE DECLARATIONS:
    5800        2052 :     std::string CompType;
    5801        2052 :     std::string CompName;
    5802        1026 :     bool Sim(false);
    5803        1026 :     bool FirstHVACIteration(false);
    5804        1026 :     bool OAHeatingCoil(false);
    5805        1026 :     bool OACoolingCoil(false);
    5806             :     int CompNum;
    5807        1026 :     int AirLoopNum(0);
    5808        1026 :     bool OAHX(false);
    5809             : 
    5810        1026 :     if (state.dataMixedAir->GetOASysInputFlag) {
    5811           0 :         GetOutsideAirSysInputs(state);
    5812           0 :         state.dataMixedAir->GetOASysInputFlag = false;
    5813             :     }
    5814             : 
    5815        1026 :     NumCoolingCoils = 0;
    5816        2172 :     for (CompNum = 1; CompNum <= state.dataAirLoop->OutsideAirSys(OASysNumber).NumComponents; ++CompNum) {
    5817        1146 :         CompType = state.dataAirLoop->OutsideAirSys(OASysNumber).ComponentType(CompNum);
    5818        1146 :         CompName = state.dataAirLoop->OutsideAirSys(OASysNumber).ComponentName(CompNum);
    5819        3438 :         SimOAComponent(state,
    5820             :                        CompType,
    5821             :                        CompName,
    5822        1146 :                        state.dataAirLoop->OutsideAirSys(OASysNumber).ComponentTypeEnum(CompNum),
    5823             :                        FirstHVACIteration,
    5824        1146 :                        state.dataAirLoop->OutsideAirSys(OASysNumber).ComponentIndex(CompNum),
    5825             :                        AirLoopNum,
    5826             :                        Sim,
    5827             :                        OASysNumber,
    5828             :                        OAHeatingCoil,
    5829             :                        OACoolingCoil,
    5830             :                        OAHX);
    5831        1146 :         if (OACoolingCoil) {
    5832          29 :             ++NumCoolingCoils;
    5833             :         }
    5834             :     }
    5835             : 
    5836        2052 :     return NumCoolingCoils;
    5837             : }
    5838             : 
    5839        1026 : int GetOASystemNumber(EnergyPlusData &state, std::string const &OASysName) // OA Sys Name
    5840             : {
    5841             : 
    5842             :     // FUNCTION INFORMATION:
    5843             :     //       AUTHOR         Linda Lawrie
    5844             :     //       DATE WRITTEN   October 2006
    5845             :     //       MODIFIED       na
    5846             :     //       RE-ENGINEERED  na
    5847             : 
    5848             :     // PURPOSE OF THIS FUNCTION:
    5849             :     // After making sure get input is done, the OA System number of indicated
    5850             :     // OA System is returned.
    5851             : 
    5852             :     // Return value
    5853             :     int OASysNumber; // OA Sys Number
    5854             : 
    5855        1026 :     if (state.dataMixedAir->GetOASysInputFlag) {
    5856         202 :         GetOutsideAirSysInputs(state);
    5857         202 :         state.dataMixedAir->GetOASysInputFlag = false;
    5858             :     }
    5859             : 
    5860        1026 :     OASysNumber = UtilityRoutines::FindItemInList(OASysName, state.dataAirLoop->OutsideAirSys);
    5861             : 
    5862        1026 :     return OASysNumber;
    5863             : }
    5864             : 
    5865        1026 : int FindOAMixerMatchForOASystem(EnergyPlusData &state, int const OASysNumber) // Which OA System
    5866             : {
    5867             : 
    5868             :     // FUNCTION INFORMATION:
    5869             :     //       AUTHOR         Linda Lawrie
    5870             :     //       DATE WRITTEN   October 2006
    5871             :     //       MODIFIED       na
    5872             :     //       RE-ENGINEERED  na
    5873             : 
    5874             :     // PURPOSE OF THIS FUNCTION:
    5875             :     // After making sure get input is done, the matched mixer number is found.
    5876             :     // Note -- only the first is looked at for an Outside Air System.
    5877             : 
    5878             :     // Return value
    5879             :     int OAMixerNumber; // Mixer Number
    5880             : 
    5881             :     // FUNCTION LOCAL VARIABLE DECLARATIONS:
    5882             :     int OACompNum;
    5883             : 
    5884        1026 :     if (state.dataMixedAir->GetOAMixerInputFlag) {
    5885         373 :         GetOAMixerInputs(state);
    5886         373 :         state.dataMixedAir->GetOAMixerInputFlag = false;
    5887             :     }
    5888             : 
    5889        1026 :     OAMixerNumber = 0;
    5890        1026 :     if (OASysNumber > 0 && OASysNumber <= state.dataAirLoop->NumOASystems) {
    5891        1144 :         for (OACompNum = 1; OACompNum <= state.dataAirLoop->OutsideAirSys(OASysNumber).NumComponents; ++OACompNum) {
    5892        1144 :             if (UtilityRoutines::SameString(state.dataAirLoop->OutsideAirSys(OASysNumber).ComponentType(OACompNum), "OUTDOORAIR:MIXER")) {
    5893        1026 :                 OAMixerNumber = UtilityRoutines::FindItemInList(state.dataAirLoop->OutsideAirSys(OASysNumber).ComponentName(OACompNum),
    5894        1026 :                                                                 state.dataMixedAir->OAMixer);
    5895        1026 :                 break;
    5896             :             }
    5897             :         }
    5898             :     }
    5899             : 
    5900        1026 :     return OAMixerNumber;
    5901             : }
    5902             : 
    5903         334 : int GetOAMixerIndex(EnergyPlusData &state, std::string const &OAMixerName) // Which Mixer
    5904             : {
    5905             : 
    5906             :     // FUNCTION INFORMATION:
    5907             :     //       AUTHOR         Linda Lawrie
    5908             :     //       DATE WRITTEN   December 2010
    5909             :     //       MODIFIED       na
    5910             :     //       RE-ENGINEERED  na
    5911             : 
    5912             :     // PURPOSE OF THIS FUNCTION:
    5913             :     // After making sure get input is done, the mixer index of indicated
    5914             :     // mixer is returned.
    5915             : 
    5916             :     // Return value
    5917             :     int OAMixerIndex; // Mixer Index
    5918             : 
    5919         334 :     if (state.dataMixedAir->GetOAMixerInputFlag) {
    5920          24 :         GetOAMixerInputs(state);
    5921          24 :         state.dataMixedAir->GetOAMixerInputFlag = false;
    5922             :     }
    5923             : 
    5924         334 :     OAMixerIndex = UtilityRoutines::FindItem(OAMixerName, state.dataMixedAir->OAMixer);
    5925             : 
    5926         334 :     if (OAMixerIndex == 0) {
    5927           0 :         ShowSevereError(state, "GetOAMixerIndex: Could not find OutdoorAir:Mixer, Name=\"" + OAMixerName + "\"");
    5928             :     }
    5929             : 
    5930         334 :     return OAMixerIndex;
    5931             : }
    5932             : 
    5933        1034 : int GetOAMixerInletNodeNumber(EnergyPlusData &state, int const OAMixerNumber) // Which Mixer
    5934             : {
    5935             : 
    5936             :     // FUNCTION INFORMATION:
    5937             :     //       AUTHOR         Linda Lawrie
    5938             :     //       DATE WRITTEN   October 2006
    5939             :     //       MODIFIED       na
    5940             :     //       RE-ENGINEERED  na
    5941             : 
    5942             :     // PURPOSE OF THIS FUNCTION:
    5943             :     // After making sure get input is done, the mixer inlet node number of indicated
    5944             :     // mixer is returned.
    5945             : 
    5946             :     // METHODOLOGY EMPLOYED:
    5947             :     // na
    5948             : 
    5949             :     // REFERENCES:
    5950             :     // na
    5951             : 
    5952             :     // USE STATEMENTS:
    5953             :     // na
    5954             : 
    5955             :     // Return value
    5956             :     int OAMixerInletNodeNumber; // Mixer Inlet Node Number
    5957             : 
    5958             :     // Locals
    5959             :     // FUNCTION ARGUMENT DEFINITIONS:
    5960             : 
    5961             :     // FUNCTION PARAMETER DEFINITIONS:
    5962             :     // na
    5963             : 
    5964             :     // INTERFACE BLOCK SPECIFICATIONS:
    5965             :     // na
    5966             : 
    5967             :     // DERIVED TYPE DEFINITIONS:
    5968             :     // na
    5969             : 
    5970             :     // FUNCTION LOCAL VARIABLE DECLARATIONS:
    5971             :     // na
    5972             : 
    5973        1034 :     if (state.dataMixedAir->GetOAMixerInputFlag) {
    5974           0 :         GetOAMixerInputs(state);
    5975           0 :         state.dataMixedAir->GetOAMixerInputFlag = false;
    5976             :     }
    5977             : 
    5978        1034 :     OAMixerInletNodeNumber = 0;
    5979        1034 :     if (OAMixerNumber > 0 && OAMixerNumber <= state.dataMixedAir->NumOAMixers) {
    5980        1034 :         OAMixerInletNodeNumber = state.dataMixedAir->OAMixer(OAMixerNumber).InletNode;
    5981             :     }
    5982             : 
    5983        1034 :     return OAMixerInletNodeNumber;
    5984             : }
    5985             : 
    5986       40158 : int GetOAMixerReturnNodeNumber(EnergyPlusData &state, int const OAMixerNumber) // Which Mixer
    5987             : {
    5988             : 
    5989             :     // FUNCTION INFORMATION:
    5990             :     //       AUTHOR         Brent Griffith
    5991             :     //       DATE WRITTEN   December 2006
    5992             :     //       MODIFIED       na
    5993             :     //       RE-ENGINEERED  na
    5994             : 
    5995             :     // PURPOSE OF THIS FUNCTION:
    5996             :     // After making sure get input is done, the mixer return node number of indicated
    5997             :     // mixer is returned.
    5998             : 
    5999             :     // METHODOLOGY EMPLOYED:
    6000             :     // followed Linda Lawrie's GetOAMixerInletNodeNumber
    6001             : 
    6002             :     // REFERENCES:
    6003             :     // na
    6004             : 
    6005             :     // USE STATEMENTS:
    6006             :     // na
    6007             : 
    6008             :     // Return value
    6009             :     int OAMixerReturnNodeNumber; // Mixer Inlet Node Number
    6010             : 
    6011             :     // Locals
    6012             :     // FUNCTION ARGUMENT DEFINITIONS:
    6013             : 
    6014             :     // FUNCTION PARAMETER DEFINITIONS:
    6015             :     // na
    6016             : 
    6017             :     // INTERFACE BLOCK SPECIFICATIONS:
    6018             :     // na
    6019             : 
    6020             :     // DERIVED TYPE DEFINITIONS:
    6021             :     // na
    6022             : 
    6023             :     // FUNCTION LOCAL VARIABLE DECLARATIONS:
    6024             :     // na
    6025             : 
    6026       40158 :     if (state.dataMixedAir->GetOAMixerInputFlag) {
    6027           0 :         GetOAMixerInputs(state);
    6028           0 :         state.dataMixedAir->GetOAMixerInputFlag = false;
    6029             :     }
    6030             : 
    6031       40158 :     OAMixerReturnNodeNumber = 0;
    6032       40158 :     if (OAMixerNumber > 0 && OAMixerNumber <= state.dataMixedAir->NumOAMixers) {
    6033       40158 :         OAMixerReturnNodeNumber = state.dataMixedAir->OAMixer(OAMixerNumber).RetNode;
    6034             :     }
    6035             : 
    6036       40158 :     return OAMixerReturnNodeNumber;
    6037             : }
    6038             : 
    6039       40158 : int GetOAMixerMixedNodeNumber(EnergyPlusData &state, int const OAMixerNumber) // Which Mixer
    6040             : {
    6041             : 
    6042             :     // FUNCTION INFORMATION:
    6043             :     //       AUTHOR         Brent Griffith
    6044             :     //       DATE WRITTEN   December 2006
    6045             :     //       MODIFIED       na
    6046             :     //       RE-ENGINEERED  na
    6047             : 
    6048             :     // PURPOSE OF THIS FUNCTION:
    6049             :     // After making sure get input is done, the mixer mixed air node number of indicated
    6050             :     // mixer is returned.
    6051             : 
    6052             :     // METHODOLOGY EMPLOYED:
    6053             :     // followed Linda Lawrie's GetOAMixerInletNodeNumber
    6054             : 
    6055             :     // REFERENCES:
    6056             :     // na
    6057             : 
    6058             :     // USE STATEMENTS:
    6059             :     // na
    6060             : 
    6061             :     // Return value
    6062             :     int OAMixerMixedNodeNumber; // Mixer Inlet Node Number
    6063             : 
    6064             :     // Locals
    6065             :     // FUNCTION ARGUMENT DEFINITIONS:
    6066             : 
    6067             :     // FUNCTION PARAMETER DEFINITIONS:
    6068             :     // na
    6069             : 
    6070             :     // INTERFACE BLOCK SPECIFICATIONS:
    6071             :     // na
    6072             : 
    6073             :     // DERIVED TYPE DEFINITIONS:
    6074             :     // na
    6075             : 
    6076             :     // FUNCTION LOCAL VARIABLE DECLARATIONS:
    6077             :     // na
    6078             : 
    6079       40158 :     if (state.dataMixedAir->GetOAMixerInputFlag) {
    6080           0 :         GetOAMixerInputs(state);
    6081           0 :         state.dataMixedAir->GetOAMixerInputFlag = false;
    6082             :     }
    6083             : 
    6084       40158 :     OAMixerMixedNodeNumber = 0;
    6085       40158 :     if (OAMixerNumber > 0 && OAMixerNumber <= state.dataMixedAir->NumOAMixers) {
    6086       40158 :         OAMixerMixedNodeNumber = state.dataMixedAir->OAMixer(OAMixerNumber).MixNode;
    6087             :     }
    6088             : 
    6089       40158 :     return OAMixerMixedNodeNumber;
    6090             : }
    6091             : 
    6092         822 : bool CheckForControllerWaterCoil(EnergyPlusData &state,
    6093             :                                  std::string const &ControllerType, // should be passed in as UPPERCASE
    6094             :                                  std::string const &ControllerName  // should be passed in as UPPERCASE
    6095             : )
    6096             : {
    6097             : 
    6098             :     // FUNCTION INFORMATION:
    6099             :     //       AUTHOR         Linda Lawrie
    6100             :     //       DATE WRITTEN   May 2009
    6101             :     //       MODIFIED       na
    6102             :     //       RE-ENGINEERED  na
    6103             : 
    6104             :     // PURPOSE OF THIS FUNCTION:
    6105             :     // This routine checks the controller list for existance of the
    6106             :     // reference coil.
    6107             : 
    6108             :     // Return value
    6109             :     bool OnControllerList; // true if found on controller list
    6110             : 
    6111             :     // FUNCTION LOCAL VARIABLE DECLARATIONS:
    6112             :     int Num;
    6113             :     int CompNum;
    6114             : 
    6115         822 :     if (state.dataMixedAir->GetOASysInputFlag) {
    6116         273 :         GetOutsideAirSysInputs(state);
    6117         273 :         state.dataMixedAir->GetOASysInputFlag = false;
    6118             :     }
    6119             : 
    6120         822 :     OnControllerList = false;
    6121             : 
    6122        5418 :     for (Num = 1; Num <= state.dataMixedAir->NumControllerLists; ++Num) {
    6123       11950 :         for (CompNum = 1; CompNum <= state.dataMixedAir->ControllerLists(Num).NumControllers; ++CompNum) {
    6124             : 
    6125        8176 :             if (!UtilityRoutines::SameString(state.dataMixedAir->ControllerLists(Num).ControllerType(CompNum), ControllerType)) continue;
    6126        5789 :             if (!UtilityRoutines::SameString(state.dataMixedAir->ControllerLists(Num).ControllerName(CompNum), ControllerName)) continue;
    6127         822 :             OnControllerList = true;
    6128         822 :             break;
    6129             :         }
    6130             :     }
    6131             : 
    6132         822 :     return OnControllerList;
    6133             : }
    6134             : 
    6135         769 : void CheckControllerLists(EnergyPlusData &state, bool &ErrFound)
    6136             : {
    6137             : 
    6138             :     // SUBROUTINE INFORMATION:
    6139             :     //       AUTHOR         Linda Lawrie
    6140             :     //       DATE WRITTEN   May 2009
    6141             :     //       MODIFIED       na
    6142             :     //       RE-ENGINEERED  na
    6143             : 
    6144             :     // PURPOSE OF THIS SUBROUTINE:
    6145             :     // This routine checks for a "dangling" controller list (AirLoopHVAC:ControllerList).
    6146             :     // It must be either found on a AirLoopHVAC or AirLoopHVAC:OutdoorAirSystem.
    6147             : 
    6148             :     // Using/Aliasing
    6149             : 
    6150             :     // SUBROUTINE PARAMETER DEFINITIONS:
    6151         769 :     static std::string const CurrentModuleObject("AirLoopHVAC:ControllerList");
    6152         769 :     static std::string const AirLoopObject("AirLoopHVAC");
    6153             : 
    6154             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    6155             :     int NumAlphas;
    6156             :     int NumNumbers;
    6157             :     int NumControllers;
    6158             :     int NumAirLoop;
    6159        1538 :     std::string ControllerListName;
    6160             :     int Item;
    6161             :     int IOStat;
    6162             :     int Found;
    6163             :     int Count;
    6164             :     int Loop;
    6165        1538 :     std::string AirLoopName;
    6166             : 
    6167         769 :     if (state.dataMixedAir->GetOASysInputFlag) {
    6168         246 :         GetOutsideAirSysInputs(state);
    6169         246 :         state.dataMixedAir->GetOASysInputFlag = false;
    6170             :     }
    6171             : 
    6172         769 :     NumControllers = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
    6173         769 :     NumAirLoop = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, AirLoopObject);
    6174         769 :     AirLoopName = "";
    6175             : 
    6176        2206 :     for (Item = 1; Item <= NumControllers; ++Item) {
    6177             : 
    6178        4311 :         state.dataInputProcessing->inputProcessor->getObjectItem(
    6179        2874 :             state, CurrentModuleObject, Item, state.dataIPShortCut->cAlphaArgs, NumAlphas, state.dataIPShortCut->rNumericArgs, NumNumbers, IOStat);
    6180        1437 :         ControllerListName = state.dataIPShortCut->cAlphaArgs(1);
    6181        1437 :         Count = 0;
    6182             : 
    6183             :         // Check AirLoopHVAC -- brute force, get each AirLoopHVAC
    6184             : 
    6185       14123 :         for (Loop = 1; Loop <= NumAirLoop; ++Loop) {
    6186       38058 :             state.dataInputProcessing->inputProcessor->getObjectItem(
    6187       25372 :                 state, AirLoopObject, Loop, state.dataIPShortCut->cAlphaArgs, NumAlphas, state.dataIPShortCut->rNumericArgs, NumNumbers, IOStat);
    6188       12686 :             if (state.dataIPShortCut->cAlphaArgs(2) != ControllerListName) continue;
    6189         415 :             ++Count;
    6190         415 :             if (Count == 1) AirLoopName = state.dataIPShortCut->cAlphaArgs(1);
    6191             :         }
    6192             : 
    6193             :         //  Now check AirLoopHVAC and AirLoopHVAC:OutdoorAirSystem
    6194        1437 :         Found = 0;
    6195        1437 :         if (state.dataAirLoop->NumOASystems > 0) {
    6196        1356 :             Found = UtilityRoutines::FindItemInList(ControllerListName, state.dataAirLoop->OutsideAirSys, &OutsideAirSysProps::ControllerListName);
    6197        1356 :             if (Found > 0) ++Count;
    6198             :         }
    6199             : 
    6200        1437 :         if (Count == 0) {
    6201           0 :             ShowSevereError(state,
    6202           0 :                             CurrentModuleObject + "=\"" + ControllerListName +
    6203             :                                 "\" is not referenced on a AirLoopHVAC or AirLoopHVAC:OutdoorAirSystem object.");
    6204           0 :             ErrFound = true;
    6205        1437 :         } else if (Count > 1) {
    6206           0 :             ShowSevereError(state,
    6207           0 :                             CurrentModuleObject + "=\"" + ControllerListName +
    6208             :                                 "\" has too many references on AirLoopHVAC or AirLoopHVAC:OutdoorAirSystem objects.");
    6209           0 :             if (Found > 0) {
    6210           0 :                 ShowContinueError(state, "...AirLoopHVAC:OutdoorAirSystem=\"" + state.dataAirLoop->OutsideAirSys(Found).Name + "\".");
    6211             :             }
    6212           0 :             ShowContinueError(state, "...also on AirLoopHVAC=\"" + AirLoopName + "\".");
    6213           0 :             ErrFound = true;
    6214             :         }
    6215             :     }
    6216         769 : }
    6217             : 
    6218         104 : void CheckOAControllerName(
    6219             :     EnergyPlusData &state, std::string &OAControllerName, std::string const &ObjectType, std::string const &FieldName, bool &ErrorsFound)
    6220             : {
    6221             : 
    6222             :     // SUBROUTINE INFORMATION:
    6223             :     //       AUTHOR         Linda Lawrie
    6224             :     //       DATE WRITTEN   October 2006
    6225             :     //       MODIFIED       na
    6226             :     //       RE-ENGINEERED  na
    6227             : 
    6228             :     // PURPOSE OF THIS SUBROUTINE:
    6229             :     // When OA Controller data is gotten from other routines, must check to make sure
    6230             :     // new name doesn't duplicate.  (Essentially a pass through to call Verify Name)
    6231             :     // Currently, this is only called from HVACStandAlongERV::GetStandaloneERV()
    6232             : 
    6233         104 :     if (state.dataMixedAir->AllocateOAControllersFlag) {
    6234             :         // Make sure OAControllers are allocated
    6235           3 :         AllocateOAControllers(state);
    6236             :     }
    6237             : 
    6238         208 :     GlobalNames::VerifyUniqueInterObjectName(
    6239         104 :         state, state.dataMixedAir->OAControllerUniqueNames, OAControllerName, ObjectType, FieldName, ErrorsFound);
    6240         104 : }
    6241             : 
    6242    14592647 : void OAControllerProps::Checksetpoints(EnergyPlusData &state,
    6243             :                                        Real64 const OutAirMinFrac,   // Local variable used to calculate min OA fraction
    6244             :                                        Real64 &OutAirSignal,         // Used to set OA mass flow rate
    6245             :                                        bool &EconomizerOperationFlag // logical used to show economizer status
    6246             : )
    6247             : {
    6248             : 
    6249             :     // SUBROUTINE INFORMATION:
    6250             :     //       AUTHOR         Amit bhansali
    6251             :     //       DATE WRITTEN   August 2008?
    6252             :     //       MODIFIED       na
    6253             :     //       RE-ENGINEERED  na
    6254             : 
    6255             :     // PURPOSE OF THIS SUBROUTINE:
    6256             :     // This subroutine checks the setpoints of the upper limits of temperatures, limit enthalpy
    6257             :     // Limit dew point, Enthalpy curve
    6258             : 
    6259             :     // METHODOLOGY EMPLOYED:
    6260             :     // na
    6261             : 
    6262             :     // REFERENCES:
    6263             :     // na
    6264             : 
    6265             :     // Using/Aliasing
    6266             :     using Curve::CurveValue;
    6267             :     using Psychrometrics::PsyTdpFnWPb;
    6268             : 
    6269             :     // Locals
    6270             :     // SUBROUTINE ARGUMENT DEFINITIONS:
    6271             : 
    6272             :     // SUBROUTINE PARAMETER DEFINITIONS:
    6273             :     // na
    6274             : 
    6275             :     // INTERFACE BLOCK SPECIFICATIONS:
    6276             :     // na
    6277             : 
    6278             :     // DERIVED TYPE DEFINITIONS:
    6279             :     // na
    6280             : 
    6281             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    6282             :     Real64 OADPTemp; // Dew Point Temperature calculation
    6283             : 
    6284    14592647 :     if (this->TempLim != BlankNumeric && this->OATemp > this->TempLim) {
    6285     5613950 :         OutAirSignal = OutAirMinFrac;
    6286     5613950 :         EconomizerOperationFlag = false;
    6287             :     }
    6288             :     // Outside air enthalpy limit
    6289    14592647 :     if (this->EnthLim != BlankNumeric && this->OAEnth > this->EnthLim) {
    6290     5219287 :         OutAirSignal = OutAirMinFrac;
    6291     5219287 :         EconomizerOperationFlag = false;
    6292             :     }
    6293             : 
    6294    14592647 :     if (this->DPTempLim != BlankNumeric) {
    6295       94609 :         OADPTemp = PsyTdpFnWPb(state, this->OAHumRat, this->OAPress);
    6296       94609 :         if (OADPTemp > this->DPTempLim) {
    6297       46695 :             OutAirSignal = OutAirMinFrac;
    6298       46695 :             EconomizerOperationFlag = false;
    6299             :         }
    6300             :     }
    6301             : 
    6302    14592647 :     if (this->EnthalpyCurvePtr > 0) {
    6303       65324 :         if (this->OAHumRat > CurveValue(state, this->EnthalpyCurvePtr, this->OATemp)) {
    6304       36603 :             OutAirSignal = OutAirMinFrac;
    6305       36603 :             EconomizerOperationFlag = false;
    6306             :         }
    6307             :     }
    6308    14592647 : }
    6309             : 
    6310         583 : int GetNumOASystems(EnergyPlusData &state)
    6311             : {
    6312             : 
    6313             :     // FUNCTION INFORMATION:
    6314             :     //       AUTHOR         Linda Lawrie
    6315             :     //       DATE WRITTEN   November 2010
    6316             :     //       MODIFIED       na
    6317             :     //       RE-ENGINEERED  na
    6318             : 
    6319             :     // PURPOSE OF THIS FUNCTION:
    6320             :     // Get Number of OA Systems, After making sure get input is done
    6321             : 
    6322             :     // METHODOLOGY EMPLOYED:
    6323             :     // na
    6324             : 
    6325             :     // REFERENCES:
    6326             :     // na
    6327             : 
    6328             :     // USE STATEMENTS:
    6329             :     // na
    6330             : 
    6331             :     // Return value
    6332             :     int NumberOfOASystems; // Number of OA Systems
    6333             : 
    6334             :     // Locals
    6335             :     // FUNCTION ARGUMENT DEFINITIONS:
    6336             : 
    6337             :     // FUNCTION PARAMETER DEFINITIONS:
    6338             :     // na
    6339             : 
    6340             :     // INTERFACE BLOCK SPECIFICATIONS:
    6341             :     // na
    6342             : 
    6343             :     // DERIVED TYPE DEFINITIONS:
    6344             :     // na
    6345             : 
    6346             :     // FUNCTION LOCAL VARIABLE DECLARATIONS:
    6347             :     // na
    6348             : 
    6349         583 :     if (state.dataMixedAir->GetOASysInputFlag) {
    6350          49 :         GetOutsideAirSysInputs(state);
    6351          49 :         state.dataMixedAir->GetOASysInputFlag = false;
    6352             :     }
    6353             : 
    6354         583 :     NumberOfOASystems = state.dataAirLoop->NumOASystems;
    6355             : 
    6356         583 :     return NumberOfOASystems;
    6357             : }
    6358             : 
    6359        1027 : int GetOACompListNumber(EnergyPlusData &state, int const OASysNum) // OA Sys Number
    6360             : {
    6361             : 
    6362             :     // FUNCTION INFORMATION:
    6363             :     //       AUTHOR         Heejin Cho
    6364             :     //       DATE WRITTEN   November 2010
    6365             :     //       MODIFIED       na
    6366             :     //       RE-ENGINEERED  na
    6367             : 
    6368             :     // PURPOSE OF THIS FUNCTION:
    6369             :     // After making sure get input is done, the OA System number of indicated
    6370             :     // OA System is returned.
    6371             : 
    6372             :     // Return value
    6373             :     int NumOACompList; // OA Comp Number
    6374             : 
    6375        1027 :     if (state.dataMixedAir->GetOASysInputFlag) {
    6376           0 :         GetOutsideAirSysInputs(state);
    6377           0 :         state.dataMixedAir->GetOASysInputFlag = false;
    6378             :     }
    6379             : 
    6380        1027 :     NumOACompList = state.dataAirLoop->OutsideAirSys(OASysNum).NumComponents;
    6381             : 
    6382        1027 :     return NumOACompList;
    6383             : }
    6384             : 
    6385          55 : std::string GetOACompName(EnergyPlusData &state,
    6386             :                           int const OASysNum, // OA Sys Number
    6387             :                           int const InListNum // In-list Number
    6388             : )
    6389             : {
    6390             : 
    6391             :     // FUNCTION INFORMATION:
    6392             :     //       AUTHOR         Heejin Cho
    6393             :     //       DATE WRITTEN   November 2010
    6394             :     //       MODIFIED       na
    6395             :     //       RE-ENGINEERED  na
    6396             : 
    6397             :     // PURPOSE OF THIS FUNCTION:
    6398             :     // After making sure get input is done, the number of heating coils in the
    6399             :     // OA System is returned.
    6400             : 
    6401             :     // METHODOLOGY EMPLOYED:
    6402             :     // na
    6403             : 
    6404             :     // REFERENCES:
    6405             :     // na
    6406             : 
    6407             :     // USE STATEMENTS:
    6408             : 
    6409             :     // Return value
    6410          55 :     std::string OACompName;
    6411             : 
    6412             :     // Locals
    6413             :     // FUNCTION ARGUMENT DEFINITIONS:
    6414             :     // FUNCTION PARAMETER DEFINITIONS:
    6415             :     // na
    6416             : 
    6417             :     // INTERFACE BLOCK SPECIFICATIONS:
    6418             :     // na
    6419             : 
    6420             :     // DERIVED TYPE DEFINITIONS:
    6421             :     // na
    6422             : 
    6423             :     // FUNCTION LOCAL VARIABLE DECLARATIONS:
    6424             : 
    6425          55 :     if (state.dataMixedAir->GetOASysInputFlag) {
    6426           0 :         GetOutsideAirSysInputs(state);
    6427           0 :         state.dataMixedAir->GetOASysInputFlag = false;
    6428             :     }
    6429             : 
    6430          55 :     OACompName = state.dataAirLoop->OutsideAirSys(OASysNum).ComponentName(InListNum);
    6431             : 
    6432          55 :     return OACompName;
    6433             : }
    6434             : 
    6435          55 : std::string GetOACompType(EnergyPlusData &state,
    6436             :                           int const OASysNum, // OA Sys Number
    6437             :                           int const InListNum // In-list Number
    6438             : )
    6439             : {
    6440             : 
    6441             :     // FUNCTION INFORMATION:
    6442             :     //       AUTHOR         Heejin Cho
    6443             :     //       DATE WRITTEN   November 2010
    6444             :     //       MODIFIED       na
    6445             :     //       RE-ENGINEERED  na
    6446             : 
    6447             :     // PURPOSE OF THIS FUNCTION:
    6448             :     // After making sure get input is done, the number of heating coils in the
    6449             :     // OA System is returned.
    6450             : 
    6451             :     // METHODOLOGY EMPLOYED:
    6452             :     // na
    6453             : 
    6454             :     // REFERENCES:
    6455             :     // na
    6456             : 
    6457             :     // USE STATEMENTS:
    6458             : 
    6459             :     // Return value
    6460          55 :     std::string OACompType;
    6461             : 
    6462             :     // Locals
    6463             :     // FUNCTION ARGUMENT DEFINITIONS:
    6464             :     // FUNCTION PARAMETER DEFINITIONS:
    6465             :     // na
    6466             : 
    6467             :     // INTERFACE BLOCK SPECIFICATIONS:
    6468             :     // na
    6469             : 
    6470             :     // DERIVED TYPE DEFINITIONS:
    6471             :     // na
    6472             : 
    6473             :     // FUNCTION LOCAL VARIABLE DECLARATIONS:
    6474             : 
    6475          55 :     if (state.dataMixedAir->GetOASysInputFlag) {
    6476           0 :         GetOutsideAirSysInputs(state);
    6477           0 :         state.dataMixedAir->GetOASysInputFlag = false;
    6478             :     }
    6479             : 
    6480          55 :     OACompType = state.dataAirLoop->OutsideAirSys(OASysNum).ComponentType(InListNum);
    6481             : 
    6482          55 :     return OACompType;
    6483             : }
    6484             : 
    6485        1149 : SimAirServingZones::CompType GetOACompTypeNum(EnergyPlusData &state,
    6486             :                                               int const OASysNum, // OA Sys Number
    6487             :                                               int const InListNum // In-list Number
    6488             : )
    6489             : {
    6490             : 
    6491             :     // FUNCTION INFORMATION:
    6492             :     //       AUTHOR         Heejin Cho
    6493             :     //       DATE WRITTEN   November 2010
    6494             :     //       MODIFIED       na
    6495             :     //       RE-ENGINEERED  na
    6496             : 
    6497             :     // PURPOSE OF THIS FUNCTION:
    6498             :     // After making sure get input is done, the number of heating coils in the
    6499             :     // OA System is returned.
    6500             : 
    6501             :     // METHODOLOGY EMPLOYED:
    6502             :     // na
    6503             : 
    6504             :     // REFERENCES:
    6505             :     // na
    6506             : 
    6507             :     // USE STATEMENTS:
    6508             : 
    6509             :     // Return value
    6510             :     SimAirServingZones::CompType OACompTypeNum;
    6511             : 
    6512             :     // Locals
    6513             :     // FUNCTION ARGUMENT DEFINITIONS:
    6514             :     // FUNCTION PARAMETER DEFINITIONS:
    6515             :     // na
    6516             : 
    6517             :     // INTERFACE BLOCK SPECIFICATIONS:
    6518             :     // na
    6519             : 
    6520             :     // DERIVED TYPE DEFINITIONS:
    6521             :     // na
    6522             : 
    6523             :     // FUNCTION LOCAL VARIABLE DECLARATIONS:
    6524             : 
    6525        1149 :     if (state.dataMixedAir->GetOASysInputFlag) {
    6526           0 :         GetOutsideAirSysInputs(state);
    6527           0 :         state.dataMixedAir->GetOASysInputFlag = false;
    6528             :     }
    6529             : 
    6530        1149 :     OACompTypeNum = state.dataAirLoop->OutsideAirSys(OASysNum).ComponentTypeEnum(InListNum);
    6531             : 
    6532        1149 :     return OACompTypeNum;
    6533             : }
    6534             : 
    6535           4 : int GetOAMixerNumber(EnergyPlusData &state, std::string const &OAMixerName // must match OA mixer names for the OA mixer type
    6536             : )
    6537             : {
    6538             : 
    6539             :     // FUNCTION INFORMATION:
    6540             :     //       AUTHOR         Lixing Gu
    6541             :     //       DATE WRITTEN   Feb. 2018
    6542             : 
    6543             :     // PURPOSE OF THIS FUNCTION:
    6544             :     // This function looks up the given OA mixer and returns the OAMixer number.  If
    6545             :     // incorrect OA mixer name is given, ErrorsFound is returned as true
    6546             : 
    6547             :     int WhichOAMixer;
    6548             : 
    6549             :     // Obtains and Allocates OA mixer related parameters from input file
    6550           4 :     if (state.dataMixedAir->GetOAMixerInputFlag) { // First time subroutine has been entered
    6551           2 :         GetOAMixerInputs(state);
    6552           2 :         state.dataMixedAir->GetOAMixerInputFlag = false;
    6553             :     }
    6554             : 
    6555           4 :     WhichOAMixer = UtilityRoutines::FindItemInList(OAMixerName, state.dataMixedAir->OAMixer);
    6556             : 
    6557           4 :     return WhichOAMixer;
    6558             : }
    6559             : // End of Utility Section of the Module
    6560             : //******************************************************************************
    6561             : 
    6562        2313 : } // namespace EnergyPlus::MixedAir

Generated by: LCOV version 1.13