LCOV - code coverage report
Current view: top level - EnergyPlus - SystemAvailabilityManager.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 35.1 % 2598 912
Test Date: 2025-05-22 16:09:37 Functions: 67.9 % 28 19

            Line data    Source code
       1              : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
       2              : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
       3              : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
       4              : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
       5              : // contributors. All rights reserved.
       6              : //
       7              : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
       8              : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
       9              : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
      10              : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
      11              : // derivative works, and perform publicly and display publicly, and to permit others to do so.
      12              : //
      13              : // Redistribution and use in source and binary forms, with or without modification, are permitted
      14              : // provided that the following conditions are met:
      15              : //
      16              : // (1) Redistributions of source code must retain the above copyright notice, this list of
      17              : //     conditions and the following disclaimer.
      18              : //
      19              : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
      20              : //     conditions and the following disclaimer in the documentation and/or other materials
      21              : //     provided with the distribution.
      22              : //
      23              : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
      24              : //     the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
      25              : //     used to endorse or promote products derived from this software without specific prior
      26              : //     written permission.
      27              : //
      28              : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
      29              : //     without changes from the version obtained under this License, or (ii) Licensee makes a
      30              : //     reference solely to the software portion of its product, Licensee must refer to the
      31              : //     software as "EnergyPlus version X" software, where "X" is the version number Licensee
      32              : //     obtained under this License and may not use a different name for the software. Except as
      33              : //     specifically required in this Section (4), Licensee shall not use in a company name, a
      34              : //     product name, in advertising, publicity, or other promotional activities any name, trade
      35              : //     name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
      36              : //     similar designation, without the U.S. Department of Energy's prior written consent.
      37              : //
      38              : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
      39              : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
      40              : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
      41              : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      42              : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      43              : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      44              : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      45              : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      46              : // POSSIBILITY OF SUCH DAMAGE.
      47              : 
      48              : // C++ Headers
      49              : #include <algorithm>
      50              : #include <cmath>
      51              : 
      52              : // ObjexxFCL Headers
      53              : #include <ObjexxFCL/Array.functions.hh>
      54              : #include <ObjexxFCL/Array2D.hh>
      55              : 
      56              : // EnergyPlus Headers
      57              : #include <AirflowNetwork/Elements.hpp>
      58              : #include <AirflowNetwork/Solver.hpp>
      59              : #include <EnergyPlus/CurveManager.hh>
      60              : #include <EnergyPlus/Data/EnergyPlusData.hh>
      61              : #include <EnergyPlus/DataAirLoop.hh>
      62              : #include <EnergyPlus/DataAirSystems.hh>
      63              : #include <EnergyPlus/DataContaminantBalance.hh>
      64              : #include <EnergyPlus/DataEnvironment.hh>
      65              : #include <EnergyPlus/DataGlobalConstants.hh>
      66              : #include <EnergyPlus/DataHeatBalFanSys.hh>
      67              : #include <EnergyPlus/DataHeatBalance.hh>
      68              : #include <EnergyPlus/DataIPShortCuts.hh>
      69              : #include <EnergyPlus/DataLoopNode.hh>
      70              : #include <EnergyPlus/DataZoneControls.hh>
      71              : #include <EnergyPlus/DataZoneEquipment.hh>
      72              : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      73              : #include <EnergyPlus/NodeInputManager.hh>
      74              : #include <EnergyPlus/OutputProcessor.hh>
      75              : #include <EnergyPlus/Psychrometrics.hh>
      76              : #include <EnergyPlus/ScheduleManager.hh>
      77              : #include <EnergyPlus/SystemAvailabilityManager.hh>
      78              : #include <EnergyPlus/ThermalComfort.hh>
      79              : #include <EnergyPlus/UtilityRoutines.hh>
      80              : #include <EnergyPlus/ZoneTempPredictorCorrector.hh>
      81              : 
      82              : namespace EnergyPlus {
      83              : 
      84              : namespace Avail {
      85              : 
      86              :     // Module containing the System Availability Manager routines
      87              : 
      88              :     // MODULE INFORMATION:
      89              :     //       AUTHOR         Fred Buhl
      90              :     //       DATE WRITTEN   August 2001
      91              :     //       MODIFIED       February 2004, PGE: Added plant managers.
      92              :     //       MODIFIED       March 2007, LG: Added hybrid ventilation control.
      93              :     //                      August 2008, R. Raustad - FSEC: added 2 new scheduled sys avail managers
      94              :     //                      March 2011, Chandan Sharma - FSEC: Added zone sys avail managers
      95              :     //                      August 2013, Xiufeng Pang (XP) - added algorithms for optimal start
      96              :     //       RE-ENGINEERED  na
      97              : 
      98              :     // PURPOSE OF THIS MODULE
      99              :     // To encapsulate the data and algorithms required to
     100              :     // determine system (loop) availability and "cycle on" status.
     101              : 
     102              :     // METHODOLOGY EMPLOYED:
     103              :     // Previous time step node data and current zone thermostat setpoints are used
     104              :     // in a set of fixed, precoded algorithms to determine the current time step
     105              :     // on/off status of systems and loops.
     106              : 
     107              :     // USE STATEMENTS:
     108              :     // Use statements for data only modules
     109              :     static constexpr std::array<std::string_view, (int)ManagerType::Num> managerTypeNamesUC = {"AVAILABILITYMANAGER:SCHEDULED",
     110              :                                                                                                "AVAILABILITYMANAGER:SCHEDULEDON",
     111              :                                                                                                "AVAILABILITYMANAGER:SCHEDULEDOFF",
     112              :                                                                                                "AVAILABILITYMANAGER:NIGHTCYCLE",
     113              :                                                                                                "AVAILABILITYMANAGER:DIFFERENTIALTHERMOSTAT",
     114              :                                                                                                "AVAILABILITYMANAGER:HIGHTEMPERATURETURNOFF",
     115              :                                                                                                "AVAILABILITYMANAGER:HIGHTEMPERATURETURNON",
     116              :                                                                                                "AVAILABILITYMANAGER:LOWTEMPERATURETURNOFF",
     117              :                                                                                                "AVAILABILITYMANAGER:LOWTEMPERATURETURNON",
     118              :                                                                                                "AVAILABILITYMANAGER:NIGHTVENTILATION",
     119              :                                                                                                "AVAILABILITYMANAGER:HYBRIDVENTILATION",
     120              :                                                                                                "AVAILABILITYMANAGER:OPTIMUMSTART"};
     121              : 
     122              :     static constexpr std::array<std::string_view, (int)ManagerType::Num> managerTypeNames = {"AvailabilityManager:Scheduled",
     123              :                                                                                              "AvailabilityManager:ScheduledOn",
     124              :                                                                                              "AvailabilityManager:ScheduledOff",
     125              :                                                                                              "AvailabilityManager:NightCycle",
     126              :                                                                                              "AvailabilityManager:DifferentialThermostat",
     127              :                                                                                              "AvailabilityManager:HighTemperatureTurnOff",
     128              :                                                                                              "AvailabilityManager:HighTemperatureTurnOn",
     129              :                                                                                              "AvailabilityManager:LowTemperatureTurnOff",
     130              :                                                                                              "AvailabilityManager:LowTemperatureTurnOn",
     131              :                                                                                              "AvailabilityManager:NightVentilation",
     132              :                                                                                              "AvailabilityManager:HybridVentilation",
     133              :                                                                                              "AvailabilityManager:OptimumStart"};
     134              : 
     135       208460 :     void ManageSystemAvailability(EnergyPlusData &state)
     136              :     {
     137              : 
     138              :         // SUBROUTINE INFORMATION:
     139              :         //       AUTHOR         Fred Buhl
     140              :         //       DATE WRITTEN   August 2001
     141              :         //       MODIFIED       L. Gu, April, 2007. Added hybrid ventilation control
     142              :         //                      Chandan Sharma, March 2011/July 2012 - FSEC: Added zone sys avail managers
     143              :         //       RE-ENGINEERED  na
     144              : 
     145              :         // PURPOSE OF THIS SUBROUTINE:
     146              :         // Manage the simulation of the System Availability Managers
     147              : 
     148              :         using DataZoneEquipment::NumValidSysAvailZoneComponents;
     149              :         using namespace DataLoopNode;
     150              :         using namespace DataAirLoop;
     151              :         using namespace DataPlant;
     152              : 
     153              :         int PriAirSysNum;         // Primary Air System index
     154              :         int PriAirSysAvailMgrNum; // Index of Sys Avail Manager in a Primary Air System
     155              :         int PlantNum;             // Plant Loop index
     156              :         int PlantAvailMgrNum;     // Index of Plant Avail Manager in a Plant Loop
     157              :         Status availStatus;
     158              :         Status previousAvailStatus;
     159              :         int ZoneInSysNum;
     160              :         int CtrldZoneNum;
     161              :         int HybridVentNum;              // Hybrid ventilation control number
     162              :         int ZoneEquipType;              // Type of ZoneHVAC:* component
     163              :         int CompNum;                    // Index of ZoneHVAC:* component
     164              :         int ZoneCompAvailMgrNum;        // Index of availability manager associated with the ZoneHVAC:* component
     165       208460 :         int constexpr DummyArgument(1); // This variable is used when SimSysAvailManager is called for a ZoneHVAC:* component
     166              : 
     167       208460 :         if (state.dataAvail->GetAvailMgrInputFlag) {
     168           62 :             GetSysAvailManagerInputs(state);
     169           62 :             state.dataAvail->GetAvailMgrInputFlag = false;
     170           62 :             return;
     171              :         }
     172              : 
     173       208398 :         InitSysAvailManagers(state);
     174              : 
     175       242671 :         for (PriAirSysNum = 1; PriAirSysNum <= state.dataHVACGlobal->NumPrimaryAirSys; ++PriAirSysNum) { // loop over the primary air systems
     176        34273 :             auto &availMgr = state.dataAirLoop->PriAirSysAvailMgr(PriAirSysNum);
     177        34273 :             previousAvailStatus = availMgr.availStatus; // Save the previous status for differential thermostat
     178        34273 :             availMgr.availStatus = Status::NoAction;    // initialize the availability to "take no action"
     179              : 
     180        68546 :             for (PriAirSysAvailMgrNum = 1; PriAirSysAvailMgrNum <= availMgr.NumAvailManagers; ++PriAirSysAvailMgrNum) {
     181              : 
     182        68546 :                 availStatus = SimSysAvailManager(state,
     183        34273 :                                                  availMgr.availManagers(PriAirSysAvailMgrNum).type,
     184        34273 :                                                  availMgr.availManagers(PriAirSysAvailMgrNum).Name,
     185        34273 :                                                  availMgr.availManagers(PriAirSysAvailMgrNum).Num,
     186              :                                                  PriAirSysNum,
     187              :                                                  previousAvailStatus);
     188              : 
     189        34273 :                 if (availStatus == Status::ForceOff) {
     190            0 :                     availMgr.availStatus = Status::ForceOff;
     191            0 :                     break; // Fans forced off takes precedence
     192        34273 :                 } else if (availStatus == Status::CycleOnZoneFansOnly) {
     193            0 :                     availMgr.availStatus = Status::CycleOnZoneFansOnly; // zone fans only takes next precedence
     194        34273 :                 } else if ((availStatus == Status::CycleOn) && (availMgr.availStatus == Status::NoAction)) {
     195        29481 :                     availMgr.availStatus = Status::CycleOn; // cycle on is lowest precedence
     196              :                 }
     197              : 
     198              :             } // end of availability manager loop
     199              : 
     200              :             // Add hybrid ventilation control
     201        34273 :             if (state.dataAvail->NumHybridVentSysAvailMgrs > 0) {
     202            0 :                 for (HybridVentNum = 1; HybridVentNum <= state.dataAvail->NumHybridVentSysAvailMgrs; ++HybridVentNum) {
     203            0 :                     if (state.dataAvail->HybridVentData(HybridVentNum).AirLoopNum == PriAirSysNum &&
     204            0 :                         state.dataAvail->HybridVentData(HybridVentNum).ctrlStatus == VentCtrlStatus::Open) {
     205            0 :                         availMgr.availStatus = Status::ForceOff; // Force the system off
     206              :                     }
     207              :                 }
     208              :             }
     209              : 
     210              :             // loop over the zones served by the system and set the zone equipment availability
     211        90150 :             for (ZoneInSysNum = 1; ZoneInSysNum <= state.dataAirLoop->AirToZoneNodeInfo(PriAirSysNum).NumZonesCooled; ++ZoneInSysNum) {
     212              : 
     213        55877 :                 CtrldZoneNum = state.dataAirLoop->AirToZoneNodeInfo(PriAirSysNum).CoolCtrlZoneNums(ZoneInSysNum);
     214        55877 :                 state.dataZoneEquip->ZoneEquipAvail(CtrldZoneNum) = availMgr.availStatus;
     215              :             }
     216              : 
     217              :         } // end of primary air system loop
     218              : 
     219       226379 :         for (PlantNum = 1; PlantNum <= state.dataHVACGlobal->NumPlantLoops; ++PlantNum) {
     220        17981 :             auto &availMgr = state.dataAvail->PlantAvailMgr(PlantNum);
     221        17981 :             previousAvailStatus = availMgr.availStatus; // Save the previous status for differential thermostat
     222        17981 :             availMgr.availStatus = Status::NoAction;    // Initialize the availability to "take no action"
     223              : 
     224        17981 :             for (PlantAvailMgrNum = 1; PlantAvailMgrNum <= availMgr.NumAvailManagers; ++PlantAvailMgrNum) { // loop over the avail managers in plant
     225              : 
     226         3824 :                 availStatus = SimSysAvailManager(state,
     227         1912 :                                                  availMgr.availManagers(PlantAvailMgrNum).type,
     228         1912 :                                                  availMgr.availManagers(PlantAvailMgrNum).Name,
     229         1912 :                                                  availMgr.availManagers(PlantAvailMgrNum).Num,
     230              :                                                  PlantNum,
     231              :                                                  previousAvailStatus);
     232              : 
     233         1912 :                 if (availStatus != Status::NoAction) {
     234         1912 :                     availMgr.availStatus = availStatus;
     235         1912 :                     break; // First manager to do anything other than "NoAction" gets to set the availability
     236              :                 }
     237              : 
     238              :             } // end of availability manager loop
     239              : 
     240              :         } // end of plant loop
     241              : 
     242       208398 :         if (!allocated(state.dataAvail->ZoneComp)) return;
     243              : 
     244              :         // loop over the zone equipment types which allow system avail managers
     245      3125970 :         for (ZoneEquipType = 1; ZoneEquipType <= NumValidSysAvailZoneComponents; ++ZoneEquipType) {
     246      2917572 :             auto &zoneComp = state.dataAvail->ZoneComp(ZoneEquipType);
     247      2917572 :             if (zoneComp.TotalNumComp == 0) continue;
     248         9205 :             if (!allocated(zoneComp.ZoneCompAvailMgrs)) continue;
     249              : 
     250        29625 :             for (CompNum = 1; CompNum <= zoneComp.TotalNumComp; ++CompNum) {
     251              : 
     252        20420 :                 auto &zcam = zoneComp.ZoneCompAvailMgrs(CompNum);
     253        20420 :                 if (zcam.NumAvailManagers > 0) {
     254              : 
     255              :                     // Save the previous status for differential thermostat
     256            0 :                     previousAvailStatus = zcam.availStatus;
     257              :                     // initialize the availability to "take no action"
     258            0 :                     zcam.availStatus = Status::NoAction;
     259            0 :                     for (ZoneCompAvailMgrNum = 1; ZoneCompAvailMgrNum <= zcam.NumAvailManagers; ++ZoneCompAvailMgrNum) {
     260              :                         // loop over the avail managers in ZoneHVAC:* components
     261            0 :                         availStatus = SimSysAvailManager(state,
     262            0 :                                                          zcam.availManagers(ZoneCompAvailMgrNum).type,
     263            0 :                                                          zcam.availManagers(ZoneCompAvailMgrNum).Name,
     264            0 :                                                          zcam.availManagers(ZoneCompAvailMgrNum).Num,
     265              :                                                          DummyArgument,
     266              :                                                          previousAvailStatus,
     267              :                                                          ZoneEquipType,
     268              :                                                          CompNum);
     269            0 :                         if (availStatus == Status::ForceOff) {
     270            0 :                             zcam.availStatus = Status::ForceOff;
     271            0 :                             break; // Fans forced off takes precedence
     272            0 :                         } else if ((availStatus == Status::CycleOn) && (zcam.availStatus == Status::NoAction)) {
     273              :                             // cycle on is next precedence
     274            0 :                             zcam.availStatus = Status::CycleOn;
     275              :                         }
     276              :                     }
     277              :                 } else {
     278        20420 :                     zcam.availStatus = Status::NoAction;
     279              :                 }
     280              : 
     281        20420 :                 if (zcam.ZoneNum == 0) continue;
     282        20419 :                 if (state.dataAvail->NumHybridVentSysAvailMgrs == 0) continue;
     283              : 
     284            0 :                 for (HybridVentNum = 1; HybridVentNum <= state.dataAvail->NumHybridVentSysAvailMgrs; ++HybridVentNum) {
     285            0 :                     if (!state.dataAvail->HybridVentData(HybridVentNum).HybridVentMgrConnectedToAirLoop) {
     286            0 :                         if (state.dataAvail->HybridVentData(HybridVentNum).ControlledZoneNum == zcam.ZoneNum) {
     287            0 :                             if (state.dataAvail->HybridVentData(HybridVentNum).ctrlStatus == VentCtrlStatus::Open) {
     288            0 :                                 zcam.availStatus = Status::ForceOff;
     289              :                             }
     290              :                         }
     291              :                     }
     292              :                 }
     293              :             }
     294              :         } // for (ZoneEquipType)
     295              :     }     // ManageSystemAvailability()
     296              : 
     297          143 :     void GetSysAvailManagerInputs(EnergyPlusData &state)
     298              :     {
     299              : 
     300              :         // SUBROUTINE INFORMATION:
     301              :         //       AUTHOR         Fred Buhl
     302              :         //       DATE WRITTEN   August 2001
     303              :         //       MODIFIED       na
     304              :         //       RE-ENGINEERED  na
     305              : 
     306              :         // PURPOSE OF THIS SUBROUTINE:
     307              :         // Obtains input data for System Availability Managers and stores it in
     308              :         // appropriate data structures.
     309              : 
     310              :         // METHODOLOGY EMPLOYED:
     311              :         // Uses InputProcessor "Get" routines to obtain data.
     312              : 
     313              :         // Using/Aliasing
     314              :         using NodeInputManager::GetOnlySingleNode;
     315              :         using NodeInputManager::MarkNode;
     316              :         using namespace DataLoopNode;
     317              :         using DataZoneEquipment::cValidSysAvailManagerCompTypes;
     318              :         using DataZoneEquipment::NumValidSysAvailZoneComponents;
     319              : 
     320              :         // SUBROUTINE PARAMETER DEFINITIONS:
     321              :         static constexpr std::string_view RoutineName("GetSysAvailManagerInputs: "); // include trailing blank
     322              :         static constexpr std::string_view routineName = "GetSysAvailManagerInputs";
     323              : 
     324          143 :         constexpr std::array<std::string_view, (int)ControlAlgorithm::Num> ControlAlgorithmNamesUC = {
     325              :             "CONSTANTTEMPERATUREGRADIENT", "ADAPTIVETEMPERATUREGRADIENT", "ADAPTIVEASHRAE", "CONSTANTSTARTTIME"};
     326              : 
     327          143 :         constexpr std::array<std::string_view, (int)CyclingRunTimeControl::Num> CyclingRunTimeControlNamesUC{
     328              :             "FIXEDRUNTIME",
     329              :             "THERMOSTAT",
     330              :             "THERMOSTATWITHMINIMUMRUNTIME",
     331              :         };
     332              : 
     333          143 :         constexpr std::array<std::string_view, (int)NightCycleControlType::Num> NightCycleControlTypeNamesUC{
     334              :             "STAYOFF",
     335              :             "CYCLEONANY",
     336              :             "CYCLEONCONTROLZONE",
     337              :             "CYCLEONANYZONEFANSONLY",
     338              :             "CYCLEONANYCOOLINGORHEATINGZONE",
     339              :             "CYCLEONANYCOOLINGZONE",
     340              :             "CYCLEONANYHEATINGZONE",
     341              :             "CYCLEONANYHEATINGZONEFANSONLY",
     342              :         };
     343              : 
     344          143 :         constexpr std::array<std::string_view, (int)OptimumStartControlType::Num> OptimumStartControlTypeNamesUC{
     345              :             "STAYOFF",
     346              :             "CONTROLZONE",
     347              :             "MAXIMUMOFZONELIST",
     348              :         };
     349              : 
     350              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     351          143 :         Array1D_string cAlphaFieldNames;
     352          143 :         Array1D_string cNumericFieldNames;
     353          143 :         Array1D_bool lNumericFieldBlanks;
     354          143 :         Array1D_bool lAlphaFieldBlanks;
     355          143 :         Array1D_string cAlphaArgs;
     356          143 :         Array1D<Real64> rNumericArgs;
     357              :         int NumAlphas;           // Number of Alphas for each GetObjectItem call
     358              :         int NumNumbers;          // Number of Numbers for each GetObjectItem call
     359          143 :         int maxAlphas = 0;       // maximum number of alphas for this set of objects
     360          143 :         int maxNumbers = 0;      // maximum number of numbers for this set of objects
     361              :         int numArgs;             // maximum number of arguments for this set of objects
     362              :         int IOStatus;            // Used in GetObjectItem
     363          143 :         bool ErrorsFound(false); // Set to true if errors in input, fatal at end of routine
     364              :         int CyclingTimeSteps;
     365              :         int ZoneEquipType;
     366              :         int TotalNumComp;
     367              : 
     368              :         // Get the number of occurrences of each type of manager and read in data
     369         1859 :         for (int currentModuleObjectCount = 0; currentModuleObjectCount < (int)ManagerType::Num; ++currentModuleObjectCount) {
     370         1716 :             std::string_view cCurrentModuleObject = managerTypeNames[currentModuleObjectCount];
     371         1716 :             state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cCurrentModuleObject, numArgs, NumAlphas, NumNumbers);
     372         1716 :             maxNumbers = max(maxNumbers, NumNumbers);
     373         1716 :             maxAlphas = max(maxAlphas, NumAlphas);
     374              :         }
     375              : 
     376          143 :         cAlphaFieldNames.allocate(maxAlphas);
     377          143 :         cAlphaArgs.allocate(maxAlphas);
     378          143 :         lAlphaFieldBlanks.dimension(maxAlphas, false);
     379          143 :         cNumericFieldNames.allocate(maxNumbers);
     380          143 :         rNumericArgs.dimension(maxNumbers, 0.0);
     381          143 :         lNumericFieldBlanks.dimension(maxNumbers, false);
     382              : 
     383          143 :         if (!allocated(state.dataAvail->ZoneComp)) {
     384          140 :             state.dataAvail->ZoneComp.allocate(NumValidSysAvailZoneComponents);
     385              :         }
     386              : 
     387         2145 :         for (ZoneEquipType = 1; ZoneEquipType <= NumValidSysAvailZoneComponents; ++ZoneEquipType) {
     388         2002 :             auto &zoneComp = state.dataAvail->ZoneComp(ZoneEquipType);
     389         2002 :             if (!allocated(zoneComp.ZoneCompAvailMgrs)) {
     390         2001 :                 TotalNumComp = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cValidSysAvailManagerCompTypes(ZoneEquipType));
     391         2001 :                 zoneComp.TotalNumComp = TotalNumComp;
     392         2001 :                 if (TotalNumComp > 0) {
     393           19 :                     zoneComp.ZoneCompAvailMgrs.allocate(TotalNumComp);
     394              :                 }
     395              :             }
     396              :         }
     397              : 
     398          143 :         std::string_view cCurrentModuleObject = managerTypeNames[(int)ManagerType::Scheduled];
     399          143 :         state.dataAvail->NumSchedSysAvailMgrs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     400              : 
     401          143 :         if (state.dataAvail->NumSchedSysAvailMgrs > 0) {
     402              : 
     403           38 :             state.dataAvail->SchedData.allocate(state.dataAvail->NumSchedSysAvailMgrs);
     404              : 
     405           87 :             for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumSchedSysAvailMgrs; ++SysAvailNum) {
     406              : 
     407           49 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
     408              :                                                                          cCurrentModuleObject,
     409              :                                                                          SysAvailNum,
     410              :                                                                          cAlphaArgs,
     411              :                                                                          NumAlphas,
     412              :                                                                          rNumericArgs,
     413              :                                                                          NumNumbers,
     414              :                                                                          IOStatus,
     415              :                                                                          lNumericFieldBlanks,
     416              :                                                                          lAlphaFieldBlanks,
     417              :                                                                          cAlphaFieldNames,
     418              :                                                                          cNumericFieldNames);
     419              : 
     420           49 :                 ErrorObjectHeader eoh{routineName, cCurrentModuleObject, cAlphaArgs(1)};
     421           49 :                 auto &schedMgr = state.dataAvail->SchedData(SysAvailNum);
     422           49 :                 schedMgr.Name = cAlphaArgs(1);
     423           49 :                 schedMgr.type = ManagerType::Scheduled;
     424              : 
     425           49 :                 if (lAlphaFieldBlanks(2)) {
     426            0 :                     ShowSevereEmptyField(state, eoh, cAlphaFieldNames(2));
     427           49 :                 } else if ((schedMgr.availSched = Sched::GetSchedule(state, cAlphaArgs(2))) == nullptr) {
     428            0 :                     ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(2), cAlphaArgs(2));
     429            0 :                     ErrorsFound = true;
     430              :                 }
     431              : 
     432           49 :                 SetupOutputVariable(state,
     433              :                                     "Availability Manager Scheduled Control Status",
     434              :                                     Constant::Units::None,
     435           49 :                                     (int &)schedMgr.availStatus,
     436              :                                     OutputProcessor::TimeStepType::System,
     437              :                                     OutputProcessor::StoreType::Average,
     438           49 :                                     schedMgr.Name);
     439              : 
     440              :             } // SysAvailNum
     441              :         }
     442              : 
     443          143 :         cCurrentModuleObject = managerTypeNames[(int)ManagerType::ScheduledOn];
     444          143 :         state.dataAvail->NumSchedOnSysAvailMgrs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     445              : 
     446          143 :         if (state.dataAvail->NumSchedOnSysAvailMgrs > 0) {
     447              : 
     448            1 :             state.dataAvail->SchedOnData.allocate(state.dataAvail->NumSchedOnSysAvailMgrs);
     449              : 
     450            2 :             for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumSchedOnSysAvailMgrs; ++SysAvailNum) {
     451              : 
     452            1 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
     453              :                                                                          cCurrentModuleObject,
     454              :                                                                          SysAvailNum,
     455              :                                                                          cAlphaArgs,
     456              :                                                                          NumAlphas,
     457              :                                                                          rNumericArgs,
     458              :                                                                          NumNumbers,
     459              :                                                                          IOStatus,
     460              :                                                                          lNumericFieldBlanks,
     461              :                                                                          lAlphaFieldBlanks,
     462              :                                                                          cAlphaFieldNames,
     463              :                                                                          cNumericFieldNames);
     464              : 
     465            1 :                 ErrorObjectHeader eoh{routineName, cCurrentModuleObject, cAlphaArgs(1)};
     466            1 :                 auto &schedOnMgr = state.dataAvail->SchedOnData(SysAvailNum);
     467            1 :                 schedOnMgr.Name = cAlphaArgs(1);
     468            1 :                 schedOnMgr.type = ManagerType::ScheduledOn;
     469              : 
     470            1 :                 if (lAlphaFieldBlanks(2)) {
     471            0 :                     ShowSevereEmptyField(state, eoh, cAlphaFieldNames(2));
     472            0 :                     ErrorsFound = true;
     473            1 :                 } else if ((schedOnMgr.availSched = Sched::GetSchedule(state, cAlphaArgs(2))) == nullptr) {
     474            0 :                     ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(2), cAlphaArgs(2));
     475            0 :                     ErrorsFound = true;
     476              :                 }
     477              : 
     478            1 :                 SetupOutputVariable(state,
     479              :                                     "Availability Manager Scheduled On Control Status",
     480              :                                     Constant::Units::None,
     481            1 :                                     (int &)schedOnMgr.availStatus,
     482              :                                     OutputProcessor::TimeStepType::System,
     483              :                                     OutputProcessor::StoreType::Average,
     484            1 :                                     schedOnMgr.Name);
     485              : 
     486              :             } // SysAvailNum
     487              :         }
     488              : 
     489          143 :         cCurrentModuleObject = managerTypeNames[(int)ManagerType::ScheduledOff];
     490          143 :         state.dataAvail->NumSchedOffSysAvailMgrs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     491              : 
     492          143 :         if (state.dataAvail->NumSchedOffSysAvailMgrs > 0) {
     493              : 
     494            1 :             state.dataAvail->SchedOffData.allocate(state.dataAvail->NumSchedOffSysAvailMgrs);
     495              : 
     496            2 :             for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumSchedOffSysAvailMgrs; ++SysAvailNum) {
     497              : 
     498            1 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
     499              :                                                                          cCurrentModuleObject,
     500              :                                                                          SysAvailNum,
     501              :                                                                          cAlphaArgs,
     502              :                                                                          NumAlphas,
     503              :                                                                          rNumericArgs,
     504              :                                                                          NumNumbers,
     505              :                                                                          IOStatus,
     506              :                                                                          lNumericFieldBlanks,
     507              :                                                                          lAlphaFieldBlanks,
     508              :                                                                          cAlphaFieldNames,
     509              :                                                                          cNumericFieldNames);
     510              : 
     511            1 :                 ErrorObjectHeader eoh{routineName, cCurrentModuleObject, cAlphaArgs(1)};
     512            1 :                 auto &schedOffMgr = state.dataAvail->SchedOffData(SysAvailNum);
     513            1 :                 schedOffMgr.Name = cAlphaArgs(1);
     514            1 :                 schedOffMgr.type = ManagerType::ScheduledOff;
     515              : 
     516            1 :                 if (lAlphaFieldBlanks(2)) {
     517            0 :                     ShowSevereEmptyField(state, eoh, cAlphaFieldNames(2));
     518            0 :                     ErrorsFound = true;
     519            1 :                 } else if ((schedOffMgr.availSched = Sched::GetSchedule(state, cAlphaArgs(2))) == nullptr) {
     520            0 :                     ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(2), cAlphaArgs(2));
     521            0 :                     ErrorsFound = true;
     522              :                 }
     523              : 
     524            1 :                 SetupOutputVariable(state,
     525              :                                     "Availability Manager Scheduled Off Control Status",
     526              :                                     Constant::Units::None,
     527            1 :                                     (int &)schedOffMgr.availStatus,
     528              :                                     OutputProcessor::TimeStepType::System,
     529              :                                     OutputProcessor::StoreType::Average,
     530            1 :                                     schedOffMgr.Name);
     531              : 
     532              :             } // SysAvailNum
     533              :         }
     534              : 
     535          143 :         cCurrentModuleObject = managerTypeNames[(int)ManagerType::NightCycle];
     536          143 :         state.dataAvail->NumNCycSysAvailMgrs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     537          143 :         CyclingTimeSteps = 0;
     538              : 
     539          143 :         if (state.dataAvail->NumNCycSysAvailMgrs > 0) {
     540              : 
     541            9 :             state.dataAvail->NightCycleData.allocate(state.dataAvail->NumNCycSysAvailMgrs);
     542              : 
     543           28 :             for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumNCycSysAvailMgrs; ++SysAvailNum) {
     544              : 
     545           19 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
     546              :                                                                          cCurrentModuleObject,
     547              :                                                                          SysAvailNum,
     548              :                                                                          cAlphaArgs,
     549              :                                                                          NumAlphas,
     550              :                                                                          rNumericArgs,
     551              :                                                                          NumNumbers,
     552              :                                                                          IOStatus,
     553              :                                                                          lNumericFieldBlanks,
     554              :                                                                          lAlphaFieldBlanks,
     555              :                                                                          cAlphaFieldNames,
     556              :                                                                          cNumericFieldNames);
     557              : 
     558           19 :                 ErrorObjectHeader eoh{routineName, cCurrentModuleObject, cAlphaArgs(1)};
     559           19 :                 auto &nightCycleMgr = state.dataAvail->NightCycleData(SysAvailNum);
     560           19 :                 nightCycleMgr.Name = cAlphaArgs(1);
     561           19 :                 nightCycleMgr.type = ManagerType::NightCycle;
     562           19 :                 nightCycleMgr.TempTolRange = rNumericArgs(1);
     563           19 :                 CyclingTimeSteps = nint((rNumericArgs(2) / Constant::rSecsInHour) * double(state.dataGlobal->TimeStepsInHour));
     564           19 :                 CyclingTimeSteps = max(1, CyclingTimeSteps);
     565           19 :                 nightCycleMgr.CyclingTimeSteps = CyclingTimeSteps;
     566              : 
     567           19 :                 if (lAlphaFieldBlanks(2)) {
     568            0 :                     ShowSevereEmptyField(state, eoh, cAlphaFieldNames(2));
     569            0 :                     ErrorsFound = true;
     570           19 :                 } else if ((nightCycleMgr.availSched = Sched::GetSchedule(state, cAlphaArgs(2))) == nullptr) {
     571            0 :                     ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(2), cAlphaArgs(2));
     572            0 :                     ErrorsFound = true;
     573              :                 }
     574              : 
     575           19 :                 if (lAlphaFieldBlanks(3)) {
     576            0 :                     ShowSevereEmptyField(state, eoh, cAlphaFieldNames(3));
     577            0 :                     ErrorsFound = true;
     578           19 :                 } else if ((nightCycleMgr.fanSched = Sched::GetSchedule(state, cAlphaArgs(3))) == nullptr) {
     579            0 :                     ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(3), cAlphaArgs(3));
     580            0 :                     ErrorsFound = true;
     581              :                 }
     582              : 
     583           19 :                 nightCycleMgr.nightCycleControlType = static_cast<NightCycleControlType>(getEnumValue(NightCycleControlTypeNamesUC, cAlphaArgs(4)));
     584              : 
     585              :                 // Cycling Run Time Control Type
     586           19 :                 nightCycleMgr.cyclingRunTimeControl = static_cast<CyclingRunTimeControl>(getEnumValue(CyclingRunTimeControlNamesUC, cAlphaArgs(5)));
     587              : 
     588              :                 // Control zone or zonelist
     589           19 :                 if (!lAlphaFieldBlanks(6)) {
     590            3 :                     nightCycleMgr.CtrlZoneListName = cAlphaArgs(6);
     591            3 :                     int ZoneNum = Util::FindItemInList(cAlphaArgs(6), state.dataHeatBal->Zone);
     592            3 :                     if (ZoneNum > 0) {
     593            3 :                         nightCycleMgr.NumOfCtrlZones = 1;
     594            3 :                         nightCycleMgr.CtrlZonePtrs.allocate(1);
     595            3 :                         nightCycleMgr.CtrlZonePtrs(1) = ZoneNum;
     596              :                     } else {
     597            0 :                         int zoneListNum = 0;
     598            0 :                         if (state.dataHeatBal->NumOfZoneLists > 0) zoneListNum = Util::FindItemInList(cAlphaArgs(6), state.dataHeatBal->ZoneList);
     599            0 :                         if (zoneListNum > 0) {
     600            0 :                             int NumZones = state.dataHeatBal->ZoneList(zoneListNum).NumOfZones;
     601            0 :                             nightCycleMgr.NumOfCtrlZones = NumZones;
     602            0 :                             nightCycleMgr.CtrlZonePtrs.allocate(NumZones);
     603            0 :                             for (int zoneNumInList = 1; zoneNumInList <= NumZones; ++zoneNumInList) {
     604            0 :                                 nightCycleMgr.CtrlZonePtrs(zoneNumInList) = state.dataHeatBal->ZoneList(zoneListNum).Zone(zoneNumInList);
     605              :                             }
     606              :                         } else {
     607            0 :                             ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(6), cAlphaArgs(6));
     608            0 :                             ErrorsFound = true;
     609              :                         }
     610              :                     }
     611           16 :                 } else if (nightCycleMgr.nightCycleControlType == NightCycleControlType::OnControlZone) {
     612            0 :                     ShowSevereEmptyField(state, eoh, cAlphaFieldNames(6), cAlphaFieldNames(4), cAlphaArgs(4));
     613            0 :                     ErrorsFound = true;
     614              :                 }
     615              : 
     616              :                 // Cooling zone or zonelist
     617           19 :                 if (!lAlphaFieldBlanks(7)) {
     618            0 :                     nightCycleMgr.CoolingZoneListName = cAlphaArgs(7);
     619            0 :                     int ZoneNum = Util::FindItemInList(cAlphaArgs(7), state.dataHeatBal->Zone);
     620            0 :                     if (ZoneNum > 0) {
     621            0 :                         nightCycleMgr.NumOfCoolingZones = 1;
     622            0 :                         nightCycleMgr.CoolingZonePtrs.allocate(1);
     623            0 :                         nightCycleMgr.CoolingZonePtrs(1) = ZoneNum;
     624              :                     } else {
     625            0 :                         int zoneListNum = 0;
     626            0 :                         if (state.dataHeatBal->NumOfZoneLists > 0) zoneListNum = Util::FindItemInList(cAlphaArgs(7), state.dataHeatBal->ZoneList);
     627            0 :                         if (zoneListNum > 0) {
     628            0 :                             int NumZones = state.dataHeatBal->ZoneList(zoneListNum).NumOfZones;
     629            0 :                             nightCycleMgr.NumOfCoolingZones = NumZones;
     630            0 :                             nightCycleMgr.CoolingZonePtrs.allocate(NumZones);
     631            0 :                             for (int zoneNumInList = 1; zoneNumInList <= NumZones; ++zoneNumInList) {
     632            0 :                                 nightCycleMgr.CoolingZonePtrs(zoneNumInList) = state.dataHeatBal->ZoneList(zoneListNum).Zone(zoneNumInList);
     633              :                             }
     634              :                         } else {
     635            0 :                             ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(7), cAlphaArgs(7));
     636            0 :                             ErrorsFound = true;
     637              :                         }
     638              :                     }
     639              :                 }
     640              : 
     641              :                 // Heating zone or zonelist
     642           19 :                 if (!lAlphaFieldBlanks(8)) {
     643            0 :                     nightCycleMgr.HeatingZoneListName = cAlphaArgs(8);
     644            0 :                     int ZoneNum = Util::FindItemInList(cAlphaArgs(8), state.dataHeatBal->Zone);
     645            0 :                     if (ZoneNum > 0) {
     646            0 :                         nightCycleMgr.NumOfHeatingZones = 1;
     647            0 :                         nightCycleMgr.HeatingZonePtrs.allocate(1);
     648            0 :                         nightCycleMgr.HeatingZonePtrs(1) = ZoneNum;
     649              :                     } else {
     650            0 :                         int zoneListNum = 0;
     651            0 :                         if (state.dataHeatBal->NumOfZoneLists > 0) zoneListNum = Util::FindItemInList(cAlphaArgs(8), state.dataHeatBal->ZoneList);
     652            0 :                         if (zoneListNum > 0) {
     653            0 :                             int NumZones = state.dataHeatBal->ZoneList(zoneListNum).NumOfZones;
     654            0 :                             nightCycleMgr.NumOfHeatingZones = NumZones;
     655            0 :                             nightCycleMgr.HeatingZonePtrs.allocate(NumZones);
     656            0 :                             for (int zoneNumInList = 1; zoneNumInList <= NumZones; ++zoneNumInList) {
     657            0 :                                 nightCycleMgr.HeatingZonePtrs(zoneNumInList) = state.dataHeatBal->ZoneList(zoneListNum).Zone(zoneNumInList);
     658              :                             }
     659              :                         } else {
     660            0 :                             ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(8), cAlphaArgs(8));
     661            0 :                             ErrorsFound = true;
     662              :                         }
     663              :                     }
     664              :                 }
     665              : 
     666              :                 // HeatZnFan zone or zonelist
     667           19 :                 if (!lAlphaFieldBlanks(9)) {
     668            0 :                     nightCycleMgr.HeatZnFanZoneListName = cAlphaArgs(9);
     669            0 :                     int ZoneNum = Util::FindItemInList(cAlphaArgs(9), state.dataHeatBal->Zone);
     670            0 :                     if (ZoneNum > 0) {
     671            0 :                         nightCycleMgr.NumOfHeatZnFanZones = 1;
     672            0 :                         nightCycleMgr.HeatZnFanZonePtrs.allocate(1);
     673            0 :                         nightCycleMgr.HeatZnFanZonePtrs(1) = ZoneNum;
     674              :                     } else {
     675            0 :                         int zoneListNum = 0;
     676            0 :                         if (state.dataHeatBal->NumOfZoneLists > 0) zoneListNum = Util::FindItemInList(cAlphaArgs(9), state.dataHeatBal->ZoneList);
     677            0 :                         if (zoneListNum > 0) {
     678            0 :                             int NumZones = state.dataHeatBal->ZoneList(zoneListNum).NumOfZones;
     679            0 :                             nightCycleMgr.NumOfHeatZnFanZones = NumZones;
     680            0 :                             nightCycleMgr.HeatZnFanZonePtrs.allocate(NumZones);
     681            0 :                             for (int zoneNumInList = 1; zoneNumInList <= NumZones; ++zoneNumInList) {
     682            0 :                                 nightCycleMgr.HeatZnFanZonePtrs(zoneNumInList) = state.dataHeatBal->ZoneList(zoneListNum).Zone(zoneNumInList);
     683              :                             }
     684              :                         } else {
     685            0 :                             ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(9), cAlphaArgs(9));
     686            0 :                             ErrorsFound = true;
     687              :                         }
     688              :                     }
     689              :                 }
     690              : 
     691           19 :                 SetupOutputVariable(state,
     692              :                                     "Availability Manager Night Cycle Control Status",
     693              :                                     Constant::Units::None,
     694           19 :                                     (int &)nightCycleMgr.availStatus,
     695              :                                     OutputProcessor::TimeStepType::System,
     696              :                                     OutputProcessor::StoreType::Average,
     697           19 :                                     nightCycleMgr.Name);
     698              : 
     699              :             } // SysAvailNum
     700              :         }
     701              : 
     702          143 :         cCurrentModuleObject = managerTypeNames[(int)ManagerType::OptimumStart];
     703          143 :         state.dataAvail->NumOptStartSysAvailMgrs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     704          143 :         CyclingTimeSteps = 0;
     705              : 
     706          143 :         if (state.dataAvail->NumOptStartSysAvailMgrs > 0) {
     707              :             // Array size of variable type OptStartSysAvailMgrData is updated
     708            1 :             state.dataAvail->OptimumStartData.allocate(state.dataAvail->NumOptStartSysAvailMgrs);
     709              : 
     710            4 :             for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumOptStartSysAvailMgrs; ++SysAvailNum) {
     711              : 
     712            3 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
     713              :                                                                          cCurrentModuleObject,
     714              :                                                                          SysAvailNum,
     715              :                                                                          cAlphaArgs,
     716              :                                                                          NumAlphas,
     717              :                                                                          rNumericArgs,
     718              :                                                                          NumNumbers,
     719              :                                                                          IOStatus,
     720              :                                                                          lNumericFieldBlanks,
     721              :                                                                          lAlphaFieldBlanks,
     722              :                                                                          cAlphaFieldNames,
     723              :                                                                          cNumericFieldNames);
     724              : 
     725            3 :                 ErrorObjectHeader eoh{routineName, cCurrentModuleObject, cAlphaArgs(1)};
     726            3 :                 auto &optimumStartMgr = state.dataAvail->OptimumStartData(SysAvailNum);
     727            3 :                 optimumStartMgr.Name = cAlphaArgs(1);
     728            3 :                 optimumStartMgr.type = ManagerType::OptimumStart;
     729              : 
     730            3 :                 if (lAlphaFieldBlanks(2)) {
     731            0 :                     ShowSevereEmptyField(state, eoh, cAlphaFieldNames(2));
     732            0 :                     ErrorsFound = true;
     733            3 :                 } else if ((optimumStartMgr.availSched = Sched::GetSchedule(state, cAlphaArgs(2))) == nullptr) {
     734            0 :                     ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(2), cAlphaArgs(2));
     735            0 :                     ErrorsFound = true;
     736              :                 }
     737              : 
     738            3 :                 if (lAlphaFieldBlanks(3)) {
     739            0 :                     ShowSevereEmptyField(state, eoh, cAlphaFieldNames(3));
     740            0 :                     ErrorsFound = true;
     741            3 :                 } else if ((optimumStartMgr.fanSched = Sched::GetSchedule(state, cAlphaArgs(3))) == nullptr) {
     742            0 :                     ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(3), cAlphaArgs(3));
     743            0 :                     ErrorsFound = true;
     744              :                 }
     745              : 
     746            3 :                 optimumStartMgr.MaxOptStartTime = rNumericArgs(1);
     747            3 :                 optimumStartMgr.optimumStartControlType =
     748            3 :                     static_cast<OptimumStartControlType>(getEnumValue(OptimumStartControlTypeNamesUC, cAlphaArgs(4)));
     749              : 
     750            3 :                 if (optimumStartMgr.optimumStartControlType == OptimumStartControlType::Invalid) {
     751            0 :                     optimumStartMgr.optimumStartControlType = OptimumStartControlType::ControlZone;
     752            0 :                     ShowSevereInvalidKey(state, eoh, cAlphaFieldNames(4), cAlphaArgs(4));
     753            0 :                     ErrorsFound = true;
     754              :                 }
     755              : 
     756            3 :                 if (optimumStartMgr.optimumStartControlType == OptimumStartControlType::ControlZone) {
     757            2 :                     optimumStartMgr.CtrlZoneName = cAlphaArgs(5);
     758            2 :                     optimumStartMgr.ZoneNum = Util::FindItemInList(cAlphaArgs(5), state.dataHeatBal->Zone);
     759            2 :                     if (optimumStartMgr.ZoneNum == 0) {
     760            0 :                         ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(5), cAlphaArgs(5));
     761            0 :                         ErrorsFound = true;
     762              :                     }
     763              :                 }
     764              : 
     765            3 :                 if (optimumStartMgr.optimumStartControlType == OptimumStartControlType::MaximumOfZoneList) {
     766            1 :                     optimumStartMgr.ZoneListName = cAlphaArgs(6);
     767            2 :                     for (int zoneListNum = 1; zoneListNum <= state.dataHeatBal->NumOfZoneLists; ++zoneListNum) {
     768            1 :                         if (state.dataHeatBal->ZoneList(zoneListNum).Name == cAlphaArgs(6)) {
     769            1 :                             optimumStartMgr.NumOfZones = state.dataHeatBal->ZoneList(zoneListNum).NumOfZones;
     770            1 :                             optimumStartMgr.ZonePtrs.allocate(state.dataHeatBal->ZoneList(zoneListNum).NumOfZones);
     771            4 :                             for (int zoneNumInList = 1; zoneNumInList <= state.dataHeatBal->ZoneList(zoneListNum).NumOfZones; ++zoneNumInList) {
     772            3 :                                 optimumStartMgr.ZonePtrs(zoneNumInList) = state.dataHeatBal->ZoneList(zoneListNum).Zone(zoneNumInList);
     773              :                             }
     774              :                         }
     775              :                     }
     776            1 :                     optimumStartMgr.NumOfZones = Util::FindItemInList(cAlphaArgs(6), state.dataHeatBal->ZoneList);
     777            1 :                     if (optimumStartMgr.NumOfZones == 0) {
     778            0 :                         ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(6), cAlphaArgs(6));
     779            0 :                         ErrorsFound = true;
     780              :                     }
     781              :                 }
     782              : 
     783            3 :                 optimumStartMgr.controlAlgorithm = static_cast<ControlAlgorithm>(getEnumValue(ControlAlgorithmNamesUC, cAlphaArgs(7)));
     784              : 
     785            3 :                 switch (optimumStartMgr.controlAlgorithm) {
     786            0 :                 case ControlAlgorithm::ConstantTemperatureGradient: {
     787            0 :                     optimumStartMgr.ConstTGradCool = rNumericArgs(2);
     788            0 :                     optimumStartMgr.ConstTGradHeat = rNumericArgs(3);
     789            0 :                 } break;
     790              : 
     791            3 :                 case ControlAlgorithm::AdaptiveTemperatureGradient: {
     792            3 :                     optimumStartMgr.InitTGradCool = rNumericArgs(4);
     793            3 :                     optimumStartMgr.InitTGradHeat = rNumericArgs(5);
     794            3 :                     optimumStartMgr.NumPreDays = rNumericArgs(7);
     795            3 :                 } break;
     796              : 
     797            0 :                 case ControlAlgorithm::ConstantStartTime: {
     798            0 :                     optimumStartMgr.ConstStartTime = rNumericArgs(6);
     799            0 :                 } break;
     800              : 
     801            0 :                 default:
     802            0 :                     break;
     803              :                 }
     804              : 
     805            3 :                 SetupOutputVariable(state,
     806              :                                     "Availability Manager Optimum Start Control Status",
     807              :                                     Constant::Units::None,
     808            3 :                                     (int &)optimumStartMgr.availStatus,
     809              :                                     OutputProcessor::TimeStepType::System,
     810              :                                     OutputProcessor::StoreType::Average,
     811            3 :                                     optimumStartMgr.Name);
     812              : 
     813              :                 // add
     814           18 :                 SetupOutputVariable(state,
     815              :                                     "Availability Manager Optimum Start Time Before Occupancy",
     816              :                                     Constant::Units::hr,
     817            3 :                                     optimumStartMgr.NumHoursBeforeOccupancy,
     818              :                                     OutputProcessor::TimeStepType::System,
     819              :                                     OutputProcessor::StoreType::Average,
     820            3 :                                     optimumStartMgr.Name,
     821              :                                     Constant::eResource::Invalid,
     822              :                                     OutputProcessor::Group::Invalid,
     823              :                                     OutputProcessor::EndUseCat::Invalid,
     824              :                                     "",   // End-use SubCat
     825              :                                     "",   // Zone
     826              :                                     1,    // ZoneMult
     827              :                                     1,    // ZoneListMult
     828              :                                     "",   // space type
     829              :                                     -999, // indexGroupKey
     830              :                                     "",   // custom units
     831              :                                     OutputProcessor::ReportFreq::Day);
     832              :             }
     833              :         }
     834              : 
     835          143 :         cCurrentModuleObject = managerTypeNames[(int)ManagerType::DiffThermo];
     836          143 :         state.dataAvail->NumDiffTSysAvailMgrs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     837              : 
     838          143 :         if (state.dataAvail->NumDiffTSysAvailMgrs > 0) {
     839              : 
     840            0 :             state.dataAvail->DiffThermoData.allocate(state.dataAvail->NumDiffTSysAvailMgrs);
     841              : 
     842            0 :             for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumDiffTSysAvailMgrs; ++SysAvailNum) {
     843              : 
     844            0 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
     845              :                                                                          cCurrentModuleObject,
     846              :                                                                          SysAvailNum,
     847              :                                                                          cAlphaArgs,
     848              :                                                                          NumAlphas,
     849              :                                                                          rNumericArgs,
     850              :                                                                          NumNumbers,
     851              :                                                                          IOStatus,
     852              :                                                                          lNumericFieldBlanks,
     853              :                                                                          lAlphaFieldBlanks,
     854              :                                                                          cAlphaFieldNames,
     855              :                                                                          cNumericFieldNames);
     856              : 
     857            0 :                 auto &diffThermoMgr = state.dataAvail->DiffThermoData(SysAvailNum);
     858            0 :                 diffThermoMgr.Name = cAlphaArgs(1);
     859            0 :                 diffThermoMgr.type = ManagerType::DiffThermo;
     860              : 
     861            0 :                 diffThermoMgr.HotNode = GetOnlySingleNode(state,
     862            0 :                                                           cAlphaArgs(2),
     863              :                                                           ErrorsFound,
     864              :                                                           DataLoopNode::ConnectionObjectType::AvailabilityManagerDifferentialThermostat,
     865            0 :                                                           cAlphaArgs(1),
     866              :                                                           DataLoopNode::NodeFluidType::Blank,
     867              :                                                           DataLoopNode::ConnectionType::Sensor,
     868              :                                                           NodeInputManager::CompFluidStream::Primary,
     869              :                                                           ObjectIsNotParent);
     870            0 :                 MarkNode(state,
     871              :                          diffThermoMgr.HotNode,
     872              :                          DataLoopNode::ConnectionObjectType::AvailabilityManagerDifferentialThermostat,
     873            0 :                          cAlphaArgs(1),
     874              :                          "Hot Node");
     875            0 :                 diffThermoMgr.ColdNode = GetOnlySingleNode(state,
     876            0 :                                                            cAlphaArgs(3),
     877              :                                                            ErrorsFound,
     878              :                                                            DataLoopNode::ConnectionObjectType::AvailabilityManagerDifferentialThermostat,
     879            0 :                                                            cAlphaArgs(1),
     880              :                                                            DataLoopNode::NodeFluidType::Blank,
     881              :                                                            DataLoopNode::ConnectionType::Sensor,
     882              :                                                            NodeInputManager::CompFluidStream::Primary,
     883              :                                                            ObjectIsNotParent);
     884            0 :                 MarkNode(state,
     885              :                          diffThermoMgr.ColdNode,
     886              :                          DataLoopNode::ConnectionObjectType::AvailabilityManagerDifferentialThermostat,
     887            0 :                          cAlphaArgs(1),
     888              :                          "Cold Node");
     889              : 
     890            0 :                 diffThermoMgr.TempDiffOn = rNumericArgs(1);
     891              : 
     892            0 :                 if (NumNumbers > 1) {
     893            0 :                     diffThermoMgr.TempDiffOff = rNumericArgs(2);
     894              :                 } else {
     895            0 :                     diffThermoMgr.TempDiffOff = diffThermoMgr.TempDiffOn;
     896              :                 }
     897              : 
     898            0 :                 if (diffThermoMgr.TempDiffOff > diffThermoMgr.TempDiffOn) {
     899            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, cAlphaArgs(1)));
     900            0 :                     ShowContinueError(state, format("The {} is greater than the {}.", cNumericFieldNames(2), cNumericFieldNames(1)));
     901            0 :                     ErrorsFound = true;
     902              :                 }
     903              : 
     904            0 :                 SetupOutputVariable(state,
     905              :                                     "Availability Manager Differential Thermostat Control Status",
     906              :                                     Constant::Units::None,
     907            0 :                                     (int &)diffThermoMgr.availStatus,
     908              :                                     OutputProcessor::TimeStepType::System,
     909              :                                     OutputProcessor::StoreType::Average,
     910            0 :                                     diffThermoMgr.Name);
     911              : 
     912              :             } // SysAvailNum
     913              :         }
     914              : 
     915          143 :         cCurrentModuleObject = managerTypeNames[(int)ManagerType::HiTempTOff];
     916          143 :         state.dataAvail->NumHiTurnOffSysAvailMgrs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     917              : 
     918          143 :         if (state.dataAvail->NumHiTurnOffSysAvailMgrs > 0) {
     919            0 :             state.dataAvail->HiTurnOffData.allocate(state.dataAvail->NumHiTurnOffSysAvailMgrs);
     920              : 
     921            0 :             for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumHiTurnOffSysAvailMgrs; ++SysAvailNum) {
     922              : 
     923            0 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
     924              :                                                                          cCurrentModuleObject,
     925              :                                                                          SysAvailNum,
     926              :                                                                          cAlphaArgs,
     927              :                                                                          NumAlphas,
     928              :                                                                          rNumericArgs,
     929              :                                                                          NumNumbers,
     930              :                                                                          IOStatus,
     931              :                                                                          lNumericFieldBlanks,
     932              :                                                                          lAlphaFieldBlanks,
     933              :                                                                          cAlphaFieldNames,
     934              :                                                                          cNumericFieldNames);
     935              : 
     936            0 :                 auto &hiTurnOffMgr = state.dataAvail->HiTurnOffData(SysAvailNum);
     937            0 :                 hiTurnOffMgr.Name = cAlphaArgs(1);
     938            0 :                 hiTurnOffMgr.type = ManagerType::HiTempTOff;
     939              : 
     940            0 :                 hiTurnOffMgr.Node = GetOnlySingleNode(state,
     941            0 :                                                       cAlphaArgs(2),
     942              :                                                       ErrorsFound,
     943              :                                                       DataLoopNode::ConnectionObjectType::AvailabilityManagerHighTemperatureTurnOff,
     944            0 :                                                       cAlphaArgs(1),
     945              :                                                       DataLoopNode::NodeFluidType::Blank,
     946              :                                                       DataLoopNode::ConnectionType::Sensor,
     947              :                                                       NodeInputManager::CompFluidStream::Primary,
     948              :                                                       ObjectIsNotParent);
     949            0 :                 MarkNode(state,
     950              :                          hiTurnOffMgr.Node,
     951              :                          DataLoopNode::ConnectionObjectType::AvailabilityManagerHighTemperatureTurnOff,
     952            0 :                          cAlphaArgs(1),
     953              :                          "Sensor Node");
     954              : 
     955            0 :                 hiTurnOffMgr.Temp = rNumericArgs(1);
     956              : 
     957            0 :                 SetupOutputVariable(state,
     958              :                                     "Availability Manager High Temperature Turn Off Control Status",
     959              :                                     Constant::Units::None,
     960            0 :                                     (int &)hiTurnOffMgr.availStatus,
     961              :                                     OutputProcessor::TimeStepType::System,
     962              :                                     OutputProcessor::StoreType::Average,
     963            0 :                                     hiTurnOffMgr.Name);
     964              : 
     965              :             } // SysAvailNum
     966              :         }
     967              : 
     968          143 :         cCurrentModuleObject = managerTypeNames[(int)ManagerType::HiTempTOn];
     969          143 :         state.dataAvail->NumHiTurnOnSysAvailMgrs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     970              : 
     971          143 :         if (state.dataAvail->NumHiTurnOnSysAvailMgrs > 0) {
     972              : 
     973            0 :             state.dataAvail->HiTurnOnData.allocate(state.dataAvail->NumHiTurnOnSysAvailMgrs);
     974              : 
     975            0 :             for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumHiTurnOnSysAvailMgrs; ++SysAvailNum) {
     976              : 
     977            0 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
     978              :                                                                          cCurrentModuleObject,
     979              :                                                                          SysAvailNum,
     980              :                                                                          cAlphaArgs,
     981              :                                                                          NumAlphas,
     982              :                                                                          rNumericArgs,
     983              :                                                                          NumNumbers,
     984              :                                                                          IOStatus,
     985              :                                                                          lNumericFieldBlanks,
     986              :                                                                          lAlphaFieldBlanks,
     987              :                                                                          cAlphaFieldNames,
     988              :                                                                          cNumericFieldNames);
     989            0 :                 auto &hiTurnOnMgr = state.dataAvail->HiTurnOnData(SysAvailNum);
     990            0 :                 hiTurnOnMgr.Name = cAlphaArgs(1);
     991            0 :                 hiTurnOnMgr.type = ManagerType::HiTempTOn;
     992              : 
     993            0 :                 hiTurnOnMgr.Node = GetOnlySingleNode(state,
     994            0 :                                                      cAlphaArgs(2),
     995              :                                                      ErrorsFound,
     996              :                                                      DataLoopNode::ConnectionObjectType::AvailabilityManagerHighTemperatureTurnOn,
     997            0 :                                                      cAlphaArgs(1),
     998              :                                                      DataLoopNode::NodeFluidType::Blank,
     999              :                                                      DataLoopNode::ConnectionType::Sensor,
    1000              :                                                      NodeInputManager::CompFluidStream::Primary,
    1001              :                                                      ObjectIsNotParent);
    1002            0 :                 MarkNode(state,
    1003              :                          hiTurnOnMgr.Node,
    1004              :                          DataLoopNode::ConnectionObjectType::AvailabilityManagerHighTemperatureTurnOn,
    1005            0 :                          cAlphaArgs(1),
    1006              :                          "Sensor Node");
    1007              : 
    1008            0 :                 hiTurnOnMgr.Temp = rNumericArgs(1);
    1009              : 
    1010            0 :                 SetupOutputVariable(state,
    1011              :                                     "Availability Manager High Temperature Turn On Control Status",
    1012              :                                     Constant::Units::None,
    1013            0 :                                     (int &)hiTurnOnMgr.availStatus,
    1014              :                                     OutputProcessor::TimeStepType::System,
    1015              :                                     OutputProcessor::StoreType::Average,
    1016            0 :                                     hiTurnOnMgr.Name);
    1017              : 
    1018              :             } // SysAvailNum
    1019              :         }
    1020              : 
    1021          143 :         cCurrentModuleObject = managerTypeNames[(int)ManagerType::LoTempTOff];
    1022          143 :         state.dataAvail->NumLoTurnOffSysAvailMgrs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    1023              : 
    1024          143 :         if (state.dataAvail->NumLoTurnOffSysAvailMgrs > 0) {
    1025              : 
    1026            1 :             state.dataAvail->LoTurnOffData.allocate(state.dataAvail->NumLoTurnOffSysAvailMgrs);
    1027              : 
    1028            2 :             for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumLoTurnOffSysAvailMgrs; ++SysAvailNum) {
    1029              : 
    1030            1 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1031              :                                                                          cCurrentModuleObject,
    1032              :                                                                          SysAvailNum,
    1033              :                                                                          cAlphaArgs,
    1034              :                                                                          NumAlphas,
    1035              :                                                                          rNumericArgs,
    1036              :                                                                          NumNumbers,
    1037              :                                                                          IOStatus,
    1038              :                                                                          lNumericFieldBlanks,
    1039              :                                                                          lAlphaFieldBlanks,
    1040              :                                                                          cAlphaFieldNames,
    1041              :                                                                          cNumericFieldNames);
    1042            1 :                 ErrorObjectHeader eoh{routineName, cCurrentModuleObject, cAlphaArgs(1)};
    1043            1 :                 auto &loTurnOffMgr = state.dataAvail->LoTurnOffData(SysAvailNum);
    1044            1 :                 loTurnOffMgr.Name = cAlphaArgs(1);
    1045            1 :                 loTurnOffMgr.type = ManagerType::LoTempTOff;
    1046              : 
    1047            2 :                 loTurnOffMgr.Node = GetOnlySingleNode(state,
    1048            1 :                                                       cAlphaArgs(2),
    1049              :                                                       ErrorsFound,
    1050              :                                                       DataLoopNode::ConnectionObjectType::AvailabilityManagerLowTemperatureTurnOff,
    1051            1 :                                                       cAlphaArgs(1),
    1052              :                                                       DataLoopNode::NodeFluidType::Blank,
    1053              :                                                       DataLoopNode::ConnectionType::Sensor,
    1054              :                                                       NodeInputManager::CompFluidStream::Primary,
    1055              :                                                       ObjectIsNotParent);
    1056            2 :                 MarkNode(state,
    1057              :                          loTurnOffMgr.Node,
    1058              :                          DataLoopNode::ConnectionObjectType::AvailabilityManagerLowTemperatureTurnOff,
    1059            1 :                          cAlphaArgs(1),
    1060              :                          "Sensor Node");
    1061              : 
    1062            1 :                 loTurnOffMgr.Temp = rNumericArgs(1);
    1063              : 
    1064            1 :                 if (lAlphaFieldBlanks(3)) {
    1065            0 :                 } else if ((loTurnOffMgr.availSched = Sched::GetSchedule(state, cAlphaArgs(3))) == nullptr) {
    1066            0 :                     ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(3), cAlphaArgs(3));
    1067            0 :                     ErrorsFound = true;
    1068              :                 }
    1069              : 
    1070            1 :                 SetupOutputVariable(state,
    1071              :                                     "Availability Manager Low Temperature Turn Off Control Status",
    1072              :                                     Constant::Units::None,
    1073            1 :                                     (int &)loTurnOffMgr.availStatus,
    1074              :                                     OutputProcessor::TimeStepType::System,
    1075              :                                     OutputProcessor::StoreType::Average,
    1076            1 :                                     loTurnOffMgr.Name);
    1077              : 
    1078              :             } // SysAvailNum
    1079              :         }
    1080              : 
    1081          143 :         cCurrentModuleObject = managerTypeNames[(int)ManagerType::LoTempTOn];
    1082          143 :         state.dataAvail->NumLoTurnOnSysAvailMgrs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    1083              : 
    1084          143 :         if (state.dataAvail->NumLoTurnOnSysAvailMgrs > 0) {
    1085              : 
    1086            0 :             state.dataAvail->LoTurnOnData.allocate(state.dataAvail->NumLoTurnOnSysAvailMgrs);
    1087              : 
    1088            0 :             for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumLoTurnOnSysAvailMgrs; ++SysAvailNum) {
    1089              : 
    1090            0 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1091              :                                                                          cCurrentModuleObject,
    1092              :                                                                          SysAvailNum,
    1093              :                                                                          cAlphaArgs,
    1094              :                                                                          NumAlphas,
    1095              :                                                                          rNumericArgs,
    1096              :                                                                          NumNumbers,
    1097              :                                                                          IOStatus,
    1098              :                                                                          lNumericFieldBlanks,
    1099              :                                                                          lAlphaFieldBlanks,
    1100              :                                                                          cAlphaFieldNames,
    1101              :                                                                          cNumericFieldNames);
    1102              : 
    1103            0 :                 auto &loTurnOnMgr = state.dataAvail->LoTurnOnData(SysAvailNum);
    1104            0 :                 loTurnOnMgr.Name = cAlphaArgs(1);
    1105            0 :                 loTurnOnMgr.type = ManagerType::LoTempTOn;
    1106              : 
    1107            0 :                 loTurnOnMgr.Node = GetOnlySingleNode(state,
    1108            0 :                                                      cAlphaArgs(2),
    1109              :                                                      ErrorsFound,
    1110              :                                                      DataLoopNode::ConnectionObjectType::AvailabilityManagerLowTemperatureTurnOn,
    1111            0 :                                                      cAlphaArgs(1),
    1112              :                                                      DataLoopNode::NodeFluidType::Blank,
    1113              :                                                      DataLoopNode::ConnectionType::Sensor,
    1114              :                                                      NodeInputManager::CompFluidStream::Primary,
    1115              :                                                      ObjectIsNotParent);
    1116            0 :                 MarkNode(state,
    1117              :                          loTurnOnMgr.Node,
    1118              :                          DataLoopNode::ConnectionObjectType::AvailabilityManagerLowTemperatureTurnOn,
    1119            0 :                          cAlphaArgs(1),
    1120              :                          "Sensor Node");
    1121              : 
    1122            0 :                 loTurnOnMgr.Temp = rNumericArgs(1);
    1123              : 
    1124            0 :                 SetupOutputVariable(state,
    1125              :                                     "Availability Manager Low Temperature Turn On Control Status",
    1126              :                                     Constant::Units::None,
    1127            0 :                                     (int &)loTurnOnMgr.availStatus,
    1128              :                                     OutputProcessor::TimeStepType::System,
    1129              :                                     OutputProcessor::StoreType::Average,
    1130            0 :                                     loTurnOnMgr.Name);
    1131              : 
    1132              :             } // SysAvailNum
    1133              :         }
    1134              : 
    1135          143 :         cCurrentModuleObject = managerTypeNames[(int)ManagerType::NightVent];
    1136          143 :         state.dataAvail->NumNVentSysAvailMgrs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    1137              : 
    1138          143 :         if (state.dataAvail->NumNVentSysAvailMgrs > 0) {
    1139              : 
    1140            0 :             state.dataAvail->NightVentData.allocate(state.dataAvail->NumNVentSysAvailMgrs);
    1141              : 
    1142            0 :             for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumNVentSysAvailMgrs; ++SysAvailNum) {
    1143              : 
    1144            0 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1145              :                                                                          cCurrentModuleObject,
    1146              :                                                                          SysAvailNum,
    1147              :                                                                          cAlphaArgs,
    1148              :                                                                          NumAlphas,
    1149              :                                                                          rNumericArgs,
    1150              :                                                                          NumNumbers,
    1151              :                                                                          IOStatus,
    1152              :                                                                          lNumericFieldBlanks,
    1153              :                                                                          lAlphaFieldBlanks,
    1154              :                                                                          cAlphaFieldNames,
    1155              :                                                                          cNumericFieldNames);
    1156              : 
    1157            0 :                 ErrorObjectHeader eoh{routineName, cCurrentModuleObject, cAlphaArgs(1)};
    1158            0 :                 auto &nightVentMgr = state.dataAvail->NightVentData(SysAvailNum);
    1159            0 :                 nightVentMgr.Name = cAlphaArgs(1);
    1160            0 :                 nightVentMgr.type = ManagerType::NightVent;
    1161              : 
    1162            0 :                 if (lAlphaFieldBlanks(2)) {
    1163            0 :                     ShowSevereEmptyField(state, eoh, cAlphaFieldNames(2));
    1164            0 :                     ErrorsFound = true;
    1165            0 :                 } else if ((nightVentMgr.availSched = Sched::GetSchedule(state, cAlphaArgs(2))) == nullptr) {
    1166            0 :                     ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(2), cAlphaArgs(2));
    1167            0 :                     ErrorsFound = true;
    1168              :                 }
    1169              : 
    1170            0 :                 if (lAlphaFieldBlanks(3)) {
    1171            0 :                     ShowSevereEmptyField(state, eoh, cAlphaFieldNames(3));
    1172            0 :                     ErrorsFound = true;
    1173            0 :                 } else if ((nightVentMgr.fanSched = Sched::GetSchedule(state, cAlphaArgs(3))) == nullptr) {
    1174            0 :                     ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(3), cAlphaArgs(3));
    1175            0 :                     ErrorsFound = true;
    1176              :                 }
    1177              : 
    1178            0 :                 if (lAlphaFieldBlanks(4)) {
    1179            0 :                     ShowSevereEmptyField(state, eoh, cAlphaFieldNames(4));
    1180            0 :                     ErrorsFound = true;
    1181            0 :                 } else if ((nightVentMgr.ventTempSched = Sched::GetSchedule(state, cAlphaArgs(4))) == nullptr) {
    1182            0 :                     ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(4), cAlphaArgs(4));
    1183            0 :                     ErrorsFound = true;
    1184              :                 }
    1185              : 
    1186            0 :                 nightVentMgr.VentDelT = rNumericArgs(1);
    1187            0 :                 nightVentMgr.VentTempLowLim = rNumericArgs(2);
    1188            0 :                 nightVentMgr.VentFlowFrac = rNumericArgs(3);
    1189            0 :                 nightVentMgr.CtrlZoneName = cAlphaArgs(5);
    1190            0 :                 nightVentMgr.ZoneNum = Util::FindItemInList(cAlphaArgs(5), state.dataHeatBal->Zone);
    1191            0 :                 if (nightVentMgr.ZoneNum == 0) {
    1192            0 :                     ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(5), cAlphaArgs(5));
    1193            0 :                     ErrorsFound = true;
    1194              :                 }
    1195              : 
    1196            0 :                 SetupOutputVariable(state,
    1197              :                                     "Availability Manager Night Ventilation Control Status",
    1198              :                                     Constant::Units::None,
    1199            0 :                                     (int &)nightVentMgr.availStatus,
    1200              :                                     OutputProcessor::TimeStepType::System,
    1201              :                                     OutputProcessor::StoreType::Average,
    1202            0 :                                     nightVentMgr.Name);
    1203              : 
    1204              :             } // SysAvailNum
    1205              :         }
    1206              : 
    1207          143 :         cAlphaFieldNames.deallocate();
    1208          143 :         cAlphaArgs.deallocate();
    1209          143 :         lAlphaFieldBlanks.deallocate();
    1210          143 :         cNumericFieldNames.deallocate();
    1211          143 :         rNumericArgs.deallocate();
    1212          143 :         lNumericFieldBlanks.deallocate();
    1213              : 
    1214          143 :         if (ErrorsFound) {
    1215            0 :             ShowFatalError(state, format("{}Errors found in input.  Preceding condition(s) cause termination.", RoutineName));
    1216              :         }
    1217          143 :     } // GetSysAvailManagerInputs()
    1218              : 
    1219           90 :     void GetSysAvailManagerListInputs(EnergyPlusData &state)
    1220              :     {
    1221              : 
    1222              :         // SUBROUTINE INFORMATION:
    1223              :         //       AUTHOR         Linda Lawrie
    1224              :         //       DATE WRITTEN   August 2007
    1225              :         //       MODIFIED       na
    1226              :         //       RE-ENGINEERED  na
    1227              : 
    1228              :         // PURPOSE OF THIS SUBROUTINE:
    1229              :         // This routine gets the System Availability Manager List object input and stores
    1230              :         // it for later retrieval of items from the Plant and Air Loops.
    1231              : 
    1232           90 :         if (state.dataAvail->GetAvailMgrInputFlag) {
    1233           78 :             GetSysAvailManagerInputs(state);
    1234           78 :             state.dataAvail->GetAvailMgrInputFlag = false;
    1235              :         }
    1236              : 
    1237           90 :         bool ErrorsFound = false;
    1238           90 :         std::string const cCurrentModuleObject = "AvailabilityManagerAssignmentList";
    1239           90 :         auto &ip = state.dataInputProcessing->inputProcessor;
    1240              : 
    1241           90 :         state.dataAvail->NumAvailManagerLists = ip->getNumObjectsFound(state, cCurrentModuleObject);
    1242              : 
    1243           90 :         if (state.dataAvail->NumAvailManagerLists > 0) {
    1244              : 
    1245           41 :             state.dataAvail->ListData.allocate(state.dataAvail->NumAvailManagerLists);
    1246           41 :             auto const instances = ip->epJSON.find(cCurrentModuleObject);
    1247           41 :             auto const &objectSchemaProps = ip->getObjectSchemaProps(state, cCurrentModuleObject);
    1248              : 
    1249           41 :             auto &instancesValue = instances.value();
    1250           41 :             int Item = 0;
    1251          106 :             for (auto instance = instancesValue.begin(); instance != instancesValue.end(); ++instance) {
    1252           65 :                 ++Item;
    1253           65 :                 auto const &objectFields = instance.value();
    1254           65 :                 std::string const thisObjectName = Util::makeUPPER(instance.key());
    1255           65 :                 ip->markObjectAsUsed(cCurrentModuleObject, instance.key());
    1256           65 :                 auto &mgrList = state.dataAvail->ListData(Item);
    1257           65 :                 mgrList.Name = thisObjectName;
    1258              : 
    1259           65 :                 auto extensibles = objectFields.find("managers");
    1260           65 :                 auto const &extensionSchemaProps = objectSchemaProps["managers"]["items"]["properties"];
    1261           65 :                 if (extensibles != objectFields.end()) {
    1262           65 :                     auto &extensiblesArray = extensibles.value();
    1263           65 :                     int numExtensibles = extensiblesArray.size();
    1264           65 :                     mgrList.NumItems = numExtensibles;
    1265           65 :                     mgrList.availManagers.allocate(numExtensibles);
    1266          131 :                     for (int extItem = 1; extItem <= numExtensibles; ++extItem) {
    1267           66 :                         mgrList.availManagers(extItem).Name = "";
    1268           66 :                         mgrList.availManagers(extItem).type = ManagerType::Invalid;
    1269              :                     }
    1270              : 
    1271           65 :                     int listItem = 0;
    1272          131 :                     for (nlohmann::json const &extensibleInstance : extensiblesArray) {
    1273           66 :                         ++listItem;
    1274           66 :                         mgrList.availManagers(listItem).Name =
    1275          198 :                             ip->getAlphaFieldValue(extensibleInstance, extensionSchemaProps, "availability_manager_name");
    1276              :                         std::string availManagerObjType =
    1277          132 :                             ip->getAlphaFieldValue(extensibleInstance, extensionSchemaProps, "availability_manager_object_type");
    1278          132 :                         mgrList.availManagers(listItem).type =
    1279           66 :                             static_cast<ManagerType>(getEnumValue(managerTypeNamesUC, Util::makeUPPER(availManagerObjType)));
    1280           66 :                         if (mgrList.availManagers(listItem).type == ManagerType::HybridVent)
    1281            0 :                             mgrList.availManagers(listItem).type = ManagerType::Invalid;
    1282              :                         // these are validated individually in the GetPlant, GetSystem and GetZoneEq lists
    1283           66 :                     }
    1284              :                 }
    1285           65 :             }
    1286              : 
    1287           41 :             if (ErrorsFound) {
    1288            0 :                 ShowFatalError(state, "GetSysAvailManagerListInputs: Program terminates due to preceding conditions.");
    1289              :             }
    1290              :         }
    1291           90 :     } // GetSysAvailManagerListInputs()
    1292              : 
    1293           54 :     void GetPlantAvailabilityManager(EnergyPlusData &state,
    1294              :                                      std::string const &AvailabilityListName, // name that should be an Availability Manager List Name
    1295              :                                      int const Loop,                          // which loop this is
    1296              :                                      int const NumPlantLoops,                 // Total number of plant loops
    1297              :                                      bool &ErrorsFound                        // true if certain errors are detected here
    1298              :     )
    1299              :     {
    1300              : 
    1301              :         // SUBROUTINE INFORMATION:
    1302              :         //       AUTHOR         Linda Lawrie
    1303              :         //       DATE WRITTEN   August 2007
    1304              :         //       MODIFIED       na
    1305              :         //       RE-ENGINEERED  na
    1306              : 
    1307              :         // PURPOSE OF THIS SUBROUTINE:
    1308              :         // This subroutine gets the plant availability manager data for the indicated
    1309              :         // loop.  If the PlantAvailMgr structure has not been allocated, it will be allocated
    1310              :         // to "number of plant loops".
    1311           54 :         auto &availMgr = state.dataAvail->PlantAvailMgr(Loop);
    1312              : 
    1313           54 :         if (state.dataAvail->GetAvailListsInput) {
    1314           37 :             GetSysAvailManagerListInputs(state);
    1315           37 :             state.dataAvail->GetAvailListsInput = false;
    1316              :         }
    1317              : 
    1318           54 :         if (!allocated(state.dataAvail->PlantAvailMgr)) {
    1319            0 :             state.dataAvail->PlantAvailMgr.allocate(NumPlantLoops);
    1320              :         }
    1321              : 
    1322           54 :         int Found = 0;
    1323           54 :         if (state.dataAvail->NumAvailManagerLists > 0) Found = Util::FindItemInList(AvailabilityListName, state.dataAvail->ListData);
    1324              : 
    1325           54 :         if (Found != 0) {
    1326            2 :             availMgr.NumAvailManagers = state.dataAvail->ListData(Found).NumItems;
    1327            2 :             availMgr.availStatus = Status::NoAction;
    1328            2 :             availMgr.StartTime = 0;
    1329            2 :             availMgr.StopTime = 0;
    1330            2 :             availMgr.availManagers.allocate(availMgr.NumAvailManagers);
    1331            4 :             for (int Num = 1; Num <= availMgr.NumAvailManagers; ++Num) {
    1332            2 :                 auto &am = availMgr.availManagers(Num);
    1333            2 :                 am.Name = state.dataAvail->ListData(Found).availManagers(Num).Name;
    1334            2 :                 am.Num = 0;
    1335            2 :                 am.type = state.dataAvail->ListData(Found).availManagers(Num).type;
    1336            2 :                 assert(am.type != ManagerType::Invalid);
    1337              : 
    1338            2 :                 if (am.type == ManagerType::DiffThermo && Num != availMgr.NumAvailManagers) {
    1339            0 :                     ShowWarningError(
    1340            0 :                         state, format("GetPlantLoopData/GetPlantAvailabilityManager: AvailabilityManager:DifferentialThermostat=\"{}\".", am.Name));
    1341            0 :                     ShowContinueError(
    1342              :                         state, "...is not the last manager on the AvailabilityManagerAssignmentList.  Any remaining managers will not be used.");
    1343            0 :                     ShowContinueError(state, format("Occurs in AvailabilityManagerAssignmentList =\"{}\".", AvailabilityListName));
    1344              :                 }
    1345            2 :                 if (am.type == ManagerType::NightVent || am.type == ManagerType::NightCycle) {
    1346            0 :                     ShowSevereError(state,
    1347            0 :                                     format("GetPlantLoopData/GetPlantAvailabilityManager: Invalid System Availability Manager Type entered=\"{}\".",
    1348            0 :                                            managerTypeNames[(int)am.type]));
    1349            0 :                     ShowContinueError(state, "...this manager is not used in a Plant Loop.");
    1350            0 :                     ShowContinueError(state, format("Occurs in AvailabilityManagerAssignmentList=\"{}\".", AvailabilityListName));
    1351            0 :                     ErrorsFound = true;
    1352              :                 }
    1353              :             } // End of Num Loop
    1354              : 
    1355              :         } else {
    1356           52 :             if (AvailabilityListName != "") {
    1357            0 :                 ShowWarningError(state,
    1358            0 :                                  format("GetPlantLoopData/GetPlantAvailabilityManager: AvailabilityManagerAssignmentList={} not found in lists.  No "
    1359              :                                         "availability will be used.",
    1360              :                                         AvailabilityListName));
    1361              :             }
    1362           52 :             availMgr.NumAvailManagers = 0;
    1363           52 :             availMgr.availStatus = Status::NoAction;
    1364           52 :             availMgr.availManagers.allocate(availMgr.NumAvailManagers);
    1365              :         }
    1366           54 :     }
    1367              : 
    1368           62 :     void GetAirLoopAvailabilityManager(EnergyPlusData &state,
    1369              :                                        std::string const &AvailabilityListName, // name that should be an Availability Manager List Name
    1370              :                                        int const Loop,                          // which loop this is
    1371              :                                        int const NumAirLoops,                   // Total number of air loops
    1372              :                                        [[maybe_unused]] bool &ErrorsFound       // true if certain errors are detected here
    1373              :     )
    1374              :     {
    1375              : 
    1376              :         // SUBROUTINE INFORMATION:
    1377              :         //       AUTHOR         Linda Lawrie
    1378              :         //       DATE WRITTEN   August 2007
    1379              :         //       MODIFIED       na
    1380              :         //       RE-ENGINEERED  na
    1381              : 
    1382              :         // PURPOSE OF THIS SUBROUTINE:
    1383              :         // This subroutine gets the availability manager data for the indicated air
    1384              :         // loop or for the indicated type of zone equipment component.
    1385              :         // If the PriAirSysAvailMgr structure has not been allocated, it will be allocated
    1386              :         // to "number of air loops".
    1387           62 :         if (state.dataAvail->GetAvailListsInput) {
    1388           40 :             GetSysAvailManagerListInputs(state);
    1389           40 :             state.dataAvail->GetAvailListsInput = false;
    1390              :         }
    1391              : 
    1392           62 :         if (!allocated(state.dataAirLoop->PriAirSysAvailMgr)) {
    1393           50 :             state.dataAirLoop->PriAirSysAvailMgr.allocate(NumAirLoops);
    1394              :         }
    1395              : 
    1396           62 :         auto &availMgr = state.dataAirLoop->PriAirSysAvailMgr(Loop);
    1397              : 
    1398           62 :         int Found = 0;
    1399           62 :         if (state.dataAvail->NumAvailManagerLists > 0) Found = Util::FindItemInList(AvailabilityListName, state.dataAvail->ListData);
    1400              : 
    1401           62 :         if (Found != 0) {
    1402           48 :             availMgr.NumAvailManagers = state.dataAvail->ListData(Found).NumItems;
    1403           48 :             availMgr.availStatus = Status::NoAction;
    1404           48 :             availMgr.StartTime = 0;
    1405           48 :             availMgr.StopTime = 0;
    1406           48 :             availMgr.ReqSupplyFrac = 1.0;
    1407           48 :             availMgr.availManagers.allocate(availMgr.NumAvailManagers);
    1408           97 :             for (int Num = 1; Num <= availMgr.NumAvailManagers; ++Num) {
    1409           49 :                 auto &am = availMgr.availManagers(Num);
    1410           49 :                 am.Name = state.dataAvail->ListData(Found).availManagers(Num).Name;
    1411           49 :                 am.Num = 0;
    1412           49 :                 am.type = state.dataAvail->ListData(Found).availManagers(Num).type;
    1413           49 :                 assert(am.type != ManagerType::Invalid);
    1414              : 
    1415           49 :                 if (am.type == ManagerType::DiffThermo && Num != availMgr.NumAvailManagers) {
    1416            0 :                     ShowWarningError(
    1417            0 :                         state, format("GetAirPathData/GetAirLoopAvailabilityManager: AvailabilityManager:DifferentialThermostat=\"{}\".", am.Name));
    1418            0 :                     ShowContinueError(
    1419              :                         state, "...is not the last manager on the AvailabilityManagerAssignmentList.  Any remaining managers will not be used.");
    1420            0 :                     ShowContinueError(state, format("Occurs in AvailabilityManagerAssignmentList=\"{}\".", am.Name));
    1421              :                 }
    1422              :             } // End of Num Loop
    1423              : 
    1424              :         } else {
    1425           14 :             if (AvailabilityListName != "") {
    1426           18 :                 ShowWarningError(state,
    1427           18 :                                  format("GetAirPathData/GetAirLoopAvailabilityManager: AvailabilityManagerAssignmentList={} not found in lists.  No "
    1428              :                                         "availability will be used.",
    1429              :                                         AvailabilityListName));
    1430              :             }
    1431           14 :             availMgr.NumAvailManagers = 0;
    1432           14 :             availMgr.availStatus = Status::NoAction;
    1433           14 :             availMgr.availManagers.allocate(availMgr.NumAvailManagers);
    1434              :         }
    1435           62 :     }
    1436              : 
    1437        40983 :     void GetZoneEqAvailabilityManager(EnergyPlusData &state,
    1438              :                                       int const ZoneEquipType,           // Type of ZoneHVAC:* component
    1439              :                                       int const CompNum,                 // Index of a particular ZoneHVAC:* component
    1440              :                                       [[maybe_unused]] bool &ErrorsFound // true if certain errors are detected here
    1441              :     )
    1442              :     {
    1443              : 
    1444              :         // SUBROUTINE INFORMATION:
    1445              :         //       AUTHOR         Linda Lawrie
    1446              :         //       DATE WRITTEN   April 2011
    1447              :         //       MODIFIED       Chandan Sharma, March 2011/July 2012 - FSEC: Added zone sys avail managers
    1448              :         //       RE-ENGINEERED  na
    1449              : 
    1450              :         // PURPOSE OF THIS SUBROUTINE:
    1451              :         // This subroutine gets the availability manager data for the indicated type of zone
    1452              :         // equipment component.
    1453              :         // If not allocated, ZoneComp structure will be allocated to "Total num of zone equip types" and
    1454              :         // ZoneCompAvailMgrs structure will be allocated to "Total number of components of the indicated type".
    1455              : 
    1456              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1457        40983 :         std::string AvailabilityListName; // name that should be an Availability Manager List Name
    1458              :         int CompNumAvailManagers;         // Number of availability managers associated with a ZoneHVAC:* component
    1459              : 
    1460        40983 :         if (state.dataAvail->GetAvailListsInput) {
    1461           12 :             GetSysAvailManagerListInputs(state);
    1462           12 :             state.dataAvail->GetAvailListsInput = false;
    1463              :         }
    1464              : 
    1465        40983 :         auto &zoneComp = state.dataAvail->ZoneComp(ZoneEquipType);
    1466        40983 :         auto &availMgr = zoneComp.ZoneCompAvailMgrs(CompNum);
    1467        40983 :         if (availMgr.Input) { // when both air loop and zone eq avail managers are present, zone
    1468              :                               // avail mngrs list name has not been read in first time through here
    1469              :                               // (see end of if block)
    1470           52 :             AvailabilityListName = availMgr.AvailManagerListName;
    1471           52 :             int Found = 0;
    1472           52 :             if (state.dataAvail->NumAvailManagerLists > 0) Found = Util::FindItemInList(AvailabilityListName, state.dataAvail->ListData);
    1473           52 :             if (Found != 0) {
    1474            1 :                 availMgr.NumAvailManagers = state.dataAvail->ListData(Found).NumItems;
    1475            1 :                 CompNumAvailManagers = availMgr.NumAvailManagers;
    1476            1 :                 availMgr.availStatus = Status::NoAction;
    1477            1 :                 availMgr.StartTime = 0;
    1478            1 :                 availMgr.StopTime = 0;
    1479            1 :                 if (!allocated(availMgr.availManagers)) {
    1480            1 :                     availMgr.availManagers.allocate(CompNumAvailManagers);
    1481              :                 }
    1482            2 :                 for (int Num = 1; Num <= availMgr.NumAvailManagers; ++Num) {
    1483            1 :                     auto &am = availMgr.availManagers(Num);
    1484            1 :                     am.Name = state.dataAvail->ListData(Found).availManagers(Num).Name;
    1485            1 :                     am.Num = 0;
    1486            1 :                     am.type = state.dataAvail->ListData(Found).availManagers(Num).type;
    1487            1 :                     assert(am.type != ManagerType::Invalid);
    1488              : 
    1489            1 :                     if (am.type == ManagerType::DiffThermo && Num != availMgr.NumAvailManagers) {
    1490            0 :                         ShowWarningError(state, format("GetZoneEqAvailabilityManager: AvailabilityManager:DifferentialThermostat=\"{}\".", am.Name));
    1491            0 :                         ShowContinueError(
    1492              :                             state, "...is not the last manager on the AvailabilityManagerAssignmentList.  Any remaining managers will not be used.");
    1493            0 :                         ShowContinueError(state, format("Occurs in AvailabilityManagerAssignmentList=\"{}\".", am.Name));
    1494              :                     }
    1495              :                 } // End of Num Loop
    1496              :             }
    1497           52 :             if (availMgr.Count > 0 || Found > 0) availMgr.Input = false;
    1498           52 :             availMgr.Count += 1;
    1499              :         }
    1500        40983 :     }
    1501              : 
    1502       208398 :     void InitSysAvailManagers(EnergyPlusData &state)
    1503              :     {
    1504              : 
    1505              :         // SUBROUTINE INFORMATION:
    1506              :         //       AUTHOR         Fred Buhl
    1507              :         //       DATE WRITTEN   August 2001
    1508              :         //       MODIFIED       Brent Griffith, CR8376 initialize to Status::NoAction every timestep
    1509              : 
    1510              :         // PURPOSE OF THIS SUBROUTINE:
    1511              :         // This subroutine is for initializations of the System Availability Manager objects.
    1512              : 
    1513              :         // METHODOLOGY EMPLOYED:
    1514              :         // Uses the status flags to trigger initializations.
    1515              : 
    1516              :         using DataZoneEquipment::NumValidSysAvailZoneComponents;
    1517              : 
    1518              :         int ZoneListNum;
    1519              :         int ScanZoneListNum;
    1520              :         int ZoneNum;
    1521              :         // One time initializations
    1522              : 
    1523       208398 :         if (state.dataAvail->InitSysAvailManagers_MyOneTimeFlag) {
    1524              : 
    1525           95 :             for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumOptStartSysAvailMgrs; ++SysAvailNum) {
    1526            3 :                 auto &optimumStartMgr = state.dataAvail->OptimumStartData(SysAvailNum);
    1527            3 :                 if (optimumStartMgr.optimumStartControlType == OptimumStartControlType::MaximumOfZoneList) {
    1528              :                     // a zone list
    1529            1 :                     ZoneListNum = Util::FindItemInList(optimumStartMgr.ZoneListName, state.dataHeatBal->ZoneList);
    1530            1 :                     if (ZoneListNum > 0) {
    1531            1 :                         optimumStartMgr.NumOfZones = state.dataHeatBal->ZoneList(ZoneListNum).NumOfZones;
    1532            1 :                         if (!allocated(optimumStartMgr.ZonePtrs)) {
    1533            0 :                             optimumStartMgr.ZonePtrs.allocate({1, state.dataHeatBal->ZoneList(ZoneListNum).NumOfZones});
    1534              :                         }
    1535            4 :                         for (ScanZoneListNum = 1; ScanZoneListNum <= state.dataHeatBal->ZoneList(ZoneListNum).NumOfZones; ++ScanZoneListNum) {
    1536            3 :                             ZoneNum = state.dataHeatBal->ZoneList(ZoneListNum).Zone(ScanZoneListNum);
    1537            3 :                             optimumStartMgr.ZonePtrs(ScanZoneListNum) = ZoneNum;
    1538              :                         }
    1539              :                     }
    1540              :                 }
    1541              :             }
    1542              : 
    1543           92 :             state.dataAvail->InitSysAvailManagers_MyOneTimeFlag = false;
    1544              : 
    1545              :         } // end 1 time initializations
    1546              : 
    1547              :         // initialize individual availability managers to no action (CR 8376 reporting issue)
    1548       208398 :         if (allocated(state.dataAvail->SchedData))
    1549        73818 :             for (auto &e : state.dataAvail->SchedData)
    1550        39738 :                 e.availStatus = Status::NoAction;
    1551       208398 :         if (allocated(state.dataAvail->SchedOnData))
    1552            0 :             for (auto &e : state.dataAvail->SchedOnData)
    1553            0 :                 e.availStatus = Status::NoAction;
    1554       208398 :         if (allocated(state.dataAvail->SchedOffData))
    1555            0 :             for (auto &e : state.dataAvail->SchedOffData)
    1556            0 :                 e.availStatus = Status::NoAction;
    1557       208398 :         if (allocated(state.dataAvail->NightCycleData))
    1558        14920 :             for (auto &e : state.dataAvail->NightCycleData)
    1559         7460 :                 e.availStatus = Status::NoAction;
    1560       208398 :         if (allocated(state.dataAvail->NightVentData))
    1561            0 :             for (auto &e : state.dataAvail->NightVentData)
    1562            0 :                 e.availStatus = Status::NoAction;
    1563       208398 :         if (allocated(state.dataAvail->DiffThermoData))
    1564            0 :             for (auto &e : state.dataAvail->DiffThermoData)
    1565            0 :                 e.availStatus = Status::NoAction;
    1566       208398 :         if (allocated(state.dataAvail->HiTurnOffData))
    1567            0 :             for (auto &e : state.dataAvail->HiTurnOffData)
    1568            0 :                 e.availStatus = Status::NoAction;
    1569       208398 :         if (allocated(state.dataAvail->HiTurnOnData))
    1570            0 :             for (auto &e : state.dataAvail->HiTurnOnData)
    1571            0 :                 e.availStatus = Status::NoAction;
    1572       208398 :         if (allocated(state.dataAvail->LoTurnOffData))
    1573          356 :             for (auto &e : state.dataAvail->LoTurnOffData)
    1574          178 :                 e.availStatus = Status::NoAction;
    1575       208398 :         if (allocated(state.dataAvail->LoTurnOnData))
    1576            0 :             for (auto &e : state.dataAvail->LoTurnOnData)
    1577            0 :                 e.availStatus = Status::NoAction;
    1578       208398 :         if (allocated(state.dataAvail->OptimumStartData)) {
    1579           24 :             for (auto &e : state.dataAvail->OptimumStartData) {
    1580           18 :                 e.availStatus = Status::NoAction;
    1581           18 :                 e.isSimulated = false;
    1582              :             }
    1583              :         }
    1584              :         //  HybridVentSysAvailMgrData%AvailStatus= Status::NoAction
    1585       208398 :         if (allocated(state.dataAvail->ZoneComp)) {
    1586      3125970 :             for (int ZoneEquipType = 1; ZoneEquipType <= NumValidSysAvailZoneComponents; ++ZoneEquipType) { // loop over the zone equipment types
    1587      2917572 :                 if (state.dataAvail->ZoneComp(ZoneEquipType).TotalNumComp > 0)
    1588        29625 :                     for (auto &e : state.dataAvail->ZoneComp(ZoneEquipType).ZoneCompAvailMgrs)
    1589        20420 :                         e.availStatus = Status::NoAction;
    1590              :             }
    1591              :         }
    1592       208398 :     }
    1593              : 
    1594        36187 :     Status SimSysAvailManager(EnergyPlusData &state,
    1595              :                               const ManagerType type,
    1596              :                               std::string const &SysAvailName,
    1597              :                               int &SysAvailNum,
    1598              :                               int const PriAirSysNum, // Primary Air System index. If being called for a ZoneHVAC:* component
    1599              :                               Status const previousStatus,
    1600              :                               ObjexxFCL::Optional_int_const ZoneEquipType, // Type of ZoneHVAC:* equipment component
    1601              :                               ObjexxFCL::Optional_int_const CompNum        // Index of ZoneHVAC:* equipment component
    1602              :     )
    1603              :     {
    1604              : 
    1605              :         // SUBROUTINE INFORMATION:
    1606              :         //       AUTHOR         Fred Buhl
    1607              :         //       DATE WRITTEN   August 2001
    1608              :         //       MODIFIED       na
    1609              :         //       RE-ENGINEERED  na
    1610              : 
    1611              :         // PURPOSE OF THIS SUBROUTINE
    1612              :         // Loop over all the System Availability Managers and invoke the correct
    1613              :         // System Availability Manager algorithm.
    1614              : 
    1615              :         Status availStatus;
    1616              : 
    1617        36187 :         switch (type) {
    1618        28532 :         case ManagerType::Scheduled: { // 'AvailabilityManager:Scheduled'
    1619        28532 :             if (SysAvailNum == 0) {
    1620           22 :                 SysAvailNum = Util::FindItemInList(SysAvailName, state.dataAvail->SchedData);
    1621              :             }
    1622        28532 :             if (SysAvailNum > 0) {
    1623        28532 :                 availStatus = CalcSchedSysAvailMgr(state, SysAvailNum);
    1624              :             } else {
    1625            0 :                 ShowFatalError(state, format("SimSysAvailManager: AvailabilityManager:Scheduled not found: {}", SysAvailName));
    1626              :             }
    1627              : 
    1628        28532 :         } break;
    1629            0 :         case ManagerType::ScheduledOn: { // 'AvailabilityManager:ScheduledOn'
    1630            0 :             if (SysAvailNum == 0) {
    1631            0 :                 SysAvailNum = Util::FindItemInList(SysAvailName, state.dataAvail->SchedOnData);
    1632              :             }
    1633            0 :             if (SysAvailNum > 0) {
    1634            0 :                 availStatus = CalcSchedOnSysAvailMgr(state, SysAvailNum);
    1635              :             } else {
    1636            0 :                 ShowFatalError(state, format("SimSysAvailManager: AvailabilityManager:ScheduledOn not found: {}", SysAvailName));
    1637              :             }
    1638              : 
    1639            0 :         } break;
    1640            0 :         case ManagerType::ScheduledOff: { // 'AvailabilityManager:ScheduledOff'
    1641            0 :             if (SysAvailNum == 0) {
    1642            0 :                 SysAvailNum = Util::FindItemInList(SysAvailName, state.dataAvail->SchedOffData);
    1643              :             }
    1644            0 :             if (SysAvailNum > 0) {
    1645            0 :                 availStatus = CalcSchedOffSysAvailMgr(state, SysAvailNum);
    1646              :             } else {
    1647            0 :                 ShowFatalError(state, format("SimSysAvailManager: AvailabilityManager:ScheduledOff not found: {}", SysAvailName));
    1648              :             }
    1649              : 
    1650            0 :         } break;
    1651         7459 :         case ManagerType::NightCycle: { // 'AvailabilityManager:NightCycle'
    1652         7459 :             if (SysAvailNum == 0) {
    1653            3 :                 SysAvailNum = Util::FindItemInList(SysAvailName, state.dataAvail->NightCycleData);
    1654              :             }
    1655         7459 :             if (SysAvailNum > 0) {
    1656         7459 :                 availStatus = CalcNCycSysAvailMgr(state, SysAvailNum, PriAirSysNum, ZoneEquipType, CompNum);
    1657              :             } else {
    1658            0 :                 ShowFatalError(state, format("SimSysAvailManager: AvailabilityManager:NightCycle not found: {}", SysAvailName));
    1659              :             }
    1660              : 
    1661         7459 :         } break;
    1662           18 :         case ManagerType::OptimumStart: { // 'AvailabilityManager:OptimumStart'
    1663           18 :             if (SysAvailNum == 0) {
    1664            0 :                 SysAvailNum = Util::FindItemInList(SysAvailName, state.dataAvail->OptimumStartData);
    1665              :             }
    1666           18 :             if (SysAvailNum > 0) {
    1667           18 :                 availStatus = CalcOptStartSysAvailMgr(state, SysAvailNum, PriAirSysNum, ZoneEquipType, CompNum);
    1668              :             } else {
    1669            0 :                 ShowFatalError(state, format("SimSysAvailManager: AvailabilityManager:OptimumStart not found: {}", SysAvailName));
    1670              :             }
    1671              : 
    1672           18 :         } break;
    1673            0 :         case ManagerType::NightVent: { // 'AvailabilityManager:NightVentilation'
    1674            0 :             if (SysAvailNum == 0) {
    1675            0 :                 SysAvailNum = Util::FindItemInList(SysAvailName, state.dataAvail->NightVentData);
    1676              :             }
    1677            0 :             if (SysAvailNum > 0) {
    1678            0 :                 availStatus = CalcNVentSysAvailMgr(state, SysAvailNum, PriAirSysNum, present(ZoneEquipType));
    1679              :             } else {
    1680            0 :                 ShowFatalError(state, format("SimSysAvailManager: AvailabilityManager:NightVentilation not found: {}", SysAvailName));
    1681              :             }
    1682              : 
    1683            0 :         } break;
    1684            0 :         case ManagerType::DiffThermo: { // 'AvailabilityManager:DifferentialThermostat'
    1685            0 :             if (SysAvailNum == 0) {
    1686            0 :                 SysAvailNum = Util::FindItemInList(SysAvailName, state.dataAvail->DiffThermoData);
    1687              :             }
    1688            0 :             if (SysAvailNum > 0) {
    1689            0 :                 availStatus = CalcDiffTSysAvailMgr(state, SysAvailNum, previousStatus);
    1690              :             } else {
    1691            0 :                 ShowFatalError(state, format("SimSysAvailManager: AvailabilityManager:DifferentialThermostat not found: {}", SysAvailName));
    1692              :             }
    1693            0 :         } break;
    1694            0 :         case ManagerType::HiTempTOff: { // 'AvailabilityManager:HighTemperatureTurnOff'
    1695            0 :             if (SysAvailNum == 0) {
    1696            0 :                 SysAvailNum = Util::FindItemInList(SysAvailName, state.dataAvail->HiTurnOffData);
    1697              :             }
    1698            0 :             if (SysAvailNum > 0) {
    1699            0 :                 availStatus = CalcHiTurnOffSysAvailMgr(state, SysAvailNum);
    1700              :             } else {
    1701            0 :                 ShowFatalError(state, format("SimSysAvailManager: AvailabilityManager:HighTemperatureTurnOff not found: {}", SysAvailName));
    1702              :             }
    1703            0 :         } break;
    1704            0 :         case ManagerType::HiTempTOn: { // 'AvailabilityManager:HighTemperatureTurnOn'
    1705            0 :             if (SysAvailNum == 0) {
    1706            0 :                 SysAvailNum = Util::FindItemInList(SysAvailName, state.dataAvail->HiTurnOnData);
    1707              :             }
    1708            0 :             if (SysAvailNum > 0) {
    1709            0 :                 availStatus = CalcHiTurnOnSysAvailMgr(state, SysAvailNum);
    1710              :             } else {
    1711            0 :                 ShowFatalError(state, format("SimSysAvailManager: AvailabilityManager:HighTemperatureTurnOn not found: {}", SysAvailName));
    1712              :             }
    1713            0 :         } break;
    1714          178 :         case ManagerType::LoTempTOff: { // 'AvailabilityManager:LowTemperatureTurnOff'
    1715          178 :             if (SysAvailNum == 0) {
    1716            1 :                 SysAvailNum = Util::FindItemInList(SysAvailName, state.dataAvail->LoTurnOffData);
    1717              :             }
    1718          178 :             if (SysAvailNum > 0) {
    1719          178 :                 availStatus = CalcLoTurnOffSysAvailMgr(state, SysAvailNum);
    1720              :             } else {
    1721            0 :                 ShowFatalError(state, format("SimSysAvailManager: AvailabilityManager:LowTemperatureTurnOff not found: {}", SysAvailName));
    1722              :             }
    1723              : 
    1724          178 :         } break;
    1725            0 :         case ManagerType::LoTempTOn: { // 'AvailabilityManager:LowTemperatureTurnOn'
    1726            0 :             if (SysAvailNum == 0) {
    1727            0 :                 SysAvailNum = Util::FindItemInList(SysAvailName, state.dataAvail->LoTurnOnData);
    1728              :             }
    1729            0 :             if (SysAvailNum > 0) {
    1730            0 :                 availStatus = CalcLoTurnOnSysAvailMgr(state, SysAvailNum);
    1731              :             } else {
    1732            0 :                 ShowFatalError(state, format("SimSysAvailManager: AvailabilityManager:LowTemperatureTurnOn not found: {}", SysAvailName));
    1733              :             }
    1734              : 
    1735            0 :         } break;
    1736              : 
    1737            0 :         default: {
    1738            0 :             ShowSevereError(state, format("AvailabilityManager Type not found: {}", type));
    1739            0 :             ShowContinueError(state, format("Occurs in Manager={}", SysAvailName));
    1740            0 :             ShowFatalError(state, "Preceding condition causes termination.");
    1741              :         }
    1742              :         }
    1743        36187 :         return availStatus;
    1744              :     }
    1745              : 
    1746        28532 :     Status CalcSchedSysAvailMgr(EnergyPlusData &state,
    1747              :                                 int const SysAvailNum // number of the current scheduled system availability manager
    1748              :     )
    1749              :     {
    1750              : 
    1751              :         // SUBROUTINE INFORMATION:
    1752              :         //       AUTHOR         Fred Buhl
    1753              :         //       DATE WRITTEN   August 2001
    1754              :         //       MODIFIED       na
    1755              :         //       RE-ENGINEERED  na
    1756              : 
    1757              :         // PURPOSE OF THIS SUBROUTINE:
    1758              :         // Set AvailStatus indicator for a primary air loop, plant loop or ZoneHVAC component.
    1759              : 
    1760              :         // METHODOLOGY EMPLOYED:
    1761              :         // Looks at the System Availability Manager schedule and sets the
    1762              :         // AvailStatus indicator accordingly. Mostly a useless algorithm
    1763              :         // since the fan schedules can do the same thing.
    1764        28532 :         auto &availMgr = state.dataAvail->SchedData(SysAvailNum);
    1765        28532 :         availMgr.availStatus = (availMgr.availSched->getCurrentVal() > 0.0) ? Status::CycleOn : Status::ForceOff;
    1766        28532 :         return availMgr.availStatus;
    1767              :     }
    1768              : 
    1769            0 :     Status CalcSchedOnSysAvailMgr(EnergyPlusData &state,
    1770              :                                   int const SysAvailNum // number of the current scheduled on system availability manager
    1771              :     )
    1772              :     {
    1773              : 
    1774              :         // SUBROUTINE INFORMATION:
    1775              :         //       AUTHOR         R. Raustad - FSEC
    1776              :         //       DATE WRITTEN   August 2008
    1777              :         //       MODIFIED       na
    1778              :         //       RE-ENGINEERED  na
    1779              : 
    1780              :         // PURPOSE OF THIS SUBROUTINE:
    1781              :         // Set AvailStatus indicator for a primary air loop, plant loop or ZoneHVAC component.
    1782              : 
    1783              :         // METHODOLOGY EMPLOYED:
    1784              :         // Looks at the System Availability Manager schedule and sets the
    1785              :         // AvailStatus indicator accordingly. If the schedule value is > 0
    1786              :         // the availability status is Status::CycleOn, ELSE the status is Status::NoAction.
    1787            0 :         auto &availMgr = state.dataAvail->SchedOnData(SysAvailNum);
    1788            0 :         availMgr.availStatus = (availMgr.availSched->getCurrentVal() > 0.0) ? Status::CycleOn : Status::NoAction;
    1789            0 :         return availMgr.availStatus;
    1790              :     }
    1791              : 
    1792            0 :     Status CalcSchedOffSysAvailMgr(EnergyPlusData &state,
    1793              :                                    int const SysAvailNum // number of the current scheduled off system availability manager
    1794              :     )
    1795              :     {
    1796              : 
    1797              :         // SUBROUTINE INFORMATION:
    1798              :         //       AUTHOR         R. Raustad - FSEC
    1799              :         //       DATE WRITTEN   August 2008
    1800              :         //       MODIFIED       na
    1801              :         //       RE-ENGINEERED  na
    1802              : 
    1803              :         // PURPOSE OF THIS SUBROUTINE:
    1804              :         // Set AvailStatus indicator for a primary air loop, plant loop or ZoneHVAC component.
    1805              : 
    1806              :         // METHODOLOGY EMPLOYED:
    1807              :         // Looks at the System Availability Manager schedule and sets the
    1808              :         // AvailStatus indicator accordingly.  If the schedule value is = 0
    1809              :         // the availability status is Status::ForceOff, ELSE the status is Status::NoAction.
    1810            0 :         auto &availMgr = state.dataAvail->SchedOffData(SysAvailNum);
    1811            0 :         availMgr.availStatus = (availMgr.availSched->getCurrentVal() == 0.0) ? Status::ForceOff : Status::NoAction;
    1812            0 :         return availMgr.availStatus;
    1813              :     }
    1814              : 
    1815         7478 :     Status CalcNCycSysAvailMgr(EnergyPlusData &state,
    1816              :                                int const SysAvailNum,                       // number of the current scheduled system availability manager
    1817              :                                int const PriAirSysNum,                      // number of the primary air system affected by this Avail. Manager
    1818              :                                ObjexxFCL::Optional_int_const ZoneEquipType, // Type of ZoneHVAC equipment component
    1819              :                                ObjexxFCL::Optional_int_const CompNum        // Index of ZoneHVAC equipment component
    1820              :     )
    1821              :     {
    1822              : 
    1823              :         // SUBROUTINE INFORMATION:
    1824              :         //       AUTHOR         Fred Buhl
    1825              :         //       DATE WRITTEN   August 2001
    1826              :         //       MODIFIED       March 2011, Chandan Sharma - FSEC: Allowed night cycle
    1827              :         //                             availability manager to work for ZoneHVAC component
    1828              :         //       RE-ENGINEERED  na
    1829              : 
    1830              :         // PURPOSE OF THIS SUBROUTINE:
    1831              :         // Set AvailStatus indicator for a primary air loop or ZoneHVAC component.
    1832              : 
    1833              :         // METHODOLOGY EMPLOYED:
    1834              :         // For air loop, depending on the type of control, looks at 1 named zone or all the zones
    1835              :         // attached to a primary air system, compares zone temperature to the setup
    1836              :         // or setback thermostat setpoint, and sets the AvailStaus indicator according
    1837              :         // to whether the system needs to be cycled on or not.
    1838              :         // For ZoneHVAC component, uses the exact same method as above but only looks at the
    1839              :         // zone where component is located.
    1840              :         int StartTime;
    1841              :         int StopTime;
    1842              :         int ZoneInSysNum;
    1843              :         Real64 TempTol;
    1844         7478 :         auto &ZoneCompNCControlType = state.dataAvail->ZoneCompNCControlType;
    1845              : 
    1846         7478 :         if (present(ZoneEquipType)) {
    1847           11 :             auto &zoneComp = state.dataAvail->ZoneComp(ZoneEquipType);
    1848           11 :             if (state.dataGlobal->WarmupFlag && state.dataGlobal->BeginDayFlag) {
    1849              :                 // reset start/stop times at beginning of each day during warmup to prevent non-convergence due to rotating start times
    1850            1 :                 zoneComp.ZoneCompAvailMgrs(CompNum).StartTime = state.dataGlobal->SimTimeSteps;
    1851            1 :                 zoneComp.ZoneCompAvailMgrs(CompNum).StopTime = state.dataGlobal->SimTimeSteps;
    1852              :             }
    1853              : 
    1854           11 :             StartTime = zoneComp.ZoneCompAvailMgrs(CompNum).StartTime;
    1855           11 :             StopTime = zoneComp.ZoneCompAvailMgrs(CompNum).StopTime;
    1856           11 :             if (state.dataAvail->CalcNCycSysAvailMgr_OneTimeFlag) {
    1857            3 :                 ZoneCompNCControlType.dimension(state.dataAvail->NumNCycSysAvailMgrs, true);
    1858            3 :                 state.dataAvail->CalcNCycSysAvailMgr_OneTimeFlag = false;
    1859              :             }
    1860              :         } else {
    1861         7467 :             auto &availMgr = state.dataAirLoop->PriAirSysAvailMgr(PriAirSysNum);
    1862         7467 :             if (state.dataGlobal->WarmupFlag && state.dataGlobal->BeginDayFlag) {
    1863              :                 // reset start/stop times at beginning of each day during warmup to prevent non-convergence due to rotating start times
    1864          102 :                 availMgr.StartTime = state.dataGlobal->SimTimeSteps;
    1865          102 :                 availMgr.StopTime = state.dataGlobal->SimTimeSteps;
    1866              :             }
    1867              : 
    1868         7467 :             StartTime = availMgr.StartTime;
    1869         7467 :             StopTime = availMgr.StopTime;
    1870              :         }
    1871              : 
    1872              :         // CR 7913 changed to allow during warmup
    1873         7478 :         auto &nightCycleMgr = state.dataAvail->NightCycleData(SysAvailNum);
    1874         7478 :         if ((nightCycleMgr.availSched->getCurrentVal() <= 0.0) || (nightCycleMgr.fanSched->getCurrentVal() > 0.0)) {
    1875         2562 :             return nightCycleMgr.availStatus = Status::NoAction; // CR 8358
    1876              :         }
    1877              : 
    1878         4916 :         TempTol = (nightCycleMgr.cyclingRunTimeControl == CyclingRunTimeControl::FixedRunTime) ? (0.5 * nightCycleMgr.TempTolRange) : 0.05;
    1879              : 
    1880              :         Status availStatus;
    1881              : 
    1882         4916 :         if (present(ZoneEquipType)) {
    1883           14 :             if (state.dataGlobal->SimTimeSteps >= StartTime && state.dataGlobal->SimTimeSteps < StopTime &&
    1884            4 :                 (nightCycleMgr.cyclingRunTimeControl == CyclingRunTimeControl::FixedRunTime ||
    1885            3 :                  nightCycleMgr.cyclingRunTimeControl == CyclingRunTimeControl::ThermostatWithMinimumRunTime)) { // if cycled on
    1886            3 :                 availStatus = Status::CycleOn;
    1887           13 :             } else if (state.dataGlobal->SimTimeSteps == StopTime &&
    1888            6 :                        nightCycleMgr.cyclingRunTimeControl == CyclingRunTimeControl::FixedRunTime) { // if end of cycle run time, shut down if fan off
    1889            1 :                 availStatus = Status::NoAction;
    1890              :             } else {
    1891              : 
    1892            6 :                 switch (nightCycleMgr.nightCycleControlType) { // select type of night cycle control
    1893              : 
    1894            0 :                 case NightCycleControlType::Off: {
    1895            0 :                     availStatus = Status::NoAction;
    1896            0 :                 } break;
    1897            6 :                 case NightCycleControlType::OnControlZone: {
    1898              : 
    1899            6 :                     int ZoneNum = nightCycleMgr.CtrlZonePtrs(1);
    1900              : 
    1901            6 :                     auto const &zoneTstatSetpt = state.dataHeatBalFanSys->zoneTstatSetpts(ZoneNum);
    1902              : 
    1903            6 :                     switch (state.dataHeatBalFanSys->TempControlType(ZoneNum)) { // select on thermostat control
    1904              : 
    1905            0 :                     case HVAC::SetptType::SingleHeat: {
    1906            0 :                         if (state.dataHeatBalFanSys->TempTstatAir(ZoneNum) < zoneTstatSetpt.setpt - TempTol) {
    1907            0 :                             availStatus = Status::CycleOn;
    1908              :                         } else {
    1909            0 :                             availStatus = Status::NoAction;
    1910              :                         }
    1911              : 
    1912            0 :                     } break;
    1913            6 :                     case HVAC::SetptType::SingleCool: {
    1914            6 :                         if (state.dataHeatBalFanSys->TempTstatAir(ZoneNum) > zoneTstatSetpt.setpt + TempTol) {
    1915            3 :                             availStatus = Status::CycleOn;
    1916              :                         } else {
    1917            3 :                             availStatus = Status::NoAction;
    1918              :                         }
    1919              : 
    1920            6 :                     } break;
    1921            0 :                     case HVAC::SetptType::SingleHeatCool: {
    1922            0 :                         if ((state.dataHeatBalFanSys->TempTstatAir(ZoneNum) < zoneTstatSetpt.setpt - TempTol) ||
    1923            0 :                             (state.dataHeatBalFanSys->TempTstatAir(ZoneNum) > zoneTstatSetpt.setpt + TempTol)) {
    1924            0 :                             availStatus = Status::CycleOn;
    1925              :                         } else {
    1926            0 :                             availStatus = Status::NoAction;
    1927              :                         }
    1928              : 
    1929            0 :                     } break;
    1930            0 :                     case HVAC::SetptType::DualHeatCool: {
    1931            0 :                         if ((state.dataHeatBalFanSys->TempTstatAir(ZoneNum) < zoneTstatSetpt.setptLo - TempTol) ||
    1932            0 :                             (state.dataHeatBalFanSys->TempTstatAir(ZoneNum) > zoneTstatSetpt.setptHi + TempTol)) {
    1933            0 :                             availStatus = Status::CycleOn;
    1934              :                         } else {
    1935            0 :                             availStatus = Status::NoAction;
    1936              :                         }
    1937              : 
    1938            0 :                     } break;
    1939            0 :                     default: {
    1940            0 :                         availStatus = Status::NoAction;
    1941              :                     }
    1942              :                     } // end select on thermostat control
    1943            6 :                 } break;
    1944            0 :                 case NightCycleControlType::OnAny:
    1945              :                 case NightCycleControlType::OnZoneFansOnly: {
    1946            0 :                     if (ZoneCompNCControlType(SysAvailNum)) {
    1947            0 :                         ShowWarningError(state,
    1948            0 :                                          format("AvailabilityManager:NightCycle = {}, is specified for a ZoneHVAC component.", nightCycleMgr.Name));
    1949            0 :                         ShowContinueError(state, "The only valid Control Types for ZoneHVAC components are Status::CycleOnControlZone and StayOff.");
    1950            0 :                         ShowContinueError(state, "Night Cycle operation will not be modeled for ZoneHVAC components that reference this manager.");
    1951            0 :                         ZoneCompNCControlType(SysAvailNum) = false;
    1952              :                     }
    1953            0 :                     availStatus = Status::NoAction;
    1954            0 :                 } break;
    1955            0 :                 default: {
    1956            0 :                     availStatus = Status::NoAction;
    1957            0 :                     break;
    1958              :                 }
    1959              :                 } // end select type of night cycle control
    1960              : 
    1961            6 :                 if (availStatus == Status::CycleOn) { // reset the start and stop times
    1962            3 :                     auto &zoneComp = state.dataAvail->ZoneComp(ZoneEquipType);
    1963            3 :                     if (nightCycleMgr.cyclingRunTimeControl == CyclingRunTimeControl::Thermostat) { // Cycling Run Time is ignored
    1964            2 :                         zoneComp.ZoneCompAvailMgrs(CompNum).StartTime = state.dataGlobal->SimTimeSteps;
    1965            2 :                         zoneComp.ZoneCompAvailMgrs(CompNum).StopTime = state.dataGlobal->SimTimeSteps;
    1966              :                     } else {
    1967            1 :                         zoneComp.ZoneCompAvailMgrs(CompNum).StartTime = state.dataGlobal->SimTimeSteps;
    1968            1 :                         zoneComp.ZoneCompAvailMgrs(CompNum).StopTime = state.dataGlobal->SimTimeSteps + nightCycleMgr.CyclingTimeSteps;
    1969              :                     }
    1970              :                 }
    1971              :             }
    1972              :         } else {
    1973         7330 :             if (state.dataGlobal->SimTimeSteps >= StartTime && state.dataGlobal->SimTimeSteps < StopTime &&
    1974         2424 :                 (nightCycleMgr.cyclingRunTimeControl == CyclingRunTimeControl::FixedRunTime ||
    1975            1 :                  nightCycleMgr.cyclingRunTimeControl == CyclingRunTimeControl::ThermostatWithMinimumRunTime)) { // if cycled on
    1976         2423 :                 availStatus = nightCycleMgr.priorAvailStatus;
    1977         2423 :                 if (nightCycleMgr.nightCycleControlType == NightCycleControlType::OnZoneFansOnly) availStatus = Status::CycleOnZoneFansOnly;
    1978         4017 :             } else if (state.dataGlobal->SimTimeSteps == StopTime &&
    1979         1534 :                        nightCycleMgr.cyclingRunTimeControl == CyclingRunTimeControl::FixedRunTime) { // if end of cycle run time, shut down if fan off
    1980         1529 :                 availStatus = Status::NoAction;
    1981              :             } else {
    1982              : 
    1983          954 :                 switch (nightCycleMgr.nightCycleControlType) { // select type of night cycle control
    1984              : 
    1985            0 :                 case NightCycleControlType::Off: {
    1986            0 :                     availStatus = Status::NoAction;
    1987            0 :                 } break;
    1988          948 :                 case NightCycleControlType::OnAny:
    1989              :                 case NightCycleControlType::OnZoneFansOnly: {
    1990              : 
    1991              :                     // If no zones cooled, Availstatus could be "unknown"
    1992          948 :                     availStatus = Status::NoAction;
    1993              : 
    1994         1640 :                     for (ZoneInSysNum = 1; ZoneInSysNum <= state.dataAirLoop->AirToZoneNodeInfo(PriAirSysNum).NumZonesCooled;
    1995              :                          ++ZoneInSysNum) { // loop over zones in system
    1996              : 
    1997          948 :                         int ZoneNum = state.dataAirLoop->AirToZoneNodeInfo(PriAirSysNum).CoolCtrlZoneNums(ZoneInSysNum);
    1998          948 :                         auto const &zoneTstatSetpt = state.dataHeatBalFanSys->zoneTstatSetpts(ZoneNum);
    1999              : 
    2000          948 :                         switch (state.dataHeatBalFanSys->TempControlType(ZoneNum)) {
    2001            0 :                         case HVAC::SetptType::SingleHeat: {
    2002            0 :                             if (state.dataHeatBalFanSys->TempTstatAir(ZoneNum) < zoneTstatSetpt.setpt - TempTol) {
    2003            0 :                                 availStatus = Status::CycleOn;
    2004              :                             } else {
    2005            0 :                                 availStatus = Status::NoAction;
    2006              :                             }
    2007            0 :                         } break;
    2008            0 :                         case HVAC::SetptType::SingleCool: {
    2009            0 :                             if (state.dataHeatBalFanSys->TempTstatAir(ZoneNum) > zoneTstatSetpt.setpt + TempTol) {
    2010            0 :                                 availStatus = Status::CycleOn;
    2011              :                             } else {
    2012            0 :                                 availStatus = Status::NoAction;
    2013              :                             }
    2014            0 :                         } break;
    2015            0 :                         case HVAC::SetptType::SingleHeatCool: {
    2016            0 :                             if ((state.dataHeatBalFanSys->TempTstatAir(ZoneNum) < zoneTstatSetpt.setpt - TempTol) ||
    2017            0 :                                 (state.dataHeatBalFanSys->TempTstatAir(ZoneNum) > zoneTstatSetpt.setpt + TempTol)) {
    2018            0 :                                 availStatus = Status::CycleOn;
    2019              :                             } else {
    2020            0 :                                 availStatus = Status::NoAction;
    2021              :                             }
    2022            0 :                         } break;
    2023          948 :                         case HVAC::SetptType::DualHeatCool: {
    2024         1640 :                             if ((state.dataHeatBalFanSys->TempTstatAir(ZoneNum) < zoneTstatSetpt.setptLo - TempTol) ||
    2025          692 :                                 (state.dataHeatBalFanSys->TempTstatAir(ZoneNum) > zoneTstatSetpt.setptHi + TempTol)) {
    2026          256 :                                 availStatus = Status::CycleOn;
    2027              :                             } else {
    2028          692 :                                 availStatus = Status::NoAction;
    2029              :                             }
    2030          948 :                         } break;
    2031            0 :                         default: {
    2032            0 :                             availStatus = Status::NoAction;
    2033              :                         }
    2034              :                         }                                          // end select on thermostat control
    2035          948 :                         if (availStatus == Status::CycleOn) break; // loop break
    2036              :                     }                                              // end loop over zones in system
    2037          948 :                 } break;
    2038              : 
    2039            6 :                 case NightCycleControlType::OnControlZone: {
    2040            6 :                     availStatus = Status::NoAction;
    2041            6 :                     if (CoolingZoneOutOfTolerance(state, nightCycleMgr.CtrlZonePtrs, nightCycleMgr.NumOfCtrlZones, TempTol))
    2042            3 :                         availStatus = Status::CycleOn;
    2043            6 :                     if (HeatingZoneOutOfTolerance(state, nightCycleMgr.CtrlZonePtrs, nightCycleMgr.NumOfCtrlZones, TempTol))
    2044            0 :                         availStatus = Status::CycleOn;
    2045            6 :                 } break;
    2046              : 
    2047            0 :                 case NightCycleControlType::OnAnyCoolingOrHeatingZone: {
    2048            0 :                     if (CoolingZoneOutOfTolerance(state, nightCycleMgr.CoolingZonePtrs, nightCycleMgr.NumOfCoolingZones, TempTol)) {
    2049            0 :                         availStatus = Status::CycleOn;
    2050            0 :                     } else if (HeatingZoneOutOfTolerance(state, nightCycleMgr.HeatingZonePtrs, nightCycleMgr.NumOfHeatingZones, TempTol)) {
    2051            0 :                         availStatus = Status::CycleOn;
    2052            0 :                     } else if (HeatingZoneOutOfTolerance(state, nightCycleMgr.HeatZnFanZonePtrs, nightCycleMgr.NumOfHeatZnFanZones, TempTol)) {
    2053            0 :                         availStatus = Status::CycleOnZoneFansOnly;
    2054              :                     } else {
    2055            0 :                         availStatus = Status::NoAction;
    2056              :                     }
    2057            0 :                 } break;
    2058              : 
    2059            0 :                 case NightCycleControlType::OnAnyCoolingZone: {
    2060            0 :                     if (CoolingZoneOutOfTolerance(state, nightCycleMgr.CoolingZonePtrs, nightCycleMgr.NumOfCoolingZones, TempTol)) {
    2061            0 :                         availStatus = Status::CycleOn;
    2062              :                     } else {
    2063            0 :                         availStatus = Status::NoAction;
    2064              :                     }
    2065            0 :                 } break;
    2066            0 :                 case NightCycleControlType::OnAnyHeatingZone: {
    2067            0 :                     if (HeatingZoneOutOfTolerance(state, nightCycleMgr.HeatingZonePtrs, nightCycleMgr.NumOfHeatingZones, TempTol)) {
    2068            0 :                         availStatus = Status::CycleOn;
    2069            0 :                     } else if (HeatingZoneOutOfTolerance(state, nightCycleMgr.HeatZnFanZonePtrs, nightCycleMgr.NumOfHeatZnFanZones, TempTol)) {
    2070            0 :                         availStatus = Status::CycleOnZoneFansOnly;
    2071              :                     } else {
    2072            0 :                         availStatus = Status::NoAction;
    2073              :                     }
    2074            0 :                 } break;
    2075              : 
    2076            0 :                 case NightCycleControlType::OnAnyHeatingZoneFansOnly: {
    2077            0 :                     if (HeatingZoneOutOfTolerance(state, nightCycleMgr.HeatZnFanZonePtrs, nightCycleMgr.NumOfHeatZnFanZones, TempTol)) {
    2078            0 :                         availStatus = Status::CycleOnZoneFansOnly;
    2079              :                     } else {
    2080            0 :                         availStatus = Status::NoAction;
    2081              :                     }
    2082            0 :                 } break;
    2083              : 
    2084            0 :                 default:
    2085            0 :                     availStatus = Status::NoAction;
    2086              :                 } // end select type of night cycle control
    2087              : 
    2088          954 :                 if ((availStatus == Status::CycleOn) || (availStatus == Status::CycleOnZoneFansOnly)) { // reset the start and stop times
    2089          259 :                     if (nightCycleMgr.nightCycleControlType == NightCycleControlType::OnZoneFansOnly) availStatus = Status::CycleOnZoneFansOnly;
    2090              :                     // issue #6151
    2091          259 :                     auto &availMgr = state.dataAirLoop->PriAirSysAvailMgr(PriAirSysNum);
    2092          259 :                     if (nightCycleMgr.cyclingRunTimeControl == CyclingRunTimeControl::Thermostat) { // Cycling Run Time is ignored
    2093            2 :                         availMgr.StartTime = state.dataGlobal->SimTimeSteps;
    2094            2 :                         availMgr.StopTime = state.dataGlobal->SimTimeSteps;
    2095              :                     } else {
    2096          257 :                         availMgr.StartTime = state.dataGlobal->SimTimeSteps;
    2097          257 :                         availMgr.StopTime = state.dataGlobal->SimTimeSteps + nightCycleMgr.CyclingTimeSteps;
    2098              :                     }
    2099              :                 }
    2100              :             }
    2101              :         }
    2102         4916 :         nightCycleMgr.availStatus = availStatus;
    2103         4916 :         nightCycleMgr.priorAvailStatus = availStatus;
    2104         4916 :         return availStatus;
    2105              :     }
    2106              : 
    2107            8 :     bool CoolingZoneOutOfTolerance(EnergyPlusData &state,
    2108              :                                    Array1D_int const ZonePtrList, // list of controlled zone pointers
    2109              :                                    int const NumZones,            // number of zones in list
    2110              :                                    Real64 const TempTolerance     // temperature tolerance
    2111              :     )
    2112              :     {
    2113              : 
    2114              :         // Check if any zone temperature is above the cooling setpoint plus tolerance
    2115           17 :         for (int Index = 1; Index <= NumZones; ++Index) { // loop over zones in list
    2116           13 :             int ZoneNum = ZonePtrList(Index);
    2117           13 :             auto const &zoneTstatSetpt = state.dataHeatBalFanSys->zoneTstatSetpts(ZoneNum);
    2118              : 
    2119           13 :             switch (state.dataHeatBalFanSys->TempControlType(ZoneNum)) {
    2120           10 :             case HVAC::SetptType::SingleCool:
    2121              :             case HVAC::SetptType::SingleHeatCool:
    2122           10 :                 if (state.dataHeatBalFanSys->TempTstatAir(ZoneNum) > zoneTstatSetpt.setpt + TempTolerance) {
    2123            4 :                     return true; // return on the first zone found
    2124              :                 }
    2125            6 :                 break;
    2126            1 :             case HVAC::SetptType::DualHeatCool:
    2127            1 :                 if (state.dataHeatBalFanSys->TempTstatAir(ZoneNum) > zoneTstatSetpt.setptHi + TempTolerance) {
    2128            0 :                     return true; // return on the first zone found
    2129              :                 }
    2130            1 :                 break;
    2131            2 :             default:
    2132            2 :                 break;
    2133              :             }
    2134              :         }
    2135            4 :         return false;
    2136              :     }
    2137              : 
    2138            8 :     bool HeatingZoneOutOfTolerance(EnergyPlusData &state,
    2139              :                                    Array1D_int const ZonePtrList, // list of controlled zone pointers
    2140              :                                    int const NumZones,            // number of zones in list
    2141              :                                    Real64 const TempTolerance     // temperature tolerance
    2142              :     )
    2143              :     {
    2144              :         // Check if any zone temperature is below the heating setpoint less tolerance
    2145           18 :         for (int Index = 1; Index <= NumZones; ++Index) { // loop over zones in list
    2146           11 :             int ZoneNum = ZonePtrList(Index);
    2147              :             { // Why is this a new scope?
    2148           11 :                 auto const &zoneTstatSetpt = state.dataHeatBalFanSys->zoneTstatSetpts(ZoneNum);
    2149              : 
    2150           11 :                 HVAC::SetptType const tstatType(state.dataHeatBalFanSys->TempControlType(ZoneNum));
    2151              : 
    2152           11 :                 if ((tstatType == HVAC::SetptType::SingleHeat) || (tstatType == HVAC::SetptType::SingleHeatCool)) {
    2153            3 :                     if (state.dataHeatBalFanSys->TempTstatAir(ZoneNum) < zoneTstatSetpt.setpt - TempTolerance) {
    2154            1 :                         return true; // return on the first zone found
    2155              :                     }
    2156            8 :                 } else if (tstatType == HVAC::SetptType::DualHeatCool) {
    2157            1 :                     if (state.dataHeatBalFanSys->TempTstatAir(ZoneNum) < zoneTstatSetpt.setptLo - TempTolerance) {
    2158            0 :                         return true; // return on the first zone found
    2159              :                     }
    2160              :                 }
    2161              :             }
    2162              :         }
    2163            7 :         return false;
    2164              :     }
    2165              : 
    2166           18 :     Status CalcOptStartSysAvailMgr(EnergyPlusData &state,
    2167              :                                    int const SysAvailNum,  // number of the current scheduled system availability manager
    2168              :                                    int const PriAirSysNum, // number of the primary air system affected by this Avail. Manager
    2169              :                                    [[maybe_unused]] ObjexxFCL::Optional_int_const ZoneEquipType, // Type of ZoneHVAC equipment component
    2170              :                                    [[maybe_unused]] ObjexxFCL::Optional_int_const CompNum        // Index of ZoneHVAC equipment component
    2171              :     )
    2172              :     {
    2173              : 
    2174              :         // SUBROUTINE INFORMATION:
    2175              :         //       AUTHOR            Xiufeng Pang (XP)
    2176              :         //       DATE WRITTEN      August 2013
    2177              :         //       MODIFIED
    2178              :         //       RE-ENGINEERED
    2179              : 
    2180              :         // PURPOSE OF THIS SUBROUTINE:
    2181              :         // Set AvailStatus indicator for a primary air loop, plant loop or ZoneHVAC component
    2182              : 
    2183              :         // METHODOLOGY EMPLOYED:
    2184              :         // Sets the AvailStatus indicator according to the
    2185              :         // optimum start algorithm
    2186              : 
    2187              :         // Using/Aliasing
    2188              :         using namespace DataAirLoop;
    2189              : 
    2190              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2191              : 
    2192           18 :         Array2D<Real64> DayValues;
    2193           18 :         Array2D<Real64> DayValuesTmr;
    2194              :         int JDay;
    2195              :         int TmrJDay;
    2196              :         int TmrDayOfWeek;
    2197              :         int ZoneNum;
    2198              :         Real64 FanStartTime;
    2199              :         Real64 FanStartTimeTmr;
    2200              :         Real64 PreStartTime;
    2201              :         Real64 PreStartTimeTmr;
    2202              :         Real64 DeltaTime;
    2203              :         Real64 TempDiff;
    2204              :         Real64 TempDiffHi;
    2205              :         Real64 TempDiffLo;
    2206           18 :         bool FirstTimeATGFlag(true);
    2207           18 :         bool OverNightStartFlag(false); // Flag to indicate the optimum start starts before mid night.
    2208           18 :         bool CycleOnFlag(false);
    2209           18 :         bool OSReportVarFlag(true);
    2210              :         int NumPreDays;
    2211              :         int NumOfZonesInList;
    2212              :         Real64 AdaTempGradHeat;
    2213              :         Real64 AdaTempGradCool;
    2214           18 :         Real64 ATGUpdateTime1(0.0);
    2215           18 :         Real64 ATGUpdateTime2(0.0);
    2216           18 :         Real64 ATGUpdateTemp1(0.0);
    2217           18 :         Real64 ATGUpdateTemp2(0.0);
    2218           18 :         bool ATGUpdateFlag1(false);
    2219           18 :         bool ATGUpdateFlag2(false);
    2220              :         int ATGCounter;
    2221              :         int ATGWCZoneNumHi;
    2222              :         int ATGWCZoneNumLo;
    2223              :         Real64 NumHoursBeforeOccupancy; // Variable to store the number of hours before occupancy in optimum start period
    2224              :         bool exitLoop;                  // exit loop on found data
    2225              : 
    2226              :         Status availStatus;
    2227              : 
    2228           18 :         auto &OptStartMgr = state.dataAvail->OptimumStartData(SysAvailNum);
    2229              : 
    2230              :         // some avail managers may be used in air loop and plant availability manager lists, if so they only need be simulated once
    2231           18 :         if (OptStartMgr.isSimulated) {
    2232            0 :             return OptStartMgr.availStatus;
    2233              :         }
    2234           18 :         OptStartMgr.isSimulated = true;
    2235              : 
    2236              :         // update air loop specific data
    2237           18 :         TempDiffLo = OptStartMgr.TempDiffLo;
    2238           18 :         TempDiffHi = OptStartMgr.TempDiffHi;
    2239           18 :         ATGWCZoneNumLo = OptStartMgr.ATGWCZoneNumLo;
    2240           18 :         ATGWCZoneNumHi = OptStartMgr.ATGWCZoneNumHi;
    2241           18 :         CycleOnFlag = OptStartMgr.CycleOnFlag;
    2242           18 :         ATGUpdateFlag1 = OptStartMgr.ATGUpdateFlag1;
    2243           18 :         ATGUpdateFlag2 = OptStartMgr.ATGUpdateFlag2;
    2244           18 :         NumHoursBeforeOccupancy = OptStartMgr.NumHoursBeforeOccupancy;
    2245           18 :         FirstTimeATGFlag = OptStartMgr.FirstTimeATGFlag;
    2246           18 :         OverNightStartFlag = OptStartMgr.OverNightStartFlag;
    2247           18 :         OSReportVarFlag = OptStartMgr.OSReportVarFlag;
    2248              : 
    2249           18 :         if (OptStartMgr.controlAlgorithm == ControlAlgorithm::AdaptiveTemperatureGradient) {
    2250           18 :             NumPreDays = OptStartMgr.NumPreDays;
    2251           18 :             if (!allocated(state.dataAvail->OptStart_AdaTempGradTrdHeat)) {
    2252            1 :                 state.dataAvail->OptStart_AdaTempGradTrdHeat.allocate(NumPreDays);
    2253            1 :                 state.dataAvail->OptStart_AdaTempGradTrdCool.allocate(NumPreDays);
    2254              :             }
    2255           18 :             if (!allocated(OptStartMgr.AdaTempGradTrdHeat)) {
    2256            3 :                 OptStartMgr.AdaTempGradTrdHeat.allocate(NumPreDays);
    2257            3 :                 OptStartMgr.AdaTempGradTrdHeat = 0.0;
    2258            3 :                 OptStartMgr.AdaTempGradTrdCool.allocate(NumPreDays);
    2259            3 :                 OptStartMgr.AdaTempGradTrdCool = 0.0;
    2260              :             }
    2261           18 :             state.dataAvail->OptStart_AdaTempGradTrdHeat = OptStartMgr.AdaTempGradTrdHeat;
    2262           18 :             state.dataAvail->OptStart_AdaTempGradTrdCool = OptStartMgr.AdaTempGradTrdCool;
    2263           18 :             AdaTempGradHeat = OptStartMgr.AdaTempGradHeat;
    2264           18 :             AdaTempGradCool = OptStartMgr.AdaTempGradCool;
    2265           18 :             ATGUpdateTime1 = OptStartMgr.ATGUpdateTime1;
    2266           18 :             ATGUpdateTime2 = OptStartMgr.ATGUpdateTime2;
    2267           18 :             ATGUpdateTemp1 = OptStartMgr.ATGUpdateTemp1;
    2268           18 :             ATGUpdateTemp2 = OptStartMgr.ATGUpdateTemp2;
    2269              :         }
    2270              : 
    2271              :         // add or use a new variable OptStartSysAvailMgrData(SysAvailNum)%FanSchIndex
    2272           18 :         if (state.dataGlobal->KickOffSimulation) {
    2273            0 :             availStatus = Status::NoAction;
    2274              :         } else {
    2275           18 :             JDay = state.dataEnvrn->DayOfYear;
    2276           18 :             TmrJDay = JDay + 1;
    2277           18 :             TmrDayOfWeek = state.dataEnvrn->DayOfWeekTomorrow;
    2278              : 
    2279           18 :             DayValues.allocate(state.dataGlobal->TimeStepsInHour, Constant::iHoursInDay);
    2280           18 :             DayValuesTmr.allocate(state.dataGlobal->TimeStepsInHour, Constant::iHoursInDay);
    2281           18 :             if (!allocated(state.dataAvail->OptStart)) {
    2282            1 :                 state.dataAvail->OptStart.allocate(state.dataGlobal->NumOfZones);
    2283              :             }
    2284              : 
    2285              :             // OptStartFlag needs to be reset each timestep to not stay set to true post-occupancy
    2286          126 :             for (auto &optStart : state.dataAvail->OptStart)
    2287          108 :                 optStart.OptStartFlag = false;
    2288              : 
    2289              :             // reset OptStartData once per beginning of day
    2290           18 :             if (state.dataGlobal->BeginDayFlag) {
    2291            3 :                 NumHoursBeforeOccupancy = 0.0; // Initialize the hours of optimum start period. This variable is for reporting purpose.
    2292            3 :                 if (state.dataAvail->BeginOfDayResetFlag) {
    2293            7 :                     for (auto &optStart : state.dataAvail->OptStart)
    2294            6 :                         optStart.OccStartTime = 22.99; // initialize the zone occupancy start time
    2295            1 :                     state.dataAvail->BeginOfDayResetFlag = false;
    2296              :                 }
    2297              :             }
    2298           18 :             if (!state.dataGlobal->BeginDayFlag) state.dataAvail->BeginOfDayResetFlag = true;
    2299              : 
    2300           18 :             std::vector<Real64> const &dayVals = OptStartMgr.fanSched->getDayVals(state);
    2301           18 :             std::vector<Real64> const &tmwDayVals = OptStartMgr.fanSched->getDayVals(state, TmrJDay, TmrDayOfWeek);
    2302              : 
    2303           18 :             FanStartTime = 0.0;
    2304           18 :             FanStartTimeTmr = 0.0;
    2305           18 :             exitLoop = false;
    2306          126 :             for (int hr = 0; hr < Constant::iHoursInDay; ++hr) {
    2307          726 :                 for (int ts = 0; ts <= state.dataGlobal->TimeStepsInHour; ++ts) {
    2308          618 :                     if (dayVals[hr * state.dataGlobal->TimeStepsInHour + ts] <= 0.0) continue;
    2309           18 :                     FanStartTime = hr + (1.0 / state.dataGlobal->TimeStepsInHour) * (ts + 1) - 0.01;
    2310           18 :                     exitLoop = true;
    2311           18 :                     break;
    2312              :                 }
    2313          126 :                 if (exitLoop) break;
    2314              :             }
    2315              : 
    2316           18 :             exitLoop = false;
    2317          138 :             for (int hr = 0; hr < Constant::iHoursInDay; ++hr) {
    2318          630 :                 for (int ts = 0; ts < state.dataGlobal->TimeStepsInHour; ++ts) {
    2319          510 :                     if (tmwDayVals[hr * state.dataGlobal->TimeStepsInHour + ts] <= 0.0) continue;
    2320           18 :                     FanStartTimeTmr = hr + (1.0 / state.dataGlobal->TimeStepsInHour) * (ts + 1) - 0.01;
    2321           18 :                     exitLoop = true;
    2322           18 :                     break;
    2323              :                 }
    2324          138 :                 if (exitLoop) break;
    2325              :             }
    2326              : 
    2327           18 :             if (FanStartTimeTmr == 0.0) FanStartTimeTmr = 24.0;
    2328              : 
    2329              :             // Pass the start time to ZoneTempPredictorCorrector
    2330           54 :             for (int counter = 1; counter <= state.dataAirLoop->AirToZoneNodeInfo(PriAirSysNum).NumZonesCooled; ++counter) {
    2331           36 :                 int actZoneNum = state.dataAirLoop->AirToZoneNodeInfo(PriAirSysNum).CoolCtrlZoneNums(counter);
    2332           36 :                 auto &optStart = state.dataAvail->OptStart(actZoneNum);
    2333           36 :                 optStart.OccStartTime = FanStartTime;
    2334           36 :                 optStart.ActualZoneNum = actZoneNum;
    2335              :             }
    2336           18 :             for (int counter = 1; counter <= state.dataAirLoop->AirToZoneNodeInfo(PriAirSysNum).NumZonesHeated; ++counter) {
    2337            0 :                 int actZoneNum = state.dataAirLoop->AirToZoneNodeInfo(PriAirSysNum).HeatCtrlZoneNums(counter);
    2338            0 :                 auto &optStart = state.dataAvail->OptStart(actZoneNum);
    2339            0 :                 optStart.OccStartTime = FanStartTime;
    2340            0 :                 optStart.ActualZoneNum = actZoneNum;
    2341              :             }
    2342              : 
    2343           18 :             if (state.dataEnvrn->DSTIndicator > 0) {
    2344            0 :                 --FanStartTime;
    2345            0 :                 --FanStartTimeTmr;
    2346              :             }
    2347              : 
    2348           18 :             switch (OptStartMgr.controlAlgorithm) {
    2349            0 :             case ControlAlgorithm::ConstantStartTime: {
    2350            0 :                 if (OptStartMgr.optimumStartControlType == OptimumStartControlType::Off) {
    2351            0 :                     availStatus = Status::NoAction;
    2352              :                 } else {
    2353            0 :                     DeltaTime = OptStartMgr.ConstStartTime;
    2354            0 :                     if (DeltaTime > OptStartMgr.MaxOptStartTime) {
    2355            0 :                         DeltaTime = OptStartMgr.MaxOptStartTime;
    2356              :                     }
    2357            0 :                     PreStartTime = FanStartTime - DeltaTime;
    2358            0 :                     if (PreStartTime < 0.0) PreStartTime = -0.1;
    2359            0 :                     PreStartTimeTmr = FanStartTimeTmr - DeltaTime;
    2360            0 :                     if (PreStartTimeTmr < 0.0) {
    2361            0 :                         PreStartTimeTmr += 24.0;
    2362            0 :                         OverNightStartFlag = true;
    2363              :                     } else {
    2364            0 :                         OverNightStartFlag = false;
    2365              :                     }
    2366            0 :                     if (!OverNightStartFlag) {
    2367            0 :                         if (FanStartTime == 0.0 || state.dataGlobal->PreviousHour > FanStartTime) {
    2368            0 :                             availStatus = Status::NoAction;
    2369            0 :                             OSReportVarFlag = true;
    2370            0 :                         } else if (PreStartTime < state.dataGlobal->CurrentTime) {
    2371            0 :                             if (OSReportVarFlag) {
    2372            0 :                                 NumHoursBeforeOccupancy = DeltaTime;
    2373            0 :                                 OSReportVarFlag = false;
    2374              :                             }
    2375            0 :                             availStatus = Status::CycleOn;
    2376            0 :                             OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
    2377              :                         } else {
    2378            0 :                             availStatus = Status::NoAction;
    2379            0 :                             OSReportVarFlag = true;
    2380              :                         }
    2381              :                     } else {
    2382            0 :                         if (FanStartTime == 0.0 || (state.dataGlobal->HourOfDay > FanStartTime && state.dataGlobal->CurrentTime <= PreStartTimeTmr)) {
    2383            0 :                             availStatus = Status::NoAction;
    2384            0 :                             OSReportVarFlag = true;
    2385            0 :                         } else if (PreStartTime < state.dataGlobal->CurrentTime || PreStartTimeTmr < state.dataGlobal->CurrentTime) {
    2386            0 :                             if (OSReportVarFlag) {
    2387            0 :                                 NumHoursBeforeOccupancy = DeltaTime;
    2388            0 :                                 OSReportVarFlag = false;
    2389              :                             }
    2390            0 :                             availStatus = Status::CycleOn;
    2391            0 :                             OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
    2392              :                         } else {
    2393            0 :                             availStatus = Status::NoAction;
    2394            0 :                             OSReportVarFlag = true;
    2395              :                         }
    2396              :                     }
    2397              :                 }
    2398            0 :             } break;
    2399              : 
    2400            0 :             case ControlAlgorithm::ConstantTemperatureGradient: {
    2401            0 :                 if (OptStartMgr.optimumStartControlType == OptimumStartControlType::ControlZone) {
    2402            0 :                     ZoneNum = OptStartMgr.ZoneNum;
    2403            0 :                     if (!allocated(state.dataHeatBalFanSys->TempTstatAir) || !allocated(state.dataHeatBalFanSys->zoneTstatSetpts)) {
    2404            0 :                         TempDiff = 0.0;
    2405              :                     } else {
    2406            0 :                         if (!CycleOnFlag) {
    2407            0 :                             if (allocated(state.dataZoneCtrls->OccRoomTSetPointHeat) && allocated(state.dataZoneCtrls->OccRoomTSetPointCool)) {
    2408            0 :                                 TempDiffHi = state.dataHeatBalFanSys->TempTstatAir(ZoneNum) - state.dataZoneCtrls->OccRoomTSetPointCool(ZoneNum);
    2409            0 :                                 TempDiffLo = state.dataHeatBalFanSys->TempTstatAir(ZoneNum) - state.dataZoneCtrls->OccRoomTSetPointHeat(ZoneNum);
    2410              :                             } else {
    2411            0 :                                 TempDiffHi = 0.0;
    2412            0 :                                 TempDiffLo = 0.0;
    2413              :                             }
    2414              :                         }
    2415              :                     }
    2416              : 
    2417            0 :                     if (TempDiffHi < 0.0) {
    2418            0 :                         TempDiff = TempDiffLo;
    2419            0 :                         if (TempDiff < 0.0) { // Heating Mode
    2420            0 :                             TempDiff = std::abs(TempDiff);
    2421            0 :                             DeltaTime = TempDiff / OptStartMgr.ConstTGradHeat;
    2422            0 :                             if (DeltaTime > OptStartMgr.MaxOptStartTime) {
    2423            0 :                                 DeltaTime = OptStartMgr.MaxOptStartTime;
    2424              :                             }
    2425            0 :                             PreStartTime = FanStartTime - DeltaTime;
    2426            0 :                             if (PreStartTime < 0) PreStartTime = -0.1;
    2427            0 :                             PreStartTimeTmr = FanStartTimeTmr - DeltaTime;
    2428            0 :                             if (PreStartTimeTmr < 0) {
    2429            0 :                                 PreStartTimeTmr += 24.0;
    2430            0 :                                 OverNightStartFlag = true;
    2431              :                             } else {
    2432            0 :                                 OverNightStartFlag = false;
    2433              :                             }
    2434            0 :                             if (!OverNightStartFlag) {
    2435            0 :                                 if (FanStartTime == 0.0 || state.dataGlobal->CurrentTime > FanStartTime) {
    2436            0 :                                     CycleOnFlag = false;
    2437            0 :                                     OSReportVarFlag = true;
    2438            0 :                                 } else if (CycleOnFlag) {
    2439            0 :                                     availStatus = Status::CycleOn;
    2440            0 :                                     OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
    2441            0 :                                     if (state.dataGlobal->CurrentTime > FanStartTime) CycleOnFlag = false;
    2442            0 :                                 } else if (PreStartTime < state.dataGlobal->CurrentTime) {
    2443            0 :                                     availStatus = Status::CycleOn;
    2444            0 :                                     CycleOnFlag = true;
    2445            0 :                                     if (OSReportVarFlag) {
    2446            0 :                                         NumHoursBeforeOccupancy = DeltaTime;
    2447            0 :                                         OSReportVarFlag = false;
    2448              :                                     }
    2449            0 :                                     OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
    2450              :                                 } else {
    2451            0 :                                     availStatus = Status::NoAction;
    2452            0 :                                     CycleOnFlag = false;
    2453            0 :                                     OSReportVarFlag = true;
    2454              :                                 }
    2455              :                             } else {
    2456            0 :                                 if (FanStartTime == 0.0 ||
    2457            0 :                                     (state.dataGlobal->CurrentTime > FanStartTime && state.dataGlobal->CurrentTime <= PreStartTimeTmr)) {
    2458            0 :                                     availStatus = Status::NoAction;
    2459            0 :                                     CycleOnFlag = false;
    2460            0 :                                     OSReportVarFlag = true;
    2461            0 :                                 } else if (CycleOnFlag) {
    2462            0 :                                     availStatus = Status::CycleOn;
    2463            0 :                                     OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
    2464            0 :                                     if (state.dataGlobal->CurrentTime > FanStartTime && state.dataGlobal->CurrentTime < PreStartTimeTmr)
    2465            0 :                                         CycleOnFlag = false;
    2466            0 :                                 } else if (PreStartTime < state.dataGlobal->CurrentTime || PreStartTimeTmr < state.dataGlobal->CurrentTime) {
    2467            0 :                                     if (OSReportVarFlag) {
    2468            0 :                                         NumHoursBeforeOccupancy = DeltaTime;
    2469            0 :                                         OSReportVarFlag = false;
    2470              :                                     }
    2471            0 :                                     availStatus = Status::CycleOn;
    2472            0 :                                     CycleOnFlag = true;
    2473            0 :                                     OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
    2474              :                                 } else {
    2475            0 :                                     availStatus = Status::NoAction;
    2476            0 :                                     CycleOnFlag = false;
    2477            0 :                                     OSReportVarFlag = true;
    2478              :                                 }
    2479              :                             }
    2480              :                         } else {
    2481            0 :                             availStatus = Status::NoAction;
    2482            0 :                             CycleOnFlag = false;
    2483              :                         }
    2484            0 :                     } else if (state.dataZoneCtrls->OccRoomTSetPointCool(ZoneNum) < 50.0) { // Cooling Mode
    2485            0 :                         TempDiff = TempDiffHi;
    2486            0 :                         DeltaTime = TempDiff / OptStartMgr.ConstTGradCool;
    2487            0 :                         if (DeltaTime > OptStartMgr.MaxOptStartTime) {
    2488            0 :                             DeltaTime = OptStartMgr.MaxOptStartTime;
    2489              :                         }
    2490            0 :                         PreStartTime = FanStartTime - DeltaTime;
    2491            0 :                         if (PreStartTime < 0) PreStartTime = -0.1;
    2492            0 :                         PreStartTimeTmr = FanStartTimeTmr - DeltaTime;
    2493            0 :                         if (PreStartTimeTmr < 0) {
    2494            0 :                             PreStartTimeTmr += 24.0;
    2495            0 :                             OverNightStartFlag = true;
    2496              :                         } else {
    2497            0 :                             OverNightStartFlag = false;
    2498              :                         }
    2499            0 :                         if (!OverNightStartFlag) {
    2500            0 :                             if (FanStartTime == 0.0 || state.dataGlobal->CurrentTime > FanStartTime) {
    2501            0 :                                 availStatus = Status::NoAction;
    2502            0 :                                 CycleOnFlag = false;
    2503            0 :                                 OSReportVarFlag = true;
    2504            0 :                             } else if (CycleOnFlag) {
    2505            0 :                                 availStatus = Status::CycleOn;
    2506            0 :                                 OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
    2507            0 :                             } else if (PreStartTime < state.dataGlobal->CurrentTime) {
    2508            0 :                                 if (OSReportVarFlag) {
    2509            0 :                                     NumHoursBeforeOccupancy = DeltaTime;
    2510            0 :                                     OSReportVarFlag = false;
    2511              :                                 }
    2512            0 :                                 availStatus = Status::CycleOn;
    2513            0 :                                 CycleOnFlag = true;
    2514            0 :                                 OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
    2515              :                             } else {
    2516            0 :                                 availStatus = Status::NoAction;
    2517            0 :                                 CycleOnFlag = false;
    2518            0 :                                 OSReportVarFlag = true;
    2519              :                             }
    2520              :                         } else {
    2521            0 :                             if (FanStartTime == 0.0 ||
    2522            0 :                                 (state.dataGlobal->CurrentTime > FanStartTime && state.dataGlobal->CurrentTime <= PreStartTimeTmr)) {
    2523            0 :                                 availStatus = Status::NoAction;
    2524            0 :                                 CycleOnFlag = false;
    2525            0 :                                 OSReportVarFlag = true;
    2526            0 :                             } else if (CycleOnFlag) {
    2527            0 :                                 availStatus = Status::CycleOn;
    2528            0 :                                 OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
    2529            0 :                             } else if (PreStartTime < state.dataGlobal->CurrentTime || PreStartTimeTmr < state.dataGlobal->CurrentTime) {
    2530            0 :                                 if (OSReportVarFlag) {
    2531            0 :                                     NumHoursBeforeOccupancy = DeltaTime;
    2532            0 :                                     OSReportVarFlag = false;
    2533              :                                 }
    2534            0 :                                 availStatus = Status::CycleOn;
    2535            0 :                                 CycleOnFlag = true;
    2536            0 :                                 OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
    2537              :                             } else {
    2538            0 :                                 availStatus = Status::NoAction;
    2539            0 :                                 CycleOnFlag = false;
    2540            0 :                                 OSReportVarFlag = true;
    2541              :                             }
    2542              :                         }
    2543              :                     } else {
    2544            0 :                         availStatus = Status::NoAction;
    2545            0 :                         CycleOnFlag = false;
    2546              :                     }
    2547            0 :                 } else if (OptStartMgr.optimumStartControlType == OptimumStartControlType::MaximumOfZoneList) {
    2548              : 
    2549            0 :                     NumOfZonesInList = OptStartMgr.NumOfZones;
    2550            0 :                     if (!allocated(state.dataHeatBalFanSys->TempTstatAir) || !allocated(state.dataHeatBalFanSys->zoneTstatSetpts)) {
    2551            0 :                         TempDiff = 0.0;
    2552              :                     } else {
    2553            0 :                         if (!CycleOnFlag) {
    2554            0 :                             if (allocated(state.dataZoneCtrls->OccRoomTSetPointHeat) && allocated(state.dataZoneCtrls->OccRoomTSetPointCool)) {
    2555            0 :                                 TempDiffHi = 0.0;
    2556            0 :                                 TempDiffLo = 0.0;
    2557            0 :                                 for (ZoneNum = 1; ZoneNum <= NumOfZonesInList; ++ZoneNum) {
    2558            0 :                                     TempDiff = state.dataHeatBalFanSys->TempTstatAir(OptStartMgr.ZonePtrs(ZoneNum)) -
    2559            0 :                                                state.dataZoneCtrls->OccRoomTSetPointCool(OptStartMgr.ZonePtrs(ZoneNum));
    2560            0 :                                     TempDiffHi = max(TempDiffHi, TempDiff);
    2561            0 :                                     TempDiff = state.dataHeatBalFanSys->TempTstatAir(OptStartMgr.ZonePtrs(ZoneNum)) -
    2562            0 :                                                state.dataZoneCtrls->OccRoomTSetPointHeat(OptStartMgr.ZonePtrs(ZoneNum));
    2563            0 :                                     TempDiffLo = min(TempDiffLo, TempDiff);
    2564              :                                 }
    2565              :                             } else {
    2566            0 :                                 TempDiffHi = 0.0;
    2567            0 :                                 TempDiffLo = 0.0;
    2568              :                             }
    2569              :                         }
    2570              :                     }
    2571            0 :                     if ((TempDiffHi < 0.0 && TempDiffLo < 0.0) || (std::abs(TempDiffLo) > std::abs(TempDiffHi) && TempDiffLo < 0)) { // Heating Mode
    2572            0 :                         TempDiff = TempDiffLo;
    2573            0 :                         TempDiff = std::abs(TempDiff);
    2574            0 :                         DeltaTime = TempDiff / OptStartMgr.ConstTGradHeat;
    2575            0 :                         if (DeltaTime > OptStartMgr.MaxOptStartTime) {
    2576            0 :                             DeltaTime = OptStartMgr.MaxOptStartTime;
    2577              :                         }
    2578            0 :                         PreStartTime = FanStartTime - DeltaTime;
    2579            0 :                         if (PreStartTime < 0) PreStartTime = -0.1;
    2580            0 :                         PreStartTimeTmr = FanStartTimeTmr - DeltaTime;
    2581            0 :                         if (PreStartTimeTmr < 0) {
    2582            0 :                             PreStartTimeTmr += 24.0;
    2583            0 :                             OverNightStartFlag = true;
    2584              :                         } else {
    2585            0 :                             OverNightStartFlag = false;
    2586              :                         }
    2587            0 :                         if (!OverNightStartFlag) {
    2588            0 :                             if (FanStartTime == 0.0 || state.dataGlobal->CurrentTime > FanStartTime) {
    2589            0 :                                 availStatus = Status::NoAction;
    2590            0 :                                 CycleOnFlag = false;
    2591            0 :                                 OSReportVarFlag = true;
    2592            0 :                             } else if (CycleOnFlag) {
    2593            0 :                                 availStatus = Status::CycleOn;
    2594            0 :                                 OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
    2595            0 :                                 if (state.dataGlobal->CurrentTime > FanStartTime) CycleOnFlag = false;
    2596            0 :                             } else if (PreStartTime < state.dataGlobal->CurrentTime) {
    2597            0 :                                 if (OSReportVarFlag) {
    2598            0 :                                     NumHoursBeforeOccupancy = DeltaTime;
    2599            0 :                                     OSReportVarFlag = false;
    2600              :                                 }
    2601            0 :                                 availStatus = Status::CycleOn;
    2602            0 :                                 CycleOnFlag = true;
    2603            0 :                                 OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
    2604              :                             } else {
    2605            0 :                                 availStatus = Status::NoAction;
    2606            0 :                                 CycleOnFlag = false;
    2607            0 :                                 OSReportVarFlag = true;
    2608              :                             }
    2609              :                         } else {
    2610            0 :                             if (FanStartTime == 0.0 ||
    2611            0 :                                 (state.dataGlobal->CurrentTime > FanStartTime && state.dataGlobal->CurrentTime <= PreStartTimeTmr)) {
    2612            0 :                                 availStatus = Status::NoAction;
    2613            0 :                                 CycleOnFlag = false;
    2614            0 :                                 OSReportVarFlag = true;
    2615            0 :                             } else if (CycleOnFlag) {
    2616            0 :                                 availStatus = Status::CycleOn;
    2617            0 :                                 OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
    2618            0 :                                 if (state.dataGlobal->CurrentTime > FanStartTime && state.dataGlobal->CurrentTime < PreStartTimeTmr)
    2619            0 :                                     CycleOnFlag = false;
    2620            0 :                             } else if (PreStartTime < state.dataGlobal->CurrentTime || PreStartTimeTmr < state.dataGlobal->CurrentTime) {
    2621            0 :                                 if (OSReportVarFlag) {
    2622            0 :                                     NumHoursBeforeOccupancy = DeltaTime;
    2623            0 :                                     OSReportVarFlag = false;
    2624              :                                 }
    2625            0 :                                 availStatus = Status::CycleOn;
    2626            0 :                                 CycleOnFlag = true;
    2627            0 :                                 OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
    2628              :                             } else {
    2629            0 :                                 availStatus = Status::NoAction;
    2630            0 :                                 CycleOnFlag = false;
    2631            0 :                                 OSReportVarFlag = true;
    2632              :                             }
    2633              :                         }
    2634            0 :                     } else if (TempDiffHi <= 0.0 && TempDiffLo >= 0.0) { // not heating and not cooling
    2635            0 :                         availStatus = Status::NoAction;
    2636            0 :                         CycleOnFlag = false;
    2637            0 :                         TempDiffHi = 0.0;
    2638            0 :                         TempDiffLo = 0.0;
    2639            0 :                     } else if (TempDiffHi < 30.0) { // Cooling Mode
    2640            0 :                         TempDiff = TempDiffHi;
    2641            0 :                         DeltaTime = TempDiff / OptStartMgr.ConstTGradCool;
    2642            0 :                         if (DeltaTime > OptStartMgr.MaxOptStartTime) {
    2643            0 :                             DeltaTime = OptStartMgr.MaxOptStartTime;
    2644              :                         }
    2645            0 :                         PreStartTime = FanStartTime - DeltaTime;
    2646            0 :                         if (PreStartTime < 0) PreStartTime = -0.1;
    2647            0 :                         PreStartTimeTmr = FanStartTimeTmr - DeltaTime;
    2648            0 :                         if (PreStartTimeTmr < 0) {
    2649            0 :                             PreStartTimeTmr += 24.0;
    2650            0 :                             OverNightStartFlag = true;
    2651              :                         } else {
    2652            0 :                             OverNightStartFlag = false;
    2653              :                         }
    2654            0 :                         if (!OverNightStartFlag) {
    2655            0 :                             if (FanStartTime == 0.0 || state.dataGlobal->CurrentTime > FanStartTime) {
    2656            0 :                                 availStatus = Status::NoAction;
    2657            0 :                                 CycleOnFlag = false;
    2658            0 :                                 OSReportVarFlag = true;
    2659            0 :                             } else if (CycleOnFlag) {
    2660            0 :                                 availStatus = Status::CycleOn;
    2661            0 :                                 OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
    2662            0 :                             } else if (PreStartTime < state.dataGlobal->CurrentTime) {
    2663            0 :                                 if (OSReportVarFlag) {
    2664            0 :                                     NumHoursBeforeOccupancy = DeltaTime;
    2665            0 :                                     OSReportVarFlag = false;
    2666              :                                 }
    2667            0 :                                 availStatus = Status::CycleOn;
    2668            0 :                                 CycleOnFlag = true;
    2669            0 :                                 OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
    2670              :                             } else {
    2671            0 :                                 availStatus = Status::NoAction;
    2672            0 :                                 CycleOnFlag = false;
    2673            0 :                                 OSReportVarFlag = true;
    2674              :                             }
    2675              :                         } else {
    2676            0 :                             if (FanStartTime == 0.0 ||
    2677            0 :                                 (state.dataGlobal->CurrentTime > FanStartTime && state.dataGlobal->CurrentTime <= PreStartTimeTmr)) {
    2678            0 :                                 availStatus = Status::NoAction;
    2679            0 :                                 CycleOnFlag = false;
    2680            0 :                                 OSReportVarFlag = true;
    2681            0 :                             } else if (CycleOnFlag) {
    2682            0 :                                 availStatus = Status::CycleOn;
    2683            0 :                                 OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
    2684            0 :                             } else if (PreStartTime < state.dataGlobal->CurrentTime || PreStartTimeTmr < state.dataGlobal->CurrentTime) {
    2685            0 :                                 if (OSReportVarFlag) {
    2686            0 :                                     NumHoursBeforeOccupancy = DeltaTime;
    2687            0 :                                     OSReportVarFlag = false;
    2688              :                                 }
    2689            0 :                                 availStatus = Status::CycleOn;
    2690            0 :                                 CycleOnFlag = true;
    2691            0 :                                 OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
    2692              :                             } else {
    2693            0 :                                 availStatus = Status::NoAction;
    2694            0 :                                 CycleOnFlag = false;
    2695            0 :                                 OSReportVarFlag = true;
    2696              :                             }
    2697              :                         }
    2698              :                     } else {
    2699            0 :                         availStatus = Status::NoAction;
    2700            0 :                         CycleOnFlag = false;
    2701              :                     }
    2702              :                 } else {
    2703            0 :                     availStatus = Status::NoAction;
    2704              :                 }
    2705            0 :             } break;
    2706              : 
    2707           18 :             case ControlAlgorithm::AdaptiveTemperatureGradient: {
    2708              : 
    2709           18 :                 if (OptStartMgr.optimumStartControlType == OptimumStartControlType::ControlZone) {
    2710           12 :                     ZoneNum = OptStartMgr.ZoneNum;
    2711           12 :                     if (!allocated(state.dataHeatBalFanSys->TempTstatAir) || !allocated(state.dataHeatBalFanSys->zoneTstatSetpts)) {
    2712            0 :                         TempDiff = 0.0;
    2713              :                     } else {
    2714           12 :                         if (!CycleOnFlag) {
    2715            8 :                             if (allocated(state.dataZoneCtrls->OccRoomTSetPointHeat) && allocated(state.dataZoneCtrls->OccRoomTSetPointCool)) {
    2716            8 :                                 TempDiffHi = state.dataHeatBalFanSys->TempTstatAir(ZoneNum) - state.dataZoneCtrls->OccRoomTSetPointCool(ZoneNum);
    2717            8 :                                 TempDiffLo = state.dataHeatBalFanSys->TempTstatAir(ZoneNum) - state.dataZoneCtrls->OccRoomTSetPointHeat(ZoneNum);
    2718              :                             } else {
    2719            0 :                                 TempDiffHi = 0.0;
    2720            0 :                                 TempDiffLo = 0.0;
    2721              :                             }
    2722              :                         }
    2723              :                     }
    2724              :                     // Store adaptive temperature gradients for previous days and calculate the adaptive temp gradients
    2725              :                     //-----------------------------------------------------------------------------
    2726           12 :                     if (state.dataGlobal->WarmupFlag) {
    2727            2 :                         AdaTempGradHeat = OptStartMgr.InitTGradHeat;
    2728            2 :                         AdaTempGradCool = OptStartMgr.InitTGradCool;
    2729           10 :                     } else if (state.dataGlobal->DayOfSim == 1 && state.dataGlobal->BeginDayFlag) {
    2730            0 :                         state.dataAvail->OptStart_AdaTempGradTrdHeat = OptStartMgr.InitTGradHeat;
    2731            0 :                         AdaTempGradHeat = OptStartMgr.InitTGradHeat;
    2732            0 :                         state.dataAvail->OptStart_AdaTempGradTrdCool = OptStartMgr.InitTGradCool;
    2733            0 :                         AdaTempGradCool = OptStartMgr.InitTGradCool;
    2734              :                     } else {
    2735           10 :                         if (state.dataGlobal->BeginDayFlag && FirstTimeATGFlag) {
    2736            0 :                             FirstTimeATGFlag = false;
    2737            0 :                             AdaTempGradHeat += state.dataAvail->OptStart_AdaTempGradTrdHeat(NumPreDays) / NumPreDays -
    2738            0 :                                                state.dataAvail->OptStart_AdaTempGradTrdHeat(1) / NumPreDays;
    2739            0 :                             AdaTempGradCool += state.dataAvail->OptStart_AdaTempGradTrdCool(NumPreDays) / NumPreDays -
    2740            0 :                                                state.dataAvail->OptStart_AdaTempGradTrdCool(1) / NumPreDays;
    2741            0 :                             if (FanStartTime > 0) {
    2742            0 :                                 for (ATGCounter = 1; ATGCounter <= NumPreDays - 1; ++ATGCounter) {
    2743            0 :                                     state.dataAvail->OptStart_AdaTempGradTrdHeat(ATGCounter) =
    2744            0 :                                         state.dataAvail->OptStart_AdaTempGradTrdHeat(ATGCounter + 1);
    2745            0 :                                     state.dataAvail->OptStart_AdaTempGradTrdCool(ATGCounter) =
    2746            0 :                                         state.dataAvail->OptStart_AdaTempGradTrdCool(ATGCounter + 1);
    2747              :                                 }
    2748              :                             }
    2749              :                         }
    2750              :                     }
    2751              : 
    2752           12 :                     if (state.dataGlobal->CurrentTime >= 1.0) FirstTimeATGFlag = true;
    2753              :                     //------------------------------------------------------------------------------
    2754              : 
    2755           12 :                     if (TempDiffHi < 0.0) {
    2756           12 :                         TempDiff = TempDiffLo;
    2757           12 :                         if (TempDiff < 0.0) { // Heating Mode
    2758           12 :                             TempDiff = std::abs(TempDiff);
    2759           12 :                             DeltaTime = TempDiff / AdaTempGradHeat;
    2760           12 :                             if (DeltaTime > OptStartMgr.MaxOptStartTime) {
    2761            6 :                                 DeltaTime = OptStartMgr.MaxOptStartTime;
    2762              :                             }
    2763           12 :                             PreStartTime = FanStartTime - DeltaTime;
    2764           12 :                             if (PreStartTime < 0.0) PreStartTime = -0.1;
    2765           12 :                             PreStartTimeTmr = FanStartTimeTmr - DeltaTime;
    2766           12 :                             if (PreStartTimeTmr < 0.0) {
    2767            0 :                                 PreStartTimeTmr += 24.0;
    2768            0 :                                 OverNightStartFlag = true;
    2769              :                             } else {
    2770           12 :                                 OverNightStartFlag = false;
    2771              :                             }
    2772           12 :                             if (!OverNightStartFlag) {
    2773           12 :                                 if (FanStartTime == 0.0 || state.dataGlobal->CurrentTime > FanStartTime) {
    2774            3 :                                     availStatus = Status::NoAction;
    2775            3 :                                     CycleOnFlag = false;
    2776            3 :                                     OSReportVarFlag = true;
    2777            9 :                                 } else if (CycleOnFlag) {
    2778            2 :                                     availStatus = Status::CycleOn;
    2779            2 :                                     OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
    2780            2 :                                     if (state.dataGlobal->CurrentTime > FanStartTime) CycleOnFlag = false;
    2781              :                                     // Calculate the current day actual temperature gradient --------------------------
    2782            2 :                                     if (!state.dataGlobal->WarmupFlag) {
    2783            2 :                                         if (ATGUpdateFlag1) {
    2784            1 :                                             ATGUpdateTime1 = state.dataGlobal->CurrentTime;
    2785            1 :                                             ATGUpdateTemp1 = state.dataHeatBalFanSys->TempTstatAir(ZoneNum);
    2786            1 :                                             ATGUpdateFlag1 = false;
    2787              :                                         }
    2788            2 :                                         if (state.dataHeatBalFanSys->TempTstatAir(ZoneNum) >= state.dataZoneCtrls->OccRoomTSetPointHeat(ZoneNum) &&
    2789              :                                             ATGUpdateFlag2) {
    2790            0 :                                             ATGUpdateTime2 = state.dataGlobal->CurrentTime;
    2791            0 :                                             ATGUpdateTemp2 = state.dataHeatBalFanSys->TempTstatAir(ZoneNum);
    2792            0 :                                             ATGUpdateFlag2 = false;
    2793            0 :                                             if (std::abs(ATGUpdateTime2 - ATGUpdateTime1) > 1.e-10) {
    2794            0 :                                                 state.dataAvail->OptStart_AdaTempGradTrdHeat(NumPreDays) =
    2795            0 :                                                     (ATGUpdateTemp2 - ATGUpdateTemp1) / (ATGUpdateTime2 - ATGUpdateTime1);
    2796              :                                             } else {
    2797            0 :                                                 state.dataAvail->OptStart_AdaTempGradTrdHeat(NumPreDays) =
    2798            0 :                                                     (ATGUpdateTemp2 - ATGUpdateTemp1) * state.dataGlobal->TimeStepsInHour;
    2799              :                                             }
    2800              :                                         }
    2801              :                                     }
    2802              :                                     //---------------------------------------------------------------------------------
    2803            7 :                                 } else if (PreStartTime < state.dataGlobal->CurrentTime) {
    2804            2 :                                     if (OSReportVarFlag) {
    2805            2 :                                         NumHoursBeforeOccupancy = DeltaTime;
    2806            2 :                                         OSReportVarFlag = false;
    2807              :                                     }
    2808            2 :                                     availStatus = Status::CycleOn;
    2809            2 :                                     CycleOnFlag = true;
    2810            2 :                                     ATGUpdateFlag1 = true;
    2811            2 :                                     ATGUpdateFlag2 = true;
    2812            2 :                                     OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
    2813              :                                 } else {
    2814            5 :                                     availStatus = Status::NoAction;
    2815            5 :                                     CycleOnFlag = false;
    2816            5 :                                     OSReportVarFlag = true;
    2817              :                                 }
    2818              :                             } else {
    2819            0 :                                 if (FanStartTime == 0.0 ||
    2820            0 :                                     (state.dataGlobal->CurrentTime > FanStartTime && state.dataGlobal->CurrentTime <= PreStartTimeTmr)) {
    2821            0 :                                     availStatus = Status::NoAction;
    2822            0 :                                     CycleOnFlag = false;
    2823            0 :                                     OSReportVarFlag = true;
    2824            0 :                                 } else if (CycleOnFlag) {
    2825            0 :                                     availStatus = Status::CycleOn;
    2826            0 :                                     OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
    2827            0 :                                     if (state.dataGlobal->CurrentTime > FanStartTime && state.dataGlobal->CurrentTime < PreStartTimeTmr)
    2828            0 :                                         CycleOnFlag = false;
    2829              :                                     // Calculate the current day actual temperature gradient --------------------------
    2830            0 :                                     if (!state.dataGlobal->WarmupFlag) {
    2831            0 :                                         if (ATGUpdateFlag1) {
    2832            0 :                                             ATGUpdateTime1 = state.dataGlobal->CurrentTime;
    2833            0 :                                             ATGUpdateTemp1 = state.dataHeatBalFanSys->TempTstatAir(ZoneNum);
    2834            0 :                                             ATGUpdateFlag1 = false;
    2835              :                                         }
    2836            0 :                                         if (state.dataHeatBalFanSys->TempTstatAir(ZoneNum) >= state.dataZoneCtrls->OccRoomTSetPointHeat(ZoneNum) &&
    2837              :                                             ATGUpdateFlag2) {
    2838            0 :                                             ATGUpdateTime2 = state.dataGlobal->CurrentTime;
    2839            0 :                                             ATGUpdateTemp2 = state.dataHeatBalFanSys->TempTstatAir(ZoneNum);
    2840            0 :                                             ATGUpdateFlag2 = false;
    2841            0 :                                             if (std::abs(ATGUpdateTime2 - ATGUpdateTime1 + 24.0) > 1.e-10) {
    2842            0 :                                                 state.dataAvail->OptStart_AdaTempGradTrdHeat(NumPreDays) =
    2843            0 :                                                     (ATGUpdateTemp2 - ATGUpdateTemp1) / (ATGUpdateTime2 - ATGUpdateTime1 + 24.0);
    2844              :                                             } else {
    2845            0 :                                                 state.dataAvail->OptStart_AdaTempGradTrdHeat(NumPreDays) =
    2846            0 :                                                     (ATGUpdateTemp2 - ATGUpdateTemp1) * state.dataGlobal->TimeStepsInHour;
    2847              :                                             }
    2848              :                                         }
    2849              :                                     }
    2850              :                                     //---------------------------------------------------------------------------------
    2851            0 :                                 } else if (PreStartTime < state.dataGlobal->CurrentTime || PreStartTimeTmr < state.dataGlobal->CurrentTime) {
    2852            0 :                                     if (OSReportVarFlag) {
    2853            0 :                                         NumHoursBeforeOccupancy = DeltaTime;
    2854            0 :                                         OSReportVarFlag = false;
    2855              :                                     }
    2856            0 :                                     availStatus = Status::CycleOn;
    2857            0 :                                     CycleOnFlag = true;
    2858            0 :                                     ATGUpdateFlag1 = true;
    2859            0 :                                     ATGUpdateFlag2 = true;
    2860            0 :                                     OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
    2861              :                                 } else {
    2862            0 :                                     availStatus = Status::NoAction;
    2863            0 :                                     CycleOnFlag = false;
    2864            0 :                                     OSReportVarFlag = true;
    2865              :                                 }
    2866              :                             }
    2867              :                         } else {
    2868            0 :                             availStatus = Status::NoAction;
    2869            0 :                             CycleOnFlag = false;
    2870              :                         }
    2871            0 :                     } else if (state.dataZoneCtrls->OccRoomTSetPointCool(ZoneNum) < 50.0) { // Cooling Mode
    2872            0 :                         TempDiff = TempDiffHi;
    2873            0 :                         DeltaTime = TempDiff / AdaTempGradCool;
    2874            0 :                         if (DeltaTime > OptStartMgr.MaxOptStartTime) {
    2875            0 :                             DeltaTime = OptStartMgr.MaxOptStartTime;
    2876              :                         }
    2877            0 :                         PreStartTime = FanStartTime - DeltaTime;
    2878            0 :                         if (PreStartTime < 0.0) PreStartTime = -0.1;
    2879            0 :                         PreStartTimeTmr = FanStartTimeTmr - DeltaTime;
    2880            0 :                         if (PreStartTimeTmr < 0.0) {
    2881            0 :                             PreStartTimeTmr += 24.0;
    2882            0 :                             OverNightStartFlag = true;
    2883              :                         } else {
    2884            0 :                             OverNightStartFlag = false;
    2885              :                         }
    2886            0 :                         if (!OverNightStartFlag) {
    2887            0 :                             if (FanStartTime == 0.0 || state.dataGlobal->CurrentTime > FanStartTime) {
    2888            0 :                                 availStatus = Status::NoAction;
    2889            0 :                                 CycleOnFlag = false;
    2890            0 :                                 OSReportVarFlag = true;
    2891            0 :                             } else if (CycleOnFlag) {
    2892            0 :                                 if (OSReportVarFlag) {
    2893            0 :                                     NumHoursBeforeOccupancy = DeltaTime;
    2894            0 :                                     OSReportVarFlag = false;
    2895              :                                 }
    2896            0 :                                 availStatus = Status::CycleOn;
    2897            0 :                                 OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
    2898            0 :                                 if (!state.dataGlobal->WarmupFlag) {
    2899            0 :                                     if (ATGUpdateFlag1) {
    2900            0 :                                         ATGUpdateTime1 = state.dataGlobal->CurrentTime;
    2901            0 :                                         ATGUpdateTemp1 = state.dataHeatBalFanSys->TempTstatAir(ZoneNum);
    2902            0 :                                         ATGUpdateFlag1 = false;
    2903              :                                     }
    2904            0 :                                     if (state.dataHeatBalFanSys->TempTstatAir(ZoneNum) <= state.dataZoneCtrls->OccRoomTSetPointCool(ZoneNum) &&
    2905              :                                         ATGUpdateFlag2) {
    2906            0 :                                         ATGUpdateTime2 = state.dataGlobal->CurrentTime;
    2907            0 :                                         ATGUpdateTemp2 = state.dataHeatBalFanSys->TempTstatAir(ZoneNum);
    2908            0 :                                         ATGUpdateFlag2 = false;
    2909            0 :                                         if (std::abs(ATGUpdateTime2 - ATGUpdateTime1) > 1.e-10) {
    2910            0 :                                             state.dataAvail->OptStart_AdaTempGradTrdCool(NumPreDays) =
    2911            0 :                                                 (ATGUpdateTemp1 - ATGUpdateTemp2) / (ATGUpdateTime2 - ATGUpdateTime1);
    2912              :                                         } else {
    2913            0 :                                             state.dataAvail->OptStart_AdaTempGradTrdCool(NumPreDays) =
    2914            0 :                                                 (ATGUpdateTemp1 - ATGUpdateTemp2) * state.dataGlobal->TimeStepsInHour;
    2915              :                                         }
    2916              :                                     }
    2917              :                                 }
    2918            0 :                             } else if (PreStartTime < state.dataGlobal->CurrentTime) {
    2919            0 :                                 availStatus = Status::CycleOn;
    2920            0 :                                 CycleOnFlag = true;
    2921            0 :                                 ATGUpdateFlag1 = true;
    2922            0 :                                 ATGUpdateFlag2 = true;
    2923            0 :                                 OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
    2924              :                             } else {
    2925            0 :                                 availStatus = Status::NoAction;
    2926            0 :                                 CycleOnFlag = false;
    2927            0 :                                 OSReportVarFlag = true;
    2928              :                             }
    2929              :                         } else {
    2930            0 :                             if (FanStartTime == 0.0 ||
    2931            0 :                                 (state.dataGlobal->CurrentTime > FanStartTime && state.dataGlobal->CurrentTime <= PreStartTimeTmr)) {
    2932            0 :                                 availStatus = Status::NoAction;
    2933            0 :                                 CycleOnFlag = false;
    2934            0 :                                 OSReportVarFlag = true;
    2935            0 :                             } else if (CycleOnFlag) {
    2936            0 :                                 availStatus = Status::CycleOn;
    2937            0 :                                 if (!state.dataGlobal->WarmupFlag) {
    2938            0 :                                     if (ATGUpdateFlag1) {
    2939            0 :                                         ATGUpdateTime1 = state.dataGlobal->CurrentTime;
    2940            0 :                                         ATGUpdateTemp1 = state.dataHeatBalFanSys->TempTstatAir(ZoneNum);
    2941            0 :                                         ATGUpdateFlag1 = false;
    2942              :                                     }
    2943            0 :                                     if (state.dataHeatBalFanSys->TempTstatAir(ZoneNum) <= state.dataZoneCtrls->OccRoomTSetPointCool(ZoneNum) &&
    2944              :                                         ATGUpdateFlag2) {
    2945            0 :                                         ATGUpdateTime2 = state.dataGlobal->CurrentTime;
    2946            0 :                                         ATGUpdateTemp2 = state.dataHeatBalFanSys->TempTstatAir(ZoneNum);
    2947            0 :                                         ATGUpdateFlag2 = false;
    2948            0 :                                         if (std::abs(ATGUpdateTime2 - ATGUpdateTime1 + 24.0) > 1.e-10) {
    2949            0 :                                             state.dataAvail->OptStart_AdaTempGradTrdCool(NumPreDays) =
    2950            0 :                                                 (ATGUpdateTemp1 - ATGUpdateTemp2) / (ATGUpdateTime2 - ATGUpdateTime1 + 24.0);
    2951              :                                         } else {
    2952            0 :                                             state.dataAvail->OptStart_AdaTempGradTrdCool(NumPreDays) =
    2953            0 :                                                 (ATGUpdateTemp1 - ATGUpdateTemp2) * state.dataGlobal->TimeStepsInHour;
    2954              :                                         }
    2955              :                                     }
    2956              :                                 }
    2957            0 :                                 OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
    2958            0 :                             } else if (PreStartTime < state.dataGlobal->CurrentTime || PreStartTimeTmr < state.dataGlobal->CurrentTime) {
    2959            0 :                                 if (OSReportVarFlag) {
    2960            0 :                                     NumHoursBeforeOccupancy = DeltaTime;
    2961            0 :                                     OSReportVarFlag = false;
    2962              :                                 }
    2963            0 :                                 availStatus = Status::CycleOn;
    2964            0 :                                 CycleOnFlag = true;
    2965            0 :                                 ATGUpdateFlag1 = true;
    2966            0 :                                 ATGUpdateFlag2 = true;
    2967            0 :                                 OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
    2968              :                             } else {
    2969            0 :                                 availStatus = Status::NoAction;
    2970            0 :                                 CycleOnFlag = false;
    2971            0 :                                 OSReportVarFlag = true;
    2972              :                             }
    2973              :                         }
    2974              :                     } else { // Not heating nor cooling mode
    2975            0 :                         availStatus = Status::NoAction;
    2976            0 :                         CycleOnFlag = false;
    2977              :                     }
    2978            6 :                 } else if (OptStartMgr.optimumStartControlType == OptimumStartControlType::MaximumOfZoneList) {
    2979              : 
    2980            6 :                     NumOfZonesInList = OptStartMgr.NumOfZones;
    2981            6 :                     ATGWCZoneNumHi = OptStartMgr.ZonePtrs(1);
    2982            6 :                     ATGWCZoneNumLo = OptStartMgr.ZonePtrs(1);
    2983            6 :                     if (!allocated(state.dataHeatBalFanSys->TempTstatAir) || !allocated(state.dataHeatBalFanSys->zoneTstatSetpts)) {
    2984            0 :                         TempDiff = 0.0;
    2985              :                     } else {
    2986            6 :                         if (!CycleOnFlag) {
    2987            3 :                             if (allocated(state.dataZoneCtrls->OccRoomTSetPointHeat) && allocated(state.dataZoneCtrls->OccRoomTSetPointCool)) {
    2988            3 :                                 TempDiffHi = 0.0;
    2989            3 :                                 TempDiffLo = 0.0;
    2990            3 :                                 ATGWCZoneNumHi = OptStartMgr.ZonePtrs(1);
    2991            3 :                                 ATGWCZoneNumLo = OptStartMgr.ZonePtrs(1);
    2992           12 :                                 for (ZoneNum = 1; ZoneNum <= NumOfZonesInList; ++ZoneNum) {
    2993            9 :                                     TempDiff = state.dataHeatBalFanSys->TempTstatAir(OptStartMgr.ZonePtrs(ZoneNum)) -
    2994            9 :                                                state.dataZoneCtrls->OccRoomTSetPointCool(OptStartMgr.ZonePtrs(ZoneNum));
    2995            9 :                                     TempDiffHi = max(TempDiffHi, TempDiff);
    2996              :                                     // Store the worse case zone number for actual temperature gradient calculation
    2997            9 :                                     if (TempDiff == TempDiffHi) {
    2998            0 :                                         ATGWCZoneNumHi = OptStartMgr.ZonePtrs(ZoneNum);
    2999              :                                     }
    3000            9 :                                     TempDiff = state.dataHeatBalFanSys->TempTstatAir(OptStartMgr.ZonePtrs(ZoneNum)) -
    3001            9 :                                                state.dataZoneCtrls->OccRoomTSetPointHeat(OptStartMgr.ZonePtrs(ZoneNum));
    3002            9 :                                     TempDiffLo = min(TempDiffLo, TempDiff);
    3003            9 :                                     if (TempDiff == TempDiffLo) {
    3004            9 :                                         ATGWCZoneNumLo = OptStartMgr.ZonePtrs(ZoneNum);
    3005              :                                     }
    3006              :                                 }
    3007              :                             } else {
    3008            0 :                                 TempDiffHi = 0.0;
    3009            0 :                                 TempDiffLo = 0.0;
    3010              :                             }
    3011              :                         }
    3012              :                     }
    3013              :                     // Store adaptive temperature gradients for previous days and calculate the adaptive temp gradients
    3014              :                     //-----------------------------------------------------------------------------
    3015            6 :                     if (state.dataGlobal->WarmupFlag) {
    3016            1 :                         AdaTempGradHeat = OptStartMgr.InitTGradHeat;
    3017            1 :                         AdaTempGradCool = OptStartMgr.InitTGradCool;
    3018            5 :                     } else if (state.dataGlobal->DayOfSim == 1 && state.dataGlobal->BeginDayFlag) {
    3019            0 :                         state.dataAvail->OptStart_AdaTempGradTrdHeat = OptStartMgr.InitTGradHeat;
    3020            0 :                         AdaTempGradHeat = OptStartMgr.InitTGradHeat;
    3021            0 :                         state.dataAvail->OptStart_AdaTempGradTrdCool = OptStartMgr.InitTGradCool;
    3022            0 :                         AdaTempGradCool = OptStartMgr.InitTGradCool;
    3023              :                     } else {
    3024            5 :                         if (state.dataGlobal->BeginDayFlag && FirstTimeATGFlag) {
    3025            0 :                             FirstTimeATGFlag = false;
    3026            0 :                             AdaTempGradHeat += state.dataAvail->OptStart_AdaTempGradTrdHeat(NumPreDays) / NumPreDays -
    3027            0 :                                                state.dataAvail->OptStart_AdaTempGradTrdHeat(1) / NumPreDays;
    3028            0 :                             AdaTempGradCool += state.dataAvail->OptStart_AdaTempGradTrdCool(NumPreDays) / NumPreDays -
    3029            0 :                                                state.dataAvail->OptStart_AdaTempGradTrdCool(1) / NumPreDays;
    3030            0 :                             if (FanStartTime > 0) {
    3031            0 :                                 for (ATGCounter = 1; ATGCounter <= NumPreDays - 1; ++ATGCounter) {
    3032            0 :                                     state.dataAvail->OptStart_AdaTempGradTrdHeat(ATGCounter) =
    3033            0 :                                         state.dataAvail->OptStart_AdaTempGradTrdHeat(ATGCounter + 1);
    3034            0 :                                     state.dataAvail->OptStart_AdaTempGradTrdCool(ATGCounter) =
    3035            0 :                                         state.dataAvail->OptStart_AdaTempGradTrdCool(ATGCounter + 1);
    3036              :                                 }
    3037              :                             }
    3038              :                         }
    3039              :                     }
    3040              : 
    3041            6 :                     if (state.dataGlobal->CurrentTime >= 1.0) FirstTimeATGFlag = true;
    3042              :                     //------------------------------------------------------------------------------
    3043              : 
    3044            6 :                     if ((TempDiffHi < 0.0 && TempDiffLo < 0.0) || (std::abs(TempDiffLo) > std::abs(TempDiffHi) && TempDiffLo < 0.0)) { // Heating Mode
    3045            6 :                         TempDiff = TempDiffLo;
    3046            6 :                         TempDiff = std::abs(TempDiff);
    3047            6 :                         DeltaTime = TempDiff / AdaTempGradHeat;
    3048            6 :                         if (DeltaTime > OptStartMgr.MaxOptStartTime) {
    3049            0 :                             DeltaTime = OptStartMgr.MaxOptStartTime;
    3050              :                         }
    3051            6 :                         PreStartTime = FanStartTime - DeltaTime;
    3052            6 :                         if (PreStartTime < 0.0) PreStartTime = -0.1;
    3053            6 :                         PreStartTimeTmr = FanStartTimeTmr - DeltaTime;
    3054            6 :                         if (PreStartTimeTmr < 0.0) {
    3055            0 :                             PreStartTimeTmr += 24.0;
    3056            0 :                             OverNightStartFlag = true;
    3057              :                         } else {
    3058            6 :                             OverNightStartFlag = false;
    3059              :                         }
    3060            6 :                         if (!OverNightStartFlag) {
    3061            6 :                             if (FanStartTime == 0.0 || state.dataGlobal->CurrentTime > FanStartTime) {
    3062            1 :                                 OSReportVarFlag = true;
    3063            1 :                                 availStatus = Status::NoAction;
    3064            1 :                                 CycleOnFlag = false;
    3065            5 :                             } else if (CycleOnFlag) {
    3066            2 :                                 availStatus = Status::CycleOn;
    3067            2 :                                 OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
    3068            2 :                                 if (state.dataGlobal->CurrentTime > FanStartTime) CycleOnFlag = false;
    3069              :                                 // Calculate the current day actual temperature gradient --------------------------
    3070            2 :                                 if (!state.dataGlobal->WarmupFlag) {
    3071            2 :                                     if (ATGUpdateFlag1) {
    3072            1 :                                         ATGUpdateTime1 = state.dataGlobal->CurrentTime;
    3073            1 :                                         ATGUpdateTemp1 = state.dataHeatBalFanSys->TempTstatAir(ATGWCZoneNumLo);
    3074            1 :                                         ATGUpdateFlag1 = false;
    3075              :                                     }
    3076            2 :                                     if (state.dataHeatBalFanSys->TempTstatAir(ATGWCZoneNumLo) >=
    3077            2 :                                             state.dataZoneCtrls->OccRoomTSetPointHeat(ATGWCZoneNumLo) &&
    3078              :                                         ATGUpdateFlag2) {
    3079            0 :                                         ATGUpdateTime2 = state.dataGlobal->CurrentTime;
    3080            0 :                                         ATGUpdateTemp2 = state.dataHeatBalFanSys->TempTstatAir(ATGWCZoneNumLo);
    3081            0 :                                         ATGUpdateFlag2 = false;
    3082            0 :                                         if (std::abs(ATGUpdateTime2 - ATGUpdateTime1) > 1.e-10) {
    3083            0 :                                             state.dataAvail->OptStart_AdaTempGradTrdHeat(NumPreDays) =
    3084            0 :                                                 (ATGUpdateTemp2 - ATGUpdateTemp1) / (ATGUpdateTime2 - ATGUpdateTime1);
    3085              :                                         } else {
    3086            0 :                                             state.dataAvail->OptStart_AdaTempGradTrdHeat(NumPreDays) =
    3087            0 :                                                 (ATGUpdateTemp2 - ATGUpdateTemp1) * state.dataGlobal->TimeStepsInHour;
    3088              :                                         }
    3089              :                                     }
    3090              :                                 }
    3091              :                                 //---------------------------------------------------------------------------------
    3092            3 :                             } else if (PreStartTime < state.dataGlobal->CurrentTime) {
    3093            1 :                                 if (OSReportVarFlag) {
    3094            1 :                                     NumHoursBeforeOccupancy = DeltaTime;
    3095            1 :                                     OSReportVarFlag = false;
    3096              :                                 }
    3097            1 :                                 availStatus = Status::CycleOn;
    3098            1 :                                 CycleOnFlag = true;
    3099            1 :                                 ATGUpdateFlag1 = true;
    3100            1 :                                 ATGUpdateFlag2 = true;
    3101            1 :                                 OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
    3102              :                             } else {
    3103            2 :                                 availStatus = Status::NoAction;
    3104            2 :                                 CycleOnFlag = false;
    3105            2 :                                 OSReportVarFlag = true;
    3106              :                             }
    3107              :                         } else {
    3108            0 :                             if (FanStartTime == 0.0 ||
    3109            0 :                                 (state.dataGlobal->CurrentTime > FanStartTime && state.dataGlobal->CurrentTime <= PreStartTimeTmr)) {
    3110            0 :                                 availStatus = Status::NoAction;
    3111            0 :                                 CycleOnFlag = false;
    3112            0 :                                 OSReportVarFlag = true;
    3113            0 :                             } else if (CycleOnFlag) {
    3114            0 :                                 availStatus = Status::CycleOn;
    3115              :                                 // Calculate the current day actual temperature gradient --------------------------
    3116            0 :                                 if (!state.dataGlobal->WarmupFlag) {
    3117            0 :                                     if (ATGUpdateFlag1) {
    3118            0 :                                         ATGUpdateTime1 = state.dataGlobal->CurrentTime;
    3119            0 :                                         ATGUpdateTemp1 = state.dataHeatBalFanSys->TempTstatAir(ATGWCZoneNumLo);
    3120            0 :                                         ATGUpdateFlag1 = false;
    3121              :                                     }
    3122            0 :                                     if (state.dataHeatBalFanSys->TempTstatAir(ATGWCZoneNumLo) >=
    3123            0 :                                             state.dataZoneCtrls->OccRoomTSetPointHeat(ATGWCZoneNumLo) &&
    3124              :                                         ATGUpdateFlag2) {
    3125            0 :                                         ATGUpdateTime2 = state.dataGlobal->CurrentTime;
    3126            0 :                                         ATGUpdateTemp2 = state.dataHeatBalFanSys->TempTstatAir(ATGWCZoneNumLo);
    3127            0 :                                         ATGUpdateFlag2 = false;
    3128            0 :                                         if (std::abs(ATGUpdateTime2 - ATGUpdateTime1 + 24.0) > 1.e-10) {
    3129            0 :                                             state.dataAvail->OptStart_AdaTempGradTrdHeat(NumPreDays) =
    3130            0 :                                                 (ATGUpdateTemp2 - ATGUpdateTemp1) / (ATGUpdateTime2 - ATGUpdateTime1 + 24.0);
    3131              :                                         } else {
    3132            0 :                                             state.dataAvail->OptStart_AdaTempGradTrdHeat(NumPreDays) =
    3133            0 :                                                 (ATGUpdateTemp2 - ATGUpdateTemp1) * state.dataGlobal->TimeStepsInHour;
    3134              :                                         }
    3135              :                                     }
    3136              :                                 }
    3137              :                                 //---------------------------------------------------------------------------------
    3138            0 :                                 OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
    3139            0 :                                 if (state.dataGlobal->CurrentTime > FanStartTime && state.dataGlobal->CurrentTime < PreStartTimeTmr)
    3140            0 :                                     CycleOnFlag = false;
    3141            0 :                             } else if (PreStartTime < state.dataGlobal->CurrentTime || PreStartTimeTmr < state.dataGlobal->CurrentTime) {
    3142            0 :                                 if (OSReportVarFlag) {
    3143            0 :                                     NumHoursBeforeOccupancy = DeltaTime;
    3144            0 :                                     OSReportVarFlag = false;
    3145              :                                 }
    3146            0 :                                 availStatus = Status::CycleOn;
    3147            0 :                                 CycleOnFlag = true;
    3148            0 :                                 ATGUpdateFlag1 = true;
    3149            0 :                                 ATGUpdateFlag2 = true;
    3150            0 :                                 OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
    3151              :                             } else {
    3152            0 :                                 availStatus = Status::NoAction;
    3153            0 :                                 CycleOnFlag = false;
    3154            0 :                                 OSReportVarFlag = true;
    3155              :                             }
    3156              :                         }
    3157            0 :                     } else if (TempDiffHi <= 0.0 && TempDiffLo >= 0.0) { // not heating and not cooling
    3158            0 :                         availStatus = Status::NoAction;
    3159            0 :                         CycleOnFlag = false;
    3160            0 :                         TempDiffHi = 0.0;
    3161            0 :                         TempDiffLo = 0.0;
    3162            0 :                     } else if (TempDiffHi < 30.0) { // Cooling Mode
    3163            0 :                         TempDiff = TempDiffHi;
    3164            0 :                         DeltaTime = TempDiff / AdaTempGradCool;
    3165            0 :                         if (DeltaTime > OptStartMgr.MaxOptStartTime) {
    3166            0 :                             DeltaTime = OptStartMgr.MaxOptStartTime;
    3167              :                         }
    3168            0 :                         PreStartTime = FanStartTime - DeltaTime;
    3169            0 :                         if (PreStartTime < 0) PreStartTime = -0.1;
    3170            0 :                         PreStartTimeTmr = FanStartTimeTmr - DeltaTime;
    3171            0 :                         if (PreStartTimeTmr < 0) {
    3172            0 :                             PreStartTimeTmr += 24.0;
    3173            0 :                             OverNightStartFlag = true;
    3174              :                         } else {
    3175            0 :                             OverNightStartFlag = false;
    3176              :                         }
    3177            0 :                         if (!OverNightStartFlag) {
    3178            0 :                             if (FanStartTime == 0.0 || state.dataGlobal->CurrentTime > FanStartTime) {
    3179            0 :                                 availStatus = Status::NoAction;
    3180            0 :                                 CycleOnFlag = false;
    3181            0 :                                 OSReportVarFlag = true;
    3182            0 :                             } else if (CycleOnFlag) {
    3183            0 :                                 availStatus = Status::CycleOn;
    3184              :                                 // Calculate the current day actual temperature gradient --------------------------
    3185            0 :                                 if (!state.dataGlobal->WarmupFlag) {
    3186            0 :                                     if (ATGUpdateFlag1) {
    3187            0 :                                         ATGUpdateTime1 = state.dataGlobal->CurrentTime;
    3188            0 :                                         ATGUpdateTemp1 = state.dataHeatBalFanSys->TempTstatAir(ATGWCZoneNumHi);
    3189            0 :                                         ATGUpdateFlag1 = false;
    3190              :                                     }
    3191            0 :                                     if (state.dataHeatBalFanSys->TempTstatAir(ATGWCZoneNumHi) <=
    3192            0 :                                             state.dataZoneCtrls->OccRoomTSetPointCool(ATGWCZoneNumHi) &&
    3193              :                                         ATGUpdateFlag2) {
    3194            0 :                                         ATGUpdateTime2 = state.dataGlobal->CurrentTime;
    3195            0 :                                         ATGUpdateTemp2 = state.dataHeatBalFanSys->TempTstatAir(ATGWCZoneNumHi);
    3196            0 :                                         ATGUpdateFlag2 = false;
    3197            0 :                                         if (std::abs(ATGUpdateTime2 - ATGUpdateTime1) > 1.e-10) {
    3198            0 :                                             state.dataAvail->OptStart_AdaTempGradTrdCool(NumPreDays) =
    3199            0 :                                                 (ATGUpdateTemp1 - ATGUpdateTemp2) / (ATGUpdateTime2 - ATGUpdateTime1);
    3200              :                                         } else {
    3201            0 :                                             state.dataAvail->OptStart_AdaTempGradTrdCool(NumPreDays) =
    3202            0 :                                                 (ATGUpdateTemp1 - ATGUpdateTemp2) * state.dataGlobal->TimeStepsInHour;
    3203              :                                         }
    3204              :                                     }
    3205              :                                 }
    3206              :                                 //---------------------------------------------------------------------------------
    3207            0 :                                 OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
    3208            0 :                             } else if (PreStartTime < state.dataGlobal->CurrentTime) {
    3209            0 :                                 if (OSReportVarFlag) {
    3210            0 :                                     NumHoursBeforeOccupancy = DeltaTime;
    3211            0 :                                     OSReportVarFlag = false;
    3212              :                                 }
    3213            0 :                                 availStatus = Status::CycleOn;
    3214            0 :                                 CycleOnFlag = true;
    3215            0 :                                 ATGUpdateFlag1 = true;
    3216            0 :                                 ATGUpdateFlag2 = true;
    3217            0 :                                 OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
    3218              :                             } else {
    3219            0 :                                 availStatus = Status::NoAction;
    3220            0 :                                 CycleOnFlag = false;
    3221            0 :                                 OSReportVarFlag = true;
    3222              :                             }
    3223              :                         } else {
    3224            0 :                             if (FanStartTime == 0.0 ||
    3225            0 :                                 (state.dataGlobal->CurrentTime > FanStartTime && state.dataGlobal->CurrentTime <= PreStartTimeTmr)) {
    3226            0 :                                 availStatus = Status::NoAction;
    3227            0 :                                 CycleOnFlag = false;
    3228            0 :                                 OSReportVarFlag = true;
    3229            0 :                             } else if (CycleOnFlag) {
    3230            0 :                                 availStatus = Status::CycleOn;
    3231              :                                 // Calculate the current day actual temperature gradient --------------------------
    3232            0 :                                 if (!state.dataGlobal->WarmupFlag) {
    3233            0 :                                     if (ATGUpdateFlag1) {
    3234            0 :                                         ATGUpdateTime1 = state.dataGlobal->CurrentTime;
    3235            0 :                                         ATGUpdateTemp1 = state.dataHeatBalFanSys->TempTstatAir(ATGWCZoneNumHi);
    3236            0 :                                         ATGUpdateFlag1 = false;
    3237              :                                     }
    3238            0 :                                     if (state.dataHeatBalFanSys->TempTstatAir(ATGWCZoneNumHi) <=
    3239            0 :                                             state.dataZoneCtrls->OccRoomTSetPointCool(ATGWCZoneNumHi) &&
    3240              :                                         ATGUpdateFlag2) {
    3241            0 :                                         ATGUpdateTime2 = state.dataGlobal->CurrentTime;
    3242            0 :                                         ATGUpdateTemp2 = state.dataHeatBalFanSys->TempTstatAir(ATGWCZoneNumHi);
    3243            0 :                                         ATGUpdateFlag2 = false;
    3244            0 :                                         if (std::abs(ATGUpdateTime2 - ATGUpdateTime1 + 24.0) > 1.e-10) {
    3245            0 :                                             state.dataAvail->OptStart_AdaTempGradTrdCool(NumPreDays) =
    3246            0 :                                                 (ATGUpdateTemp1 - ATGUpdateTemp2) / (ATGUpdateTime2 - ATGUpdateTime1 + 24.0);
    3247              :                                         } else {
    3248            0 :                                             state.dataAvail->OptStart_AdaTempGradTrdCool(NumPreDays) =
    3249            0 :                                                 (ATGUpdateTemp1 - ATGUpdateTemp2) * state.dataGlobal->TimeStepsInHour;
    3250              :                                         }
    3251              :                                     }
    3252              :                                 }
    3253              :                                 //---------------------------------------------------------------------------------
    3254            0 :                                 OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
    3255            0 :                             } else if (PreStartTime < state.dataGlobal->CurrentTime || PreStartTimeTmr < state.dataGlobal->CurrentTime) {
    3256            0 :                                 if (OSReportVarFlag) {
    3257            0 :                                     NumHoursBeforeOccupancy = DeltaTime;
    3258            0 :                                     OSReportVarFlag = false;
    3259              :                                 }
    3260            0 :                                 availStatus = Status::CycleOn;
    3261            0 :                                 CycleOnFlag = true;
    3262            0 :                                 ATGUpdateFlag2 = true;
    3263            0 :                                 ATGUpdateFlag1 = true;
    3264            0 :                                 OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
    3265              :                             } else {
    3266            0 :                                 availStatus = Status::NoAction;
    3267            0 :                                 CycleOnFlag = false;
    3268            0 :                                 OSReportVarFlag = true;
    3269              :                             }
    3270              :                         }
    3271              :                     } else {
    3272            0 :                         availStatus = Status::NoAction;
    3273            0 :                         CycleOnFlag = false;
    3274              :                     }
    3275              :                 } else {
    3276            0 :                     availStatus = Status::NoAction;
    3277              :                 }
    3278           18 :             } break;
    3279            0 :             case ControlAlgorithm::AdaptiveASHRAE: {
    3280            0 :                 availStatus = Status::NoAction;
    3281            0 :             } break;
    3282            0 :             default:
    3283            0 :                 break;
    3284              :             }
    3285              :         }
    3286              : 
    3287           18 :         OptStartMgr.availStatus = availStatus;
    3288           18 :         OptStartMgr.NumHoursBeforeOccupancy = NumHoursBeforeOccupancy;
    3289           18 :         OptStartMgr.TempDiffLo = TempDiffLo;
    3290           18 :         OptStartMgr.TempDiffHi = TempDiffHi;
    3291           18 :         OptStartMgr.ATGWCZoneNumLo = ATGWCZoneNumLo;
    3292           18 :         OptStartMgr.ATGWCZoneNumHi = ATGWCZoneNumHi;
    3293           18 :         OptStartMgr.CycleOnFlag = CycleOnFlag;
    3294           18 :         OptStartMgr.ATGUpdateFlag1 = ATGUpdateFlag1;
    3295           18 :         OptStartMgr.ATGUpdateFlag2 = ATGUpdateFlag2;
    3296           18 :         OptStartMgr.FirstTimeATGFlag = FirstTimeATGFlag;
    3297           18 :         OptStartMgr.OverNightStartFlag = OverNightStartFlag;
    3298           18 :         OptStartMgr.OSReportVarFlag = OSReportVarFlag;
    3299           18 :         if (OptStartMgr.controlAlgorithm == ControlAlgorithm::AdaptiveTemperatureGradient) {
    3300           18 :             OptStartMgr.AdaTempGradTrdHeat = state.dataAvail->OptStart_AdaTempGradTrdHeat;
    3301           18 :             OptStartMgr.AdaTempGradTrdCool = state.dataAvail->OptStart_AdaTempGradTrdCool;
    3302           18 :             OptStartMgr.AdaTempGradHeat = AdaTempGradHeat;
    3303           18 :             OptStartMgr.AdaTempGradCool = AdaTempGradCool;
    3304           18 :             OptStartMgr.ATGUpdateTime1 = ATGUpdateTime1;
    3305           18 :             OptStartMgr.ATGUpdateTime2 = ATGUpdateTime2;
    3306           18 :             OptStartMgr.ATGUpdateTemp1 = ATGUpdateTemp1;
    3307           18 :             OptStartMgr.ATGUpdateTemp2 = ATGUpdateTemp2;
    3308              :         }
    3309              : 
    3310           18 :         return availStatus;
    3311           18 :     }
    3312              : 
    3313            7 :     void SysAvailManagerOptimumStart::SetOptStartFlag(EnergyPlusData &state, int const AirLoopNum)
    3314              :     {
    3315              :         // Set the OptStartFlag true for all zones on the air loop
    3316            7 :         auto const &thisAirToZoneNodeInfo = state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum);
    3317           23 :         for (int counter = 1; counter <= thisAirToZoneNodeInfo.NumZonesCooled; ++counter) {
    3318           16 :             state.dataAvail->OptStart(thisAirToZoneNodeInfo.CoolCtrlZoneNums(counter)).OptStartFlag = true;
    3319              :         }
    3320            7 :         for (int counter = 1; counter <= thisAirToZoneNodeInfo.NumZonesHeated; ++counter) {
    3321            0 :             state.dataAvail->OptStart(thisAirToZoneNodeInfo.HeatCtrlZoneNums(counter)).OptStartFlag = true;
    3322              :         }
    3323            7 :     }
    3324              : 
    3325            0 :     Status CalcNVentSysAvailMgr(EnergyPlusData &state,
    3326              :                                 int const SysAvailNum,     // number of the current scheduled system availability manager
    3327              :                                 int const PriAirSysNum,    // number of the primary air system affected by this Avail. Manager
    3328              :                                 bool const isZoneEquipType // Type of zone equipment component
    3329              :     )
    3330              :     {
    3331              : 
    3332              :         // SUBROUTINE INFORMATION:
    3333              :         //       AUTHOR         Fred Buhl
    3334              :         //       DATE WRITTEN   December 2004
    3335              :         //       MODIFIED       March 2011, Chandan Sharma - FSEC: Allowed night ventilation
    3336              :         //                             availability manager to work for zone component
    3337              :         //       RE-ENGINEERED  na
    3338              : 
    3339              :         // PURPOSE OF THIS SUBROUTINE:
    3340              :         // Set AvailStatus indicator for a primary air loop and ZoneHVAC component and sets a specified flow
    3341              :         // rate fraction for the air loop for use during night ventilation.
    3342              : 
    3343              :         // METHODOLOGY EMPLOYED:
    3344              :         // Looks at outside and indoor conditions to determine if night ventilation
    3345              :         // is beneficial. If it is and it is scheduled on the AvailStatus is set to cycle
    3346              :         // on and the loop flow rate fractionis set to the specified night ventilation
    3347              :         // value.
    3348              : 
    3349              :         using namespace DataAirLoop;
    3350              : 
    3351              :         int ZoneInSysNum;
    3352              :         bool TempCheck;   // TRUE if one zone's temperature is above the value of the vent temp sched
    3353              :         bool DelTCheck;   // TRUE if the control zone temperature - outside temperature > VentDelT
    3354              :         bool LowLimCheck; // TRUE if one zones's air temperature is below this value
    3355              :         Real64 VentTemp;  // value of the ventilation temperature schedule
    3356              : 
    3357              :         Status availStatus;
    3358              : 
    3359            0 :         TempCheck = false;
    3360            0 :         DelTCheck = false;
    3361            0 :         LowLimCheck = false;
    3362              :         // check if night venting allowed: not allowed if avail sched is off or fan sched is on
    3363              :         // CR 7913 changed to allow during warmup
    3364            0 :         auto &nightVentMgr = state.dataAvail->NightVentData(SysAvailNum);
    3365            0 :         if ((nightVentMgr.availSched->getCurrentVal() <= 0.0) || (nightVentMgr.fanSched->getCurrentVal() > 0.0)) {
    3366            0 :             availStatus = Status::NoAction;
    3367              :         } else {
    3368              : 
    3369            0 :             VentTemp = nightVentMgr.ventTempSched->getCurrentVal();
    3370            0 :             int ControlZoneNum = nightVentMgr.ZoneNum;
    3371              : 
    3372            0 :             if (isZoneEquipType) {
    3373              :                 // if the room temperature is greater than the vent temp sched value, set the vent temp check to TRUE
    3374            0 :                 if (state.dataHeatBalFanSys->TempTstatAir(ControlZoneNum) > VentTemp) {
    3375            0 :                     TempCheck = true;
    3376              :                 }
    3377              :                 // if the room temperature is less than the low limit set the low limit check to TRUE
    3378            0 :                 if (state.dataHeatBalFanSys->TempTstatAir(ControlZoneNum) < nightVentMgr.VentTempLowLim) {
    3379            0 :                     LowLimCheck = true;
    3380              :                 }
    3381              :             } else {
    3382            0 :                 for (ZoneInSysNum = 1; ZoneInSysNum <= state.dataAirLoop->AirToZoneNodeInfo(PriAirSysNum).NumZonesCooled;
    3383              :                      ++ZoneInSysNum) { // loop over zones in system
    3384              : 
    3385            0 :                     int ZoneNum = state.dataAirLoop->AirToZoneNodeInfo(PriAirSysNum).CoolCtrlZoneNums(ZoneInSysNum);
    3386              :                     // if the room temperature is greater than the vent temp sched value, set the vent temp check to TRUE
    3387            0 :                     if (state.dataHeatBalFanSys->TempTstatAir(ZoneNum) > VentTemp) {
    3388            0 :                         TempCheck = true;
    3389              :                     }
    3390              :                     // if the room temperature is less than the low limit set the low limit check to TRUE
    3391            0 :                     if (state.dataHeatBalFanSys->TempTstatAir(ZoneNum) < nightVentMgr.VentTempLowLim) {
    3392            0 :                         LowLimCheck = true;
    3393              :                     }
    3394              :                 }
    3395              :             }
    3396              :             // If the difference between the control zone temperature and the outside temperature is greater than
    3397              :             // the specified night venting delta T then set the delta T check to TRUE
    3398            0 :             if ((state.dataHeatBalFanSys->TempTstatAir(ControlZoneNum) - state.dataEnvrn->OutDryBulbTemp) > nightVentMgr.VentDelT) {
    3399            0 :                 DelTCheck = true;
    3400              :             }
    3401              :             // If the limit requirements are met turn on night ventilation
    3402            0 :             if (TempCheck && DelTCheck && !LowLimCheck) {
    3403            0 :                 availStatus = Status::CycleOn;
    3404              :             } else {
    3405            0 :                 availStatus = Status::NoAction;
    3406              :             }
    3407              :         }
    3408              : 
    3409            0 :         if (!isZoneEquipType) {
    3410            0 :             if (availStatus == Status::CycleOn) {
    3411            0 :                 state.dataAirLoop->AirLoopControlInfo(PriAirSysNum).LoopFlowRateSet = true;
    3412            0 :                 state.dataAirLoop->AirLoopControlInfo(PriAirSysNum).NightVent = true;
    3413            0 :                 state.dataAirLoop->AirLoopFlow(PriAirSysNum).ReqSupplyFrac = nightVentMgr.VentFlowFrac;
    3414              :             }
    3415              :         }
    3416              : 
    3417            0 :         nightVentMgr.availStatus = availStatus;
    3418            0 :         return availStatus;
    3419              :     }
    3420              : 
    3421            0 :     Status CalcDiffTSysAvailMgr(EnergyPlusData &state,
    3422              :                                 int const SysAvailNum,      // Number of the current scheduled system availability manager
    3423              :                                 Status const previousStatus // System status for the previous timestep
    3424              :     )
    3425              :     {
    3426              : 
    3427              :         // SUBROUTINE INFORMATION:
    3428              :         //       AUTHOR         Peter Graham Ellis
    3429              :         //       DATE WRITTEN   February 2004
    3430              :         //       MODIFIED       na
    3431              :         //       RE-ENGINEERED  na
    3432              : 
    3433              :         // PURPOSE OF THIS SUBROUTINE:
    3434              :         // Set AvailStatus indicator for a plant loop, primary air loop or ZoneHVAC component.
    3435              : 
    3436              :         // METHODOLOGY EMPLOYED:
    3437              : 
    3438              :         Status availStatus;
    3439              : 
    3440            0 :         auto &diffThermoMgr = state.dataAvail->DiffThermoData(SysAvailNum);
    3441            0 :         Real64 DeltaTemp = state.dataLoopNodes->Node(diffThermoMgr.HotNode).Temp - state.dataLoopNodes->Node(diffThermoMgr.ColdNode).Temp;
    3442              : 
    3443            0 :         if (DeltaTemp >= diffThermoMgr.TempDiffOn) {
    3444            0 :             availStatus = Status::CycleOn;
    3445            0 :         } else if (DeltaTemp <= diffThermoMgr.TempDiffOff) {
    3446            0 :             availStatus = Status::ForceOff;
    3447            0 :         } else if (previousStatus == Status::NoAction) {
    3448            0 :             availStatus = Status::ForceOff;
    3449              :         } else {
    3450            0 :             availStatus = previousStatus; // No change, but not "NoAction"; it should always be on or off.
    3451              :         }
    3452              : 
    3453            0 :         diffThermoMgr.availStatus = availStatus;
    3454            0 :         return availStatus;
    3455              :     }
    3456              : 
    3457            0 :     Status CalcHiTurnOffSysAvailMgr(EnergyPlusData &state,
    3458              :                                     int const SysAvailNum // Number of the current scheduled system availability manager
    3459              :     )
    3460              :     {
    3461              : 
    3462              :         // SUBROUTINE INFORMATION:
    3463              :         //       AUTHOR         Peter Graham Ellis
    3464              :         //       DATE WRITTEN   February 2004
    3465              :         //       MODIFIED       na
    3466              :         //       RE-ENGINEERED  na
    3467              : 
    3468              :         // PURPOSE OF THIS SUBROUTINE:
    3469              :         // Set AvailStatus indicator for a plant loop, primary air loop or ZoneHVAC component.
    3470              :         Status availStatus;
    3471            0 :         if (state.dataLoopNodes->Node(state.dataAvail->HiTurnOffData(SysAvailNum).Node).Temp >= state.dataAvail->HiTurnOffData(SysAvailNum).Temp) {
    3472            0 :             availStatus = Status::ForceOff;
    3473              :         } else {
    3474            0 :             availStatus = Status::NoAction;
    3475              :         }
    3476              : 
    3477            0 :         state.dataAvail->HiTurnOffData(SysAvailNum).availStatus = availStatus;
    3478            0 :         return availStatus;
    3479              :     }
    3480              : 
    3481            0 :     Status CalcHiTurnOnSysAvailMgr(EnergyPlusData &state,
    3482              :                                    int const SysAvailNum // Number of the current scheduled system availability manager
    3483              :     )
    3484              :     {
    3485              : 
    3486              :         // SUBROUTINE INFORMATION:
    3487              :         //       AUTHOR         Peter Graham Ellis
    3488              :         //       DATE WRITTEN   February 2004
    3489              :         //       MODIFIED       na
    3490              :         //       RE-ENGINEERED  na
    3491              : 
    3492              :         // PURPOSE OF THIS SUBROUTINE:
    3493              :         // Set AvailStatus indicator for a plant loop, primary air loop or ZoneHVAC component.
    3494              : 
    3495              :         Status availStatus;
    3496            0 :         if (state.dataLoopNodes->Node(state.dataAvail->HiTurnOnData(SysAvailNum).Node).Temp >= state.dataAvail->HiTurnOnData(SysAvailNum).Temp) {
    3497            0 :             availStatus = Status::CycleOn;
    3498              :         } else {
    3499            0 :             availStatus = Status::NoAction;
    3500              :         }
    3501              : 
    3502            0 :         state.dataAvail->HiTurnOnData(SysAvailNum).availStatus = availStatus;
    3503            0 :         return availStatus;
    3504              :     }
    3505              : 
    3506          178 :     Status CalcLoTurnOffSysAvailMgr(EnergyPlusData &state,
    3507              :                                     int const SysAvailNum // Number of the current scheduled system availability manager
    3508              :     )
    3509              :     {
    3510              : 
    3511              :         // SUBROUTINE INFORMATION:
    3512              :         //       AUTHOR         Peter Graham Ellis
    3513              :         //       DATE WRITTEN   February 2004
    3514              :         //       MODIFIED       na
    3515              :         //       RE-ENGINEERED  na
    3516              : 
    3517              :         // PURPOSE OF THIS SUBROUTINE:
    3518              :         // Set AvailStatus indicator for a plant loop, primary air loop or ZoneHVAC component.
    3519              : 
    3520              :         Status availStatus;
    3521              :         // If applicability schedule is off, then availability manager is inactive, return no action
    3522          178 :         auto &loTurnOffMgr = state.dataAvail->LoTurnOffData(SysAvailNum);
    3523          178 :         if (loTurnOffMgr.availSched != nullptr) {
    3524            0 :             if (loTurnOffMgr.availSched->getCurrentVal() <= 0.0) {
    3525            0 :                 availStatus = Status::NoAction;
    3526            0 :                 loTurnOffMgr.availStatus = availStatus;
    3527            0 :                 return availStatus;
    3528              :             }
    3529              :         }
    3530              : 
    3531              :         // Availability manager is active, check temperature limit
    3532          178 :         if (state.dataLoopNodes->Node(loTurnOffMgr.Node).Temp <= loTurnOffMgr.Temp) {
    3533          178 :             availStatus = Status::ForceOff;
    3534              :         } else {
    3535            0 :             availStatus = Status::NoAction;
    3536              :         }
    3537              : 
    3538          178 :         loTurnOffMgr.availStatus = availStatus;
    3539          178 :         return availStatus;
    3540              :     }
    3541              : 
    3542            0 :     Status CalcLoTurnOnSysAvailMgr(EnergyPlusData &state,
    3543              :                                    int const SysAvailNum // Number of the current scheduled system availability manager
    3544              :     )
    3545              :     {
    3546              : 
    3547              :         // SUBROUTINE INFORMATION:
    3548              :         //       AUTHOR         Peter Graham Ellis
    3549              :         //       DATE WRITTEN   February 2004
    3550              :         //       MODIFIED       na
    3551              :         //       RE-ENGINEERED  na
    3552              : 
    3553              :         // PURPOSE OF THIS SUBROUTINE:
    3554              :         // Set AvailStatus indicator for a plant loop, primary air loop or ZoneHVAC component.
    3555              :         Status availStatus;
    3556            0 :         if (state.dataLoopNodes->Node(state.dataAvail->LoTurnOnData(SysAvailNum).Node).Temp <= state.dataAvail->LoTurnOnData(SysAvailNum).Temp) {
    3557            0 :             availStatus = Status::CycleOn;
    3558              :         } else {
    3559            0 :             availStatus = Status::NoAction;
    3560              :         }
    3561              : 
    3562            0 :         state.dataAvail->LoTurnOnData(SysAvailNum).availStatus = availStatus;
    3563            0 :         return availStatus;
    3564              :     }
    3565              : 
    3566       297256 :     void ManageHybridVentilation(EnergyPlusData &state)
    3567              :     {
    3568              :         // SUBROUTINE INFORMATION:
    3569              :         //       AUTHOR         Lixing Gu
    3570              :         //       DATE WRITTEN   March 2007
    3571              :         //       MODIFIED       July 2012, Chandan Sharma - FSEC: Added zone sys avail managers
    3572              :         //       RE-ENGINEERED  na
    3573              : 
    3574              :         // PURPOSE OF THIS SUBROUTINE:
    3575              :         // Manage the simulation of the Hybrid Ventilation Control System Availability Managers
    3576              : 
    3577              :         using namespace DataLoopNode;
    3578              :         using namespace DataAirLoop;
    3579              : 
    3580              :         int PriAirSysNum; // Primary Air System index
    3581              : 
    3582       297256 :         if (state.dataAvail->GetHybridInputFlag) {
    3583          102 :             GetHybridVentilationInputs(state);
    3584          102 :             state.dataAvail->GetHybridInputFlag = false;
    3585              :         }
    3586              : 
    3587       297256 :         if (state.dataAvail->NumHybridVentSysAvailMgrs == 0) return;
    3588              : 
    3589            0 :         InitHybridVentSysAvailMgr(state);
    3590              : 
    3591            0 :         for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumHybridVentSysAvailMgrs; ++SysAvailNum) {
    3592            0 :             if (state.dataAvail->HybridVentData(SysAvailNum).HybridVentMgrConnectedToAirLoop) {
    3593            0 :                 for (PriAirSysNum = 1; PriAirSysNum <= state.dataHVACGlobal->NumPrimaryAirSys; ++PriAirSysNum) {
    3594            0 :                     if (state.dataAvail->HybridVentData(SysAvailNum).AirLoopNum == PriAirSysNum)
    3595            0 :                         CalcHybridVentSysAvailMgr(state, SysAvailNum, PriAirSysNum);
    3596              :                 }
    3597              :             } else {
    3598              :                 // Hybrid ventilation manager is applied to zone component
    3599            0 :                 if (state.dataAvail->HybridVentData(SysAvailNum).SimHybridVentSysAvailMgr) {
    3600            0 :                     CalcHybridVentSysAvailMgr(state, SysAvailNum);
    3601              :                 }
    3602              :             }
    3603              :         }
    3604              :     }
    3605              : 
    3606          103 :     void GetHybridVentilationInputs(EnergyPlusData &state)
    3607              :     {
    3608              : 
    3609              :         // SUBROUTINE INFORMATION:
    3610              :         //       AUTHOR         Lixing Gu
    3611              :         //       DATE WRITTEN   March 2007
    3612              :         //       MODIFIED       L. GU, 6/23/08, Added more controls, including simple airflow objects
    3613              :         //       RE-ENGINEERED  na
    3614              : 
    3615              :         // PURPOSE OF THIS SUBROUTINE:
    3616              :         // Obtains input data for Hybrid Ventilation Control System Availability Managers and stores it in
    3617              :         // appropriate data structures.
    3618              : 
    3619              :         // METHODOLOGY EMPLOYED:
    3620              :         // Uses InputProcessor "Get" routines to obtain data.
    3621              : 
    3622              :         // Using/Aliasing
    3623              :         using NodeInputManager::GetOnlySingleNode;
    3624              :         using NodeInputManager::MarkNode;
    3625              :         using namespace DataLoopNode;
    3626              : 
    3627              :         using Curve::CurveValue;
    3628              :         using Curve::GetCurveIndex;
    3629              :         using Curve::GetCurveMinMaxValues;
    3630              : 
    3631              :         // SUBROUTINE PARAMETER DEFINITIONS:
    3632              :         static constexpr std::string_view RoutineName("GetHybridVentilationInputs: "); // include trailing blank
    3633              :         static constexpr std::string_view routineName = "GetHybridVentilationInputs";
    3634              : 
    3635              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    3636              :         int NumAlphas;           // Number of Alphas for each GetObjectItem call
    3637              :         int NumNumbers;          // Number of Numbers for each GetObjectItem call
    3638              :         int IOStatus;            // Used in GetObjectItem
    3639          103 :         bool ErrorsFound(false); // Set to true if errors in input, fatal at end of routine
    3640              :         Real64 SchedMin;         // Minimum value specified in a schedule
    3641              :         Real64 SchedMax;         // Maximum value specified in a schedule
    3642              :         Real64 CurveMin;         // Minimum value specified in a curve
    3643              :         Real64 CurveMax;         // Maximum value specified in a curve
    3644              :         Real64 CurveVal;         // Curve value
    3645              : 
    3646          103 :         auto &ipsc = state.dataIPShortCut;
    3647              : 
    3648              :         // Get the number of occurrences of each type of System Availability Manager
    3649          103 :         std::string_view cCurrentModuleObject = managerTypeNames[(int)ManagerType::HybridVent];
    3650          103 :         state.dataAvail->NumHybridVentSysAvailMgrs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    3651              : 
    3652          103 :         if (state.dataAvail->NumHybridVentSysAvailMgrs == 0) return;
    3653              : 
    3654              :         // Allocate the data arrays
    3655            0 :         state.dataAvail->HybridVentData.allocate(state.dataAvail->NumHybridVentSysAvailMgrs);
    3656              : 
    3657            0 :         for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumHybridVentSysAvailMgrs; ++SysAvailNum) {
    3658              : 
    3659            0 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    3660              :                                                                      cCurrentModuleObject,
    3661              :                                                                      SysAvailNum,
    3662            0 :                                                                      ipsc->cAlphaArgs,
    3663              :                                                                      NumAlphas,
    3664            0 :                                                                      ipsc->rNumericArgs,
    3665              :                                                                      NumNumbers,
    3666              :                                                                      IOStatus,
    3667            0 :                                                                      ipsc->lNumericFieldBlanks,
    3668            0 :                                                                      ipsc->lAlphaFieldBlanks,
    3669            0 :                                                                      ipsc->cAlphaFieldNames,
    3670            0 :                                                                      ipsc->cNumericFieldNames);
    3671              : 
    3672            0 :             ErrorObjectHeader eoh{routineName, cCurrentModuleObject, ipsc->cAlphaArgs(1)};
    3673            0 :             auto &hybridVentMgr = state.dataAvail->HybridVentData(SysAvailNum);
    3674            0 :             hybridVentMgr.Name = ipsc->cAlphaArgs(1);
    3675            0 :             hybridVentMgr.type = ManagerType::HybridVent;
    3676              : 
    3677            0 :             hybridVentMgr.AirLoopName = ipsc->cAlphaArgs(2);
    3678              : 
    3679            0 :             if (ipsc->lAlphaFieldBlanks(2)) { // Hybrid ventilation manager applied to zone
    3680            0 :                 hybridVentMgr.HybridVentMgrConnectedToAirLoop = false;
    3681              :             }
    3682            0 :             hybridVentMgr.ControlZoneName = ipsc->cAlphaArgs(3);
    3683              :             // Check zone number
    3684            0 :             hybridVentMgr.ControlledZoneNum = Util::FindItemInList(ipsc->cAlphaArgs(3), state.dataHeatBal->Zone);
    3685            0 :             if (hybridVentMgr.ControlledZoneNum == 0) {
    3686            0 :                 ShowSevereItemNotFound(state, eoh, ipsc->cAlphaFieldNames(3), ipsc->cAlphaArgs(3));
    3687            0 :                 ErrorsFound = true;
    3688              :             }
    3689              : 
    3690            0 :             if (ipsc->lAlphaFieldBlanks(4)) {
    3691            0 :                 ShowSevereEmptyField(state, eoh, ipsc->cAlphaFieldNames(4));
    3692            0 :                 ErrorsFound = true;
    3693            0 :             } else if ((hybridVentMgr.controlModeSched = Sched::GetSchedule(state, ipsc->cAlphaArgs(4))) == nullptr) {
    3694            0 :                 ShowSevereItemNotFound(state, eoh, ipsc->cAlphaFieldNames(4), ipsc->cAlphaArgs(4));
    3695            0 :                 ErrorsFound = true;
    3696              :             }
    3697              : 
    3698              :             // Check schedule values
    3699            0 :             SchedMin = hybridVentMgr.controlModeSched->getMinVal(state);
    3700            0 :             SchedMax = hybridVentMgr.controlModeSched->getMaxVal(state);
    3701            0 :             if (SchedMin == 0 && SchedMax == 0) {
    3702            0 :                 ShowWarningCustomField(state,
    3703              :                                        eoh,
    3704            0 :                                        ipsc->cAlphaFieldNames(4),
    3705            0 :                                        ipsc->cAlphaArgs(4),
    3706              :                                        "Schedule specifies control mode 0 for all entries, "
    3707              :                                        "All zones using this schedule have no hybrid ventilation control.");
    3708              :             }
    3709            0 :             if (SchedMax > 7.0) {
    3710            0 :                 ShowSevereCustomField(state,
    3711              :                                       eoh,
    3712            0 :                                       ipsc->cAlphaFieldNames(4),
    3713            0 :                                       ipsc->cAlphaArgs(4),
    3714            0 :                                       format("Maximum value should be 7. However, the maximum value in the schedule is {:.1T}", SchedMax));
    3715            0 :                 ErrorsFound = true;
    3716              :             }
    3717              : 
    3718            0 :             if (SchedMin < 0.0) {
    3719            0 :                 ShowSevereCustomField(state,
    3720              :                                       eoh,
    3721            0 :                                       ipsc->cAlphaFieldNames(4),
    3722            0 :                                       ipsc->cAlphaArgs(4),
    3723            0 :                                       format("Minimum value should be 0. However, the minimum value in the schedule is {:.1T}", SchedMin));
    3724            0 :                 ErrorsFound = true;
    3725              :             }
    3726              : 
    3727            0 :             if (SchedMax == 7.0 && !state.dataContaminantBalance->Contaminant.CO2Simulation) {
    3728            0 :                 ShowSevereCustomField(state,
    3729              :                                       eoh,
    3730            0 :                                       ipsc->cAlphaFieldNames(4),
    3731            0 :                                       ipsc->cAlphaArgs(4),
    3732              :                                       "When the schedule value is 7, carbon dioxide (CO2) control is requested."
    3733              :                                       "However, CO2 simulation is not enabled. Please use ZoneAirContaminantBalance object to simulate CO2.");
    3734            0 :                 ErrorsFound = true;
    3735              :             }
    3736              : 
    3737              :             // Read use weather rain indicator
    3738            0 :             BooleanSwitch b = static_cast<BooleanSwitch>(getYesNoValue(ipsc->cAlphaArgs(5)));
    3739            0 :             if (b == BooleanSwitch::Invalid) {
    3740            0 :                 ShowSevereInvalidKey(state, eoh, ipsc->cAlphaFieldNames(5), ipsc->cAlphaArgs(5));
    3741            0 :                 ErrorsFound = true;
    3742              :             } else {
    3743            0 :                 hybridVentMgr.UseRainIndicator = static_cast<bool>(b);
    3744              :             }
    3745              : 
    3746              :             // Check max wind speed
    3747            0 :             if (NumNumbers > 0) {
    3748            0 :                 hybridVentMgr.MaxWindSpeed = ipsc->rNumericArgs(1);
    3749            0 :                 if (ipsc->rNumericArgs(1) > 40.0 || ipsc->rNumericArgs(1) < 0.0) {
    3750            0 :                     ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, cCurrentModuleObject, ipsc->cAlphaArgs(1)));
    3751            0 :                     ShowContinueError(state, format("{} is beyond the range.", ipsc->cNumericFieldNames(1)));
    3752            0 :                     ShowContinueError(state,
    3753            0 :                                       format("The input value is {:.0T}. The allowed value must be >= 0 and <= 40 m/s", ipsc->rNumericArgs(1)));
    3754            0 :                     ErrorsFound = true;
    3755              :                 }
    3756              :             }
    3757              : 
    3758              :             // Read Max and Min outdoor temperature
    3759            0 :             if (NumNumbers > 1) {
    3760            0 :                 hybridVentMgr.MinOutdoorTemp = ipsc->rNumericArgs(2);
    3761            0 :                 if (ipsc->rNumericArgs(2) > 100.0 || ipsc->rNumericArgs(2) < -100.0) {
    3762            0 :                     ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, cCurrentModuleObject, ipsc->cAlphaArgs(1)));
    3763            0 :                     ShowContinueError(state, format("{} is beyond the range.", ipsc->cNumericFieldNames(2)));
    3764            0 :                     ShowContinueError(
    3765            0 :                         state, format("The input value is {:.0T}. The allowed value must be between -100 C and +100 C", ipsc->rNumericArgs(2)));
    3766            0 :                     ErrorsFound = true;
    3767              :                 }
    3768              :             }
    3769            0 :             if (NumNumbers > 2) {
    3770            0 :                 hybridVentMgr.MaxOutdoorTemp = ipsc->rNumericArgs(3);
    3771            0 :                 if (ipsc->rNumericArgs(3) > 100.0 || ipsc->rNumericArgs(3) < -100.0) {
    3772            0 :                     ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, cCurrentModuleObject, ipsc->cAlphaArgs(1)));
    3773            0 :                     ShowContinueError(state, format("{} is beyond the range.", ipsc->cNumericFieldNames(3)));
    3774            0 :                     ShowContinueError(
    3775            0 :                         state, format("The input value is {:.0T}. The allowed value must be between -100 C and +100 C", ipsc->rNumericArgs(3)));
    3776            0 :                     ErrorsFound = true;
    3777              :                 }
    3778              :             }
    3779              :             // Ensure MaxTemp >= MinTemp
    3780            0 :             if (ipsc->rNumericArgs(2) >= ipsc->rNumericArgs(3)) {
    3781            0 :                 ShowSevereError(state,
    3782            0 :                                 format("{}{}=\"{}\" The {} must be less than the {}",
    3783              :                                        RoutineName,
    3784              :                                        cCurrentModuleObject,
    3785            0 :                                        ipsc->cAlphaArgs(1),
    3786            0 :                                        ipsc->cNumericFieldNames(2),
    3787            0 :                                        ipsc->cNumericFieldNames(3)));
    3788            0 :                 ShowContinueError(state,
    3789            0 :                                   format("The {} is {:.0T}. The {} is {:.0T}.",
    3790            0 :                                          ipsc->cNumericFieldNames(2),
    3791            0 :                                          ipsc->rNumericArgs(2),
    3792            0 :                                          ipsc->cNumericFieldNames(3),
    3793            0 :                                          ipsc->rNumericArgs(3)));
    3794            0 :                 ErrorsFound = true;
    3795              :             }
    3796              : 
    3797              :             // Read Max and Min outdoor enthalpy
    3798            0 :             if (NumNumbers > 3) {
    3799            0 :                 hybridVentMgr.MinOutdoorEnth = ipsc->rNumericArgs(4);
    3800            0 :                 if (ipsc->rNumericArgs(4) > 300000.0 || ipsc->rNumericArgs(4) < 0.0) {
    3801            0 :                     ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, cCurrentModuleObject, ipsc->cAlphaArgs(1)));
    3802            0 :                     ShowContinueError(state, format("{} is beyond the range.", ipsc->cNumericFieldNames(4)));
    3803            0 :                     ShowContinueError(
    3804            0 :                         state, format("The input value is {:.0T}. The allowed value must be between 0 and 300000 J/kg", ipsc->rNumericArgs(4)));
    3805            0 :                     ErrorsFound = true;
    3806              :                 }
    3807              :             }
    3808            0 :             if (NumNumbers > 4) {
    3809            0 :                 hybridVentMgr.MaxOutdoorEnth = ipsc->rNumericArgs(5);
    3810            0 :                 if (ipsc->rNumericArgs(5) > 300000.0 || ipsc->rNumericArgs(5) < 0.0) {
    3811            0 :                     ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, cCurrentModuleObject, ipsc->cAlphaArgs(1)));
    3812            0 :                     ShowContinueError(state, format("{} is beyond the range.", ipsc->cNumericFieldNames(5)));
    3813            0 :                     ShowContinueError(
    3814            0 :                         state, format("The input value is {:.0T}. The allowed value must be between 0 and 300000 J/kg", ipsc->rNumericArgs(5)));
    3815            0 :                     ErrorsFound = true;
    3816              :                 }
    3817              :             }
    3818              :             // Ensure MaxEnth >= MiniEnth
    3819            0 :             if (ipsc->rNumericArgs(4) >= ipsc->rNumericArgs(5)) {
    3820            0 :                 ShowSevereError(state,
    3821            0 :                                 format("{}{}=\"{}\" The {} must be less than the {}",
    3822              :                                        RoutineName,
    3823              :                                        cCurrentModuleObject,
    3824            0 :                                        ipsc->cAlphaArgs(1),
    3825            0 :                                        ipsc->cNumericFieldNames(4),
    3826            0 :                                        ipsc->cNumericFieldNames(5)));
    3827            0 :                 ShowContinueError(state,
    3828            0 :                                   format("The {} is {:.0T}. The {} is {:.0T}.",
    3829            0 :                                          ipsc->cNumericFieldNames(4),
    3830            0 :                                          ipsc->rNumericArgs(4),
    3831            0 :                                          ipsc->cNumericFieldNames(5),
    3832            0 :                                          ipsc->rNumericArgs(5)));
    3833            0 :                 ErrorsFound = true;
    3834              :             }
    3835              : 
    3836              :             // Read Max and Min outdoor dew point
    3837            0 :             if (NumNumbers > 5) {
    3838            0 :                 hybridVentMgr.MinOutdoorDewPoint = ipsc->rNumericArgs(6);
    3839            0 :                 if (ipsc->rNumericArgs(6) > 100.0 || ipsc->rNumericArgs(6) < -100.0) {
    3840            0 :                     ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, cCurrentModuleObject, ipsc->cAlphaArgs(1)));
    3841            0 :                     ShowContinueError(state, format("{} is beyond the range.", ipsc->cNumericFieldNames(6)));
    3842            0 :                     ShowContinueError(
    3843            0 :                         state, format("The input value is {:.0T}. The allowed value must be between -100 C and +100 C", ipsc->rNumericArgs(6)));
    3844            0 :                     ErrorsFound = true;
    3845              :                 }
    3846              :             }
    3847            0 :             if (NumNumbers > 6) {
    3848            0 :                 hybridVentMgr.MaxOutdoorDewPoint = ipsc->rNumericArgs(7);
    3849            0 :                 if (ipsc->rNumericArgs(7) > 100.0 || ipsc->rNumericArgs(7) < -100.0) {
    3850            0 :                     ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, cCurrentModuleObject, ipsc->cAlphaArgs(1)));
    3851            0 :                     ShowContinueError(state, format("{} is beyond the range.", ipsc->cNumericFieldNames(7)));
    3852            0 :                     ShowContinueError(
    3853            0 :                         state, format("The input value is {:.0T}. The allowed value must be between -100 C and +100 C", ipsc->rNumericArgs(7)));
    3854            0 :                     ErrorsFound = true;
    3855              :                 }
    3856              :             }
    3857              :             // Ensure MaxTemp >= MinTemp
    3858            0 :             if (ipsc->rNumericArgs(6) >= ipsc->rNumericArgs(7)) {
    3859            0 :                 ShowSevereError(state,
    3860            0 :                                 format("{}{}=\"{}\" The {} must be less than the {}",
    3861              :                                        RoutineName,
    3862              :                                        cCurrentModuleObject,
    3863            0 :                                        ipsc->cAlphaArgs(1),
    3864            0 :                                        ipsc->cNumericFieldNames(6),
    3865            0 :                                        ipsc->cNumericFieldNames(7)));
    3866            0 :                 ShowContinueError(state,
    3867            0 :                                   format("The {} is {:.0T}. The {} is {:.0T}.",
    3868            0 :                                          ipsc->cNumericFieldNames(6),
    3869            0 :                                          ipsc->rNumericArgs(6),
    3870            0 :                                          ipsc->cNumericFieldNames(7),
    3871            0 :                                          ipsc->rNumericArgs(7)));
    3872            0 :                 ErrorsFound = true;
    3873              :             }
    3874              : 
    3875            0 :             if (ipsc->lAlphaFieldBlanks(6)) {
    3876            0 :                 ShowSevereEmptyField(state, eoh, ipsc->cAlphaFieldNames(6));
    3877            0 :                 ErrorsFound = true;
    3878            0 :             } else if ((hybridVentMgr.minOASched = Sched::GetSchedule(state, ipsc->cAlphaArgs(6))) == nullptr) {
    3879            0 :                 ShowSevereItemNotFound(state, eoh, ipsc->cAlphaFieldNames(6), ipsc->cAlphaArgs(6));
    3880            0 :                 ErrorsFound = true;
    3881            0 :             } else if (!hybridVentMgr.minOASched->checkMinVal(state, Clusive::In, 0.0)) {
    3882            0 :                 Sched::ShowSevereBadMin(state, eoh, ipsc->cAlphaFieldNames(6), ipsc->cAlphaArgs(6), Clusive::In, 0.0);
    3883            0 :                 ErrorsFound = true;
    3884              :             }
    3885              : 
    3886            0 :             if (!ipsc->lAlphaFieldBlanks(7)) {
    3887            0 :                 hybridVentMgr.OpeningFactorFWS = GetCurveIndex(state, ipsc->cAlphaArgs(7));
    3888            0 :                 if (hybridVentMgr.OpeningFactorFWS <= 0) {
    3889            0 :                     ShowSevereItemNotFound(state, eoh, ipsc->cAlphaFieldNames(7), ipsc->cAlphaArgs(7));
    3890            0 :                     ErrorsFound = true;
    3891              :                 } else {
    3892            0 :                     GetCurveMinMaxValues(state, hybridVentMgr.OpeningFactorFWS, CurveMin, CurveMax);
    3893            0 :                     if (CurveMin < 0.0) {
    3894            0 :                         ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, cCurrentModuleObject, ipsc->cAlphaArgs(1)));
    3895            0 :                         ShowContinueError(state,
    3896            0 :                                           format("The minimum wind speed used in {}=\"{}should be greater than or equal to 0.0 (m/s)",
    3897            0 :                                                  ipsc->cAlphaFieldNames(7),
    3898            0 :                                                  ipsc->cAlphaArgs(7)));
    3899            0 :                         ShowContinueError(state, "Curve minimum value appears to be less than 0.");
    3900            0 :                         ErrorsFound = true;
    3901              :                     }
    3902            0 :                     CurveVal = CurveValue(state, hybridVentMgr.OpeningFactorFWS, CurveMin);
    3903            0 :                     if (CurveVal < 0.0) {
    3904            0 :                         ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, cCurrentModuleObject, ipsc->cAlphaArgs(1)));
    3905            0 :                         ShowContinueError(state,
    3906            0 :                                           format("The minimum value of {} must be greater than or equal to 0.0 at the minimum value of wind speed.",
    3907            0 :                                                  ipsc->cAlphaFieldNames(7)));
    3908            0 :                         ShowContinueError(state, format("{}=\"{}\".", ipsc->cAlphaFieldNames(7), ipsc->cAlphaArgs(7)));
    3909            0 :                         ShowContinueError(state, format("Curve output at the minimum wind speed = {:.3T}", CurveVal));
    3910            0 :                         ErrorsFound = true;
    3911              :                     }
    3912            0 :                     CurveVal = CurveValue(state, hybridVentMgr.OpeningFactorFWS, CurveMax);
    3913            0 :                     if (CurveVal > 1.0) {
    3914            0 :                         ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, cCurrentModuleObject, ipsc->cAlphaArgs(1)));
    3915            0 :                         ShowContinueError(state,
    3916            0 :                                           format("The maximum value of {} must be less than or equal to 1.0 at the maximum value of wind speed.",
    3917            0 :                                                  ipsc->cAlphaFieldNames(7)));
    3918            0 :                         ShowContinueError(state, format("{}=\"{}\".", ipsc->cAlphaFieldNames(7), ipsc->cAlphaArgs(7)));
    3919            0 :                         ShowContinueError(state, format("Curve output at the maximum wind speed = {:.3T}", CurveVal));
    3920            0 :                         ErrorsFound = true;
    3921              :                     }
    3922              :                     // Check curve type
    3923            0 :                     ErrorsFound |= Curve::CheckCurveDims(state,
    3924              :                                                          hybridVentMgr.OpeningFactorFWS, // Curve index
    3925              :                                                          {1},                            // Valid dimensions
    3926              :                                                          RoutineName,                    // Routine name
    3927              :                                                          cCurrentModuleObject,           // Object Type
    3928              :                                                          hybridVentMgr.Name,             // Object Name
    3929            0 :                                                          ipsc->cAlphaFieldNames(7));     // Field Name
    3930              :                 }
    3931              :             }
    3932              : 
    3933            0 :             if (ipsc->lAlphaFieldBlanks(8)) {
    3934            0 :             } else if ((hybridVentMgr.afnControlTypeSched = Sched::GetSchedule(state, ipsc->cAlphaArgs(8))) == nullptr) {
    3935            0 :                 ShowSevereItemNotFound(state, eoh, ipsc->cAlphaFieldNames(8), ipsc->cAlphaArgs(8));
    3936            0 :                 ErrorsFound = true;
    3937            0 :             } else if (!hybridVentMgr.afnControlTypeSched->checkMinMaxVals(state, Clusive::In, 0.0, Clusive::In, 1.0)) {
    3938            0 :                 Sched::ShowSevereBadMinMax(state, eoh, ipsc->cAlphaFieldNames(8), ipsc->cAlphaArgs(8), Clusive::In, 0.0, Clusive::In, 1.0);
    3939            0 :                 ErrorsFound = true;
    3940              :             } else {
    3941            0 :                 hybridVentMgr.Master = hybridVentMgr.ControlledZoneNum;
    3942            0 :                 hybridVentMgr.afnControlStatus = hybridVentMgr.afnControlTypeSched->getCurrentVal(); // this was ANControlTypeSchedPtr!!
    3943              :             }
    3944              : 
    3945            0 :             if (ipsc->lAlphaFieldBlanks(9)) {
    3946            0 :             } else if ((hybridVentMgr.simpleControlTypeSched = Sched::GetSchedule(state, ipsc->cAlphaArgs(9))) == nullptr) {
    3947            0 :                 ShowSevereItemNotFound(state, eoh, ipsc->cAlphaFieldNames(9), ipsc->cAlphaArgs(9));
    3948            0 :                 ErrorsFound = true;
    3949            0 :             } else if (hybridVentMgr.afnControlTypeSched != nullptr) {
    3950            0 :                 ShowWarningCustom(state,
    3951              :                                   eoh,
    3952            0 :                                   format("{} and {} cannot be used at the same time, {} is disabled.",
    3953            0 :                                          ipsc->cAlphaFieldNames(8),
    3954            0 :                                          ipsc->cAlphaFieldNames(9),
    3955            0 :                                          ipsc->cAlphaFieldNames(9)));
    3956            0 :                 hybridVentMgr.simpleControlTypeSched = nullptr;
    3957            0 :             } else if (!hybridVentMgr.simpleControlTypeSched->checkMinMaxVals(state, Clusive::In, 0.0, Clusive::In, 1.0)) {
    3958            0 :                 Sched::ShowSevereBadMinMax(state, eoh, ipsc->cAlphaFieldNames(9), ipsc->cAlphaArgs(9), Clusive::In, 0.0, Clusive::In, 1.0);
    3959            0 :                 ErrorsFound = true;
    3960              :             }
    3961              : 
    3962            0 :             if (hybridVentMgr.simpleControlTypeSched != nullptr) {
    3963              : 
    3964            0 :                 hybridVentMgr.VentilationName = ipsc->cAlphaArgs(10);
    3965            0 :                 if (state.dataHeatBal->TotVentilation > 0) {
    3966              : 
    3967            0 :                     hybridVentMgr.VentilationPtr = Util::FindItemInList(ipsc->cAlphaArgs(10), state.dataHeatBal->Ventilation);
    3968            0 :                     hybridVentMgr.Master = hybridVentMgr.VentilationPtr;
    3969              : 
    3970            0 :                     if (hybridVentMgr.VentilationPtr <= 0) {
    3971            0 :                         if (int(hybridVentMgr.simpleControlTypeSched->getMaxVal(state)) == 1) {
    3972            0 :                             ShowSevereItemNotFound(state, eoh, ipsc->cAlphaFieldNames(10), ipsc->cAlphaArgs(10));
    3973            0 :                             ErrorsFound = true;
    3974              :                         }
    3975              : 
    3976            0 :                         if (state.afn->simulation_control.type == AirflowNetwork::ControlType::NoMultizoneOrDistribution) {
    3977            0 :                             ShowWarningError(state, format("{}{}=\"{}\"", RoutineName, cCurrentModuleObject, hybridVentMgr.Name));
    3978            0 :                             ShowContinueError(state, "The Airflow Network model is not available for Hybrid Ventilation Control.");
    3979            0 :                         } else if (state.afn->simulation_control.type ==
    3980              :                                    AirflowNetwork::ControlType::MultizoneWithDistributionOnlyDuringFanOperation) {
    3981            0 :                             ShowWarningError(state, format("{}{}=\"{}\"", RoutineName, cCurrentModuleObject, hybridVentMgr.Name));
    3982            0 :                             ShowContinueError(state, "Please check the AirflowNetwork Control field in the AirflowNetwork:SimulationControl object.");
    3983            0 :                             ShowContinueError(state, "The suggested choices are MultizoneWithDistribution or MultizoneWithoutDistribution.");
    3984              :                         }
    3985              : 
    3986              :                     } else { // hybridVentMgr.VentilationPtr > 0
    3987            0 :                         if (hybridVentMgr.ControlledZoneNum != state.dataHeatBal->Ventilation(hybridVentMgr.VentilationPtr).ZonePtr) {
    3988            0 :                             ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, cCurrentModuleObject, ipsc->cAlphaArgs(1)));
    3989            0 :                             ShowContinueError(
    3990              :                                 state,
    3991            0 :                                 format("The Zone name specified in the Ventilation object {}",
    3992            0 :                                        state.dataHeatBal->Zone(state.dataHeatBal->Ventilation(hybridVentMgr.VentilationPtr).ZonePtr).Name));
    3993            0 :                             ShowContinueError(state, format("is not equal to the {}=\"{}\".", ipsc->cAlphaFieldNames(3), ipsc->cAlphaArgs(3)));
    3994            0 :                             ErrorsFound = true;
    3995              :                         }
    3996              : 
    3997            0 :                         if (state.afn->simulation_control.type != AirflowNetwork::ControlType::NoMultizoneOrDistribution) {
    3998            0 :                             ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, cCurrentModuleObject, hybridVentMgr.Name));
    3999            0 :                             ShowContinueError(state, "The simple airflow objects are used for natural ventilation calculation.");
    4000            0 :                             ShowContinueError(
    4001              :                                 state,
    4002              :                                 "The Airflow Network model is not allowed to perform. Please set the control type = NoMultizoneOrDistribution");
    4003            0 :                             ErrorsFound = true;
    4004              :                         }
    4005              :                     }
    4006              :                 }
    4007              :             }
    4008              : 
    4009              :             // Disallow combination of simple control and OA control mode
    4010            0 :             if (hybridVentMgr.simpleControlTypeSched != nullptr && hybridVentMgr.controlModeSched->getMaxVal(state) == 4.0) {
    4011            0 :                 ShowSevereCustom(state,
    4012              :                                  eoh,
    4013            0 :                                  format("The outdoor ventilation air control type defined in {} cannot work together with {}",
    4014            0 :                                         ipsc->cAlphaArgs(4),
    4015            0 :                                         ipsc->cAlphaFieldNames(9)));
    4016            0 :                 ErrorsFound = true;
    4017              :             }
    4018              : 
    4019            0 :             if (!ipsc->lNumericFieldBlanks(8)) {
    4020            0 :                 hybridVentMgr.MinOperTime = ipsc->rNumericArgs(8);
    4021              :             }
    4022            0 :             if (!ipsc->lNumericFieldBlanks(9)) {
    4023            0 :                 hybridVentMgr.MinVentTime = ipsc->rNumericArgs(9);
    4024              :             }
    4025              : 
    4026              :         } // SysAvailNum
    4027              : 
    4028            0 :         if (state.dataAvail->NumHybridVentSysAvailMgrs > 1) {
    4029            0 :             for (int SysAvailNum = 2; SysAvailNum <= state.dataAvail->NumHybridVentSysAvailMgrs; ++SysAvailNum) {
    4030            0 :                 if (state.dataAvail->HybridVentData(SysAvailNum - 1).afnControlTypeSched != nullptr) {
    4031            0 :                     if (state.dataAvail->HybridVentData(SysAvailNum).simpleControlTypeSched != nullptr) {
    4032            0 :                         ShowSevereError(state,
    4033            0 :                                         format("The AirflowNetwork model is used for natural ventilation calculation in {}=\"{}\"",
    4034              :                                                cCurrentModuleObject,
    4035            0 :                                                state.dataAvail->HybridVentData(SysAvailNum - 1).Name));
    4036            0 :                         ShowContinueError(state,
    4037            0 :                                           format("The simple airflow objects are used for natural ventilation calculation in {}=\"{}\"",
    4038              :                                                  cCurrentModuleObject,
    4039            0 :                                                  state.dataAvail->HybridVentData(SysAvailNum).Name));
    4040            0 :                         ShowContinueError(state, "The hybrid ventilation control requires the same models to calculate natural ventilation");
    4041            0 :                         ErrorsFound = true;
    4042              :                     }
    4043              :                 }
    4044            0 :                 if (state.dataAvail->HybridVentData(SysAvailNum - 1).simpleControlTypeSched != nullptr) {
    4045            0 :                     if (state.dataAvail->HybridVentData(SysAvailNum).afnControlTypeSched != nullptr) {
    4046            0 :                         ShowSevereError(state,
    4047            0 :                                         format("The Airflow Network model is used for natural ventilation calculation in {}=\"{}\"",
    4048              :                                                cCurrentModuleObject,
    4049            0 :                                                state.dataAvail->HybridVentData(SysAvailNum).Name));
    4050            0 :                         ShowContinueError(state,
    4051            0 :                                           format("The simple airflow objects are used for natural ventilation calculation in {}=\"{}\"",
    4052              :                                                  cCurrentModuleObject,
    4053            0 :                                                  state.dataAvail->HybridVentData(SysAvailNum - 1).Name));
    4054            0 :                         ShowContinueError(state, "The hybrid ventilation control requires the same models to calculate natural ventilation");
    4055            0 :                         ErrorsFound = true;
    4056              :                     }
    4057              :                 }
    4058              :             } // SysAvailNum
    4059              :         }
    4060              : 
    4061            0 :         if (ErrorsFound) {
    4062            0 :             ShowFatalError(state, format("{} Errors found in input.  Preceding condition(s) cause termination.", RoutineName));
    4063              :         }
    4064              : 
    4065              :         // Set up output variables
    4066            0 :         for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumHybridVentSysAvailMgrs; ++SysAvailNum) {
    4067            0 :             if (state.dataAvail->HybridVentData(SysAvailNum).HybridVentMgrConnectedToAirLoop) {
    4068            0 :                 SetupOutputVariable(state,
    4069              :                                     "Availability Manager Hybrid Ventilation Control Status",
    4070              :                                     Constant::Units::None,
    4071            0 :                                     (int &)state.dataAvail->HybridVentData(SysAvailNum).ctrlStatus,
    4072              :                                     OutputProcessor::TimeStepType::System,
    4073              :                                     OutputProcessor::StoreType::Average,
    4074            0 :                                     state.dataAvail->HybridVentData(SysAvailNum).AirLoopName);
    4075            0 :                 SetupOutputVariable(state,
    4076              :                                     "Availability Manager Hybrid Ventilation Control Mode",
    4077              :                                     Constant::Units::None,
    4078            0 :                                     (int &)state.dataAvail->HybridVentData(SysAvailNum).ctrlType,
    4079              :                                     OutputProcessor::TimeStepType::System,
    4080              :                                     OutputProcessor::StoreType::Average,
    4081            0 :                                     state.dataAvail->HybridVentData(SysAvailNum).AirLoopName);
    4082              :             } else {
    4083            0 :                 SetupOutputVariable(state,
    4084              :                                     "Availability Manager Hybrid Ventilation Control Status",
    4085              :                                     Constant::Units::None,
    4086            0 :                                     (int &)state.dataAvail->HybridVentData(SysAvailNum).ctrlStatus,
    4087              :                                     OutputProcessor::TimeStepType::System,
    4088              :                                     OutputProcessor::StoreType::Average,
    4089            0 :                                     state.dataAvail->HybridVentData(SysAvailNum).ControlZoneName);
    4090            0 :                 SetupOutputVariable(state,
    4091              :                                     "Availability Manager Hybrid Ventilation Control Mode",
    4092              :                                     Constant::Units::None,
    4093            0 :                                     (int &)state.dataAvail->HybridVentData(SysAvailNum).ctrlType,
    4094              :                                     OutputProcessor::TimeStepType::System,
    4095              :                                     OutputProcessor::StoreType::Average,
    4096            0 :                                     state.dataAvail->HybridVentData(SysAvailNum).ControlZoneName);
    4097              :             }
    4098              : 
    4099            0 :             if (state.dataAvail->HybridVentData(SysAvailNum).MinOperTime > 0) {
    4100            0 :                 SetupOutputVariable(state,
    4101              :                                     "Hybrid Ventilation Control HVAC System Operation Elapsed Time",
    4102              :                                     Constant::Units::min,
    4103            0 :                                     state.dataAvail->HybridVentData(SysAvailNum).TimeOperDuration,
    4104              :                                     OutputProcessor::TimeStepType::System,
    4105              :                                     OutputProcessor::StoreType::Average,
    4106            0 :                                     state.dataAvail->HybridVentData(SysAvailNum).Name);
    4107              :             }
    4108              : 
    4109            0 :             if (state.dataAvail->HybridVentData(SysAvailNum).MinVentTime > 0) {
    4110            0 :                 SetupOutputVariable(state,
    4111              :                                     "Hybrid Ventilation Control Natural Ventilation Elapsed Time",
    4112              :                                     Constant::Units::min,
    4113            0 :                                     state.dataAvail->HybridVentData(SysAvailNum).TimeVentDuration,
    4114              :                                     OutputProcessor::TimeStepType::System,
    4115              :                                     OutputProcessor::StoreType::Average,
    4116            0 :                                     state.dataAvail->HybridVentData(SysAvailNum).Name);
    4117              :             }
    4118              : 
    4119            0 :             if (state.dataAvail->HybridVentData(SysAvailNum).controlModeSched->hasVal(state, (int)VentCtrlType::OperT80) ||
    4120            0 :                 state.dataAvail->HybridVentData(SysAvailNum).controlModeSched->hasVal(state, (int)VentCtrlType::OperT90)) {
    4121            0 :                 SetupOutputVariable(state,
    4122              :                                     "Hybrid Ventilation Operative Temperature",
    4123              :                                     Constant::Units::C,
    4124            0 :                                     state.dataAvail->HybridVentData(SysAvailNum).OperativeTemp,
    4125              :                                     OutputProcessor::TimeStepType::System,
    4126              :                                     OutputProcessor::StoreType::Average,
    4127            0 :                                     state.dataAvail->HybridVentData(SysAvailNum).Name);
    4128            0 :                 SetupOutputVariable(state,
    4129              :                                     "Hybrid Ventilation Lower Limit Operative Temperature",
    4130              :                                     Constant::Units::C,
    4131            0 :                                     state.dataAvail->HybridVentData(SysAvailNum).minAdaTem,
    4132              :                                     OutputProcessor::TimeStepType::System,
    4133              :                                     OutputProcessor::StoreType::Average,
    4134            0 :                                     state.dataAvail->HybridVentData(SysAvailNum).Name);
    4135            0 :                 SetupOutputVariable(state,
    4136              :                                     "Hybrid Ventilation Upper Limit Operative Temperature",
    4137              :                                     Constant::Units::C,
    4138            0 :                                     state.dataAvail->HybridVentData(SysAvailNum).maxAdaTem,
    4139              :                                     OutputProcessor::TimeStepType::System,
    4140              :                                     OutputProcessor::StoreType::Average,
    4141            0 :                                     state.dataAvail->HybridVentData(SysAvailNum).Name);
    4142              :             }
    4143              : 
    4144            0 :             if (state.dataAvail->HybridVentData(SysAvailNum).controlModeSched->hasVal(state, (int)VentCtrlType::CO2)) {
    4145            0 :                 SetupOutputVariable(state,
    4146              :                                     "Hybrid Ventilation CO2 Concentration",
    4147              :                                     Constant::Units::ppm,
    4148            0 :                                     state.dataAvail->HybridVentData(SysAvailNum).CO2,
    4149              :                                     OutputProcessor::TimeStepType::System,
    4150              :                                     OutputProcessor::StoreType::Average,
    4151            0 :                                     state.dataAvail->HybridVentData(SysAvailNum).Name);
    4152              :             }
    4153              :         }
    4154              :     }
    4155              : 
    4156            0 :     void InitHybridVentSysAvailMgr(EnergyPlusData &state)
    4157              :     {
    4158              : 
    4159              :         // SUBROUTINE INFORMATION:
    4160              :         //       AUTHOR         Lixing Gu
    4161              :         //       DATE WRITTEN   March 2007
    4162              :         //       MODIFIED       na
    4163              :         //       RE-ENGINEERED  na
    4164              : 
    4165              :         // PURPOSE OF THIS SUBROUTINE:
    4166              :         // This subroutine is for initializations of the Hybrid Ventilation Control System Availability Manager
    4167              : 
    4168              :         // METHODOLOGY EMPLOYED:
    4169              :         // Uses the status flags to trigger initializations.
    4170              : 
    4171              :         // Using/Aliasing
    4172              :         using DataZoneEquipment::NumValidSysAvailZoneComponents;
    4173              : 
    4174              :         static constexpr std::string_view routineName = "InitHybridVentSysAvailMgr";
    4175              : 
    4176              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    4177            0 :         bool ErrorsFound(false); // Set to true if errors in input, fatal at end of routine
    4178              :         int AirLoopNum;          // Air loop number
    4179              :         int AirLoopCount;        // Air loop name count
    4180              :         int SysAvailIndex;       // Hybrid Ventilation Sys Avail Manager index
    4181              :         int ZoneEquipType;
    4182              :         int HybridVentNum;
    4183              : 
    4184              :         // One time initializations
    4185            0 :         if (state.dataAvail->MyOneTimeFlag && allocated(state.dataZoneEquip->ZoneEquipConfig) &&
    4186            0 :             allocated(state.dataAirSystemsData->PrimaryAirSystems)) {
    4187              : 
    4188              :             // Ensure the controlled zone is listed and defined in an HVAC Air Loop
    4189            0 :             for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumHybridVentSysAvailMgrs; ++SysAvailNum) {
    4190            0 :                 auto &hybridVentMgr = state.dataAvail->HybridVentData(SysAvailNum);
    4191            0 :                 ErrorObjectHeader eoh{routineName, managerTypeNames[(int)ManagerType::HybridVent], hybridVentMgr.Name};
    4192            0 :                 if (hybridVentMgr.simpleControlTypeSched != nullptr && state.dataHeatBal->TotVentilation > 0 && hybridVentMgr.VentilationPtr == 0) {
    4193            0 :                     hybridVentMgr.VentilationPtr = Util::FindItemInList(hybridVentMgr.VentilationName, state.dataHeatBal->Ventilation);
    4194            0 :                     hybridVentMgr.Master = hybridVentMgr.VentilationPtr;
    4195            0 :                     if (hybridVentMgr.VentilationPtr <= 0 && int(hybridVentMgr.simpleControlTypeSched->getMaxVal(state)) == 1) {
    4196            0 :                         ShowSevereItemNotFound(state, eoh, "ZoneVentilation Object Name", hybridVentMgr.VentilationName);
    4197            0 :                         ErrorsFound = true;
    4198              :                     }
    4199              :                 }
    4200              :                 // Check air loop number
    4201            0 :                 for (AirLoopNum = 1; AirLoopNum <= state.dataHVACGlobal->NumPrimaryAirSys; ++AirLoopNum) { // loop over the primary air systems
    4202            0 :                     if (Util::SameString(state.dataAirSystemsData->PrimaryAirSystems(AirLoopNum).Name, hybridVentMgr.AirLoopName)) {
    4203            0 :                         hybridVentMgr.AirLoopNum = AirLoopNum;
    4204              :                     }
    4205              :                 }
    4206              : 
    4207            0 :                 bool zoneFound = false;
    4208            0 :                 int ControlledZoneNum = hybridVentMgr.ControlledZoneNum;
    4209            0 :                 if (hybridVentMgr.HybridVentMgrConnectedToAirLoop) {
    4210            0 :                     if (hybridVentMgr.ControlledZoneNum > 0) {
    4211            0 :                         for (int zoneInNode = 1; zoneInNode <= state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).NumInletNodes; ++zoneInNode) {
    4212            0 :                             if (state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).InletNodeAirLoopNum(zoneInNode) == hybridVentMgr.AirLoopNum) {
    4213            0 :                                 zoneFound = true;
    4214              :                             }
    4215              :                         }
    4216            0 :                         if (!zoneFound) {
    4217            0 :                             ShowSevereError(state,
    4218            0 :                                             format("{}, The controlled zone ={} is not served by this Air Loop={}",
    4219            0 :                                                    managerTypeNames[(int)hybridVentMgr.type],
    4220            0 :                                                    hybridVentMgr.ControlZoneName,
    4221            0 :                                                    hybridVentMgr.AirLoopName));
    4222            0 :                             ErrorsFound = true;
    4223              :                         }
    4224              :                     }
    4225              :                 }
    4226            0 :                 if (std::any_of(state.dataAvail->HybridVentData.begin(),
    4227            0 :                                 state.dataAvail->HybridVentData.end(),
    4228            0 :                                 [](SysAvailManagerHybridVent const &e) { return e.HybridVentMgrConnectedToAirLoop; })) {
    4229            0 :                     for (int zoneInNode = 1; zoneInNode <= state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).NumInletNodes; ++zoneInNode) {
    4230            0 :                         if (state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).InletNodeAirLoopNum(zoneInNode) == hybridVentMgr.AirLoopNum &&
    4231            0 :                             hybridVentMgr.AirLoopNum > 0) {
    4232            0 :                             for (HybridVentNum = 1; HybridVentNum <= state.dataAvail->NumHybridVentSysAvailMgrs; ++HybridVentNum) {
    4233            0 :                                 if (!state.dataAvail->HybridVentData(HybridVentNum).HybridVentMgrConnectedToAirLoop &&
    4234              :                                     (HybridVentNum != SysAvailNum)) {
    4235            0 :                                     if (ControlledZoneNum == state.dataAvail->HybridVentData(HybridVentNum).ControlledZoneNum &&
    4236              :                                         ControlledZoneNum > 0) {
    4237            0 :                                         ShowWarningError(
    4238              :                                             state,
    4239            0 :                                             format("AvailabilityManager:HybridVentilation = \"{}\" has the controlled zone name = \"{}\".",
    4240            0 :                                                    state.dataAvail->HybridVentData(HybridVentNum).Name,
    4241            0 :                                                    state.dataAvail->HybridVentData(HybridVentNum).ControlZoneName));
    4242            0 :                                         ShowContinueError(
    4243              :                                             state,
    4244            0 :                                             format("This controlled zone already has hybrid ventilation control through this air loop = \"{}\".",
    4245            0 :                                                    hybridVentMgr.AirLoopName));
    4246            0 :                                         ShowContinueError(
    4247              :                                             state,
    4248            0 :                                             format("Only AvailabilityManager:HybridVentilation = \"{}\" will be simulated. Simulation continues...",
    4249            0 :                                                    hybridVentMgr.Name));
    4250              :                                     } else {
    4251            0 :                                         state.dataAvail->HybridVentData(HybridVentNum).SimHybridVentSysAvailMgr = true;
    4252              :                                     }
    4253              :                                 }
    4254              :                             }
    4255              :                         }
    4256              :                     }
    4257              :                 } else {
    4258            0 :                     for (auto &e : state.dataAvail->HybridVentData)
    4259            0 :                         e.SimHybridVentSysAvailMgr = true;
    4260              :                 }
    4261              : 
    4262            0 :                 if (hybridVentMgr.ControlledZoneNum == 0) {
    4263            0 :                     ShowSevereError(state,
    4264            0 :                                     format("{}, The controlled zone is not defined correctly ={}",
    4265            0 :                                            managerTypeNames[(int)hybridVentMgr.type],
    4266            0 :                                            hybridVentMgr.ControlZoneName));
    4267            0 :                     ErrorsFound = true;
    4268              :                 }
    4269              :                 // check schedule value for adaptive temperature control
    4270            0 :                 if (hybridVentMgr.controlModeSched->hasVal(state, 5.0) || hybridVentMgr.controlModeSched->hasVal(state, 6.0)) {
    4271            0 :                     if (!state.dataHeatBal->AdaptiveComfortRequested_ASH55) {
    4272            0 :                         ShowSevereError(state,
    4273            0 :                                         format("GetHybridVentilationInputs: AvailabilityManager:HybridVentilation =\"{}\"", hybridVentMgr.Name));
    4274            0 :                         ShowContinueError(state,
    4275            0 :                                           format("Ventilation Control Mode Schedule Name =\"{}\", When the schedule value is 5 or 6, operative "
    4276              :                                                  "temperature control is requested. ",
    4277            0 :                                                  hybridVentMgr.controlModeSched->Name));
    4278            0 :                         ShowContinueError(state,
    4279              :                                           "However, AdaptiveASH55 is not entered in the Thermal Comfort Model Type fields in the People object.");
    4280            0 :                         ErrorsFound = true;
    4281              :                     }
    4282              :                 }
    4283              :             }
    4284              : 
    4285              :             // Ensure an airloop name is not used more than once in the hybrid ventilation control objects
    4286            0 :             for (AirLoopNum = 1; AirLoopNum <= state.dataHVACGlobal->NumPrimaryAirSys; ++AirLoopNum) { // loop over the primary air systems
    4287            0 :                 AirLoopCount = 0;
    4288            0 :                 for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumHybridVentSysAvailMgrs; ++SysAvailNum) {
    4289            0 :                     if (Util::SameString(state.dataAirSystemsData->PrimaryAirSystems(AirLoopNum).Name,
    4290            0 :                                          state.dataAvail->HybridVentData(SysAvailNum).AirLoopName)) {
    4291            0 :                         ++AirLoopCount;
    4292            0 :                         if (AirLoopCount > 1) SysAvailIndex = SysAvailNum;
    4293              :                     }
    4294              :                 }
    4295            0 :                 if (AirLoopCount > 1) {
    4296            0 :                     ShowSevereError(state,
    4297            0 :                                     format("{}, The AirLoopHVAC name found more than once={}",
    4298            0 :                                            managerTypeNames[(int)state.dataAvail->HybridVentData(SysAvailIndex).type],
    4299            0 :                                            state.dataAirSystemsData->PrimaryAirSystems(AirLoopNum).Name));
    4300            0 :                     ShowContinueError(state, "Each AirLoopHVAC allows one hybrid ventilation control object.");
    4301            0 :                     ErrorsFound = true;
    4302              :                 }
    4303              :             }
    4304              : 
    4305            0 :             if (ErrorsFound) {
    4306            0 :                 ShowFatalError(state, "Errors found in getting AvailabilityManager:* inputs");
    4307              :             }
    4308              : 
    4309            0 :             state.dataAvail->MyOneTimeFlag = false;
    4310              : 
    4311              :         } // end 1 time initializations
    4312              : 
    4313            0 :         for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumHybridVentSysAvailMgrs; ++SysAvailNum) {
    4314            0 :             auto &hybridVentMgr = state.dataAvail->HybridVentData(SysAvailNum);
    4315            0 :             hybridVentMgr.ctrlType = static_cast<VentCtrlType>(hybridVentMgr.controlModeSched->getCurrentVal());
    4316              :             // -1 means that the value will be determined inside CalcHybridVentSysAvailMgr.
    4317              :             // IF the value is still -1, the program will stop.
    4318              :             // hybridVentMgr.ctrlStatus = VentCtrlStatus::Invalid; // Not sure what this is for
    4319            0 :             hybridVentMgr.WindModifier = -1.0;
    4320              :         }
    4321              : 
    4322            0 :         if (allocated(state.dataAvail->HybridVentData))
    4323            0 :             for (auto &e : state.dataAvail->HybridVentData)
    4324            0 :                 e.availStatus = Status::NoAction;
    4325              : 
    4326            0 :         if (allocated(state.dataAvail->ZoneComp)) {
    4327            0 :             for (ZoneEquipType = 1; ZoneEquipType <= NumValidSysAvailZoneComponents; ++ZoneEquipType) { // loop over the zone equipment types
    4328            0 :                 if (state.dataAvail->ZoneComp(ZoneEquipType).TotalNumComp > 0)
    4329            0 :                     for (auto &e : state.dataAvail->ZoneComp(ZoneEquipType).ZoneCompAvailMgrs)
    4330            0 :                         e.availStatus = Status::NoAction;
    4331              :             }
    4332              :         }
    4333              : 
    4334            0 :         if (state.dataGlobal->BeginEnvrnFlag && state.dataAvail->MyEnvrnFlag) {
    4335            0 :             for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumHybridVentSysAvailMgrs; ++SysAvailNum) {
    4336            0 :                 state.dataAvail->HybridVentData(SysAvailNum).TimeVentDuration = 0.0;
    4337            0 :                 state.dataAvail->HybridVentData(SysAvailNum).TimeOperDuration = 0.0;
    4338              :             }
    4339            0 :             state.dataAvail->MyEnvrnFlag = false;
    4340              :         }
    4341            0 :         if (!state.dataGlobal->BeginEnvrnFlag) {
    4342            0 :             state.dataAvail->MyEnvrnFlag = true;
    4343              :         }
    4344              :         // check minimum operation time
    4345            0 :         state.dataAvail->CurrentEndTime = state.dataGlobal->CurrentTime + state.dataHVACGlobal->SysTimeElapsed;
    4346            0 :         if (state.dataAvail->CurrentEndTime > state.dataAvail->CurrentEndTimeLast &&
    4347            0 :             state.dataHVACGlobal->TimeStepSys >= state.dataAvail->TimeStepSysLast) {
    4348            0 :             for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumHybridVentSysAvailMgrs; ++SysAvailNum) {
    4349            0 :                 auto &hybridVentMgr = state.dataAvail->HybridVentData(SysAvailNum);
    4350            0 :                 if (hybridVentMgr.ctrlStatus == VentCtrlStatus::NoAction) {
    4351            0 :                     hybridVentMgr.TimeOperDuration = 0.0;
    4352            0 :                     hybridVentMgr.TimeVentDuration = 0.0;
    4353              :                 }
    4354            0 :                 if (hybridVentMgr.MinVentTime > 0.0) {
    4355            0 :                     if (hybridVentMgr.ctrlStatus == VentCtrlStatus::Open) {
    4356            0 :                         hybridVentMgr.TimeVentDuration += (state.dataAvail->CurrentEndTime - state.dataAvail->CurrentEndTimeLast) * 60.0;
    4357            0 :                         hybridVentMgr.TimeOperDuration = 0.0;
    4358              :                     }
    4359              :                 }
    4360            0 :                 if (hybridVentMgr.MinOperTime > 0.0) {
    4361            0 :                     if (hybridVentMgr.ctrlStatus == VentCtrlStatus::Close) {
    4362            0 :                         hybridVentMgr.TimeOperDuration += (state.dataAvail->CurrentEndTime - state.dataAvail->CurrentEndTimeLast) * 60.0;
    4363            0 :                         hybridVentMgr.TimeVentDuration = 0.0;
    4364              :                     }
    4365              :                 }
    4366              :             }
    4367              :         }
    4368            0 :         state.dataAvail->TimeStepSysLast = state.dataHVACGlobal->TimeStepSys;
    4369            0 :         state.dataAvail->CurrentEndTimeLast = state.dataAvail->CurrentEndTime;
    4370            0 :     }
    4371              : 
    4372           13 :     void CalcHybridVentSysAvailMgr(EnergyPlusData &state,
    4373              :                                    int const SysAvailNum,                     // number of the current scheduled system availability manager
    4374              :                                    ObjexxFCL::Optional_int_const PriAirSysNum // number of the primary air system affected by this Avail. Manager
    4375              :     )
    4376              :     {
    4377              : 
    4378              :         // SUBROUTINE INFORMATION:
    4379              :         //       AUTHOR         Lixing Gu
    4380              :         //       DATE WRITTEN   March 2007
    4381              :         //       MODIFIED       July 2012, Chandan Sharma - FSEC: Added zone sys avail managers
    4382              :         //       RE-ENGINEERED  na
    4383              : 
    4384              :         // PURPOSE OF THIS SUBROUTINE:
    4385              :         // Set AvailStatus indicator for a primary air loop and AirflowNetwork model to prevent
    4386              :         // windows or doors open during HVAC system operation
    4387              : 
    4388              :         // METHODOLOGY EMPLOYED:
    4389              :         // Looks at outside and indoor conditions to determine if hybrid ventilation
    4390              :         // is beneficial. If it is and it is scheduled on the AvailStatus is set to cycle
    4391              :         // on and open windows or doors.
    4392              : 
    4393              :         using namespace DataAirLoop;
    4394              :         using Curve::CurveValue;
    4395              :         using DataZoneEquipment::NumValidSysAvailZoneComponents;
    4396              :         using Psychrometrics::PsyHFnTdbW;
    4397              :         using Psychrometrics::PsyRhFnTdbWPb;
    4398              :         using Psychrometrics::PsyTdpFnWPb;
    4399              :         using Psychrometrics::PsyWFnTdbRhPb;
    4400              : 
    4401              :         int HStatZoneNum;                   // Humidity control zone number
    4402              :         Real64 ZoneAirEnthalpy;             // Zone air enthalpy
    4403              :         Real64 ZoneAirDewPoint;             // Zone air dew point temperature
    4404              :         Real64 ZoneAirRH;                   // Zone air relative humidity
    4405              :         Real64 TempExt;                     // Outdoor dry bulb temperature at zone height
    4406              :         Real64 WindExt;                     // Outdoor wind speed at zone height
    4407              :         Real64 WSetPoint;                   // Humidity ratio setpoint from a given RH setpoint schedule
    4408              :         Real64 OASetPoint;                  // Outdoor air setpoint from a given OA setpoint schedule
    4409              :         Real64 ACH;                         // Zone air change per hour
    4410              :         bool found;                         // Used for humidistat object
    4411              :         bool HybridVentModeOA;              // USed to check whether HybridVentModeOA is allowed
    4412              :         Real64 ZoneRHHumidifyingSetPoint;   // Zone humidifying setpoint (%)
    4413              :         Real64 ZoneRHDehumidifyingSetPoint; // Zone dehumidifying setpoint (%)
    4414              :         int SimpleControlType;              // Simple control type from a schedule: 0 individual, 1 global
    4415              :         int i;                              // Array index
    4416              :         Real64 minAdaTem;                   // minimum adaptive temperature for adaptive temperature control
    4417              :         Real64 maxAdaTem;                   // maximum adaptive temperature for adaptive temperature control
    4418              :         bool KeepStatus;                    // true, if minimum time operation is needed
    4419              :         int ZoneEquipType;
    4420              :         int ZoneCompNum;
    4421              :         int AirLoopNum;
    4422              :         int Num;
    4423              :         Status availStatus;
    4424              : 
    4425           13 :         KeepStatus = false;
    4426           13 :         auto &hybridVentMgr = state.dataAvail->HybridVentData(SysAvailNum);
    4427           13 :         if (hybridVentMgr.TimeVentDuration > 0.0 && hybridVentMgr.TimeVentDuration <= hybridVentMgr.MinVentTime) {
    4428            1 :             KeepStatus = true;
    4429              :         }
    4430           13 :         if (hybridVentMgr.TimeOperDuration > 0.0 && hybridVentMgr.TimeOperDuration <= hybridVentMgr.MinOperTime) {
    4431            1 :             KeepStatus = true;
    4432              :         }
    4433              : 
    4434           13 :         int ZoneNum = hybridVentMgr.ControlledZoneNum;
    4435           13 :         auto &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum);
    4436           13 :         if (!KeepStatus) hybridVentMgr.ctrlStatus = VentCtrlStatus::NoAction;
    4437           13 :         TempExt = state.dataHeatBal->Zone(ZoneNum).OutDryBulbTemp;
    4438           13 :         WindExt = state.dataHeatBal->Zone(ZoneNum).WindSpeed;
    4439           13 :         hybridVentMgr.OperativeTemp = 0.0;
    4440           13 :         hybridVentMgr.minAdaTem = 0.0;
    4441           13 :         hybridVentMgr.maxAdaTem = 0.0;
    4442              : 
    4443           13 :         if (!KeepStatus) {
    4444           11 :             switch (hybridVentMgr.ctrlType) {
    4445              : 
    4446            0 :             case VentCtrlType::No: {
    4447            0 :                 hybridVentMgr.ctrlStatus = VentCtrlStatus::NoAction;
    4448              : 
    4449              :                 // Temperature control
    4450            0 :             } break;
    4451              : 
    4452            2 :             case VentCtrlType::Temp: {
    4453            2 :                 if (TempExt >= hybridVentMgr.MinOutdoorTemp && TempExt <= hybridVentMgr.MaxOutdoorTemp) {
    4454            1 :                     hybridVentMgr.ctrlStatus = VentCtrlStatus::Open;
    4455              :                 } else {
    4456            1 :                     hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
    4457              :                 }
    4458              : 
    4459              :                 // Enthalpy control
    4460            2 :             } break;
    4461              : 
    4462            0 :             case VentCtrlType::Enth: {
    4463            0 :                 ZoneAirEnthalpy = PsyHFnTdbW(thisZoneHB.MAT, thisZoneHB.airHumRat);
    4464            0 :                 if (state.dataEnvrn->OutEnthalpy >= hybridVentMgr.MinOutdoorEnth && state.dataEnvrn->OutEnthalpy <= hybridVentMgr.MaxOutdoorEnth) {
    4465            0 :                     hybridVentMgr.ctrlStatus = VentCtrlStatus::Open;
    4466              :                 } else {
    4467            0 :                     hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
    4468              :                 }
    4469              : 
    4470              :                 // Dew point control
    4471            0 :             } break;
    4472              : 
    4473            0 :             case VentCtrlType::DewPoint: {
    4474            0 :                 if (state.dataEnvrn->OutDewPointTemp >= hybridVentMgr.MinOutdoorDewPoint &&
    4475            0 :                     state.dataEnvrn->OutDewPointTemp <= hybridVentMgr.MaxOutdoorDewPoint) {
    4476            0 :                     hybridVentMgr.ctrlStatus = VentCtrlStatus::Open;
    4477              :                 } else {
    4478            0 :                     hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
    4479              :                 }
    4480              : 
    4481            0 :             } break;
    4482              : 
    4483            0 :             case VentCtrlType::OA: {
    4484            0 :                 OASetPoint = hybridVentMgr.minOASched->getCurrentVal();
    4485            0 :                 ACH = 0.0;
    4486            0 :                 HybridVentModeOA = true;
    4487            0 :                 if (!hybridVentMgr.HybridVentMgrConnectedToAirLoop) {
    4488            0 :                     if (state.afn->simulation_control.type == AirflowNetwork::ControlType::NoMultizoneOrDistribution) {
    4489            0 :                         HybridVentModeOA = false;
    4490              :                     }
    4491              :                 }
    4492              : 
    4493            0 :                 if (hybridVentMgr.afnControlTypeSched != nullptr && HybridVentModeOA) {
    4494            0 :                     state.afn->manage_balance(true);
    4495            0 :                     ACH = state.afn->zone_OA_change_rate(ZoneNum);
    4496              :                 }
    4497            0 :                 if (ACH > OASetPoint) {
    4498            0 :                     hybridVentMgr.ctrlStatus = VentCtrlStatus::Open;
    4499              :                 } else {
    4500            0 :                     hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
    4501              :                 }
    4502              : 
    4503            0 :             } break;
    4504              : 
    4505            2 :             case VentCtrlType::OperT80: {
    4506            2 :                 if (state.dataThermalComforts->runningAverageASH >= 10.0 && state.dataThermalComforts->runningAverageASH <= 33.5) {
    4507            2 :                     hybridVentMgr.OperativeTemp = 0.5 * (thisZoneHB.MAT + thisZoneHB.MRT);
    4508            2 :                     minAdaTem = 0.31 * state.dataThermalComforts->runningAverageASH + 14.3;
    4509            2 :                     maxAdaTem = 0.31 * state.dataThermalComforts->runningAverageASH + 21.3;
    4510            2 :                     hybridVentMgr.minAdaTem = minAdaTem;
    4511            2 :                     hybridVentMgr.maxAdaTem = maxAdaTem;
    4512            2 :                     if (hybridVentMgr.OperativeTemp <= maxAdaTem && hybridVentMgr.OperativeTemp >= minAdaTem) {
    4513            1 :                         hybridVentMgr.ctrlStatus = VentCtrlStatus::Open;
    4514              :                     } else {
    4515            1 :                         hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
    4516              :                     }
    4517              :                 } else {
    4518            0 :                     hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
    4519              :                 }
    4520              : 
    4521            2 :             } break;
    4522              : 
    4523            2 :             case VentCtrlType::OperT90: {
    4524            2 :                 if (state.dataThermalComforts->runningAverageASH >= 10.0 && state.dataThermalComforts->runningAverageASH <= 33.5) {
    4525            2 :                     hybridVentMgr.OperativeTemp = 0.5 * (thisZoneHB.MAT + thisZoneHB.MRT);
    4526            2 :                     minAdaTem = 0.31 * state.dataThermalComforts->runningAverageASH + 15.3;
    4527            2 :                     maxAdaTem = 0.31 * state.dataThermalComforts->runningAverageASH + 20.3;
    4528            2 :                     hybridVentMgr.minAdaTem = minAdaTem;
    4529            2 :                     hybridVentMgr.maxAdaTem = maxAdaTem;
    4530            2 :                     if (hybridVentMgr.OperativeTemp <= maxAdaTem && hybridVentMgr.OperativeTemp >= minAdaTem) {
    4531            1 :                         hybridVentMgr.ctrlStatus = VentCtrlStatus::Open;
    4532              :                     } else {
    4533            1 :                         hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
    4534              :                     }
    4535              :                 } else {
    4536            0 :                     hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
    4537              :                 }
    4538              : 
    4539            2 :             } break;
    4540            5 :             case VentCtrlType::CO2: {
    4541            5 :                 hybridVentMgr.CO2 = state.dataContaminantBalance->ZoneAirCO2(ZoneNum);
    4542            5 :                 if (state.dataContaminantBalance->ZoneAirCO2(ZoneNum) > state.dataContaminantBalance->ZoneCO2SetPoint(ZoneNum)) {
    4543            4 :                     if (hybridVentMgr.HybridVentMgrConnectedToAirLoop) {
    4544            2 :                         AirLoopNum = hybridVentMgr.AirLoopNum;
    4545            4 :                         for (Num = 1; Num <= state.dataAirLoop->PriAirSysAvailMgr(hybridVentMgr.AirLoopNum).NumAvailManagers; ++Num) {
    4546            4 :                             availStatus = SimSysAvailManager(state,
    4547            2 :                                                              state.dataAirLoop->PriAirSysAvailMgr(AirLoopNum).availManagers(Num).type,
    4548            2 :                                                              state.dataAirLoop->PriAirSysAvailMgr(AirLoopNum).availManagers(Num).Name,
    4549            2 :                                                              state.dataAirLoop->PriAirSysAvailMgr(AirLoopNum).availManagers(Num).Num,
    4550              :                                                              AirLoopNum,
    4551            2 :                                                              state.dataAirLoop->PriAirSysAvailMgr(AirLoopNum).availStatus);
    4552              :                         }
    4553            2 :                         if (availStatus == Status::CycleOn) {
    4554            1 :                             hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
    4555              :                         } else {
    4556            1 :                             hybridVentMgr.ctrlStatus = VentCtrlStatus::Open;
    4557              :                         }
    4558            2 :                     } else if (hybridVentMgr.SimHybridVentSysAvailMgr) {
    4559            2 :                         hybridVentMgr.ctrlStatus = VentCtrlStatus::Open;
    4560           30 :                         for (ZoneEquipType = 1; ZoneEquipType <= NumValidSysAvailZoneComponents; ++ZoneEquipType) {
    4561           29 :                             for (ZoneCompNum = 1; ZoneCompNum <= state.dataAvail->ZoneComp(ZoneEquipType).TotalNumComp; ++ZoneCompNum) {
    4562            2 :                                 if (state.dataAvail->ZoneComp(ZoneEquipType).ZoneCompAvailMgrs(ZoneCompNum).availStatus == Status::CycleOn) {
    4563            1 :                                     hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
    4564            1 :                                     break;
    4565              :                                 }
    4566              :                             }
    4567              :                         }
    4568              :                     } else {
    4569            0 :                         hybridVentMgr.ctrlStatus = VentCtrlStatus::Open;
    4570              :                     }
    4571              :                 }
    4572            5 :             } break;
    4573            0 :             default: {
    4574            0 :                 ShowSevereError(state,
    4575            0 :                                 format("{}: incorrect Control Type: {}", managerTypeNames[(int)hybridVentMgr.type], hybridVentMgr.AirLoopName));
    4576            0 :                 ShowFatalError(state, format("Errors found in getting {} Control mode value", managerTypeNames[(int)hybridVentMgr.type]));
    4577              :             }
    4578              :             }
    4579              : 
    4580           11 :             if (hybridVentMgr.ctrlStatus == VentCtrlStatus::Open) {
    4581              : 
    4582            5 :                 auto const &zoneTstatSetpt = state.dataHeatBalFanSys->zoneTstatSetpts(ZoneNum);
    4583              :                 // Temperature and enthalpy control
    4584            5 :                 if (hybridVentMgr.ctrlType == VentCtrlType::Temp || hybridVentMgr.ctrlType == VentCtrlType::Enth) {
    4585              : 
    4586            1 :                     switch (state.dataHeatBalFanSys->TempControlType(ZoneNum)) {
    4587              : 
    4588            1 :                     case HVAC::SetptType::SingleHeat: {
    4589            1 :                         if (thisZoneHB.MAT < zoneTstatSetpt.setpt) {
    4590            0 :                             hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
    4591              :                         }
    4592              : 
    4593            1 :                     } break;
    4594            0 :                     case HVAC::SetptType::SingleCool: {
    4595            0 :                         if (thisZoneHB.MAT > zoneTstatSetpt.setpt) {
    4596            0 :                             hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
    4597              :                         }
    4598              : 
    4599            0 :                     } break;
    4600            0 :                     case HVAC::SetptType::SingleHeatCool: {
    4601            0 :                         hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
    4602            0 :                         ++hybridVentMgr.SingleHCErrCount;
    4603            0 :                         if (hybridVentMgr.SingleHCErrCount < 2) {
    4604            0 :                             ShowWarningError(state,
    4605            0 :                                              format("Hybrid ventilation control: {}: The zone temperature control type is "
    4606              :                                                     "ThermostatSetpoint:SingleHeatingOrCooling. Natural ventilation is not allowed.",
    4607            0 :                                                     hybridVentMgr.AirLoopName));
    4608            0 :                             ShowContinueErrorTimeStamp(state, "");
    4609              :                         } else {
    4610            0 :                             ShowRecurringWarningErrorAtEnd(
    4611              :                                 state,
    4612            0 :                                 "Hybrid ventilation control: " + hybridVentMgr.AirLoopName +
    4613              :                                     ": No natural ventilation continues with a ThermostatSetpoint:SingleHeatingOrCooling type...",
    4614            0 :                                 hybridVentMgr.SingleHCErrIndex,
    4615            0 :                                 double(hybridVentMgr.ctrlType),
    4616            0 :                                 double(hybridVentMgr.ctrlType));
    4617              :                         }
    4618              : 
    4619            0 :                     } break;
    4620              : 
    4621            0 :                     case HVAC::SetptType::DualHeatCool: {
    4622            0 :                         if (thisZoneHB.MAT < zoneTstatSetpt.setptLo || thisZoneHB.MAT > zoneTstatSetpt.setptHi) {
    4623            0 :                             hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
    4624              :                         }
    4625              : 
    4626            0 :                     } break;
    4627            0 :                     default:
    4628            0 :                         break;
    4629              :                     } // end select on thermostat control
    4630              :                 }
    4631              : 
    4632              :                 // Dew point control mode
    4633            5 :                 if (hybridVentMgr.ctrlType == VentCtrlType::DewPoint) {
    4634            0 :                     ZoneAirRH = PsyRhFnTdbWPb(state, thisZoneHB.MAT, thisZoneHB.airHumRat, state.dataEnvrn->OutBaroPress) * 100.0;
    4635            0 :                     ZoneAirDewPoint = PsyTdpFnWPb(state, thisZoneHB.airHumRat, state.dataEnvrn->OutBaroPress);
    4636            0 :                     if (state.dataZoneCtrls->NumHumidityControlZones == 0) {
    4637            0 :                         ++hybridVentMgr.DewPointNoRHErrCount;
    4638            0 :                         if (hybridVentMgr.DewPointNoRHErrCount < 2) {
    4639            0 :                             ShowWarningError(
    4640              :                                 state,
    4641            0 :                                 format("Hybrid ventilation control: Dew point control mode is selected, but no ZoneControl:Humidistat object={}",
    4642            0 :                                        hybridVentMgr.AirLoopName));
    4643            0 :                             ShowContinueError(state, "The hybrid ventilation control is triggered by outdoor min and max dewpoint only.");
    4644            0 :                             ShowContinueError(state, "HVAC system may turn off when outdoor dewpoint is between min and max dewpoint.");
    4645            0 :                             ShowContinueErrorTimeStamp(state, "");
    4646              :                         } else {
    4647            0 :                             ShowRecurringWarningErrorAtEnd(state,
    4648            0 :                                                            "Hybrid ventilation control: " + hybridVentMgr.AirLoopName +
    4649              :                                                                ": no ZoneControl:Humidistat object continues...",
    4650            0 :                                                            hybridVentMgr.DewPointNoRHErrIndex,
    4651            0 :                                                            double(hybridVentMgr.ctrlType),
    4652            0 :                                                            double(hybridVentMgr.ctrlType));
    4653              :                         }
    4654              :                     }
    4655            0 :                     found = false;
    4656            0 :                     for (HStatZoneNum = 1; HStatZoneNum <= state.dataZoneCtrls->NumHumidityControlZones; ++HStatZoneNum) {
    4657            0 :                         if (state.dataZoneCtrls->HumidityControlZone(HStatZoneNum).ActualZoneNum == ZoneNum) {
    4658            0 :                             found = true;
    4659            0 :                             ZoneRHHumidifyingSetPoint = state.dataZoneCtrls->HumidityControlZone(HStatZoneNum).humidifyingSched->getCurrentVal();
    4660            0 :                             ZoneRHDehumidifyingSetPoint = state.dataZoneCtrls->HumidityControlZone(HStatZoneNum).dehumidifyingSched->getCurrentVal();
    4661            0 :                             if (ZoneAirRH > ZoneRHDehumidifyingSetPoint) { // Need dehumidification
    4662              :                                 WSetPoint =
    4663            0 :                                     PsyWFnTdbRhPb(state, thisZoneHB.MAT, (ZoneRHDehumidifyingSetPoint / 100.0), state.dataEnvrn->OutBaroPress);
    4664            0 :                                 if (WSetPoint < state.dataEnvrn->OutHumRat) hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
    4665            0 :                             } else if (ZoneAirRH < ZoneRHHumidifyingSetPoint) { // Need humidification
    4666            0 :                                 WSetPoint = PsyWFnTdbRhPb(state, thisZoneHB.MAT, (ZoneRHHumidifyingSetPoint / 100.0), state.dataEnvrn->OutBaroPress);
    4667            0 :                                 if (WSetPoint > state.dataEnvrn->OutHumRat) hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
    4668              :                             } else {
    4669            0 :                                 hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
    4670              :                             }
    4671              :                         }
    4672              :                     }
    4673            0 :                     if (!found && state.dataZoneCtrls->NumHumidityControlZones > 0) {
    4674            0 :                         ++hybridVentMgr.DewPointErrCount;
    4675            0 :                         if (hybridVentMgr.DewPointErrCount < 2) {
    4676            0 :                             ShowWarningError(state,
    4677            0 :                                              format("Hybrid ventilation control: The zone for dew point control mode is different from the zone for "
    4678              :                                                     "ZoneControl:Humidistat={}",
    4679            0 :                                                     hybridVentMgr.AirLoopName));
    4680            0 :                             ShowContinueError(
    4681              :                                 state,
    4682            0 :                                 format("The Zone name for hybrid control is {}. Humidistat has no impact", state.dataHeatBal->Zone(ZoneNum).Name));
    4683            0 :                             ShowContinueError(state, "HVAC system may turn off when outdoor dewpoint is between min and max dewpoint.");
    4684            0 :                             ShowContinueErrorTimeStamp(state, "");
    4685              :                         } else {
    4686            0 :                             ShowRecurringWarningErrorAtEnd(state,
    4687            0 :                                                            "Hybrid ventilation control: " + hybridVentMgr.AirLoopName +
    4688              :                                                                " No humidistat control impact continues...",
    4689            0 :                                                            hybridVentMgr.DewPointErrIndex,
    4690            0 :                                                            double(hybridVentMgr.ctrlType),
    4691            0 :                                                            double(hybridVentMgr.ctrlType));
    4692              :                         }
    4693              :                     }
    4694              :                 }
    4695              : 
    4696              :                 // Outdoor ventilation air control mode
    4697            5 :                 if (hybridVentMgr.ctrlType == VentCtrlType::OA) {
    4698              :                 }
    4699              :             }
    4700              :         }
    4701              : 
    4702           13 :         if (WindExt > hybridVentMgr.MaxWindSpeed) {
    4703            0 :             hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
    4704              :         }
    4705              : 
    4706           13 :         if (state.dataEnvrn->IsRain && hybridVentMgr.UseRainIndicator) {
    4707            0 :             hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
    4708              :         }
    4709              :         // Sent a signal to the AirflowNetwork to ensure large onpenings are close or open based on this logic
    4710           13 :         if (hybridVentMgr.ctrlStatus == VentCtrlStatus::Invalid) {
    4711              :             // Fatal error
    4712            0 :             ShowFatalError(state,
    4713              :                            "Hybrid ventilation control: the ventilation control status is beyond the range. Please check input of control "
    4714              :                            "mode schedule");
    4715              :         }
    4716              : 
    4717           13 :         if (hybridVentMgr.HybridVentMgrConnectedToAirLoop) {
    4718            7 :             if (hybridVentMgr.ctrlStatus == VentCtrlStatus::Close) {
    4719            3 :                 state.dataAirLoop->PriAirSysAvailMgr(PriAirSysNum).availStatus = Status::CycleOn;
    4720              :             }
    4721              :         }
    4722              : 
    4723           13 :         if (hybridVentMgr.ctrlStatus == VentCtrlStatus::Open && hybridVentMgr.afnControlTypeSched != nullptr && hybridVentMgr.OpeningFactorFWS > 0) {
    4724            0 :             hybridVentMgr.WindModifier = CurveValue(state, hybridVentMgr.OpeningFactorFWS, WindExt);
    4725              :         }
    4726              : 
    4727              :         // Set up flags to control simple airflow objects
    4728           13 :         if (hybridVentMgr.AirLoopNum > 0 && hybridVentMgr.simpleControlTypeSched != nullptr) {
    4729            0 :             SimpleControlType = hybridVentMgr.simpleControlTypeSched->getCurrentVal();
    4730            0 :             for (int ControlledZoneNum = 1; ControlledZoneNum <= state.dataGlobal->NumOfZones; ++ControlledZoneNum) {
    4731            0 :                 for (int zoneInNode = 1; zoneInNode <= state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).NumInletNodes; ++zoneInNode) {
    4732            0 :                     if (hybridVentMgr.AirLoopNum == state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).InletNodeAirLoopNum(zoneInNode)) {
    4733              :                         // Setup flag for ventilation objects
    4734            0 :                         for (i = 1; i <= state.dataHeatBal->TotVentilation; ++i) {
    4735            0 :                             if (state.dataHeatBal->Ventilation(i).ZonePtr == ControlledZoneNum) {
    4736            0 :                                 state.dataHeatBal->Ventilation(i).HybridControlType = DataHeatBalance::HybridCtrlType::Indiv;
    4737            0 :                                 if (hybridVentMgr.ctrlStatus == VentCtrlStatus::Close) {
    4738            0 :                                     state.dataHeatBal->Ventilation(i).HybridControlType = DataHeatBalance::HybridCtrlType::Close;
    4739              :                                 } else {
    4740            0 :                                     if (SimpleControlType == 1) {
    4741            0 :                                         state.dataHeatBal->Ventilation(i).HybridControlType = DataHeatBalance::HybridCtrlType::Global;
    4742            0 :                                         state.dataHeatBal->Ventilation(i).HybridControlMasterNum = hybridVentMgr.VentilationPtr;
    4743              :                                     }
    4744              :                                 }
    4745              :                             }
    4746              :                         }
    4747              :                         // Setup flag for Mixing objects
    4748            0 :                         for (i = 1; i <= state.dataHeatBal->TotMixing; ++i) {
    4749            0 :                             if (state.dataHeatBal->Mixing(i).ZonePtr == ControlledZoneNum) {
    4750            0 :                                 state.dataHeatBal->Mixing(i).HybridControlType = DataHeatBalance::HybridCtrlType::Indiv;
    4751            0 :                                 if (hybridVentMgr.ctrlStatus == VentCtrlStatus::Close) {
    4752            0 :                                     state.dataHeatBal->Mixing(i).HybridControlType = DataHeatBalance::HybridCtrlType::Close;
    4753              :                                 } else {
    4754            0 :                                     if (SimpleControlType == 1) {
    4755            0 :                                         state.dataHeatBal->Mixing(i).HybridControlType = DataHeatBalance::HybridCtrlType::Global;
    4756            0 :                                         state.dataHeatBal->Mixing(i).HybridControlMasterNum = hybridVentMgr.VentilationPtr;
    4757              :                                     }
    4758              :                                 }
    4759              :                             }
    4760              :                         }
    4761              :                     }
    4762              :                 }
    4763              :             }
    4764           13 :         } else if (hybridVentMgr.simpleControlTypeSched != nullptr) {
    4765            0 :             SimpleControlType = hybridVentMgr.simpleControlTypeSched->getCurrentVal();
    4766              :             // Hybrid ventilation manager is applied to zone component
    4767              :             // setup flag for ventilation objects
    4768            0 :             for (i = 1; i <= state.dataHeatBal->TotVentilation; ++i) {
    4769            0 :                 if (state.dataHeatBal->Ventilation(i).ZonePtr == hybridVentMgr.ControlledZoneNum) {
    4770            0 :                     state.dataHeatBal->Ventilation(i).HybridControlType = DataHeatBalance::HybridCtrlType::Indiv;
    4771            0 :                     if (hybridVentMgr.ctrlStatus == VentCtrlStatus::Close) {
    4772            0 :                         state.dataHeatBal->Ventilation(i).HybridControlType = DataHeatBalance::HybridCtrlType::Close;
    4773              :                     } else {
    4774            0 :                         if (SimpleControlType == 1) {
    4775            0 :                             state.dataHeatBal->Ventilation(i).HybridControlType = DataHeatBalance::HybridCtrlType::Global;
    4776            0 :                             state.dataHeatBal->Ventilation(i).HybridControlMasterNum = hybridVentMgr.VentilationPtr;
    4777              :                         }
    4778              :                     }
    4779              :                 }
    4780              :             }
    4781              :             // Setup flag for Mixing objects
    4782            0 :             for (i = 1; i <= state.dataHeatBal->TotMixing; ++i) {
    4783            0 :                 if (state.dataHeatBal->Mixing(i).ZonePtr == hybridVentMgr.ControlledZoneNum) {
    4784            0 :                     state.dataHeatBal->Mixing(i).HybridControlType = DataHeatBalance::HybridCtrlType::Indiv;
    4785            0 :                     if (hybridVentMgr.ctrlStatus == VentCtrlStatus::Close) {
    4786            0 :                         state.dataHeatBal->Mixing(i).HybridControlType = DataHeatBalance::HybridCtrlType::Close;
    4787              :                     } else {
    4788            0 :                         if (SimpleControlType == 1) {
    4789            0 :                             state.dataHeatBal->Mixing(i).HybridControlType = DataHeatBalance::HybridCtrlType::Global;
    4790            0 :                             state.dataHeatBal->Mixing(i).HybridControlMasterNum = hybridVentMgr.VentilationPtr;
    4791              :                         }
    4792              :                     }
    4793              :                 }
    4794              :             }
    4795              :         }
    4796           13 :     }
    4797              : 
    4798            2 :     bool GetHybridVentilationControlStatus(EnergyPlusData &state, int const ZoneNum) // Index of zone
    4799              :     {
    4800              : 
    4801              :         // SUBROUTINE INFORMATION:
    4802              :         //       AUTHOR         Lixing Gu
    4803              :         //       DATE WRITTEN   July 2010
    4804              :         //       MODIFIED       na
    4805              :         //       RE-ENGINEERED  na
    4806              : 
    4807              :         // PURPOSE OF THIS SUBROUTINE:
    4808              :         // This routine was designed to find whether this zone is controlled by hybrid ventilation
    4809              :         // ventilation control option.
    4810              : 
    4811              :         // Return value
    4812              :         bool VentControl; // Set to true if ventilation control in the same zone
    4813              : 
    4814            2 :         if (state.dataAvail->GetHybridInputFlag) { // First time subroutine has been entered
    4815            1 :             GetHybridVentilationInputs(state);
    4816            1 :             state.dataAvail->GetHybridInputFlag = false;
    4817              :         }
    4818              : 
    4819            2 :         VentControl = false;
    4820              : 
    4821            2 :         for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumHybridVentSysAvailMgrs; ++SysAvailNum) {
    4822            0 :             if (state.dataAvail->HybridVentData(SysAvailNum).ControlledZoneNum == ZoneNum) {
    4823            0 :                 if (state.dataAvail->HybridVentData(SysAvailNum).simpleControlTypeSched != nullptr) {
    4824            0 :                     VentControl = true;
    4825              :                 }
    4826              :             }
    4827              :         }
    4828              : 
    4829            2 :         return VentControl;
    4830              :     }
    4831              : 
    4832              : } // namespace Avail
    4833              : 
    4834              : } // namespace EnergyPlus
        

Generated by: LCOV version 2.0-1