LCOV - code coverage report
Current view: top level - EnergyPlus - ZoneTempPredictorCorrector.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 2959 4318 68.5 %
Date: 2023-01-17 19:17:23 Functions: 44 46 95.7 %

          Line data    Source code
       1             : // EnergyPlus, Copyright (c) 1996-2023, The Board of Trustees of the University of Illinois,
       2             : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
       3             : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
       4             : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
       5             : // contributors. All rights reserved.
       6             : //
       7             : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
       8             : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
       9             : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
      10             : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
      11             : // derivative works, and perform publicly and display publicly, and to permit others to do so.
      12             : //
      13             : // Redistribution and use in source and binary forms, with or without modification, are permitted
      14             : // provided that the following conditions are met:
      15             : //
      16             : // (1) Redistributions of source code must retain the above copyright notice, this list of
      17             : //     conditions and the following disclaimer.
      18             : //
      19             : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
      20             : //     conditions and the following disclaimer in the documentation and/or other materials
      21             : //     provided with the distribution.
      22             : //
      23             : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
      24             : //     the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
      25             : //     used to endorse or promote products derived from this software without specific prior
      26             : //     written permission.
      27             : //
      28             : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
      29             : //     without changes from the version obtained under this License, or (ii) Licensee makes a
      30             : //     reference solely to the software portion of its product, Licensee must refer to the
      31             : //     software as "EnergyPlus version X" software, where "X" is the version number Licensee
      32             : //     obtained under this License and may not use a different name for the software. Except as
      33             : //     specifically required in this Section (4), Licensee shall not use in a company name, a
      34             : //     product name, in advertising, publicity, or other promotional activities any name, trade
      35             : //     name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
      36             : //     similar designation, without the U.S. Department of Energy's prior written consent.
      37             : //
      38             : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
      39             : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
      40             : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
      41             : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      42             : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      43             : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      44             : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      45             : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      46             : // POSSIBILITY OF SUCH DAMAGE.
      47             : 
      48             : // C++ Headers
      49             : #include <cmath>
      50             : #include <string>
      51             : 
      52             : // ObjexxFCL Headers
      53             : #include <ObjexxFCL/Array.functions.hh>
      54             : #include <ObjexxFCL/Fmath.hh>
      55             : 
      56             : // EnergyPlus Headers
      57             : #include <AirflowNetwork/Elements.hpp>
      58             : #include <AirflowNetwork/Solver.hpp>
      59             : #include <EnergyPlus/Construction.hh>
      60             : #include <EnergyPlus/Data/EnergyPlusData.hh>
      61             : #include <EnergyPlus/DataDefineEquip.hh>
      62             : #include <EnergyPlus/DataEnvironment.hh>
      63             : #include <EnergyPlus/DataHVACGlobals.hh>
      64             : #include <EnergyPlus/DataHeatBalFanSys.hh>
      65             : #include <EnergyPlus/DataHeatBalSurface.hh>
      66             : #include <EnergyPlus/DataHeatBalance.hh>
      67             : #include <EnergyPlus/DataIPShortCuts.hh>
      68             : #include <EnergyPlus/DataLoopNode.hh>
      69             : #include <EnergyPlus/DataPrecisionGlobals.hh>
      70             : #include <EnergyPlus/DataRoomAirModel.hh>
      71             : #include <EnergyPlus/DataSizing.hh>
      72             : #include <EnergyPlus/DataStringGlobals.hh>
      73             : #include <EnergyPlus/DataSurfaces.hh>
      74             : #include <EnergyPlus/DataZoneControls.hh>
      75             : #include <EnergyPlus/DataZoneEnergyDemands.hh>
      76             : #include <EnergyPlus/DataZoneEquipment.hh>
      77             : #include <EnergyPlus/FaultsManager.hh>
      78             : #include <EnergyPlus/FileSystem.hh>
      79             : #include <EnergyPlus/General.hh>
      80             : #include <EnergyPlus/GeneralRoutines.hh>
      81             : #include <EnergyPlus/GlobalNames.hh>
      82             : #include <EnergyPlus/HeatBalFiniteDiffManager.hh>
      83             : #include <EnergyPlus/HeatBalanceSurfaceManager.hh>
      84             : #include <EnergyPlus/HybridModel.hh>
      85             : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      86             : #include <EnergyPlus/InternalHeatGains.hh>
      87             : #include <EnergyPlus/OutputProcessor.hh>
      88             : #include <EnergyPlus/OutputReportPredefined.hh>
      89             : #include <EnergyPlus/OutputReportTabular.hh>
      90             : #include <EnergyPlus/Psychrometrics.hh>
      91             : #include <EnergyPlus/RoomAirModelAirflowNetwork.hh>
      92             : #include <EnergyPlus/RoomAirModelManager.hh>
      93             : #include <EnergyPlus/ScheduleManager.hh>
      94             : #include <EnergyPlus/ThermalComfort.hh>
      95             : #include <EnergyPlus/UtilityRoutines.hh>
      96             : #include <EnergyPlus/WeatherManager.hh>
      97             : #include <EnergyPlus/ZonePlenum.hh>
      98             : #include <EnergyPlus/ZoneTempPredictorCorrector.hh>
      99             : 
     100             : namespace EnergyPlus::ZoneTempPredictorCorrector {
     101             : 
     102             : // MODULE INFORMATION:
     103             : //       AUTHOR         Russell D. Taylor
     104             : //       DATE WRITTEN   1997
     105             : //       MODIFIED       Aug 2001(FW): make SNLoadHeatRate public
     106             : //                      Nov 2010  BN(FSEC) added TemperatureAndHumidity Control
     107             : //       RE-ENGINEERED  July 2003 (Peter Graham Ellis)
     108             : //                      July 2006 (BG) added operative temp control
     109             : //                      February 2008 (BG) reworked zone air temp histories
     110             : 
     111             : // PURPOSE OF THIS MODULE:
     112             : // This module contains routines to predict and correct zone temperatures.
     113             : //  also includes zone thermostatic controlling
     114             : //  Model the "Air Heat Balance" part of the the "Zone Heat Balance Method."
     115             : 
     116             : // METHODOLOGY EMPLOYED:
     117             : // apply model equations for air heat balance solved for zone air temp.
     118             : //    sum up values for the terms (e.g SUMHAT, SUMHA etc. )
     119             : //    "Predict" step is used to get zone loads for HVAC equipment
     120             : //    "correct" step determines zone air temp with available HVAC
     121             : 
     122             : enum class ZoneControlTypes
     123             : {
     124             :     Invalid = -1,
     125             :     TStat = 1,
     126             :     TCTStat = 2,
     127             :     OTTStat = 3,
     128             :     HStat = 4,
     129             :     TandHStat = 5,
     130             :     StagedDual = 6,
     131             :     Num
     132             : };
     133             : 
     134             : enum class AdaptiveComfortModel
     135             : {
     136             :     Invalid = -1,
     137             :     ADAP_NONE = 1,
     138             :     ASH55_CENTRAL = 2,
     139             :     ASH55_UPPER_90 = 3,
     140             :     ASH55_UPPER_80 = 4,
     141             :     CEN15251_CENTRAL = 5,
     142             :     CEN15251_UPPER_I = 6,
     143             :     CEN15251_UPPER_II = 7,
     144             :     CEN15251_UPPER_III = 8,
     145             :     Num
     146             : };
     147             : 
     148             : static constexpr std::array<std::string_view, static_cast<int>(DataHVACGlobals::ThermostatType::Num)> ValidControlTypes = {
     149             :     "Uncontrolled",
     150             :     "ThermostatSetpoint:SingleHeating",
     151             :     "ThermostatSetpoint:SingleCooling",
     152             :     "ThermostatSetpoint:SingleHeatingOrCooling",
     153             :     "ThermostatSetpoint:DualSetpoint"};
     154             : 
     155             : static constexpr std::array<std::string_view, static_cast<int>(DataHVACGlobals::ThermostatType::Num)> ValidControlTypesUC = {
     156             :     "UNCONTROLLED",
     157             :     "THERMOSTATSETPOINT:SINGLEHEATING",
     158             :     "THERMOSTATSETPOINT:SINGLECOOLING",
     159             :     "THERMOSTATSETPOINT:SINGLEHEATINGORCOOLING",
     160             :     "THERMOSTATSETPOINT:DUALSETPOINT"};
     161             : 
     162             : static constexpr std::array<std::string_view, static_cast<int>(DataHVACGlobals::ThermostatType::Num)> ValidComfortControlTypes = {
     163             :     "Uncontrolled",
     164             :     "ThermostatSetpoint:ThermalComfort:Fanger:SingleHeating",
     165             :     "ThermostatSetpoint:ThermalComfort:Fanger:SingleCooling",
     166             :     "ThermostatSetpoint:ThermalComfort:Fanger:SingleHeatingOrCooling",
     167             :     "ThermostatSetpoint:ThermalComfort:Fanger:DualSetpoint"};
     168             : 
     169             : static constexpr std::array<std::string_view, static_cast<int>(DataHVACGlobals::ThermostatType::Num)> ValidComfortControlTypesUC = {
     170             :     "UNCONTROLLED",
     171             :     "THERMOSTATSETPOINT:THERMALCOMFORT:FANGER:SINGLEHEATING",
     172             :     "THERMOSTATSETPOINT:THERMALCOMFORT:FANGER:SINGLECOOLING",
     173             :     "THERMOSTATSETPOINT:THERMALCOMFORT:FANGER:SINGLEHEATINGORCOOLING",
     174             :     "THERMOSTATSETPOINT:THERMALCOMFORT:FANGER:DUALSETPOINT"};
     175             : 
     176         771 : Array1D_string const cZControlTypes(6,
     177             :                                     {"ZoneControl:Thermostat",
     178             :                                      "ZoneControl:Thermostat:ThermalComfort",
     179             :                                      "ZoneControl:Thermostat:OperativeTemperature",
     180             :                                      "ZoneControl:Humidistat",
     181             :                                      "ZoneControl:Thermostat:TemperatureAndHumidity",
     182         771 :                                      "ZoneControl:Thermostat:StagedDualSetpoint"});
     183             : 
     184         771 : Array1D_string const AdaptiveComfortModelTypes(8,
     185             :                                                {"None",
     186             :                                                 "AdaptiveASH55CentralLine",
     187             :                                                 "AdaptiveASH5590PercentUpperLine",
     188             :                                                 "AdaptiveASH5580PercentUpperLine",
     189             :                                                 "AdaptiveCEN15251CentralLine",
     190             :                                                 "AdaptiveCEN15251CategoryIUpperLine",
     191             :                                                 "AdaptiveCEN15251CategoryIIUpperLine",
     192         771 :                                                 "AdaptiveCEN15251CategoryIIIUpperLine"});
     193             : 
     194             : // Functions
     195    13440069 : void ManageZoneAirUpdates(EnergyPlusData &state,
     196             :                           DataHeatBalFanSys::PredictorCorrectorCtrl const UpdateType, // Can be iGetZoneSetPoints, iPredictStep, iCorrectStep
     197             :                           Real64 &ZoneTempChange,                                     // Temp change in zone air btw previous and current timestep
     198             :                           bool const ShortenTimeStepSys,
     199             :                           bool const UseZoneTimeStepHistory, // if true then use zone timestep history, if false use system time step
     200             :                           Real64 const PriorTimeStep         // the old value for timestep length is passed for possible use in interpolating
     201             : )
     202             : {
     203             : 
     204             :     // SUBROUTINE INFORMATION
     205             :     //       AUTHOR         Russ Taylor
     206             :     //       DATE WRITTEN   September 1998
     207             :     //       MODIFIED       na
     208             :     //       RE-ENGINEERED  Brent Griffith Feb. 2008,  added arguments
     209             : 
     210             :     // PURPOSE OF THIS SUBROUTINE:
     211             :     // This subroutine predicts or corrects the zone air temperature
     212             :     // depending on the simulation status and determines the correct
     213             :     // temperature setpoint for each zone from the schedule manager.
     214             : 
     215    13440069 :     if (state.dataZoneCtrls->GetZoneAirStatsInputFlag) {
     216         762 :         GetZoneAirSetPoints(state);
     217         762 :         state.dataZoneCtrls->GetZoneAirStatsInputFlag = false;
     218             :     }
     219             : 
     220    13440069 :     InitZoneAirSetPoints(state);
     221             : 
     222    13440069 :     switch (UpdateType) {
     223     2568551 :     case DataHeatBalFanSys::PredictorCorrectorCtrl::GetZoneSetPoints: {
     224     2568551 :         CalcZoneAirTempSetPoints(state);
     225     2568551 :     } break;
     226     3623998 :     case DataHeatBalFanSys::PredictorCorrectorCtrl::PredictStep: {
     227     3623998 :         PredictSystemLoads(state, ShortenTimeStepSys, UseZoneTimeStepHistory, PriorTimeStep);
     228     3623998 :     } break;
     229     3623760 :     case DataHeatBalFanSys::PredictorCorrectorCtrl::CorrectStep: {
     230     3623760 :         ZoneTempChange = correctZoneAirTemps(state, UseZoneTimeStepHistory);
     231     3623760 :     } break;
     232           0 :     case DataHeatBalFanSys::PredictorCorrectorCtrl::RevertZoneTimestepHistories: {
     233           0 :         RevertZoneTimestepHistories(state);
     234           0 :     } break;
     235     2568313 :     case DataHeatBalFanSys::PredictorCorrectorCtrl::PushZoneTimestepHistories: {
     236     2568313 :         PushZoneTimestepHistories(state);
     237     2568313 :     } break;
     238     1055447 :     case DataHeatBalFanSys::PredictorCorrectorCtrl::PushSystemTimestepHistories: {
     239     1055447 :         PushSystemTimestepHistories(state);
     240     1055447 :     } break;
     241           0 :     default:
     242           0 :         break;
     243             :     }
     244    13440069 : }
     245             : 
     246         771 : void GetZoneAirSetPoints(EnergyPlusData &state)
     247             : {
     248             : 
     249             :     // SUBROUTINE INFORMATION:
     250             :     //       AUTHOR         Russell Taylor
     251             :     //       DATE WRITTEN   September 1998
     252             :     //       MODIFIED       L.Gu, May 2006, B. Griffith June 2006
     253             :     //       RE-ENGINEERED  na
     254             : 
     255             :     // PURPOSE OF THIS SUBROUTINE:
     256             :     // This subroutine gets the inputs related to thermostatic control.
     257             : 
     258             :     // METHODOLOGY EMPLOYED:
     259             :     // Uses the status flags to trigger events.
     260             : 
     261             :     // Using/Aliasing
     262             :     using General::CheckCreatedZoneItemName;
     263             :     using General::FindNumberInList;
     264             : 
     265             :     using ScheduleManager::CheckScheduleValue;
     266             :     using ScheduleManager::CheckScheduleValueMinMax;
     267             :     using ScheduleManager::GetScheduleIndex;
     268             :     using ScheduleManager::GetScheduleMaxValue;
     269             :     using ScheduleManager::GetScheduleMinValue;
     270             : 
     271             :     // SUBROUTINE PARAMETER DEFINITIONS:
     272             :     static constexpr std::string_view RoutineName("GetZoneAirSetpoints: ");
     273             : 
     274             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     275             :     int TempControlledZoneNum; // The Splitter that you are currently loading input into
     276             :     int NumAlphas;
     277             :     int NumNums;
     278             :     int ControlTypeNum;
     279             :     int IOStat;
     280         771 :     bool ErrorsFound(false);
     281             :     bool errFlag;
     282             :     int CTIndex;
     283             :     int HumidControlledZoneNum; // The Humidity Controller that information is being loaded into
     284             :     bool ValidScheduleControlType;
     285             :     bool ValidRadFractSched;          // check for if radiative fraction schedule has valid numbers
     286             :     bool ValidZoneOvercoolRangeSched; // check for if Zone Overcool range schedule has valid numbers
     287             :     int SchedMin;
     288             :     int SchedMax;
     289             :     int ActualZoneNum;
     290             :     int SchedTypeIndex;
     291             : 
     292             :     int ComfortControlledZoneNum; // The Splitter that you are currently loading input into
     293             :     int i;
     294             :     int IZoneCount;
     295             :     int found;
     296             :     int NumStageControlledZones; // Number of staged controlled objects
     297             :     int StageControlledZoneNum;  // Index for staged controlled zones
     298             : 
     299        1542 :     Array1D_int CTSchedMapToControlledZone;
     300        1542 :     Array1D_int CCmSchedMapToControlledZone;
     301             :     int Item;
     302             :     int Item1;
     303             :     int ZLItem;
     304             : 
     305         665 :     struct NeededControlTypes
     306             :     {
     307             :         // Members 4= the four control types + uncontrolled
     308             :         std::array<bool, static_cast<int>(DataHVACGlobals::ThermostatType::Num)> MustHave = {false, false, false, false, false};
     309             :         std::array<bool, static_cast<int>(DataHVACGlobals::ThermostatType::Num)> DidHave = {false, false, false, false, false};
     310             :     };
     311             : 
     312           1 :     struct NeededComfortControlTypes
     313             :     {
     314             :         // Members 4= the four control types + uncontrolled
     315             :         std::array<bool, static_cast<int>(DataHVACGlobals::ThermostatType::Num)> MustHave = {false, false, false, false, false};
     316             :         std::array<bool, static_cast<int>(DataHVACGlobals::ThermostatType::Num)> DidHave = {false, false, false, false, false};
     317             :     };
     318             : 
     319             :     // Object Data
     320        1542 :     Array1D<NeededControlTypes> TStatControlTypes;
     321        1542 :     Array1D<NeededComfortControlTypes> TComfortControlTypes;
     322             : 
     323             :     // Formats
     324             :     static constexpr std::string_view Header(
     325             :         "! <Zone Volume Capacitance Multiplier>, Sensible Heat Capacity Multiplier, Moisture Capacity Multiplier, Carbon "
     326             :         "Dioxide Capacity Multiplier, Generic Contaminant Capacity Multiplier\n");
     327             :     static constexpr std::string_view Format_701("Zone Volume Capacitance Multiplier,{:8.3F} ,{:8.3F},{:8.3F},{:8.3F}\n");
     328             : 
     329         771 :     auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
     330         771 :     auto &TStatObjects = state.dataZoneCtrls->TStatObjects;
     331         771 :     auto &NumTStatStatements = state.dataZoneCtrls->NumTStatStatements;
     332         771 :     auto &NumTempControlledZones = state.dataZoneCtrls->NumTempControlledZones;
     333         771 :     auto &Zone = state.dataHeatBal->Zone;
     334         771 :     auto &ZoneList = state.dataHeatBal->ZoneList;
     335         771 :     auto &TempControlledZone = state.dataZoneCtrls->TempControlledZone;
     336         771 :     auto &HumidityControlZone = state.dataZoneCtrls->HumidityControlZone;
     337         771 :     auto &ComfortTStatObjects = state.dataZoneCtrls->ComfortTStatObjects;
     338         771 :     auto &ComfortControlledZone = state.dataZoneCtrls->ComfortControlledZone;
     339         771 :     auto &NumOfZones = state.dataGlobal->NumOfZones;
     340         771 :     auto &StageControlledZone = state.dataZoneCtrls->StageControlledZone;
     341         771 :     auto &SetPointSingleHeating = state.dataZoneTempPredictorCorrector->SetPointSingleHeating;
     342         771 :     auto &SetPointSingleCooling = state.dataZoneTempPredictorCorrector->SetPointSingleCooling;
     343         771 :     auto &cAlphaArgs = state.dataIPShortCut->cAlphaArgs;
     344         771 :     auto &rNumericArgs = state.dataIPShortCut->rNumericArgs;
     345         771 :     auto &lNumericFieldBlanks = state.dataIPShortCut->lNumericFieldBlanks;
     346         771 :     auto &lAlphaFieldBlanks = state.dataIPShortCut->lAlphaFieldBlanks;
     347         771 :     auto &cAlphaFieldNames = state.dataIPShortCut->cAlphaFieldNames;
     348         771 :     auto &cNumericFieldNames = state.dataIPShortCut->cNumericFieldNames;
     349         771 :     auto &inputProcessor = state.dataInputProcessing->inputProcessor;
     350         771 :     auto &SetPointDualHeatCool = state.dataZoneTempPredictorCorrector->SetPointDualHeatCool;
     351             : 
     352         771 :     cCurrentModuleObject = cZControlTypes(static_cast<int>(ZoneControlTypes::TStat));
     353         771 :     NumTStatStatements = inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     354         771 :     TStatObjects.allocate(NumTStatStatements);
     355             : 
     356             :     // Pre-scan for use of Zone lists in TStat statements (i.e. Global application of TStat)
     357         771 :     NumTempControlledZones = 0;
     358        4719 :     for (Item = 1; Item <= NumTStatStatements; ++Item) {
     359        3948 :         inputProcessor->getObjectItem(state,
     360             :                                       cCurrentModuleObject,
     361             :                                       Item,
     362             :                                       cAlphaArgs,
     363             :                                       NumAlphas,
     364             :                                       rNumericArgs,
     365             :                                       NumNums,
     366             :                                       IOStat,
     367             :                                       lNumericFieldBlanks,
     368             :                                       lAlphaFieldBlanks,
     369             :                                       cAlphaFieldNames,
     370             :                                       cNumericFieldNames);
     371        3948 :         UtilityRoutines::IsNameEmpty(state, cAlphaArgs(1), cCurrentModuleObject, ErrorsFound);
     372             : 
     373        3948 :         TStatObjects(Item).Name = cAlphaArgs(1);
     374        3948 :         Item1 = UtilityRoutines::FindItemInList(cAlphaArgs(2), Zone);
     375        3948 :         ZLItem = 0;
     376        3948 :         if (Item1 == 0 && state.dataHeatBal->NumOfZoneLists > 0) ZLItem = UtilityRoutines::FindItemInList(cAlphaArgs(2), ZoneList);
     377        3948 :         if (Item1 > 0) {
     378        3939 :             TStatObjects(Item).TempControlledZoneStartPtr = NumTempControlledZones + 1;
     379        3939 :             ++NumTempControlledZones;
     380        3939 :             TStatObjects(Item).NumOfZones = 1;
     381        3939 :             TStatObjects(Item).ZoneListActive = false;
     382        3939 :             TStatObjects(Item).ZoneOrZoneListPtr = Item1;
     383           9 :         } else if (ZLItem > 0) {
     384           9 :             TStatObjects(Item).TempControlledZoneStartPtr = NumTempControlledZones + 1;
     385           9 :             NumTempControlledZones += ZoneList(ZLItem).NumOfZones;
     386           9 :             TStatObjects(Item).NumOfZones = ZoneList(ZLItem).NumOfZones;
     387           9 :             TStatObjects(Item).ZoneListActive = true;
     388           9 :             TStatObjects(Item).ZoneOrZoneListPtr = ZLItem;
     389             :         } else {
     390           0 :             ShowSevereError(
     391           0 :                 state, cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) + "\" not found.");
     392           0 :             ErrorsFound = true;
     393             :         }
     394             :     }
     395             : 
     396         771 :     if (ErrorsFound) {
     397           0 :         ShowSevereError(state, "GetZoneAirSetpoints: Errors with invalid names in " + cCurrentModuleObject + " objects.");
     398           0 :         ShowContinueError(state, "...These will not be read in.  Other errors may occur.");
     399           0 :         NumTempControlledZones = 0;
     400             :     }
     401             : 
     402         771 :     if (NumTempControlledZones > 0) {
     403         665 :         TempControlledZone.allocate(NumTempControlledZones);
     404         665 :         TStatControlTypes.allocate(NumTempControlledZones); // Number of set point types
     405         665 :         CTSchedMapToControlledZone.dimension(NumTempControlledZones, 0);
     406             : 
     407         665 :         TempControlledZoneNum = 0;
     408         665 :         state.dataZoneTempPredictorCorrector->NumOnOffCtrZone = 0;
     409        4613 :         for (Item = 1; Item <= NumTStatStatements; ++Item) {
     410        3948 :             inputProcessor->getObjectItem(state,
     411             :                                           cCurrentModuleObject,
     412             :                                           Item,
     413             :                                           cAlphaArgs,
     414             :                                           NumAlphas,
     415             :                                           rNumericArgs,
     416             :                                           NumNums,
     417             :                                           IOStat,
     418             :                                           lNumericFieldBlanks,
     419             :                                           lAlphaFieldBlanks,
     420             :                                           cAlphaFieldNames,
     421             :                                           cNumericFieldNames);
     422        7930 :             for (Item1 = 1; Item1 <= TStatObjects(Item).NumOfZones; ++Item1) {
     423        3982 :                 ++TempControlledZoneNum;
     424        3982 :                 if (TStatObjects(Item).ZoneListActive) {
     425          43 :                     cAlphaArgs(2) = Zone(ZoneList(TStatObjects(Item).ZoneOrZoneListPtr).Zone(Item1)).Name;
     426             :                 }
     427        7964 :                 int ZoneAssigned = UtilityRoutines::FindItemInList(
     428        7964 :                     cAlphaArgs(2), TempControlledZone, &DataZoneControls::ZoneTempControls::ZoneName, TempControlledZoneNum - 1);
     429        3982 :                 if (ZoneAssigned == 0) {
     430        3982 :                     TempControlledZone(TempControlledZoneNum).ZoneName = cAlphaArgs(2);
     431        3982 :                     TempControlledZone(TempControlledZoneNum).ActualZoneNum = UtilityRoutines::FindItemInList(cAlphaArgs(2), Zone);
     432        3982 :                     if (TempControlledZone(TempControlledZoneNum).ActualZoneNum == 0) {
     433           0 :                         ShowSevereError(state,
     434           0 :                                         cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) +
     435             :                                             "\" not found.");
     436           0 :                         ErrorsFound = true;
     437             :                     } else {
     438        3982 :                         Zone(TempControlledZone(TempControlledZoneNum).ActualZoneNum).TempControlledZoneIndex = TempControlledZoneNum;
     439             :                     }
     440             :                 } else {
     441           0 :                     TempControlledZone(TempControlledZoneNum).ZoneName = cAlphaArgs(2); // for continuity
     442           0 :                     ShowSevereError(state,
     443           0 :                                     cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) +
     444             :                                         "\" zone previously assigned.");
     445           0 :                     ShowContinueError(state, "...Zone was previously assigned to Thermostat=\"" + TempControlledZone(ZoneAssigned).Name + "\".");
     446           0 :                     ErrorsFound = true;
     447           0 :                     continue;
     448             :                 }
     449             : 
     450        3982 :                 if (!TStatObjects(Item).ZoneListActive) {
     451        3939 :                     TempControlledZone(TempControlledZoneNum).Name = cAlphaArgs(1);
     452             :                 } else {
     453         172 :                     CheckCreatedZoneItemName(state,
     454             :                                              RoutineName,
     455             :                                              cCurrentModuleObject,
     456          43 :                                              Zone(ZoneList(TStatObjects(Item).ZoneOrZoneListPtr).Zone(Item1)).Name,
     457          43 :                                              ZoneList(TStatObjects(Item).ZoneOrZoneListPtr).MaxZoneNameLength,
     458          43 :                                              TStatObjects(Item).Name,
     459             :                                              TempControlledZone,
     460             :                                              TempControlledZoneNum - 1,
     461          43 :                                              TempControlledZone(TempControlledZoneNum).Name,
     462             :                                              errFlag);
     463          43 :                     if (errFlag) ErrorsFound = true;
     464             :                 }
     465             : 
     466        3982 :                 TempControlledZone(TempControlledZoneNum).ControlTypeSchedName = cAlphaArgs(3);
     467        3982 :                 TempControlledZone(TempControlledZoneNum).CTSchedIndex = GetScheduleIndex(state, cAlphaArgs(3));
     468        3982 :                 if (Item1 == 1) { // only show error on first of several if zone list
     469        3948 :                     if (TempControlledZone(TempControlledZoneNum).CTSchedIndex == 0) {
     470           0 :                         ShowSevereError(state,
     471           0 :                                         cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(3) + "=\"" + cAlphaArgs(3) +
     472             :                                             "\" not found.");
     473           0 :                         ErrorsFound = true;
     474             :                     } else {
     475             :                         // Check validity of control types.
     476        3948 :                         ValidScheduleControlType =
     477        7896 :                             CheckScheduleValueMinMax(state, TempControlledZone(TempControlledZoneNum).CTSchedIndex, ">=", 0.0, "<=", 4.0);
     478        3948 :                         if (!ValidScheduleControlType) {
     479           0 :                             ShowSevereError(state,
     480           0 :                                             cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid range " + cAlphaFieldNames(2) + "=\"" +
     481           0 :                                                 cAlphaArgs(2) + "\"");
     482           0 :                             ShowContinueError(state, "..contains values outside of range [0,4].");
     483           0 :                             ErrorsFound = true;
     484             :                         }
     485             :                     }
     486             :                 }
     487             : 
     488        3982 :                 if (lAlphaFieldBlanks(7)) {
     489        2872 :                     NumAlphas = 5;
     490        1110 :                 } else if (lAlphaFieldBlanks(9)) {
     491         468 :                     NumAlphas = 7;
     492         642 :                 } else if (lAlphaFieldBlanks(11)) {
     493         642 :                     NumAlphas = 9;
     494             :                 }
     495             : 
     496        3982 :                 TempControlledZone(TempControlledZoneNum).NumControlTypes = nint((NumAlphas - 3.0) / 2.0);
     497        3982 :                 TempControlledZone(TempControlledZoneNum).ControlType.allocate(TempControlledZone(TempControlledZoneNum).NumControlTypes);
     498        3982 :                 TempControlledZone(TempControlledZoneNum).ControlTypeName.allocate(TempControlledZone(TempControlledZoneNum).NumControlTypes);
     499        3982 :                 TempControlledZone(TempControlledZoneNum).ControlTypeEnum.allocate(TempControlledZone(TempControlledZoneNum).NumControlTypes);
     500             : 
     501        9716 :                 for (ControlTypeNum = 1; ControlTypeNum <= TempControlledZone(TempControlledZoneNum).NumControlTypes; ++ControlTypeNum) {
     502             : 
     503        5734 :                     TempControlledZone(TempControlledZoneNum).ControlType(ControlTypeNum) = cAlphaArgs(nint(2.0 * ControlTypeNum - 1 + 3));
     504        5734 :                     TempControlledZone(TempControlledZoneNum).ControlTypeName(ControlTypeNum) = cAlphaArgs(nint(2.0 * ControlTypeNum + 3));
     505             : 
     506        5734 :                     if (!TempControlledZone(TempControlledZoneNum).ControlType(ControlTypeNum).empty()) {
     507             :                         auto ctrlType = static_cast<DataHVACGlobals::ThermostatType>(
     508        5734 :                             getEnumerationValue(ValidControlTypesUC, TempControlledZone(TempControlledZoneNum).ControlType(ControlTypeNum)));
     509        5734 :                         TempControlledZone(TempControlledZoneNum).ControlTypeEnum(ControlTypeNum) = ctrlType;
     510        5734 :                         if (ctrlType == DataHVACGlobals::ThermostatType::Invalid) {
     511           0 :                             ShowSevereError(state,
     512           0 :                                             cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " +
     513           0 :                                                 cAlphaFieldNames(nint(2.0 * ControlTypeNum - 1 + 3)) + "=\"" +
     514           0 :                                                 cAlphaArgs(nint(2.0 * ControlTypeNum - 1 + 3)) + "\"");
     515           0 :                             ErrorsFound = true;
     516             :                         }
     517             :                     } else {
     518           0 :                         ShowSevereError(state,
     519           0 :                                         cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " +
     520           0 :                                             cAlphaFieldNames(nint(2.0 * ControlTypeNum - 1 + 3)) + "=\"<blank>\"");
     521           0 :                         ErrorsFound = true;
     522             :                     }
     523             :                 }
     524        3982 :                 if (NumNums > 0) {
     525           9 :                     if (rNumericArgs(1) >= 0.0) {
     526           9 :                         TempControlledZone(TempControlledZoneNum).DeltaTCutSet = rNumericArgs(1);
     527           9 :                         if (rNumericArgs(1) > 0.0) state.dataZoneTempPredictorCorrector->NumOnOffCtrZone++;
     528             :                     } else {
     529           0 :                         ShowSevereError(
     530             :                             state,
     531           0 :                             format("{}=\"{} invalid {}=[{:.0T}].", cCurrentModuleObject, cAlphaArgs(1), cNumericFieldNames(1), rNumericArgs(1)));
     532           0 :                         ShowContinueError(state, "..Allowable values must be greater or equal to 0");
     533           0 :                         ErrorsFound = true;
     534             :                     }
     535             :                 }
     536        3982 :                 if (TempControlledZone(TempControlledZoneNum).DeltaTCutSet > 0.0) {
     537          14 :                     for (ControlTypeNum = 1; ControlTypeNum <= TempControlledZone(TempControlledZoneNum).NumControlTypes; ++ControlTypeNum) {
     538           7 :                         if (UtilityRoutines::SameString(TempControlledZone(TempControlledZoneNum).ControlType(ControlTypeNum),
     539           7 :                                                         "ThermostatSetpoint:SingleHeatingOrCooling")) {
     540           0 :                             ShowWarningError(state,
     541           0 :                                              cCurrentModuleObject + "=\"" + cAlphaArgs(1) +
     542             :                                                  ": The choice of Temperature Difference Between Cutout And Setpoint will not be applied to "
     543             :                                                  "ThermostatSetpoint:SingleHeatingOrCooling.");
     544             :                         }
     545             :                     }
     546             :                 }
     547             :             }
     548             :         } // NumTStatStatements
     549             :     }     // Check on number of TempControlledZones
     550             : 
     551         771 :     cCurrentModuleObject = ValidControlTypesUC[static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeating)];
     552         771 :     state.dataZoneTempPredictorCorrector->NumSingleTempHeatingControls = inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     553             : 
     554         771 :     if (state.dataZoneTempPredictorCorrector->NumSingleTempHeatingControls > 0)
     555         316 :         SetPointSingleHeating.allocate(state.dataZoneTempPredictorCorrector->NumSingleTempHeatingControls);
     556             : 
     557        1206 :     for (int idx = 1; idx <= state.dataZoneTempPredictorCorrector->NumSingleTempHeatingControls; ++idx) {
     558         435 :         inputProcessor->getObjectItem(state,
     559             :                                       cCurrentModuleObject,
     560             :                                       idx,
     561             :                                       cAlphaArgs,
     562             :                                       NumAlphas,
     563             :                                       rNumericArgs,
     564             :                                       NumNums,
     565             :                                       IOStat,
     566             :                                       lNumericFieldBlanks,
     567             :                                       lAlphaFieldBlanks,
     568             :                                       cAlphaFieldNames,
     569             :                                       cNumericFieldNames);
     570         435 :         UtilityRoutines::IsNameEmpty(state, cAlphaArgs(1), cCurrentModuleObject, ErrorsFound);
     571         435 :         auto &singleHtgSetpoint = SetPointSingleHeating(idx);
     572         435 :         singleHtgSetpoint.Name = cAlphaArgs(1);
     573         435 :         singleHtgSetpoint.TempSchedName = cAlphaArgs(2);
     574         435 :         singleHtgSetpoint.TempSchedIndex = GetScheduleIndex(state, cAlphaArgs(2));
     575         435 :         if (singleHtgSetpoint.TempSchedIndex == 0) {
     576           0 :             ShowSevereError(
     577           0 :                 state, cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) + "\" not found.");
     578           0 :             ErrorsFound = true;
     579             :         }
     580             : 
     581             :     } // SingleTempHeatingControlNum
     582             : 
     583         771 :     cCurrentModuleObject = ValidControlTypesUC[static_cast<int>(DataHVACGlobals::ThermostatType::SingleCooling)];
     584         771 :     state.dataZoneTempPredictorCorrector->NumSingleTempCoolingControls = inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     585             : 
     586         771 :     if (state.dataZoneTempPredictorCorrector->NumSingleTempCoolingControls > 0)
     587         310 :         SetPointSingleCooling.allocate(state.dataZoneTempPredictorCorrector->NumSingleTempCoolingControls);
     588             : 
     589        1200 :     for (int idx = 1; idx <= state.dataZoneTempPredictorCorrector->NumSingleTempCoolingControls; ++idx) {
     590         429 :         inputProcessor->getObjectItem(state,
     591             :                                       cCurrentModuleObject,
     592             :                                       idx,
     593             :                                       cAlphaArgs,
     594             :                                       NumAlphas,
     595             :                                       rNumericArgs,
     596             :                                       NumNums,
     597             :                                       IOStat,
     598             :                                       lNumericFieldBlanks,
     599             :                                       lAlphaFieldBlanks,
     600             :                                       cAlphaFieldNames,
     601             :                                       cNumericFieldNames);
     602         429 :         UtilityRoutines::IsNameEmpty(state, cAlphaArgs(1), cCurrentModuleObject, ErrorsFound);
     603         429 :         auto &singleClgSetpoint = SetPointSingleCooling(idx);
     604         429 :         singleClgSetpoint.Name = cAlphaArgs(1);
     605         429 :         singleClgSetpoint.TempSchedName = cAlphaArgs(2);
     606         429 :         singleClgSetpoint.TempSchedIndex = GetScheduleIndex(state, cAlphaArgs(2));
     607         429 :         if (singleClgSetpoint.TempSchedIndex == 0) {
     608           0 :             ShowSevereError(
     609           0 :                 state, cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) + "\" not found.");
     610           0 :             ErrorsFound = true;
     611             :         }
     612             : 
     613             :     } // SingleTempCoolingControlNum
     614             : 
     615         771 :     cCurrentModuleObject = ValidControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeatCool)];
     616         771 :     state.dataZoneTempPredictorCorrector->NumSingleTempHeatCoolControls = inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     617             : 
     618         771 :     if (state.dataZoneTempPredictorCorrector->NumSingleTempHeatCoolControls > 0)
     619          11 :         state.dataZoneTempPredictorCorrector->SetPointSingleHeatCool.allocate(state.dataZoneTempPredictorCorrector->NumSingleTempHeatCoolControls);
     620             : 
     621         782 :     for (int idx = 1; idx <= state.dataZoneTempPredictorCorrector->NumSingleTempHeatCoolControls; ++idx) {
     622          11 :         inputProcessor->getObjectItem(state,
     623             :                                       cCurrentModuleObject,
     624             :                                       idx,
     625             :                                       cAlphaArgs,
     626             :                                       NumAlphas,
     627             :                                       rNumericArgs,
     628             :                                       NumNums,
     629             :                                       IOStat,
     630             :                                       lNumericFieldBlanks,
     631             :                                       lAlphaFieldBlanks,
     632             :                                       cAlphaFieldNames,
     633             :                                       cNumericFieldNames);
     634          11 :         auto &singleHeatCoolSetpoint = state.dataZoneTempPredictorCorrector->SetPointSingleHeatCool(idx);
     635          11 :         singleHeatCoolSetpoint.Name = cAlphaArgs(1);
     636          11 :         singleHeatCoolSetpoint.TempSchedName = cAlphaArgs(2);
     637          11 :         singleHeatCoolSetpoint.TempSchedIndex = GetScheduleIndex(state, cAlphaArgs(2));
     638          11 :         if (singleHeatCoolSetpoint.TempSchedIndex == 0) {
     639           0 :             ShowSevereError(
     640           0 :                 state, cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) + "\" not found.");
     641           0 :             ErrorsFound = true;
     642             :         }
     643             : 
     644             :     } // SingleTempHeatCoolControlNum
     645             : 
     646         771 :     cCurrentModuleObject = ValidControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand)];
     647         771 :     state.dataZoneTempPredictorCorrector->NumDualTempHeatCoolControls = inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     648             : 
     649         771 :     if (state.dataZoneTempPredictorCorrector->NumDualTempHeatCoolControls > 0)
     650         478 :         SetPointDualHeatCool.allocate(state.dataZoneTempPredictorCorrector->NumDualTempHeatCoolControls);
     651             : 
     652        3067 :     for (int idx = 1; idx <= state.dataZoneTempPredictorCorrector->NumDualTempHeatCoolControls; ++idx) {
     653        2296 :         inputProcessor->getObjectItem(state,
     654             :                                       cCurrentModuleObject,
     655             :                                       idx,
     656             :                                       cAlphaArgs,
     657             :                                       NumAlphas,
     658             :                                       rNumericArgs,
     659             :                                       NumNums,
     660             :                                       IOStat,
     661             :                                       lNumericFieldBlanks,
     662             :                                       lAlphaFieldBlanks,
     663             :                                       cAlphaFieldNames,
     664             :                                       cNumericFieldNames);
     665        2296 :         UtilityRoutines::IsNameEmpty(state, cAlphaArgs(1), cCurrentModuleObject, ErrorsFound);
     666        2296 :         auto &dualHeatCoolSetpoint = SetPointDualHeatCool(idx);
     667        2296 :         dualHeatCoolSetpoint.Name = cAlphaArgs(1);
     668        2296 :         dualHeatCoolSetpoint.HeatTempSetptSchedName = cAlphaArgs(2);
     669        2296 :         dualHeatCoolSetpoint.HeatTempSchedIndex = GetScheduleIndex(state, cAlphaArgs(2));
     670        2296 :         if (dualHeatCoolSetpoint.HeatTempSchedIndex == 0) {
     671           0 :             ShowSevereError(
     672           0 :                 state, cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) + "\" not found.");
     673           0 :             ErrorsFound = true;
     674             :         }
     675        2296 :         dualHeatCoolSetpoint.CoolTempSetptSchedName = cAlphaArgs(3);
     676        2296 :         dualHeatCoolSetpoint.CoolTempSchedIndex = GetScheduleIndex(state, cAlphaArgs(3));
     677        2296 :         if (dualHeatCoolSetpoint.CoolTempSchedIndex == 0) {
     678           0 :             ShowSevereError(
     679           0 :                 state, cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(3) + "=\"" + cAlphaArgs(3) + "\" not found.");
     680           0 :             ErrorsFound = true;
     681             :         }
     682             : 
     683             :     } // DualTempHeatCoolControlNum
     684             : 
     685             :     // Finish filling in Schedule pointing indexes
     686             :     int setPointObjectArrayIndex;
     687        4753 :     for (TempControlledZoneNum = 1; TempControlledZoneNum <= NumTempControlledZones; ++TempControlledZoneNum) {
     688        9716 :         for (int ct = 1; ct <= state.dataZoneCtrls->TempControlledZone(TempControlledZoneNum).NumControlTypes; ct++) {
     689        5734 :             switch (state.dataZoneCtrls->TempControlledZone(TempControlledZoneNum).ControlTypeEnum(ct)) {
     690        1127 :             case DataHVACGlobals::ThermostatType::SingleHeating:
     691        1127 :                 setPointObjectArrayIndex =
     692        1127 :                     UtilityRoutines::FindItem(TempControlledZone(TempControlledZoneNum).ControlTypeName(ct), SetPointSingleHeating);
     693        1127 :                 TempControlledZone(TempControlledZoneNum).SchIndx_SingleHeatSetPoint =
     694        1127 :                     state.dataZoneTempPredictorCorrector->SetPointSingleHeating(setPointObjectArrayIndex).TempSchedIndex;
     695        1127 :                 break;
     696        1113 :             case DataHVACGlobals::ThermostatType::SingleCooling:
     697        1113 :                 setPointObjectArrayIndex =
     698        1113 :                     UtilityRoutines::FindItem(TempControlledZone(TempControlledZoneNum).ControlTypeName(ct), SetPointSingleCooling);
     699        1113 :                 TempControlledZone(TempControlledZoneNum).SchIndx_SingleCoolSetPoint =
     700        1113 :                     state.dataZoneTempPredictorCorrector->SetPointSingleCooling(setPointObjectArrayIndex).TempSchedIndex;
     701        1113 :                 break;
     702          25 :             case DataHVACGlobals::ThermostatType::SingleHeatCool:
     703          25 :                 setPointObjectArrayIndex = UtilityRoutines::FindItem(TempControlledZone(TempControlledZoneNum).ControlTypeName(ct),
     704          25 :                                                                      state.dataZoneTempPredictorCorrector->SetPointSingleHeatCool);
     705          25 :                 TempControlledZone(TempControlledZoneNum).SchIndx_SingleHeatCoolSetPoint =
     706          25 :                     state.dataZoneTempPredictorCorrector->SetPointSingleHeatCool(setPointObjectArrayIndex).TempSchedIndex;
     707          25 :                 break;
     708        3469 :             case DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand:
     709        3469 :                 setPointObjectArrayIndex = UtilityRoutines::FindItem(TempControlledZone(TempControlledZoneNum).ControlTypeName(ct),
     710        3469 :                                                                      state.dataZoneTempPredictorCorrector->SetPointDualHeatCool);
     711        3469 :                 TempControlledZone(TempControlledZoneNum).SchIndx_DualSetPointWDeadBandHeat =
     712        3469 :                     state.dataZoneTempPredictorCorrector->SetPointDualHeatCool(setPointObjectArrayIndex).HeatTempSchedIndex;
     713        3469 :                 TempControlledZone(TempControlledZoneNum).SchIndx_DualSetPointWDeadBandCool =
     714        3469 :                     state.dataZoneTempPredictorCorrector->SetPointDualHeatCool(setPointObjectArrayIndex).CoolTempSchedIndex;
     715        3469 :                 break;
     716           0 :             default:
     717           0 :                 assert(false);
     718             :             }
     719             :         }
     720             :     }
     721             : 
     722             :     // Now, Check the schedule values/indices for validity
     723             : 
     724        4753 :     for (TempControlledZoneNum = 1; TempControlledZoneNum <= NumTempControlledZones; ++TempControlledZoneNum) {
     725             : 
     726        3982 :         ActualZoneNum = TempControlledZone(TempControlledZoneNum).ActualZoneNum;
     727        3982 :         CTIndex = TempControlledZone(TempControlledZoneNum).CTSchedIndex;
     728        3982 :         if (CTIndex == 0) continue; // error will be caught elsewhere
     729        3982 :         SchedMin = GetScheduleMinValue(state, CTIndex);
     730        3982 :         SchedMax = GetScheduleMaxValue(state, CTIndex);
     731             : 
     732        3982 :         if (SchedMin == 0 && SchedMax == 0) {
     733           0 :             if (FindNumberInList(CTIndex, CTSchedMapToControlledZone, NumTempControlledZones) == 0) {
     734           0 :                 ShowSevereError(state, "Control Type Schedule=" + TempControlledZone(TempControlledZoneNum).ControlTypeSchedName);
     735           0 :                 ShowContinueError(state, "..specifies control type 0 for all entries.");
     736           0 :                 ShowContinueError(state, "All zones using this Control Type Schedule have no heating or cooling available.");
     737             :             }
     738           0 :             CTSchedMapToControlledZone(TempControlledZoneNum) = CTIndex;
     739             :         }
     740             : 
     741       10370 :         for (ControlTypeNum = SchedMin; ControlTypeNum <= SchedMax; ++ControlTypeNum) {
     742             : 
     743        6388 :             int TempIndex = 0;
     744        6388 :             switch (static_cast<DataHVACGlobals::ThermostatType>(ControlTypeNum)) {
     745           9 :             case DataHVACGlobals::ThermostatType::Uncontrolled:
     746           9 :                 break;
     747        1130 :             case DataHVACGlobals::ThermostatType::SingleHeating:
     748        1130 :                 TempIndex = TempControlledZone(TempControlledZoneNum).SchIndx_SingleHeatSetPoint;
     749        1130 :                 if (TempIndex == 0) {
     750           3 :                     if (CheckScheduleValue(state, CTIndex, static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeating))) {
     751           0 :                         ShowSevereError(state, "Control Type Schedule=" + TempControlledZone(TempControlledZoneNum).ControlTypeSchedName);
     752           0 :                         ShowContinueError(state,
     753           0 :                                           format("..specifies control type 1 ({}) as the control type. Not valid for this zone.",
     754           0 :                                                  ValidControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeating)]));
     755           0 :                         ShowContinueError(state,
     756           0 :                                           "..reference " + cZControlTypes(static_cast<int>(ZoneControlTypes::TStat)) + '=' +
     757           0 :                                               TempControlledZone(TempControlledZoneNum).Name);
     758           0 :                         ShowContinueError(state, "..reference ZONE=" + TempControlledZone(TempControlledZoneNum).ZoneName);
     759           0 :                         ErrorsFound = true;
     760             :                     }
     761             :                 }
     762        1130 :                 break;
     763        1113 :             case DataHVACGlobals::ThermostatType::SingleCooling:
     764        1113 :                 TempIndex = TempControlledZone(TempControlledZoneNum).SchIndx_SingleCoolSetPoint;
     765        1113 :                 if (TempIndex == 0) {
     766           0 :                     if (CheckScheduleValue(state, CTIndex, static_cast<int>(DataHVACGlobals::ThermostatType::SingleCooling))) {
     767           0 :                         ShowSevereError(state, "Control Type Schedule=" + TempControlledZone(TempControlledZoneNum).ControlTypeSchedName);
     768           0 :                         ShowContinueError(state,
     769           0 :                                           format("..specifies control type 2 ({}) as the control type. Not valid for this zone.",
     770           0 :                                                  ValidControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::SingleCooling)]));
     771           0 :                         ShowContinueError(state,
     772           0 :                                           "..reference " + cZControlTypes(static_cast<int>(ZoneControlTypes::TStat)) + '=' +
     773           0 :                                               TempControlledZone(TempControlledZoneNum).Name);
     774           0 :                         ShowContinueError(state, "..reference ZONE=" + TempControlledZone(TempControlledZoneNum).ZoneName);
     775           0 :                         ErrorsFound = true;
     776             :                     }
     777             :                 }
     778        1113 :                 break;
     779         667 :             case DataHVACGlobals::ThermostatType::SingleHeatCool:
     780         667 :                 TempIndex = TempControlledZone(TempControlledZoneNum).SchIndx_SingleHeatCoolSetPoint;
     781         667 :                 if (TempIndex == 0) {
     782         642 :                     if (CheckScheduleValue(state, CTIndex, static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeatCool))) {
     783           0 :                         ShowSevereError(state, "Schedule=" + TempControlledZone(TempControlledZoneNum).ControlTypeSchedName);
     784           0 :                         ShowContinueError(state,
     785           0 :                                           format("..specifies control type 3 ({}) as the control type. Not valid for this zone.",
     786           0 :                                                  ValidControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeatCool)]));
     787           0 :                         ShowContinueError(state,
     788           0 :                                           "..reference " + cZControlTypes(static_cast<int>(ZoneControlTypes::TStat)) + '=' +
     789           0 :                                               TempControlledZone(TempControlledZoneNum).Name);
     790           0 :                         ShowContinueError(state, "..reference ZONE=" + TempControlledZone(TempControlledZoneNum).ZoneName);
     791           0 :                         ErrorsFound = true;
     792             :                     }
     793             :                 }
     794         667 :                 break;
     795        3469 :             case DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand:
     796        3469 :                 TempIndex = TempControlledZone(TempControlledZoneNum)
     797             :                                 .SchIndx_DualSetPointWDeadBandHeat; // using "Heat" as a sentinel that dualsetpoint is on this zone control object
     798        3469 :                 if (TempIndex == 0) {
     799           0 :                     if (CheckScheduleValue(state, CTIndex, static_cast<int>(DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand))) {
     800           0 :                         ShowSevereError(state, "Schedule=" + TempControlledZone(TempControlledZoneNum).ControlTypeSchedName);
     801           0 :                         ShowContinueError(state,
     802           0 :                                           format("..specifies control type 4 ({}) as the control type. Not valid for this zone.",
     803           0 :                                                  ValidControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand)]));
     804           0 :                         ShowContinueError(state,
     805           0 :                                           "..reference " + cZControlTypes(static_cast<int>(ZoneControlTypes::TStat)) + '=' +
     806           0 :                                               TempControlledZone(TempControlledZoneNum).Name);
     807           0 :                         ShowContinueError(state, "..reference ZONE=" + TempControlledZone(TempControlledZoneNum).ZoneName);
     808           0 :                         ErrorsFound = true;
     809             :                     }
     810             :                 }
     811        3469 :                 break;
     812           0 :             default:
     813           0 :                 ShowSevereError(state,
     814           0 :                                 format("GetZoneAirSetpoints: Illegal control type for Zone={}, Found value={}, in Schedule={}",
     815           0 :                                        Zone(ActualZoneNum).Name,
     816             :                                        ControlTypeNum,
     817           0 :                                        TempControlledZone(TempControlledZoneNum).ControlTypeSchedName));
     818           0 :                 ShowContinueError(state, "..valid range values are [0,4].");
     819           0 :                 ErrorsFound = true;
     820             :             }
     821             :         }
     822             :     }
     823             : 
     824        4753 :     for (TempControlledZoneNum = 1; TempControlledZoneNum <= NumTempControlledZones; ++TempControlledZoneNum) {
     825             : 
     826        3982 :         ActualZoneNum = TempControlledZone(TempControlledZoneNum).ActualZoneNum;
     827        3982 :         CTIndex = TempControlledZone(TempControlledZoneNum).CTSchedIndex;
     828        3982 :         if (CTIndex == 0) continue; // error caught elsewhere -- would just be confusing here
     829             : 
     830       19910 :         for (ControlTypeNum = 1; ControlTypeNum <= 4; ++ControlTypeNum) {
     831       15928 :             if (TStatControlTypes(TempControlledZoneNum).MustHave[ControlTypeNum] && TStatControlTypes(TempControlledZoneNum).DidHave[ControlTypeNum])
     832           0 :                 continue;
     833             : 
     834       15928 :             switch (static_cast<DataHVACGlobals::ThermostatType>(ControlTypeNum)) {
     835        3982 :             case DataHVACGlobals::ThermostatType::SingleHeating:
     836        3982 :                 if (!TStatControlTypes(TempControlledZoneNum).MustHave[ControlTypeNum]) continue;
     837           0 :                 ShowWarningError(state, "Schedule=" + TempControlledZone(TempControlledZoneNum).ControlTypeSchedName);
     838           0 :                 ShowContinueError(state,
     839           0 :                                   format("...should include control type 1 ({}) but does not.",
     840           0 :                                          ValidControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeating)]));
     841           0 :                 ShowContinueError(state,
     842           0 :                                   "..reference " + cZControlTypes(static_cast<int>(ZoneControlTypes::TStat)) + '=' +
     843           0 :                                       TempControlledZone(TempControlledZoneNum).Name);
     844           0 :                 ShowContinueError(state, "..reference ZONE=" + TempControlledZone(TempControlledZoneNum).ZoneName);
     845           0 :                 break;
     846        3982 :             case DataHVACGlobals::ThermostatType::SingleCooling:
     847        3982 :                 if (!TStatControlTypes(TempControlledZoneNum).MustHave[ControlTypeNum]) continue;
     848           0 :                 ShowWarningError(state, "Schedule=" + TempControlledZone(TempControlledZoneNum).ControlTypeSchedName);
     849           0 :                 ShowContinueError(state,
     850           0 :                                   format("...should include control type 2 ({}) but does not.",
     851           0 :                                          ValidControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::SingleCooling)]));
     852           0 :                 ShowContinueError(state,
     853           0 :                                   "..reference " + cZControlTypes(static_cast<int>(ZoneControlTypes::TStat)) + '=' +
     854           0 :                                       TempControlledZone(TempControlledZoneNum).Name);
     855           0 :                 ShowContinueError(state, "..reference ZONE=" + TempControlledZone(TempControlledZoneNum).ZoneName);
     856           0 :                 break;
     857        3982 :             case DataHVACGlobals::ThermostatType::SingleHeatCool:
     858        3982 :                 if (!TStatControlTypes(TempControlledZoneNum).MustHave[ControlTypeNum]) continue;
     859           0 :                 ShowWarningError(state, "Schedule=" + TempControlledZone(TempControlledZoneNum).ControlTypeSchedName);
     860           0 :                 ShowContinueError(state,
     861           0 :                                   format("...should include control type 3 ({}) but does not.",
     862           0 :                                          ValidControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeating)]));
     863           0 :                 ShowContinueError(state,
     864           0 :                                   "..reference " + cZControlTypes(static_cast<int>(ZoneControlTypes::TStat)) + '=' +
     865           0 :                                       TempControlledZone(TempControlledZoneNum).Name);
     866           0 :                 ShowContinueError(state, "..reference ZONE=" + TempControlledZone(TempControlledZoneNum).ZoneName);
     867           0 :                 break;
     868        3982 :             case DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand:
     869        3982 :                 if (!TStatControlTypes(TempControlledZoneNum).MustHave[ControlTypeNum]) continue;
     870           0 :                 ShowWarningError(state, "Schedule=" + TempControlledZone(TempControlledZoneNum).ControlTypeSchedName);
     871           0 :                 ShowContinueError(state,
     872           0 :                                   format("...should include control type 4 ({}) but does not.",
     873           0 :                                          ValidControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand)]));
     874           0 :                 ShowContinueError(state,
     875           0 :                                   "..reference " + cZControlTypes(static_cast<int>(ZoneControlTypes::TStat)) + '=' +
     876           0 :                                       TempControlledZone(TempControlledZoneNum).Name);
     877           0 :                 ShowContinueError(state, "..reference ZONE=" + TempControlledZone(TempControlledZoneNum).ZoneName);
     878           0 :                 break;
     879           0 :             default:
     880           0 :                 break;
     881             :             }
     882             :         }
     883             :     }
     884             : 
     885         771 :     if (allocated(TStatControlTypes)) TStatControlTypes.deallocate();
     886             :     // This starts the Humidity Control Get Input section
     887         771 :     cCurrentModuleObject = cZControlTypes(static_cast<int>(ZoneControlTypes::HStat));
     888         771 :     state.dataZoneCtrls->NumHumidityControlZones = inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     889             : 
     890         771 :     if (state.dataZoneCtrls->NumHumidityControlZones > 0) {
     891          88 :         HumidityControlZone.allocate(state.dataZoneCtrls->NumHumidityControlZones);
     892         176 :         state.dataZoneTempPredictorCorrector->HumidityControlZoneUniqueNames.reserve(
     893          88 :             static_cast<unsigned>(state.dataZoneCtrls->NumHumidityControlZones));
     894             :     }
     895             : 
     896         930 :     for (HumidControlledZoneNum = 1; HumidControlledZoneNum <= state.dataZoneCtrls->NumHumidityControlZones; ++HumidControlledZoneNum) {
     897         159 :         inputProcessor->getObjectItem(state,
     898             :                                       cCurrentModuleObject,
     899             :                                       HumidControlledZoneNum,
     900             :                                       cAlphaArgs,
     901             :                                       NumAlphas,
     902             :                                       rNumericArgs,
     903             :                                       NumNums,
     904             :                                       IOStat,
     905             :                                       lNumericFieldBlanks,
     906             :                                       lAlphaFieldBlanks,
     907             :                                       cAlphaFieldNames,
     908             :                                       cNumericFieldNames);
     909         159 :         UtilityRoutines::IsNameEmpty(state, cAlphaArgs(1), cCurrentModuleObject, ErrorsFound);
     910             : 
     911         159 :         HumidityControlZone(HumidControlledZoneNum).ControlName = cAlphaArgs(1);
     912         477 :         GlobalNames::IntraObjUniquenessCheck(state,
     913         159 :                                              cAlphaArgs(2),
     914             :                                              cCurrentModuleObject,
     915         159 :                                              cAlphaFieldNames(2),
     916         159 :                                              state.dataZoneTempPredictorCorrector->HumidityControlZoneUniqueNames,
     917             :                                              ErrorsFound);
     918             : 
     919         159 :         HumidityControlZone(HumidControlledZoneNum).ZoneName = cAlphaArgs(2);
     920         159 :         HumidityControlZone(HumidControlledZoneNum).ActualZoneNum = UtilityRoutines::FindItem(cAlphaArgs(2), Zone);
     921         159 :         if (HumidityControlZone(HumidControlledZoneNum).ActualZoneNum == 0) {
     922           0 :             ShowSevereError(
     923           0 :                 state, cCurrentModuleObject + "=\"" + cAlphaArgs(1) + " invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) + "\" not found.");
     924           0 :             ErrorsFound = true;
     925             :         } else {
     926         159 :             state.dataHeatBal->Zone(HumidityControlZone(HumidControlledZoneNum).ActualZoneNum).humidityControlZoneIndex = HumidControlledZoneNum;
     927             :         }
     928         159 :         HumidityControlZone(HumidControlledZoneNum).HumidifyingSched = cAlphaArgs(3);
     929         159 :         HumidityControlZone(HumidControlledZoneNum).HumidifyingSchedIndex = GetScheduleIndex(state, cAlphaArgs(3));
     930         159 :         if (HumidityControlZone(HumidControlledZoneNum).HumidifyingSchedIndex == 0) {
     931           0 :             ShowSevereError(
     932           0 :                 state, cCurrentModuleObject + "=\"" + cAlphaArgs(1) + " invalid " + cAlphaFieldNames(3) + "=\"" + cAlphaArgs(3) + "\" not found.");
     933           0 :             ErrorsFound = true;
     934             :         }
     935         159 :         if (NumAlphas == 4) {
     936          89 :             HumidityControlZone(HumidControlledZoneNum).DehumidifyingSched = cAlphaArgs(4);
     937          89 :             HumidityControlZone(HumidControlledZoneNum).DehumidifyingSchedIndex = GetScheduleIndex(state, cAlphaArgs(4));
     938          89 :             if (HumidityControlZone(HumidControlledZoneNum).DehumidifyingSchedIndex == 0) {
     939           0 :                 ShowSevereError(state,
     940           0 :                                 cCurrentModuleObject + "=\"" + cAlphaArgs(1) + " invalid " + cAlphaFieldNames(4) + "=\"" + cAlphaArgs(4) +
     941             :                                     "\" not found.");
     942           0 :                 ErrorsFound = true;
     943             :             }
     944             :         } else {
     945          70 :             HumidityControlZone(HumidControlledZoneNum).DehumidifyingSched = cAlphaArgs(3);
     946          70 :             HumidityControlZone(HumidControlledZoneNum).DehumidifyingSchedIndex = GetScheduleIndex(state, cAlphaArgs(3));
     947             :         }
     948             : 
     949             :     } // HumidControlledZoneNum
     950             : 
     951             :     // Start to read Thermal comfort control objects
     952         771 :     cCurrentModuleObject = cZControlTypes(static_cast<int>(ZoneControlTypes::TCTStat));
     953         771 :     state.dataZoneCtrls->NumComfortTStatStatements = inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     954         771 :     ComfortTStatObjects.allocate(state.dataZoneCtrls->NumComfortTStatStatements);
     955             : 
     956             :     // Pre-scan for use of Zone lists in TStat statements (i.e. Global application of TStat)
     957         771 :     state.dataZoneCtrls->NumComfortControlledZones = 0;
     958         771 :     errFlag = false;
     959         772 :     for (Item = 1; Item <= state.dataZoneCtrls->NumComfortTStatStatements; ++Item) {
     960           1 :         inputProcessor->getObjectItem(state,
     961             :                                       cCurrentModuleObject,
     962             :                                       Item,
     963             :                                       cAlphaArgs,
     964             :                                       NumAlphas,
     965             :                                       rNumericArgs,
     966             :                                       NumNums,
     967             :                                       IOStat,
     968             :                                       lNumericFieldBlanks,
     969             :                                       lAlphaFieldBlanks,
     970             :                                       cAlphaFieldNames,
     971             :                                       cNumericFieldNames);
     972           1 :         UtilityRoutines::IsNameEmpty(state, cAlphaArgs(1), cCurrentModuleObject, ErrorsFound);
     973             : 
     974           1 :         Item1 = UtilityRoutines::FindItemInList(cAlphaArgs(2), Zone);
     975           1 :         ZLItem = 0;
     976           1 :         if (Item1 == 0 && state.dataHeatBal->NumOfZoneLists > 0) ZLItem = UtilityRoutines::FindItemInList(cAlphaArgs(2), ZoneList);
     977           1 :         ComfortTStatObjects(Item).Name = cAlphaArgs(1);
     978           1 :         if (Item1 > 0) {
     979           1 :             ComfortTStatObjects(Item).ComfortControlledZoneStartPtr = state.dataZoneCtrls->NumComfortControlledZones + 1;
     980           1 :             ++state.dataZoneCtrls->NumComfortControlledZones;
     981           1 :             ComfortTStatObjects(Item).NumOfZones = 1;
     982           1 :             ComfortTStatObjects(Item).ZoneListActive = false;
     983           1 :             ComfortTStatObjects(Item).ZoneOrZoneListPtr = Item1;
     984           0 :         } else if (ZLItem > 0) {
     985           0 :             ComfortTStatObjects(Item).ComfortControlledZoneStartPtr = state.dataZoneCtrls->NumComfortControlledZones + 1;
     986           0 :             state.dataZoneCtrls->NumComfortControlledZones += ZoneList(ZLItem).NumOfZones;
     987           0 :             ComfortTStatObjects(Item).NumOfZones = ZoneList(ZLItem).NumOfZones;
     988           0 :             ComfortTStatObjects(Item).ZoneListActive = true;
     989           0 :             ComfortTStatObjects(Item).ZoneOrZoneListPtr = ZLItem;
     990             :         } else {
     991           0 :             ShowSevereError(
     992           0 :                 state, cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) + "\" not found.");
     993           0 :             errFlag = true;
     994           0 :             ErrorsFound = true;
     995             :         }
     996             :     }
     997             : 
     998         771 :     if (errFlag) {
     999           0 :         ShowSevereError(state, "GetZoneAirSetpoints: Errors with invalid names in " + cCurrentModuleObject + " objects.");
    1000           0 :         ShowContinueError(state, "...These will not be read in.  Other errors may occur.");
    1001           0 :         state.dataZoneCtrls->NumComfortControlledZones = 0;
    1002             :     }
    1003             : 
    1004         771 :     if (state.dataZoneCtrls->NumComfortControlledZones > 0) {
    1005           1 :         ComfortControlledZone.allocate(state.dataZoneCtrls->NumComfortControlledZones);
    1006           1 :         TComfortControlTypes.allocate(state.dataZoneCtrls->NumComfortControlledZones); // Number of set point types
    1007           1 :         CCmSchedMapToControlledZone.dimension(state.dataZoneCtrls->NumComfortControlledZones, 0);
    1008             : 
    1009           1 :         ComfortControlledZoneNum = 0;
    1010           2 :         for (Item = 1; Item <= state.dataZoneCtrls->NumComfortTStatStatements; ++Item) {
    1011           1 :             inputProcessor->getObjectItem(state,
    1012             :                                           cCurrentModuleObject,
    1013             :                                           Item,
    1014             :                                           cAlphaArgs,
    1015             :                                           NumAlphas,
    1016             :                                           rNumericArgs,
    1017             :                                           NumNums,
    1018             :                                           IOStat,
    1019             :                                           lNumericFieldBlanks,
    1020             :                                           lAlphaFieldBlanks,
    1021             :                                           cAlphaFieldNames,
    1022             :                                           cNumericFieldNames);
    1023           2 :             for (Item1 = 1; Item1 <= ComfortTStatObjects(Item).NumOfZones; ++Item1) {
    1024           1 :                 ++ComfortControlledZoneNum;
    1025           1 :                 if (ComfortTStatObjects(Item).ZoneListActive) {
    1026           0 :                     cAlphaArgs(2) = state.dataHeatBal->Zone(ZoneList(ComfortTStatObjects(Item).ZoneOrZoneListPtr).Zone(Item1)).Name;
    1027             :                 }
    1028           2 :                 int ZoneAssigned = UtilityRoutines::FindItemInList(
    1029           2 :                     cAlphaArgs(2), ComfortControlledZone, &DataZoneControls::ZoneComfortControls::ZoneName, ComfortControlledZoneNum - 1);
    1030           1 :                 if (ZoneAssigned == 0) {
    1031           1 :                     ComfortControlledZone(ComfortControlledZoneNum).ZoneName = cAlphaArgs(2);
    1032           1 :                     ComfortControlledZone(ComfortControlledZoneNum).ActualZoneNum = UtilityRoutines::FindItemInList(cAlphaArgs(2), Zone);
    1033           1 :                     if (ComfortControlledZone(ComfortControlledZoneNum).ActualZoneNum == 0) {
    1034           0 :                         ShowSevereError(state,
    1035           0 :                                         cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) +
    1036             :                                             "\" not found.");
    1037           0 :                         ErrorsFound = true;
    1038             :                     }
    1039             :                 } else {
    1040           0 :                     ComfortControlledZone(ComfortControlledZoneNum).ZoneName = cAlphaArgs(2); // for continuity
    1041           0 :                     ShowSevereError(state,
    1042           0 :                                     cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) +
    1043             :                                         "\" zone previously assigned.");
    1044           0 :                     ShowContinueError(state, "...Zone was previously assigned to Thermostat=\"" + ComfortControlledZone(ZoneAssigned).Name + "\".");
    1045           0 :                     ErrorsFound = true;
    1046           0 :                     continue;
    1047             :                 }
    1048             : 
    1049           1 :                 if (!ComfortTStatObjects(Item).ZoneListActive) {
    1050           1 :                     ComfortControlledZone(ComfortControlledZoneNum).Name = cAlphaArgs(1);
    1051             :                 } else {
    1052           0 :                     ComfortControlledZone(ComfortControlledZoneNum).Name =
    1053           0 :                         state.dataHeatBal->Zone(ZoneList(ComfortTStatObjects(Item).ZoneOrZoneListPtr).Zone(Item1)).Name + ' ' +
    1054           0 :                         ComfortTStatObjects(Item).Name;
    1055             :                 }
    1056             : 
    1057             :                 // Read Fields A3 and A4 for averaging method
    1058           1 :                 IZoneCount = 0;
    1059           4 :                 for (i = 1; i <= state.dataHeatBal->TotPeople; ++i) {
    1060           3 :                     if (ComfortControlledZone(ComfortControlledZoneNum).ActualZoneNum == state.dataHeatBal->People(i).ZonePtr) {
    1061           1 :                         ++IZoneCount;
    1062             :                     }
    1063             :                 }
    1064             :                 // Could not find a people object for this particular zone
    1065           1 :                 if (IZoneCount == 0 && ComfortControlledZone(ComfortControlledZoneNum).ActualZoneNum > 0) {
    1066           0 :                     ShowSevereError(state,
    1067           0 :                                     cCurrentModuleObject + "=\"" + cAlphaArgs(1) + " no PEOPLE in " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) +
    1068             :                                         "\" - cannot use Comfort Control.");
    1069           0 :                     ErrorsFound = true;
    1070             :                 }
    1071           1 :                 ComfortControlledZone(ComfortControlledZoneNum).AverageMethod = DataZoneControls::AverageMethod::NO;
    1072           1 :                 if (IZoneCount > 1) {
    1073           0 :                     ComfortControlledZone(ComfortControlledZoneNum).AverageMethodName = cAlphaArgs(3);
    1074           0 :                     if (UtilityRoutines::SameString(cAlphaArgs(3), "SpecificObject")) {
    1075           0 :                         ComfortControlledZone(ComfortControlledZoneNum).AverageMethod = DataZoneControls::AverageMethod::SPE;
    1076             :                     }
    1077           0 :                     if (UtilityRoutines::SameString(cAlphaArgs(3), "ObjectAverage")) {
    1078           0 :                         ComfortControlledZone(ComfortControlledZoneNum).AverageMethod = DataZoneControls::AverageMethod::OBJ;
    1079             :                     }
    1080           0 :                     if (UtilityRoutines::SameString(cAlphaArgs(3), "PeopleAverage")) {
    1081           0 :                         ComfortControlledZone(ComfortControlledZoneNum).AverageMethod = DataZoneControls::AverageMethod::PEO;
    1082             :                     }
    1083           0 :                     if (ComfortControlledZone(ComfortControlledZoneNum).AverageMethod == DataZoneControls::AverageMethod::NO) {
    1084           0 :                         ShowSevereError(
    1085           0 :                             state, cCurrentModuleObject + "=\"" + cAlphaArgs(1) + " invalid " + cAlphaFieldNames(3) + "=\"" + cAlphaArgs(3) + "\".");
    1086           0 :                         ShowContinueError(state, "Allowed keys are SpecificObject, ObjectAverage, or PeopleAverage");
    1087           0 :                         ErrorsFound = true;
    1088             :                     }
    1089           0 :                     if (ComfortControlledZone(ComfortControlledZoneNum).AverageMethod == DataZoneControls::AverageMethod::SPE) {
    1090           0 :                         ComfortControlledZone(ComfortControlledZoneNum).AverageObjectName = cAlphaArgs(4);
    1091           0 :                         if (UtilityRoutines::FindItem(cAlphaArgs(4), state.dataHeatBal->People) == 0) {
    1092           0 :                             ShowSevereError(state,
    1093           0 :                                             cCurrentModuleObject + "=\"" + cAlphaArgs(1) + " invalid " + cAlphaFieldNames(4) + "=\"" + cAlphaArgs(4) +
    1094             :                                                 "\".");
    1095           0 :                             ErrorsFound = true;
    1096             :                         } else {
    1097           0 :                             ComfortControlledZone(ComfortControlledZoneNum).SpecificObjectNum =
    1098           0 :                                 UtilityRoutines::FindItem(cAlphaArgs(4), state.dataHeatBal->People);
    1099             :                         }
    1100             :                     }
    1101             :                 } else {
    1102           2 :                     for (i = 1; i <= state.dataHeatBal->TotPeople; ++i) {
    1103           2 :                         if (ComfortControlledZone(ComfortControlledZoneNum).ActualZoneNum == state.dataHeatBal->People(i).ZonePtr) break;
    1104             :                     }
    1105           1 :                     ComfortControlledZone(ComfortControlledZoneNum).SpecificObjectNum = i;
    1106             :                 }
    1107             :                 // Check values used for thermal comfort calculation
    1108           4 :                 for (i = 1; i <= state.dataHeatBal->TotPeople; ++i) {
    1109           3 :                     if (ComfortControlledZone(ComfortControlledZoneNum).ActualZoneNum == state.dataHeatBal->People(i).ZonePtr) {
    1110             :                         // Check activity level
    1111           1 :                         if (state.dataHeatBal->People(i).ActivityLevelPtr > 0) {
    1112           1 :                             ValidScheduleControlType =
    1113           2 :                                 CheckScheduleValueMinMax(state, state.dataHeatBal->People(i).ActivityLevelPtr, ">=", 72.0, "<=", 909.0);
    1114           1 :                             if (!ValidScheduleControlType) {
    1115           0 :                                 ShowSevereError(state,
    1116             :                                                 "GetPeople Activity Level: Invalid activity level values entered for thermal comfort calculation");
    1117           0 :                                 ShowContinueError(state, "Outside of range values [72,909], Reference object=" + state.dataHeatBal->People(i).Name);
    1118           0 :                                 ErrorsFound = true;
    1119             :                             }
    1120             :                         } else {
    1121           0 :                             ShowSevereError(state,
    1122           0 :                                             "GetPeople Activity Level: Activity level schedule is not found=" + state.dataHeatBal->People(i).Name);
    1123           0 :                             ShowContinueError(state, "Required when the zone has Thermal Comfort Controls.");
    1124           0 :                             ErrorsFound = true;
    1125             :                         }
    1126             :                         // Check Work Efficiency
    1127           1 :                         if (state.dataHeatBal->People(i).WorkEffPtr > 0) {
    1128           1 :                             ValidScheduleControlType = CheckScheduleValueMinMax(state, state.dataHeatBal->People(i).WorkEffPtr, ">=", 0.0, "<=", 1.0);
    1129           1 :                             if (!ValidScheduleControlType) {
    1130           0 :                                 ShowSevereError(state,
    1131             :                                                 "GetPeople work efficiency: Invalid work efficiency values entered for thermal comfort calculation");
    1132           0 :                                 ShowContinueError(state, "Outside of range values [0,1], Reference object=" + state.dataHeatBal->People(i).Name);
    1133           0 :                                 ErrorsFound = true;
    1134             :                             }
    1135             :                         } else {
    1136           0 :                             ShowSevereError(state,
    1137           0 :                                             "GetPeople work efficiency: Work efficiency schedule is not found=" + state.dataHeatBal->People(i).Name);
    1138           0 :                             ShowContinueError(state, "Required when the zone has Thermal Comfort Controls.");
    1139           0 :                             ErrorsFound = true;
    1140             :                         }
    1141             :                         // Check Clothing Insulation
    1142           1 :                         if (state.dataHeatBal->People(i).ClothingPtr > 0) {
    1143           1 :                             ValidScheduleControlType = CheckScheduleValueMinMax(state, state.dataHeatBal->People(i).ClothingPtr, ">", 0.0, "<=", 2.0);
    1144           1 :                             if (!ValidScheduleControlType) {
    1145           0 :                                 ShowSevereError(
    1146             :                                     state,
    1147             :                                     "GetPeople Clothing Insulation: Invalid Clothing Insulation values entered for thermal comfort calculation");
    1148           0 :                                 ShowContinueError(state, "Outside of range values [0.0,2.0], Reference object=" + state.dataHeatBal->People(i).Name);
    1149           0 :                                 ErrorsFound = true;
    1150             :                             }
    1151             :                         } else {
    1152           0 :                             ShowSevereError(state,
    1153           0 :                                             "GetPeople Clothing Insulation: Clothing Insulation schedule is not found=" +
    1154           0 :                                                 state.dataHeatBal->People(i).Name);
    1155           0 :                             ShowContinueError(state, "Required when the zone has Thermal Comfort Controls.");
    1156           0 :                             ErrorsFound = true;
    1157             :                         }
    1158             :                         // Check Air velocity
    1159           1 :                         if (state.dataHeatBal->People(i).AirVelocityPtr <= 0) {
    1160           0 :                             ShowSevereError(state, "GetPeople Air Velocity: Air velocity schedule is not found=" + state.dataHeatBal->People(i).Name);
    1161           0 :                             ShowContinueError(state, "Required when the zone has Thermal Comfort Controls.");
    1162           0 :                             ErrorsFound = true;
    1163             :                         }
    1164             :                     }
    1165             :                 }
    1166             : 
    1167             :                 // Read Max and Min temperature setpoint
    1168           1 :                 if (NumNums > 0) {
    1169           1 :                     ComfortControlledZone(ComfortControlledZoneNum).TdbMinSetPoint = rNumericArgs(1);
    1170           1 :                     if (rNumericArgs(1) > 50 || rNumericArgs(1) < 0) {
    1171           0 :                         ShowSevereError(
    1172             :                             state,
    1173           0 :                             format("{}=\"{} invalid {}=[{:.0T}].", cCurrentModuleObject, cAlphaArgs(1), cNumericFieldNames(1), rNumericArgs(1)));
    1174           0 :                         ShowContinueError(state, "..Allowable values must be between 0 C and 50 C");
    1175           0 :                         ErrorsFound = true;
    1176             :                     }
    1177             :                 }
    1178           1 :                 if (NumNums > 1) {
    1179           1 :                     ComfortControlledZone(ComfortControlledZoneNum).TdbMaxSetPoint = rNumericArgs(2);
    1180           1 :                     if (rNumericArgs(2) > 50 || rNumericArgs(2) < 0) {
    1181           0 :                         ShowSevereError(
    1182             :                             state,
    1183           0 :                             format("{}=\"{} invalid {}=[{:.0T}].", cCurrentModuleObject, cAlphaArgs(1), cNumericFieldNames(2), rNumericArgs(2)));
    1184           0 :                         ShowContinueError(state, "..Allowable values must be between 0 C and 50 C");
    1185           0 :                         ErrorsFound = true;
    1186             :                     }
    1187             :                 }
    1188             :                 // Ensure MaxTemp >= MinTemp
    1189           1 :                 if (ComfortControlledZone(ComfortControlledZoneNum).TdbMinSetPoint > ComfortControlledZone(ComfortControlledZoneNum).TdbMaxSetPoint) {
    1190           0 :                     ShowSevereError(state, cCurrentModuleObject + "=\"" + cAlphaArgs(1));
    1191           0 :                     ShowContinueError(state, ".." + cNumericFieldNames(1) + " > " + cNumericFieldNames(2));
    1192           0 :                     ShowContinueError(state, format("..[{:.0T}] > [{:.0T}].", rNumericArgs(1), rNumericArgs(2)));
    1193           0 :                     ErrorsFound = true;
    1194             :                 }
    1195             :                 // If MaxTemp = MinTemp, no thermal comfort control
    1196           2 :                 if (ComfortControlledZone(ComfortControlledZoneNum).TdbMinSetPoint ==
    1197           1 :                     ComfortControlledZone(ComfortControlledZoneNum).TdbMaxSetPoint) {
    1198           0 :                     ShowSevereError(state, cCurrentModuleObject + "=\"" + cAlphaArgs(1));
    1199           0 :                     ShowContinueError(state, ".." + cNumericFieldNames(1) + " = " + cNumericFieldNames(2));
    1200           0 :                     ShowContinueError(state, "The zone will be controlled using this dry-bulb temperature setpoint.");
    1201             :                 }
    1202             :                 // read Thermal comfort type schedule name
    1203           1 :                 ComfortControlledZone(ComfortControlledZoneNum).ControlTypeSchedName = cAlphaArgs(5);
    1204           1 :                 ComfortControlledZone(ComfortControlledZoneNum).ComfortSchedIndex = GetScheduleIndex(state, cAlphaArgs(5));
    1205           1 :                 if (ComfortControlledZone(ComfortControlledZoneNum).ComfortSchedIndex == 0) {
    1206           0 :                     ShowSevereError(state,
    1207           0 :                                     cCurrentModuleObject + "=\"" + cAlphaArgs(1) + " invalid " + cAlphaFieldNames(5) + "=\"" + cAlphaArgs(5) +
    1208             :                                         "\" not found.");
    1209           0 :                     ErrorsFound = true;
    1210             :                 } else {
    1211             :                     // Check validity of control types.
    1212           1 :                     ValidScheduleControlType =
    1213           2 :                         CheckScheduleValueMinMax(state, ComfortControlledZone(ComfortControlledZoneNum).ComfortSchedIndex, ">=", 0.0, "<=", 4.0);
    1214           1 :                     if (!ValidScheduleControlType) {
    1215           0 :                         ShowSevereError(state,
    1216           0 :                                         cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid range " + cAlphaFieldNames(5) + "=\"" +
    1217           0 :                                             cAlphaArgs(5) + "\"");
    1218           0 :                         ShowContinueError(state, "..contains values outside of range [0,4].");
    1219           0 :                         ErrorsFound = true;
    1220             :                     }
    1221             :                 }
    1222           1 :                 ComfortControlledZone(ComfortControlledZoneNum).NumControlTypes = nint((NumAlphas - 5.0) / 2.0);
    1223           1 :                 ComfortControlledZone(ComfortControlledZoneNum).ControlType.allocate(ComfortControlledZone(ComfortControlledZoneNum).NumControlTypes);
    1224           1 :                 ComfortControlledZone(ComfortControlledZoneNum)
    1225           1 :                     .ControlTypeName.allocate(ComfortControlledZone(ComfortControlledZoneNum).NumControlTypes);
    1226           1 :                 ComfortControlledZone(ComfortControlledZoneNum)
    1227           1 :                     .ControlTypeSchIndx.allocate(ComfortControlledZone(ComfortControlledZoneNum).NumControlTypes);
    1228             : 
    1229           5 :                 for (ControlTypeNum = 1; ControlTypeNum <= ComfortControlledZone(ComfortControlledZoneNum).NumControlTypes; ++ControlTypeNum) {
    1230           4 :                     ComfortControlledZone(ComfortControlledZoneNum).ControlType(ControlTypeNum) = cAlphaArgs(nint(2.0 * ControlTypeNum - 1 + 5));
    1231           4 :                     ComfortControlledZone(ComfortControlledZoneNum).ControlTypeName(ControlTypeNum) = cAlphaArgs(nint(2.0 * ControlTypeNum + 5));
    1232           4 :                     if (ComfortControlledZone(ComfortControlledZoneNum).ControlType(ControlTypeNum) != "") {
    1233           8 :                         CTIndex = getEnumerationValue(
    1234             :                             ValidComfortControlTypesUC,
    1235          12 :                             UtilityRoutines::MakeUPPERCase(ComfortControlledZone(ComfortControlledZoneNum).ControlType(ControlTypeNum)));
    1236           4 :                         if (CTIndex == 0) {
    1237           0 :                             ShowSevereError(state,
    1238           0 :                                             cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " +
    1239           0 :                                                 cAlphaFieldNames(nint(2.0 * ControlTypeNum - 1 + 5)) + "=\"" +
    1240           0 :                                                 cAlphaArgs(nint(2.0 * ControlTypeNum - 1 + 5)) + "\"");
    1241           0 :                             ErrorsFound = true;
    1242             :                         }
    1243           4 :                         if (CTIndex > 4) { // For Fanger control only for the time being
    1244           0 :                             ShowSevereError(state,
    1245           0 :                                             cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " +
    1246           0 :                                                 cAlphaFieldNames(nint(2.0 * ControlTypeNum - 1 + 5)) + "=\"" +
    1247           0 :                                                 cAlphaArgs(nint(2.0 * ControlTypeNum - 1 + 5)) + "\"");
    1248           0 :                             ShowContinueError(state, "..Fanger is the only valid model.");
    1249           0 :                             ErrorsFound = true;
    1250             :                         }
    1251             :                     } else {
    1252           0 :                         ShowSevereError(state,
    1253           0 :                                         cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " +
    1254           0 :                                             cAlphaFieldNames(nint(2.0 * ControlTypeNum - 1 + 5)) + "=\"<blank>\"");
    1255           0 :                         ErrorsFound = true;
    1256             :                     }
    1257           4 :                     ComfortControlledZone(ComfortControlledZoneNum).ControlTypeSchIndx(ControlTypeNum) = 0;
    1258             :                 }
    1259             :             }
    1260             :         } // NumComfortTStatStatements
    1261             :     }
    1262             :     // End of Thermal comfort control reading and checking
    1263             : 
    1264         771 :     cCurrentModuleObject = ValidComfortControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeating)];
    1265         771 :     state.dataZoneTempPredictorCorrector->NumSingleFangerHeatingControls = inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    1266             : 
    1267         771 :     if (state.dataZoneTempPredictorCorrector->NumSingleFangerHeatingControls > 0)
    1268           2 :         state.dataZoneTempPredictorCorrector->SetPointSingleHeatingFanger.allocate(
    1269           1 :             state.dataZoneTempPredictorCorrector->NumSingleFangerHeatingControls);
    1270             : 
    1271         772 :     for (int idx = 1; idx <= state.dataZoneTempPredictorCorrector->NumSingleFangerHeatingControls; ++idx) {
    1272           1 :         inputProcessor->getObjectItem(state,
    1273             :                                       cCurrentModuleObject,
    1274             :                                       idx,
    1275             :                                       cAlphaArgs,
    1276             :                                       NumAlphas,
    1277             :                                       rNumericArgs,
    1278             :                                       NumNums,
    1279             :                                       IOStat,
    1280             :                                       lNumericFieldBlanks,
    1281             :                                       lAlphaFieldBlanks,
    1282             :                                       cAlphaFieldNames,
    1283             :                                       cNumericFieldNames);
    1284           1 :         UtilityRoutines::IsNameEmpty(state, cAlphaArgs(1), cCurrentModuleObject, ErrorsFound);
    1285           1 :         auto &singleSetpointHtgFanger = state.dataZoneTempPredictorCorrector->SetPointSingleHeatingFanger(idx);
    1286           1 :         singleSetpointHtgFanger.Name = cAlphaArgs(1);
    1287           1 :         singleSetpointHtgFanger.PMVSchedName = cAlphaArgs(2);
    1288           1 :         singleSetpointHtgFanger.PMVSchedIndex = GetScheduleIndex(state, cAlphaArgs(2));
    1289           1 :         if (singleSetpointHtgFanger.PMVSchedIndex == 0) {
    1290           0 :             ShowSevereError(
    1291           0 :                 state, cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) + "\" not found.");
    1292           0 :             ErrorsFound = true;
    1293             :         } else {
    1294           1 :             ValidScheduleControlType = CheckScheduleValueMinMax(state, singleSetpointHtgFanger.PMVSchedIndex, ">=", -3.0, "<=", 3.0);
    1295           1 :             if (!ValidScheduleControlType) {
    1296           0 :                 ShowSevereError(state,
    1297           0 :                                 cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid PMV values " + cAlphaFieldNames(2) + "=\"" +
    1298           0 :                                     cAlphaArgs(2) + "\" entered.");
    1299           0 :                 ShowContinueError(state, "..Values outside of range [-3,+3].");
    1300           0 :                 ErrorsFound = true;
    1301             :             }
    1302             :         }
    1303             :     } // SingleFangerHeatingControlNum
    1304             : 
    1305         771 :     cCurrentModuleObject = ValidComfortControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::SingleCooling)];
    1306         771 :     state.dataZoneTempPredictorCorrector->NumSingleFangerCoolingControls = inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    1307             : 
    1308         771 :     if (state.dataZoneTempPredictorCorrector->NumSingleFangerCoolingControls > 0) {
    1309           2 :         state.dataZoneTempPredictorCorrector->SetPointSingleCoolingFanger.allocate(
    1310           1 :             state.dataZoneTempPredictorCorrector->NumSingleFangerCoolingControls);
    1311             :     }
    1312             : 
    1313         772 :     for (int idx = 1; idx <= state.dataZoneTempPredictorCorrector->NumSingleFangerCoolingControls; ++idx) {
    1314           1 :         inputProcessor->getObjectItem(state,
    1315             :                                       cCurrentModuleObject,
    1316             :                                       idx,
    1317             :                                       cAlphaArgs,
    1318             :                                       NumAlphas,
    1319             :                                       rNumericArgs,
    1320             :                                       NumNums,
    1321             :                                       IOStat,
    1322             :                                       lNumericFieldBlanks,
    1323             :                                       lAlphaFieldBlanks,
    1324             :                                       cAlphaFieldNames,
    1325             :                                       cNumericFieldNames);
    1326           1 :         UtilityRoutines::IsNameEmpty(state, cAlphaArgs(1), cCurrentModuleObject, ErrorsFound);
    1327           1 :         auto &singleSetpointClgFanger = state.dataZoneTempPredictorCorrector->SetPointSingleCoolingFanger(idx);
    1328           1 :         singleSetpointClgFanger.Name = cAlphaArgs(1);
    1329           1 :         singleSetpointClgFanger.PMVSchedName = cAlphaArgs(2);
    1330           1 :         singleSetpointClgFanger.PMVSchedIndex = GetScheduleIndex(state, cAlphaArgs(2));
    1331           1 :         if (singleSetpointClgFanger.PMVSchedIndex == 0) {
    1332           0 :             ShowSevereError(
    1333           0 :                 state, cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) + "\" not found.");
    1334           0 :             ErrorsFound = true;
    1335             :         } else {
    1336           1 :             ValidScheduleControlType = CheckScheduleValueMinMax(state, singleSetpointClgFanger.PMVSchedIndex, ">=", -3.0, "<=", 3.0);
    1337           1 :             if (!ValidScheduleControlType) {
    1338           0 :                 ShowSevereError(state,
    1339           0 :                                 cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid PMV values " + cAlphaFieldNames(2) + "=\"" +
    1340           0 :                                     cAlphaArgs(2) + "\" entered.");
    1341           0 :                 ShowContinueError(state, "..Values outside of range [-3,+3].");
    1342           0 :                 ErrorsFound = true;
    1343             :             }
    1344             :         }
    1345             : 
    1346             :     } // SingleFangerCoolingControlNum
    1347             : 
    1348         771 :     cCurrentModuleObject = ValidComfortControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeatCool)];
    1349         771 :     state.dataZoneTempPredictorCorrector->NumSingleFangerHeatCoolControls = inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    1350             : 
    1351         771 :     if (state.dataZoneTempPredictorCorrector->NumSingleFangerHeatCoolControls > 0)
    1352           2 :         state.dataZoneTempPredictorCorrector->SetPointSingleHeatCoolFanger.allocate(
    1353           1 :             state.dataZoneTempPredictorCorrector->NumSingleFangerHeatCoolControls);
    1354             : 
    1355         772 :     for (int idx = 1; idx <= state.dataZoneTempPredictorCorrector->NumSingleFangerHeatCoolControls; ++idx) {
    1356           1 :         inputProcessor->getObjectItem(state,
    1357             :                                       cCurrentModuleObject,
    1358             :                                       idx,
    1359             :                                       cAlphaArgs,
    1360             :                                       NumAlphas,
    1361             :                                       rNumericArgs,
    1362             :                                       NumNums,
    1363             :                                       IOStat,
    1364             :                                       lNumericFieldBlanks,
    1365             :                                       lAlphaFieldBlanks,
    1366             :                                       cAlphaFieldNames,
    1367             :                                       cNumericFieldNames);
    1368           1 :         UtilityRoutines::IsNameEmpty(state, cAlphaArgs(1), cCurrentModuleObject, ErrorsFound);
    1369           1 :         auto &singleSetpointHeatCoolFanger = state.dataZoneTempPredictorCorrector->SetPointSingleHeatCoolFanger(idx);
    1370           1 :         singleSetpointHeatCoolFanger.Name = cAlphaArgs(1);
    1371           1 :         singleSetpointHeatCoolFanger.PMVSchedName = cAlphaArgs(2);
    1372           1 :         singleSetpointHeatCoolFanger.PMVSchedIndex = GetScheduleIndex(state, cAlphaArgs(2));
    1373           1 :         if (singleSetpointHeatCoolFanger.PMVSchedIndex == 0) {
    1374           0 :             ShowSevereError(
    1375           0 :                 state, cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) + "\" not found.");
    1376           0 :             ErrorsFound = true;
    1377             :         } else {
    1378           1 :             ValidScheduleControlType = CheckScheduleValueMinMax(state, singleSetpointHeatCoolFanger.PMVSchedIndex, ">=", -3.0, "<=", 3.0);
    1379           1 :             if (!ValidScheduleControlType) {
    1380           0 :                 ShowSevereError(state,
    1381           0 :                                 cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid PMV values " + cAlphaFieldNames(2) + "=\"" +
    1382           0 :                                     cAlphaArgs(2) + "\" entered.");
    1383           0 :                 ShowContinueError(state, "..Values outside of range [-3,+3].");
    1384           0 :                 ErrorsFound = true;
    1385             :             }
    1386             :         }
    1387             : 
    1388             :     } // SingleFangerHeatCoolControlNum
    1389             : 
    1390         771 :     cCurrentModuleObject = ValidComfortControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand)];
    1391         771 :     state.dataZoneTempPredictorCorrector->NumDualFangerHeatCoolControls = inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    1392             : 
    1393         771 :     if (state.dataZoneTempPredictorCorrector->NumDualFangerHeatCoolControls > 0)
    1394           2 :         state.dataZoneTempPredictorCorrector->SetPointDualHeatCoolFanger.allocate(
    1395           1 :             state.dataZoneTempPredictorCorrector->NumDualFangerHeatCoolControls);
    1396             : 
    1397         772 :     for (int idx = 1; idx <= state.dataZoneTempPredictorCorrector->NumDualFangerHeatCoolControls; ++idx) {
    1398           1 :         inputProcessor->getObjectItem(state,
    1399             :                                       cCurrentModuleObject,
    1400             :                                       idx,
    1401             :                                       cAlphaArgs,
    1402             :                                       NumAlphas,
    1403             :                                       rNumericArgs,
    1404             :                                       NumNums,
    1405             :                                       IOStat,
    1406             :                                       lNumericFieldBlanks,
    1407             :                                       lAlphaFieldBlanks,
    1408             :                                       cAlphaFieldNames,
    1409             :                                       cNumericFieldNames);
    1410           1 :         UtilityRoutines::IsNameEmpty(state, cAlphaArgs(1), cCurrentModuleObject, ErrorsFound);
    1411           1 :         auto &dualSetpointHeatCoolFanger = state.dataZoneTempPredictorCorrector->SetPointDualHeatCoolFanger(idx);
    1412           1 :         dualSetpointHeatCoolFanger.Name = cAlphaArgs(1);
    1413           1 :         dualSetpointHeatCoolFanger.HeatPMVSetptSchedName = cAlphaArgs(2);
    1414           1 :         dualSetpointHeatCoolFanger.HeatPMVSchedIndex = GetScheduleIndex(state, cAlphaArgs(2));
    1415           1 :         if (dualSetpointHeatCoolFanger.HeatPMVSchedIndex == 0) {
    1416           0 :             ShowSevereError(
    1417           0 :                 state, cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) + "\" not found.");
    1418           0 :             ErrorsFound = true;
    1419             :         }
    1420           1 :         dualSetpointHeatCoolFanger.CoolPMVSetptSchedName = cAlphaArgs(3);
    1421           1 :         dualSetpointHeatCoolFanger.CoolPMVSchedIndex = GetScheduleIndex(state, cAlphaArgs(3));
    1422           1 :         if (dualSetpointHeatCoolFanger.CoolPMVSchedIndex == 0) {
    1423           0 :             ShowSevereError(
    1424           0 :                 state, cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(3) + "=\"" + cAlphaArgs(3) + "\" not found.");
    1425           0 :             ErrorsFound = true;
    1426             :         } else {
    1427           1 :             ValidScheduleControlType = CheckScheduleValueMinMax(state, dualSetpointHeatCoolFanger.HeatPMVSchedIndex, ">=", -3.0, "<=", 3.0);
    1428           1 :             if (!ValidScheduleControlType) {
    1429           0 :                 ShowSevereError(state,
    1430           0 :                                 cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid PMV values " + cAlphaFieldNames(2) + "=\"" +
    1431           0 :                                     cAlphaArgs(2) + "\" entered.");
    1432           0 :                 ShowContinueError(state, "..Values outside of range [-3,+3].");
    1433           0 :                 ErrorsFound = true;
    1434             :             }
    1435           1 :             ValidScheduleControlType = CheckScheduleValueMinMax(state, dualSetpointHeatCoolFanger.CoolPMVSchedIndex, ">=", -3.0, "<=", 3.0);
    1436           1 :             if (!ValidScheduleControlType) {
    1437           0 :                 ShowSevereError(state,
    1438           0 :                                 cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid PMV values " + cAlphaFieldNames(3) + "=\"" +
    1439           0 :                                     cAlphaArgs(3) + "\" entered.");
    1440           0 :                 ShowContinueError(state, "..Values outside of range [-3,+3].");
    1441           0 :                 ErrorsFound = true;
    1442             :             }
    1443             :         }
    1444             : 
    1445             :     } // DualFangerHeatCoolControlNum
    1446             : 
    1447             :     // Finish filling in Schedule pointing indexes for Thermal Comfort Control
    1448         772 :     for (ComfortControlledZoneNum = 1; ComfortControlledZoneNum <= state.dataZoneCtrls->NumComfortControlledZones; ++ComfortControlledZoneNum) {
    1449             : 
    1450           2 :         int ComfortIndex = UtilityRoutines::FindItem(ValidComfortControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeating)],
    1451           1 :                                                      ComfortControlledZone(ComfortControlledZoneNum).ControlType,
    1452           2 :                                                      ComfortControlledZone(ComfortControlledZoneNum).NumControlTypes);
    1453           1 :         ComfortControlledZone(ComfortControlledZoneNum).SchIndx_SingleHeating = ComfortIndex;
    1454           1 :         if (ComfortIndex > 0) {
    1455           1 :             ComfortControlledZone(ComfortControlledZoneNum).ControlTypeSchIndx(ComfortIndex) =
    1456           1 :                 UtilityRoutines::FindItem(ComfortControlledZone(ComfortControlledZoneNum).ControlTypeName(ComfortIndex),
    1457           1 :                                           state.dataZoneTempPredictorCorrector->SetPointSingleHeatingFanger);
    1458           1 :             TComfortControlTypes(ComfortControlledZoneNum).MustHave[static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeating)] = true;
    1459             :         }
    1460             : 
    1461           2 :         ComfortIndex = UtilityRoutines::FindItem(ValidComfortControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::SingleCooling)],
    1462           1 :                                                  ComfortControlledZone(ComfortControlledZoneNum).ControlType,
    1463           1 :                                                  ComfortControlledZone(ComfortControlledZoneNum).NumControlTypes);
    1464           1 :         ComfortControlledZone(ComfortControlledZoneNum).SchIndx_SingleCooling = ComfortIndex;
    1465           1 :         if (ComfortIndex > 0) {
    1466           1 :             ComfortControlledZone(ComfortControlledZoneNum).ControlTypeSchIndx(ComfortIndex) =
    1467           1 :                 UtilityRoutines::FindItem(ComfortControlledZone(ComfortControlledZoneNum).ControlTypeName(ComfortIndex),
    1468           1 :                                           state.dataZoneTempPredictorCorrector->SetPointSingleCoolingFanger);
    1469           1 :             TComfortControlTypes(ComfortControlledZoneNum).MustHave[static_cast<int>(DataHVACGlobals::ThermostatType::SingleCooling)] = true;
    1470             :         }
    1471             : 
    1472           2 :         ComfortIndex = UtilityRoutines::FindItem(ValidComfortControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeatCool)],
    1473           1 :                                                  ComfortControlledZone(ComfortControlledZoneNum).ControlType,
    1474           1 :                                                  ComfortControlledZone(ComfortControlledZoneNum).NumControlTypes);
    1475           1 :         ComfortControlledZone(ComfortControlledZoneNum).SchIndx_SingleHeatCool = ComfortIndex;
    1476           1 :         if (ComfortIndex > 0) {
    1477           1 :             ComfortControlledZone(ComfortControlledZoneNum).ControlTypeSchIndx(ComfortIndex) =
    1478           1 :                 UtilityRoutines::FindItem(ComfortControlledZone(ComfortControlledZoneNum).ControlTypeName(ComfortIndex),
    1479           1 :                                           state.dataZoneTempPredictorCorrector->SetPointSingleHeatCoolFanger);
    1480           1 :             TComfortControlTypes(ComfortControlledZoneNum).MustHave[static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeatCool)] = true;
    1481             :         }
    1482             : 
    1483           1 :         ComfortIndex =
    1484           2 :             UtilityRoutines::FindItem(ValidComfortControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand)],
    1485           1 :                                       ComfortControlledZone(ComfortControlledZoneNum).ControlType,
    1486           1 :                                       ComfortControlledZone(ComfortControlledZoneNum).NumControlTypes);
    1487           1 :         ComfortControlledZone(ComfortControlledZoneNum).SchIndx_DualSetPointWithDeadBand = ComfortIndex;
    1488           1 :         if (ComfortIndex > 0) {
    1489           1 :             ComfortControlledZone(ComfortControlledZoneNum).ControlTypeSchIndx(ComfortIndex) =
    1490           1 :                 UtilityRoutines::FindItem(ComfortControlledZone(ComfortControlledZoneNum).ControlTypeName(ComfortIndex),
    1491           1 :                                           state.dataZoneTempPredictorCorrector->SetPointDualHeatCoolFanger);
    1492           1 :             TComfortControlTypes(ComfortControlledZoneNum).MustHave[static_cast<int>(DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand)] =
    1493             :                 true;
    1494             :         }
    1495             :     }
    1496             : 
    1497             :     // Now, Check the schedule values/indices for validity for Thermal Comfort Control
    1498             : 
    1499         772 :     for (ComfortControlledZoneNum = 1; ComfortControlledZoneNum <= state.dataZoneCtrls->NumComfortControlledZones; ++ComfortControlledZoneNum) {
    1500             : 
    1501           1 :         ActualZoneNum = ComfortControlledZone(ComfortControlledZoneNum).ActualZoneNum;
    1502           1 :         CTIndex = ComfortControlledZone(ComfortControlledZoneNum).ComfortSchedIndex;
    1503           1 :         if (CTIndex == 0) continue; // error will be caught elsewhere
    1504           1 :         SchedMin = GetScheduleMinValue(state, CTIndex);
    1505           1 :         SchedMax = GetScheduleMaxValue(state, CTIndex);
    1506             : 
    1507           1 :         if (SchedMin == 0 && SchedMax == 0) {
    1508           0 :             if (FindNumberInList(CTIndex, CCmSchedMapToControlledZone, state.dataZoneCtrls->NumComfortControlledZones) == 0) {
    1509           0 :                 ShowWarningError(state, "Control Type Schedule=" + ComfortControlledZone(ComfortControlledZoneNum).ControlTypeSchedName);
    1510           0 :                 ShowContinueError(state, "..specifies control type 0 for all entries.");
    1511           0 :                 ShowContinueError(state, "All zones using this Control Type Schedule have no thermal comfort control.");
    1512             :             }
    1513           0 :             CCmSchedMapToControlledZone(ComfortControlledZoneNum) = CTIndex;
    1514             :         }
    1515             : 
    1516           6 :         for (ControlTypeNum = SchedMin; ControlTypeNum <= SchedMax; ++ControlTypeNum) {
    1517             : 
    1518             :             int ComfortIndex;
    1519           5 :             switch (static_cast<DataHVACGlobals::ThermostatType>(ControlTypeNum)) {
    1520           1 :             case DataHVACGlobals::ThermostatType::Uncontrolled:
    1521           1 :                 break;
    1522           1 :             case DataHVACGlobals::ThermostatType::SingleHeating:
    1523           1 :                 ComfortIndex = ComfortControlledZone(ComfortControlledZoneNum).SchIndx_SingleHeating;
    1524           1 :                 TComfortControlTypes(ComfortControlledZoneNum).DidHave[static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeating)] = true;
    1525           1 :                 if (ComfortIndex != 0) {
    1526           1 :                     SchedTypeIndex = ComfortControlledZone(ComfortControlledZoneNum).ControlTypeSchIndx(ComfortIndex);
    1527           1 :                     if (SchedTypeIndex == 0) {
    1528           0 :                         ShowSevereError(state,
    1529           0 :                                         format("GetZoneAirSetpoints: Could not find {} Schedule={}",
    1530           0 :                                                ValidComfortControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeating)],
    1531           0 :                                                ComfortControlledZone(ComfortControlledZoneNum).ControlTypeName(ComfortIndex)));
    1532           0 :                         ErrorsFound = true;
    1533             :                     }
    1534             :                 } else { // ComfortIndex = 0
    1535           0 :                     if (CheckScheduleValue(state, CTIndex, static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeating))) {
    1536           0 :                         ShowSevereError(state, "Control Type Schedule=" + ComfortControlledZone(ComfortControlledZoneNum).ControlTypeSchedName);
    1537           0 :                         ShowContinueError(state,
    1538           0 :                                           format("..specifies thermal control type 1 ({}) as the control type. Not valid for this zone.",
    1539           0 :                                                  ValidComfortControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeating)]));
    1540           0 :                         ShowContinueError(state,
    1541           0 :                                           "..reference " + cZControlTypes(static_cast<int>(ZoneControlTypes::TCTStat)) + '=' +
    1542           0 :                                               ComfortControlledZone(ComfortControlledZoneNum).Name);
    1543           0 :                         ShowContinueError(state, "..reference ZONE=" + ComfortControlledZone(ComfortControlledZoneNum).ZoneName);
    1544           0 :                         ErrorsFound = true;
    1545             :                     }
    1546             :                 }
    1547           1 :                 break;
    1548           1 :             case DataHVACGlobals::ThermostatType::SingleCooling:
    1549           1 :                 ComfortIndex = ComfortControlledZone(ComfortControlledZoneNum).SchIndx_SingleCooling;
    1550           1 :                 TComfortControlTypes(ComfortControlledZoneNum).DidHave[static_cast<int>(DataHVACGlobals::ThermostatType::SingleCooling)] = true;
    1551           1 :                 if (ComfortIndex != 0) {
    1552           1 :                     SchedTypeIndex = ComfortControlledZone(ComfortControlledZoneNum).ControlTypeSchIndx(ComfortIndex);
    1553           1 :                     if (SchedTypeIndex == 0) {
    1554           0 :                         ShowSevereError(state,
    1555           0 :                                         format("GetZoneAirSetpoints: Could not find {} Schedule={}",
    1556           0 :                                                ValidComfortControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::SingleCooling)],
    1557           0 :                                                ComfortControlledZone(ComfortControlledZoneNum).ControlTypeName(ComfortIndex)));
    1558           0 :                         ErrorsFound = true;
    1559             :                     }
    1560             :                 } else { // ComfortIndex = 0
    1561           0 :                     if (CheckScheduleValue(state, CTIndex, static_cast<int>(DataHVACGlobals::ThermostatType::SingleCooling))) {
    1562           0 :                         ShowSevereError(state, "Control Type Schedule=" + ComfortControlledZone(ComfortControlledZoneNum).ControlTypeSchedName);
    1563           0 :                         ShowContinueError(state,
    1564           0 :                                           format("..specifies thermal control type 2 ({}) as the control type. Not valid for this zone.",
    1565           0 :                                                  ValidComfortControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::SingleCooling)]));
    1566           0 :                         ShowContinueError(state,
    1567           0 :                                           "..reference " + cZControlTypes(static_cast<int>(ZoneControlTypes::TCTStat)) + '=' +
    1568           0 :                                               ComfortControlledZone(ComfortControlledZoneNum).Name);
    1569           0 :                         ShowContinueError(state, "..reference ZONE=" + ComfortControlledZone(ComfortControlledZoneNum).ZoneName);
    1570           0 :                         ErrorsFound = true;
    1571             :                     }
    1572             :                 }
    1573           1 :                 break;
    1574           1 :             case DataHVACGlobals::ThermostatType::SingleHeatCool:
    1575           1 :                 ComfortIndex = ComfortControlledZone(ComfortControlledZoneNum).SchIndx_SingleHeatCool;
    1576           1 :                 TComfortControlTypes(ComfortControlledZoneNum).DidHave[static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeatCool)] = true;
    1577           1 :                 if (ComfortIndex != 0) {
    1578           1 :                     SchedTypeIndex = ComfortControlledZone(ComfortControlledZoneNum).ControlTypeSchIndx(ComfortIndex);
    1579           1 :                     if (SchedTypeIndex == 0) {
    1580           0 :                         ShowSevereError(state,
    1581           0 :                                         format("GetZoneAirSetpoints: Could not find {} Schedule={}",
    1582           0 :                                                ValidComfortControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeatCool)],
    1583           0 :                                                ComfortControlledZone(ComfortControlledZoneNum).ControlTypeName(ComfortIndex)));
    1584           0 :                         ErrorsFound = true;
    1585             :                     }
    1586             :                 } else { // ComfortIndex = 0
    1587           0 :                     if (CheckScheduleValue(state, CTIndex, static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeatCool))) {
    1588           0 :                         ShowSevereError(state, "Schedule=" + ComfortControlledZone(ComfortControlledZoneNum).ControlTypeSchedName);
    1589           0 :                         ShowContinueError(state,
    1590           0 :                                           format("..specifies thermal control type 3 ({}) as the control type. Not valid for this zone.",
    1591           0 :                                                  ValidComfortControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeatCool)]));
    1592           0 :                         ShowContinueError(state,
    1593           0 :                                           "..reference " + cZControlTypes(static_cast<int>(ZoneControlTypes::TCTStat)) + '=' +
    1594           0 :                                               ComfortControlledZone(ComfortControlledZoneNum).Name);
    1595           0 :                         ShowContinueError(state, "..reference ZONE=" + ComfortControlledZone(ComfortControlledZoneNum).ZoneName);
    1596           0 :                         ErrorsFound = true;
    1597             :                     }
    1598             :                 }
    1599           1 :                 break;
    1600           1 :             case DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand:
    1601           1 :                 ComfortIndex = ComfortControlledZone(ComfortControlledZoneNum).SchIndx_DualSetPointWithDeadBand;
    1602           1 :                 TComfortControlTypes(ComfortControlledZoneNum).DidHave[static_cast<int>(DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand)] =
    1603             :                     true;
    1604           1 :                 if (ComfortIndex != 0) {
    1605           1 :                     SchedTypeIndex = ComfortControlledZone(ComfortControlledZoneNum).ControlTypeSchIndx(ComfortIndex);
    1606           1 :                     if (SchedTypeIndex == 0) {
    1607           0 :                         ShowSevereError(state,
    1608           0 :                                         format("GetZoneAirSetpoints: Could not find {} Schedule={}",
    1609           0 :                                                ValidComfortControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand)],
    1610           0 :                                                ComfortControlledZone(ComfortControlledZoneNum).ControlTypeName(ComfortIndex)));
    1611           0 :                         ErrorsFound = true;
    1612             :                     }
    1613             :                 } else { // ComfortIndex = 0
    1614           0 :                     if (CheckScheduleValue(state, CTIndex, static_cast<int>(DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand))) {
    1615           0 :                         ShowSevereError(state, "Schedule=" + ComfortControlledZone(ComfortControlledZoneNum).ControlTypeSchedName);
    1616           0 :                         ShowContinueError(
    1617             :                             state,
    1618           0 :                             format("..specifies thermal control type 4 ({}) as the control type. Not valid for this zone.",
    1619           0 :                                    ValidComfortControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand)]));
    1620           0 :                         ShowContinueError(state,
    1621           0 :                                           "..reference " + cZControlTypes(static_cast<int>(ZoneControlTypes::TCTStat)) + '=' +
    1622           0 :                                               ComfortControlledZone(ComfortControlledZoneNum).Name);
    1623           0 :                         ShowContinueError(state, "..reference ZONE=" + ComfortControlledZone(ComfortControlledZoneNum).ZoneName);
    1624           0 :                         ErrorsFound = true;
    1625             :                     }
    1626             :                 }
    1627           1 :                 break;
    1628           0 :             default:
    1629           0 :                 ShowSevereError(state,
    1630           0 :                                 format("GetZoneAirSetpoints: Illegal control type for Zone={}, Found value={}, in Schedule={}",
    1631           0 :                                        Zone(ActualZoneNum).Name,
    1632             :                                        ControlTypeNum,
    1633           0 :                                        ComfortControlledZone(ComfortControlledZoneNum).ControlTypeSchedName));
    1634           0 :                 ShowContinueError(state, "..valid range values are [0,4].");
    1635           0 :                 ErrorsFound = true;
    1636           0 :                 break;
    1637             :             }
    1638             :         }
    1639             :     }
    1640             : 
    1641         772 :     for (ComfortControlledZoneNum = 1; ComfortControlledZoneNum <= state.dataZoneCtrls->NumComfortControlledZones; ++ComfortControlledZoneNum) {
    1642             : 
    1643           1 :         ActualZoneNum = ComfortControlledZone(ComfortControlledZoneNum).ActualZoneNum;
    1644           1 :         CTIndex = ComfortControlledZone(ComfortControlledZoneNum).ComfortSchedIndex;
    1645           1 :         if (CTIndex == 0) continue; // error caught elsewhere -- would just be confusing here
    1646             : 
    1647           5 :         for (ControlTypeNum = 1; ControlTypeNum <= 4; ++ControlTypeNum) {
    1648           8 :             if (TComfortControlTypes(ComfortControlledZoneNum).MustHave[ControlTypeNum] &&
    1649           4 :                 TComfortControlTypes(ComfortControlledZoneNum).DidHave[ControlTypeNum])
    1650           4 :                 continue;
    1651             : 
    1652           0 :             switch (static_cast<DataHVACGlobals::ThermostatType>(ControlTypeNum)) {
    1653           0 :             case DataHVACGlobals::ThermostatType::SingleHeating:
    1654           0 :                 if (!TComfortControlTypes(ComfortControlledZoneNum).MustHave[ControlTypeNum]) continue;
    1655           0 :                 ShowWarningError(state, "Schedule=" + ComfortControlledZone(ComfortControlledZoneNum).ControlTypeSchedName);
    1656           0 :                 ShowContinueError(state,
    1657           0 :                                   format("...should include control type 1 ({}) but does not.",
    1658           0 :                                          ValidComfortControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeating)]));
    1659           0 :                 ShowContinueError(state,
    1660           0 :                                   "..reference " + cZControlTypes(static_cast<int>(ZoneControlTypes::TCTStat)) + '=' +
    1661           0 :                                       ComfortControlledZone(ComfortControlledZoneNum).Name);
    1662           0 :                 ShowContinueError(state, "..reference ZONE=" + ComfortControlledZone(ComfortControlledZoneNum).ZoneName);
    1663           0 :                 break;
    1664           0 :             case DataHVACGlobals::ThermostatType::SingleCooling:
    1665           0 :                 if (!TComfortControlTypes(ComfortControlledZoneNum).MustHave[ControlTypeNum]) continue;
    1666           0 :                 ShowWarningError(state, "Schedule=" + ComfortControlledZone(ComfortControlledZoneNum).ControlTypeSchedName);
    1667           0 :                 ShowContinueError(state,
    1668           0 :                                   format("...should include control type 2 ({}) but does not.",
    1669           0 :                                          ValidComfortControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::SingleCooling)]));
    1670           0 :                 ShowContinueError(state,
    1671           0 :                                   "..reference " + cZControlTypes(static_cast<int>(ZoneControlTypes::TCTStat)) + '=' +
    1672           0 :                                       ComfortControlledZone(ComfortControlledZoneNum).Name);
    1673           0 :                 ShowContinueError(state, "..reference ZONE=" + ComfortControlledZone(ComfortControlledZoneNum).ZoneName);
    1674           0 :                 break;
    1675           0 :             case DataHVACGlobals::ThermostatType::SingleHeatCool:
    1676           0 :                 if (!TComfortControlTypes(ComfortControlledZoneNum).MustHave[ControlTypeNum]) continue;
    1677           0 :                 ShowWarningError(state, "Schedule=" + ComfortControlledZone(ComfortControlledZoneNum).ControlTypeSchedName);
    1678           0 :                 ShowContinueError(state,
    1679           0 :                                   format("...should include control type 3 ({}) but does not.",
    1680           0 :                                          ValidComfortControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeatCool)]));
    1681           0 :                 ShowContinueError(state,
    1682           0 :                                   "..reference " + cZControlTypes(static_cast<int>(ZoneControlTypes::TCTStat)) + '=' +
    1683           0 :                                       ComfortControlledZone(ComfortControlledZoneNum).Name);
    1684           0 :                 ShowContinueError(state, "..reference ZONE=" + ComfortControlledZone(ComfortControlledZoneNum).ZoneName);
    1685           0 :                 break;
    1686           0 :             case DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand:
    1687           0 :                 if (!TComfortControlTypes(ComfortControlledZoneNum).MustHave[ControlTypeNum]) continue;
    1688           0 :                 ShowWarningError(state, "Schedule=" + ComfortControlledZone(ComfortControlledZoneNum).ControlTypeSchedName);
    1689           0 :                 ShowContinueError(state,
    1690           0 :                                   format("...should include control type 4 ({}) but does not.",
    1691           0 :                                          ValidComfortControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand)]));
    1692           0 :                 ShowContinueError(state,
    1693           0 :                                   "..reference " + cZControlTypes(static_cast<int>(ZoneControlTypes::TCTStat)) + '=' +
    1694           0 :                                       ComfortControlledZone(ComfortControlledZoneNum).Name);
    1695           0 :                 ShowContinueError(state, "..reference ZONE=" + ComfortControlledZone(ComfortControlledZoneNum).ZoneName);
    1696           0 :                 break;
    1697           0 :             default:
    1698           0 :                 break;
    1699             :             }
    1700             :         }
    1701             :     }
    1702             : 
    1703         771 :     if (allocated(TComfortControlTypes)) TComfortControlTypes.deallocate();
    1704             : 
    1705             :     // Get the Hybrid Model setting inputs
    1706         771 :     HybridModel::GetHybridModelZone(state);
    1707             : 
    1708             :     // Default multiplier values
    1709         771 :     Real64 ZoneVolCapMultpSens = 1.0;
    1710         771 :     Real64 ZoneVolCapMultpMoist = 1.0;
    1711         771 :     Real64 ZoneVolCapMultpCO2 = 1.0;
    1712         771 :     Real64 ZoneVolCapMultpGenContam = 1.0;
    1713             : 
    1714             :     // Get the Zone Air Capacitance Multiplier for use in the Predictor-Corrector Procedure
    1715         771 :     cCurrentModuleObject = "ZoneCapacitanceMultiplier:ResearchSpecial";
    1716         771 :     int NumZoneCapaMultiplier = inputProcessor->getNumObjectsFound(state, cCurrentModuleObject); // Number of ZonesCapacityMultiplier object
    1717         771 :     if (NumZoneCapaMultiplier == 0) {
    1718             :         // Assign default multiplier values to all zones
    1719        5423 :         for (int ZoneNum = 1; ZoneNum <= NumOfZones; ZoneNum++) {
    1720        4688 :             Zone(ZoneNum).ZoneVolCapMultpSens = ZoneVolCapMultpSens;
    1721        4688 :             Zone(ZoneNum).ZoneVolCapMultpMoist = ZoneVolCapMultpMoist;
    1722        4688 :             Zone(ZoneNum).ZoneVolCapMultpCO2 = ZoneVolCapMultpCO2;
    1723        4688 :             Zone(ZoneNum).ZoneVolCapMultpGenContam = ZoneVolCapMultpGenContam;
    1724             :         }
    1725             : 
    1726             :     } else {
    1727             : 
    1728             :         // Allow user to specify ZoneCapacitanceMultiplier:ResearchSpecial at zone level
    1729             :         // Added by S. Lee and R. Zhang in Oct. 2016.
    1730             :         // Assign the user inputted multipliers to specified zones
    1731          81 :         for (int ZoneCapNum = 1; ZoneCapNum <= NumZoneCapaMultiplier; ZoneCapNum++) {
    1732          45 :             inputProcessor->getObjectItem(state,
    1733             :                                           cCurrentModuleObject,
    1734             :                                           ZoneCapNum,
    1735             :                                           cAlphaArgs,
    1736             :                                           NumAlphas,
    1737             :                                           rNumericArgs,
    1738             :                                           NumNums,
    1739             :                                           IOStat,
    1740             :                                           lNumericFieldBlanks,
    1741             :                                           lAlphaFieldBlanks,
    1742             :                                           cAlphaFieldNames,
    1743             :                                           cNumericFieldNames);
    1744             : 
    1745          45 :             if (lAlphaFieldBlanks(2)) {
    1746             :                 // default multiplier values for all the zones not specified (zone or zonelist name field is empty)
    1747          33 :                 ZoneVolCapMultpSens = rNumericArgs(1);
    1748          33 :                 ZoneVolCapMultpMoist = rNumericArgs(2);
    1749          33 :                 ZoneVolCapMultpCO2 = rNumericArgs(3);
    1750          33 :                 ZoneVolCapMultpGenContam = rNumericArgs(4);
    1751             :             } else {
    1752             :                 // multiplier values for the specified zone(s)
    1753          12 :                 int ZoneNum = 0;
    1754          12 :                 ZLItem = 0;
    1755          12 :                 Item1 = UtilityRoutines::FindItemInList(cAlphaArgs(2), Zone);
    1756          12 :                 if (Item1 == 0 && state.dataHeatBal->NumOfZoneLists > 0) ZLItem = UtilityRoutines::FindItemInList(cAlphaArgs(2), ZoneList);
    1757          12 :                 if (Item1 > 0) {
    1758          12 :                     ZoneNum = Item1;
    1759          12 :                     Zone(ZoneNum).FlagCustomizedZoneCap = true;
    1760          12 :                     Zone(ZoneNum).ZoneVolCapMultpSens = rNumericArgs(1);
    1761          12 :                     Zone(ZoneNum).ZoneVolCapMultpMoist = rNumericArgs(2);
    1762          12 :                     Zone(ZoneNum).ZoneVolCapMultpCO2 = rNumericArgs(3);
    1763          12 :                     Zone(ZoneNum).ZoneVolCapMultpGenContam = rNumericArgs(4);
    1764           0 :                 } else if (ZLItem > 0) {
    1765           0 :                     for (int ZonePtrNum = 1; ZonePtrNum < ZoneList(ZLItem).NumOfZones; ZonePtrNum++) {
    1766           0 :                         ZoneNum = ZoneList(ZLItem).Zone(ZonePtrNum);
    1767           0 :                         Zone(ZoneNum).FlagCustomizedZoneCap = true;
    1768           0 :                         Zone(ZoneNum).ZoneVolCapMultpSens = rNumericArgs(1);
    1769           0 :                         Zone(ZoneNum).ZoneVolCapMultpMoist = rNumericArgs(2);
    1770           0 :                         Zone(ZoneNum).ZoneVolCapMultpCO2 = rNumericArgs(3);
    1771           0 :                         Zone(ZoneNum).ZoneVolCapMultpGenContam = rNumericArgs(4);
    1772             :                     }
    1773             : 
    1774             :                 } else {
    1775           0 :                     ShowSevereError(state,
    1776           0 :                                     cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) +
    1777             :                                         "\" not found.");
    1778           0 :                     ErrorsFound = true;
    1779             :                 }
    1780             :             }
    1781             :         }
    1782             : 
    1783             :         // Assign default multiplier values to all the other zones
    1784         162 :         for (int ZoneNum = 1; ZoneNum <= NumOfZones; ZoneNum++) {
    1785         126 :             if (!Zone(ZoneNum).FlagCustomizedZoneCap) {
    1786         114 :                 Zone(ZoneNum).ZoneVolCapMultpSens = ZoneVolCapMultpSens;
    1787         114 :                 Zone(ZoneNum).ZoneVolCapMultpMoist = ZoneVolCapMultpMoist;
    1788         114 :                 Zone(ZoneNum).ZoneVolCapMultpCO2 = ZoneVolCapMultpCO2;
    1789         114 :                 Zone(ZoneNum).ZoneVolCapMultpGenContam = ZoneVolCapMultpGenContam;
    1790             :             }
    1791             :         }
    1792             : 
    1793             :         // Calculate the average multiplier value from all zones
    1794             :         {
    1795          36 :             Real64 ZoneVolCapMultpSens_temp = 0.0;
    1796          36 :             Real64 ZoneVolCapMultpMoist_temp = 0.0;
    1797          36 :             Real64 ZoneVolCapMultpCO2_temp = 0.0;
    1798          36 :             Real64 ZoneVolCapMultpGenContam_temp = 0.0;
    1799             : 
    1800         162 :             for (int ZoneNum = 1; ZoneNum <= NumOfZones; ZoneNum++) {
    1801         126 :                 ZoneVolCapMultpSens_temp += Zone(ZoneNum).ZoneVolCapMultpSens;
    1802         126 :                 ZoneVolCapMultpMoist_temp += Zone(ZoneNum).ZoneVolCapMultpMoist;
    1803         126 :                 ZoneVolCapMultpCO2_temp += Zone(ZoneNum).ZoneVolCapMultpCO2;
    1804         126 :                 ZoneVolCapMultpGenContam_temp += Zone(ZoneNum).ZoneVolCapMultpGenContam;
    1805             :             }
    1806             : 
    1807          36 :             if (NumOfZones > 0) {
    1808          36 :                 ZoneVolCapMultpSens = ZoneVolCapMultpSens_temp / NumOfZones;
    1809          36 :                 ZoneVolCapMultpMoist = ZoneVolCapMultpMoist_temp / NumOfZones;
    1810          36 :                 ZoneVolCapMultpCO2 = ZoneVolCapMultpCO2_temp / NumOfZones;
    1811          36 :                 ZoneVolCapMultpGenContam = ZoneVolCapMultpGenContam_temp / NumOfZones;
    1812             :             }
    1813             :         }
    1814             :     }
    1815             : 
    1816         771 :     print(state.files.eio, Header);
    1817         771 :     print(state.files.eio, Format_701, ZoneVolCapMultpSens, ZoneVolCapMultpMoist, ZoneVolCapMultpCO2, ZoneVolCapMultpGenContam);
    1818             : 
    1819         771 :     cCurrentModuleObject = cZControlTypes(static_cast<int>(ZoneControlTypes::OTTStat));
    1820         771 :     state.dataZoneCtrls->NumOpTempControlledZones = inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    1821             : 
    1822         771 :     if (state.dataZoneCtrls->NumOpTempControlledZones > 0) {
    1823           3 :         state.dataZoneCtrls->AnyOpTempControl = true;
    1824             : 
    1825           6 :         for (int idx = 1; idx <= state.dataZoneCtrls->NumOpTempControlledZones; ++idx) {
    1826           3 :             inputProcessor->getObjectItem(state,
    1827             :                                           cCurrentModuleObject,
    1828             :                                           idx,
    1829             :                                           cAlphaArgs,
    1830             :                                           NumAlphas,
    1831             :                                           rNumericArgs,
    1832             :                                           NumNums,
    1833             :                                           IOStat,
    1834             :                                           lNumericFieldBlanks,
    1835             :                                           lAlphaFieldBlanks,
    1836             :                                           cAlphaFieldNames,
    1837             :                                           cNumericFieldNames);
    1838             :             // find matching name of  ZONECONTROL:THERMOSTAT object
    1839           3 :             found = UtilityRoutines::FindItem(cAlphaArgs(1), TStatObjects);
    1840           3 :             if (found == 0) {
    1841             :                 // It might be in the TempControlledZones
    1842           1 :                 found = UtilityRoutines::FindItem(cAlphaArgs(1), TempControlledZone);
    1843           1 :                 if (found == 0) { // throw error
    1844           0 :                     ShowSevereError(state,
    1845           0 :                                     cCurrentModuleObject + '=' + cAlphaArgs(1) + " invalid " +
    1846           0 :                                         cZControlTypes(static_cast<int>(ZoneControlTypes::TStat)) + " reference not found.");
    1847           0 :                     ErrorsFound = true;
    1848             :                 } else {
    1849           1 :                     TempControlledZoneNum = found;
    1850           1 :                     TempControlledZone(TempControlledZoneNum).OperativeTempControl = true;
    1851           1 :                     if (UtilityRoutines::SameString(cAlphaArgs(2), "Scheduled")) {
    1852           0 :                         TempControlledZone(TempControlledZoneNum).OpTempCntrlModeScheduled = true;
    1853             :                     }
    1854           1 :                     if ((!(UtilityRoutines::SameString(cAlphaArgs(2), "Scheduled"))) && (!(UtilityRoutines::SameString(cAlphaArgs(2), "Constant")))) {
    1855           0 :                         ShowSevereError(
    1856           0 :                             state, cCurrentModuleObject + '=' + cAlphaArgs(1) + " invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) + "\".");
    1857           0 :                         ErrorsFound = true;
    1858             :                     }
    1859             : 
    1860           1 :                     TempControlledZone(TempControlledZoneNum).FixedRadiativeFraction = rNumericArgs(1);
    1861           1 :                     TempControlledZone(TempControlledZoneNum).OpTempRadiativeFractionSched = GetScheduleIndex(state, cAlphaArgs(3));
    1862           2 :                     if ((TempControlledZone(TempControlledZoneNum).OpTempRadiativeFractionSched == 0) &&
    1863           1 :                         (TempControlledZone(TempControlledZoneNum).OpTempCntrlModeScheduled)) { // throw error
    1864           0 :                         ShowSevereError(state,
    1865           0 :                                         cCurrentModuleObject + '=' + cAlphaArgs(1) + " invalid " + cAlphaFieldNames(3) + "=\"" + cAlphaArgs(3) +
    1866             :                                             "\" not found.");
    1867           0 :                         ErrorsFound = true;
    1868             :                     }
    1869             : 
    1870             :                     // check validity of fixed radiative fraction
    1871           1 :                     if ((TempControlledZone(TempControlledZoneNum).FixedRadiativeFraction < 0.0) &&
    1872           0 :                         (!(TempControlledZone(TempControlledZoneNum).OpTempCntrlModeScheduled))) {
    1873           0 :                         ShowSevereError(state,
    1874           0 :                                         format("{}={} invalid {}=[{:.2T}\" cannot be negative.",
    1875             :                                                cCurrentModuleObject,
    1876             :                                                cAlphaArgs(1),
    1877             :                                                cNumericFieldNames(1),
    1878           0 :                                                rNumericArgs(1)));
    1879           0 :                         ErrorsFound = true;
    1880             :                     }
    1881           1 :                     if ((TempControlledZone(TempControlledZoneNum).FixedRadiativeFraction >= 0.9) &&
    1882           0 :                         (!(TempControlledZone(TempControlledZoneNum).OpTempCntrlModeScheduled))) {
    1883           0 :                         ShowSevereError(state,
    1884           0 :                                         format("{}={} invalid {}=[{:.2T}\" cannot >= .9.",
    1885             :                                                cCurrentModuleObject,
    1886             :                                                cAlphaArgs(1),
    1887             :                                                cNumericFieldNames(1),
    1888           0 :                                                rNumericArgs(1)));
    1889           0 :                         ErrorsFound = true;
    1890             :                     }
    1891             : 
    1892             :                     // check schedule min max.
    1893           1 :                     if (TempControlledZone(TempControlledZoneNum).OpTempCntrlModeScheduled) {
    1894           0 :                         ValidRadFractSched = CheckScheduleValueMinMax(
    1895           0 :                             state, TempControlledZone(TempControlledZoneNum).OpTempRadiativeFractionSched, ">=", 0.0, "<", 0.9);
    1896           0 :                         if (!ValidRadFractSched) {
    1897           0 :                             ShowSevereError(state,
    1898           0 :                                             cCurrentModuleObject + '=' + cAlphaArgs(1) + " invalid values " + cAlphaFieldNames(3) + "=[" +
    1899           0 :                                                 cAlphaArgs(3) + "\".");
    1900           0 :                             ShowContinueError(state, "..Values outside of range [0.0,0.9).");
    1901           0 :                             ErrorsFound = true;
    1902             :                         }
    1903             :                     }
    1904             : 
    1905             :                     // added Jan, 2017 - Xuan Luo
    1906             :                     // read adaptive comfort model and calculate adaptive thermal comfort setpoint
    1907           1 :                     if (TempControlledZone(TempControlledZoneNum).OperativeTempControl) {
    1908           1 :                         if (NumAlphas >= 4 && !lAlphaFieldBlanks(4)) {
    1909             :                             int adaptiveComfortModelTypeIndex =
    1910           0 :                                 UtilityRoutines::FindItem(cAlphaArgs(4), AdaptiveComfortModelTypes, AdaptiveComfortModelTypes.isize());
    1911           0 :                             if (!adaptiveComfortModelTypeIndex) {
    1912           0 :                                 ShowSevereError(state,
    1913           0 :                                                 cCurrentModuleObject + '=' + cAlphaArgs(1) + " invalid " + cAlphaFieldNames(4) + "=\"" +
    1914           0 :                                                     cAlphaArgs(4) + "\" not found.");
    1915           0 :                                 ErrorsFound = true;
    1916           0 :                             } else if (adaptiveComfortModelTypeIndex != static_cast<int>(AdaptiveComfortModel::ADAP_NONE)) {
    1917           0 :                                 TempControlledZone(TempControlledZoneNum).AdaptiveComfortTempControl = true;
    1918           0 :                                 TempControlledZone(TempControlledZoneNum).AdaptiveComfortModelTypeIndex =
    1919           0 :                                     UtilityRoutines::FindItem(cAlphaArgs(4), AdaptiveComfortModelTypes, AdaptiveComfortModelTypes.isize());
    1920           0 :                                 if (!state.dataZoneTempPredictorCorrector->AdapComfortDailySetPointSchedule.initialized) {
    1921           0 :                                     Array1D<Real64> runningAverageASH(state.dataWeatherManager->NumDaysInYear, 0.0);
    1922           0 :                                     Array1D<Real64> runningAverageCEN(state.dataWeatherManager->NumDaysInYear, 0.0);
    1923           0 :                                     CalculateMonthlyRunningAverageDryBulb(state, runningAverageASH, runningAverageCEN);
    1924           0 :                                     CalculateAdaptiveComfortSetPointSchl(state, runningAverageASH, runningAverageCEN);
    1925             :                                 }
    1926             :                             }
    1927             :                         }
    1928             :                     }
    1929             : 
    1930             :                     // CurrentModuleObject='ZoneControl:Thermostat:OperativeTemperature'
    1931           4 :                     SetupOutputVariable(state,
    1932             :                                         "Zone Thermostat Operative Temperature",
    1933             :                                         OutputProcessor::Unit::C,
    1934           1 :                                         state.dataHeatBal->ZnAirRpt(TempControlledZone(TempControlledZoneNum).ActualZoneNum).ThermOperativeTemp,
    1935             :                                         OutputProcessor::SOVTimeStepType::Zone,
    1936             :                                         OutputProcessor::SOVStoreType::Average,
    1937           2 :                                         Zone(TempControlledZone(TempControlledZoneNum).ActualZoneNum).Name);
    1938             :                 }
    1939             :             } else {
    1940           8 :                 for (Item = 1; Item <= TStatObjects(found).NumOfZones; ++Item) {
    1941           6 :                     TempControlledZoneNum = TStatObjects(found).TempControlledZoneStartPtr + Item - 1;
    1942           6 :                     if (NumTempControlledZones == 0) continue;
    1943           6 :                     TempControlledZone(TempControlledZoneNum).OperativeTempControl = true;
    1944           6 :                     if (UtilityRoutines::SameString(cAlphaArgs(2), "Scheduled")) {
    1945           0 :                         TempControlledZone(TempControlledZoneNum).OpTempCntrlModeScheduled = true;
    1946             :                     }
    1947           6 :                     if (Item == 1) {
    1948           6 :                         if ((!(UtilityRoutines::SameString(cAlphaArgs(2), "Scheduled"))) &&
    1949           4 :                             (!(UtilityRoutines::SameString(cAlphaArgs(2), "Constant")))) {
    1950           0 :                             ShowSevereError(state,
    1951           0 :                                             cCurrentModuleObject + '=' + cAlphaArgs(1) + " invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) +
    1952             :                                                 "\".");
    1953           0 :                             ErrorsFound = true;
    1954             :                         }
    1955             :                     }
    1956             : 
    1957           6 :                     TempControlledZone(TempControlledZoneNum).FixedRadiativeFraction = rNumericArgs(1);
    1958           6 :                     TempControlledZone(TempControlledZoneNum).OpTempRadiativeFractionSched = GetScheduleIndex(state, cAlphaArgs(3));
    1959           6 :                     if (Item == 1) {
    1960           4 :                         if ((TempControlledZone(TempControlledZoneNum).OpTempRadiativeFractionSched == 0) &&
    1961           2 :                             (TempControlledZone(TempControlledZoneNum).OpTempCntrlModeScheduled)) { // throw error
    1962           0 :                             ShowSevereError(state,
    1963           0 :                                             cCurrentModuleObject + '=' + cAlphaArgs(1) + " invalid " + cAlphaFieldNames(3) + "=\"" + cAlphaArgs(3) +
    1964             :                                                 "\" not found.");
    1965           0 :                             ErrorsFound = true;
    1966             :                         }
    1967             :                     }
    1968             : 
    1969             :                     // check validity of fixed radiative fraction
    1970           6 :                     if (Item == 1) {
    1971           2 :                         if ((TempControlledZone(TempControlledZoneNum).FixedRadiativeFraction < 0.0) &&
    1972           0 :                             (!(TempControlledZone(TempControlledZoneNum).OpTempCntrlModeScheduled))) {
    1973           0 :                             ShowSevereError(state,
    1974           0 :                                             format("{}={} invalid {}=[{:.2T}\" cannot be negative.",
    1975             :                                                    cCurrentModuleObject,
    1976             :                                                    cAlphaArgs(1),
    1977             :                                                    cNumericFieldNames(1),
    1978           0 :                                                    rNumericArgs(1)));
    1979           0 :                             ErrorsFound = true;
    1980             :                         }
    1981             :                     }
    1982           6 :                     if (Item == 1) {
    1983           2 :                         if ((TempControlledZone(TempControlledZoneNum).FixedRadiativeFraction >= 0.9) &&
    1984           0 :                             (!(TempControlledZone(TempControlledZoneNum).OpTempCntrlModeScheduled))) {
    1985           0 :                             ShowSevereError(state,
    1986           0 :                                             format("{}={} invalid {}=[{:.2T}\" cannot >= .9.",
    1987             :                                                    cCurrentModuleObject,
    1988             :                                                    cAlphaArgs(1),
    1989             :                                                    cNumericFieldNames(1),
    1990           0 :                                                    rNumericArgs(1)));
    1991           0 :                             ErrorsFound = true;
    1992             :                         }
    1993             :                     }
    1994             : 
    1995             :                     // check schedule min max.
    1996           6 :                     if (Item == 1) {
    1997           2 :                         if (TempControlledZone(TempControlledZoneNum).OpTempCntrlModeScheduled) {
    1998           0 :                             ValidRadFractSched = CheckScheduleValueMinMax(
    1999           0 :                                 state, TempControlledZone(TempControlledZoneNum).OpTempRadiativeFractionSched, ">=", 0.0, "<", 0.9);
    2000           0 :                             if (!ValidRadFractSched) {
    2001           0 :                                 ShowSevereError(state,
    2002           0 :                                                 cCurrentModuleObject + '=' + cAlphaArgs(1) + " invalid values " + cAlphaFieldNames(3) + "=[" +
    2003           0 :                                                     cAlphaArgs(3) + "\".");
    2004           0 :                                 ShowContinueError(state, "..Values outside of range [0.0,0.9).");
    2005           0 :                                 ErrorsFound = true;
    2006             :                             }
    2007             :                         }
    2008             :                     }
    2009             : 
    2010             :                     // added Jan, 2017 - Xuan Luo
    2011             :                     // read adaptive comfort model and calculate adaptive thermal comfort setpoint
    2012           6 :                     if (TempControlledZone(TempControlledZoneNum).OperativeTempControl) {
    2013           6 :                         if (NumAlphas >= 4 && !lAlphaFieldBlanks(4)) {
    2014             :                             int adaptiveComfortModelTypeIndex =
    2015           5 :                                 UtilityRoutines::FindItem(cAlphaArgs(4), AdaptiveComfortModelTypes, AdaptiveComfortModelTypes.isize());
    2016           5 :                             if (!adaptiveComfortModelTypeIndex) {
    2017           0 :                                 ShowSevereError(state,
    2018           0 :                                                 cCurrentModuleObject + '=' + cAlphaArgs(1) + " invalid " + cAlphaFieldNames(4) + "=\"" +
    2019           0 :                                                     cAlphaArgs(4) + "\" not found.");
    2020           0 :                                 ErrorsFound = true;
    2021           5 :                             } else if (adaptiveComfortModelTypeIndex != static_cast<int>(AdaptiveComfortModel::ADAP_NONE)) {
    2022           5 :                                 TempControlledZone(TempControlledZoneNum).AdaptiveComfortTempControl = true;
    2023           5 :                                 TempControlledZone(TempControlledZoneNum).AdaptiveComfortModelTypeIndex =
    2024           5 :                                     UtilityRoutines::FindItem(cAlphaArgs(4), AdaptiveComfortModelTypes, AdaptiveComfortModelTypes.isize());
    2025           5 :                                 if (!state.dataZoneTempPredictorCorrector->AdapComfortDailySetPointSchedule.initialized) {
    2026           2 :                                     Array1D<Real64> runningAverageASH(state.dataWeatherManager->NumDaysInYear, 0.0);
    2027           2 :                                     Array1D<Real64> runningAverageCEN(state.dataWeatherManager->NumDaysInYear, 0.0);
    2028           1 :                                     CalculateMonthlyRunningAverageDryBulb(state, runningAverageASH, runningAverageCEN);
    2029           1 :                                     CalculateAdaptiveComfortSetPointSchl(state, runningAverageASH, runningAverageCEN);
    2030             :                                 }
    2031             :                             }
    2032             :                         }
    2033             :                     }
    2034             : 
    2035             :                     // CurrentModuleObject='ZoneControl:Thermostat:OperativeTemperature'
    2036          24 :                     SetupOutputVariable(state,
    2037             :                                         "Zone Thermostat Operative Temperature",
    2038             :                                         OutputProcessor::Unit::C,
    2039           6 :                                         state.dataHeatBal->ZnAirRpt(TempControlledZone(TempControlledZoneNum).ActualZoneNum).ThermOperativeTemp,
    2040             :                                         OutputProcessor::SOVTimeStepType::Zone,
    2041             :                                         OutputProcessor::SOVStoreType::Average,
    2042          12 :                                         Zone(TempControlledZone(TempControlledZoneNum).ActualZoneNum).Name);
    2043             :                 } // TStat Objects Loop
    2044             :             }     // found thermostat referene
    2045             :         }         // loop over NumOpTempControlledZones
    2046             :     }             // NumOpTempControlledZones > 0
    2047             : 
    2048             :     // Overcool dehumidificaton GetInput starts here
    2049         771 :     cCurrentModuleObject = cZControlTypes(static_cast<int>(ZoneControlTypes::TandHStat));
    2050         771 :     state.dataZoneCtrls->NumTempAndHumidityControlledZones = inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    2051             : 
    2052         771 :     if (state.dataZoneCtrls->NumTempAndHumidityControlledZones > 0) {
    2053           1 :         state.dataZoneCtrls->AnyZoneTempAndHumidityControl = true;
    2054             : 
    2055           2 :         for (int idx = 1; idx <= state.dataZoneCtrls->NumTempAndHumidityControlledZones; ++idx) {
    2056           1 :             inputProcessor->getObjectItem(state,
    2057             :                                           cCurrentModuleObject,
    2058             :                                           idx,
    2059             :                                           cAlphaArgs,
    2060             :                                           NumAlphas,
    2061             :                                           rNumericArgs,
    2062             :                                           NumNums,
    2063             :                                           IOStat,
    2064             :                                           lNumericFieldBlanks,
    2065             :                                           lAlphaFieldBlanks,
    2066             :                                           cAlphaFieldNames,
    2067             :                                           cNumericFieldNames);
    2068             :             // find matching name of  ZONECONTROL:THERMOSTAT object
    2069           1 :             found = UtilityRoutines::FindItem(cAlphaArgs(1), TStatObjects);
    2070           1 :             if (found == 0) {
    2071             :                 // It might be in the TempControlledZones
    2072           0 :                 found = UtilityRoutines::FindItem(cAlphaArgs(1), TempControlledZone);
    2073           0 :                 if (found == 0) { // throw error
    2074           0 :                     ShowSevereError(state,
    2075           0 :                                     cCurrentModuleObject + '=' + cAlphaArgs(1) + " invalid " +
    2076           0 :                                         cZControlTypes(static_cast<int>(ZoneControlTypes::TStat)) + " reference not found.");
    2077           0 :                     ErrorsFound = true;
    2078             :                 } else {
    2079           0 :                     TempControlledZoneNum = found;
    2080           0 :                     TempControlledZone(TempControlledZoneNum).DehumidifyingSched = cAlphaArgs(2);
    2081           0 :                     TempControlledZone(TempControlledZoneNum).DehumidifyingSchedIndex = GetScheduleIndex(state, cAlphaArgs(2));
    2082           0 :                     if (TempControlledZone(TempControlledZoneNum).DehumidifyingSchedIndex == 0) {
    2083           0 :                         ShowSevereError(state,
    2084           0 :                                         cCurrentModuleObject + "=\"" + cAlphaArgs(1) + " invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) +
    2085             :                                             "\" not found.");
    2086           0 :                         ErrorsFound = true;
    2087             :                     }
    2088           0 :                     TempControlledZone(TempControlledZoneNum).ZoneOvercoolControl = true;
    2089           0 :                     if ((UtilityRoutines::SameString(cAlphaArgs(3), "None"))) {
    2090           0 :                         TempControlledZone(TempControlledZoneNum).ZoneOvercoolControl = false;
    2091             :                     }
    2092           0 :                     if (UtilityRoutines::SameString(cAlphaArgs(4), "Scheduled")) {
    2093           0 :                         TempControlledZone(TempControlledZoneNum).OvercoolCntrlModeScheduled = true;
    2094             :                     }
    2095           0 :                     if ((!(UtilityRoutines::SameString(cAlphaArgs(4), "Scheduled"))) && (!(UtilityRoutines::SameString(cAlphaArgs(4), "Constant")))) {
    2096           0 :                         ShowSevereError(
    2097           0 :                             state, cCurrentModuleObject + '=' + cAlphaArgs(1) + " invalid " + cAlphaFieldNames(4) + "=\"" + cAlphaArgs(4) + "\".");
    2098           0 :                         ErrorsFound = true;
    2099             :                     }
    2100             : 
    2101           0 :                     TempControlledZone(TempControlledZoneNum).ZoneOvercoolConstRange = rNumericArgs(1);
    2102           0 :                     TempControlledZone(TempControlledZoneNum).ZoneOvercoolRangeSchedIndex = GetScheduleIndex(state, cAlphaArgs(4));
    2103           0 :                     if ((TempControlledZone(TempControlledZoneNum).ZoneOvercoolRangeSchedIndex == 0) &&
    2104           0 :                         (TempControlledZone(TempControlledZoneNum).OvercoolCntrlModeScheduled)) { // throw error
    2105           0 :                         ShowSevereError(state,
    2106           0 :                                         cCurrentModuleObject + '=' + cAlphaArgs(1) + " invalid " + cAlphaFieldNames(5) + "=\"" + cAlphaArgs(5) +
    2107             :                                             "\" not found.");
    2108           0 :                         ErrorsFound = true;
    2109             :                     }
    2110             : 
    2111             :                     // check validity of zone Overcool constant range
    2112           0 :                     if ((TempControlledZone(TempControlledZoneNum).ZoneOvercoolConstRange < 0.0) &&
    2113           0 :                         (!(TempControlledZone(TempControlledZoneNum).OvercoolCntrlModeScheduled))) {
    2114           0 :                         ShowSevereError(state,
    2115           0 :                                         format("{}={} invalid {}=[{:.2T}\" cannot be negative.",
    2116             :                                                cCurrentModuleObject,
    2117             :                                                cAlphaArgs(1),
    2118             :                                                cNumericFieldNames(1),
    2119           0 :                                                rNumericArgs(1)));
    2120           0 :                         ErrorsFound = true;
    2121             :                     }
    2122           0 :                     if ((TempControlledZone(TempControlledZoneNum).ZoneOvercoolConstRange > 3.0) &&
    2123           0 :                         (!(TempControlledZone(TempControlledZoneNum).OvercoolCntrlModeScheduled))) {
    2124           0 :                         ShowSevereError(state,
    2125           0 :                                         format("{}={} invalid {}=[{:.2T}\" cannot be > 3.0",
    2126             :                                                cCurrentModuleObject,
    2127             :                                                cAlphaArgs(1),
    2128             :                                                cNumericFieldNames(1),
    2129           0 :                                                rNumericArgs(1)));
    2130           0 :                         ErrorsFound = true;
    2131             :                     }
    2132             : 
    2133             :                     // check zone Overcool range schedule min/max values.
    2134           0 :                     if (TempControlledZone(TempControlledZoneNum).OvercoolCntrlModeScheduled) {
    2135           0 :                         ValidZoneOvercoolRangeSched = CheckScheduleValueMinMax(
    2136           0 :                             state, TempControlledZone(TempControlledZoneNum).ZoneOvercoolRangeSchedIndex, ">=", 0.0, "<=", 3.0);
    2137           0 :                         if (!ValidZoneOvercoolRangeSched) {
    2138           0 :                             ShowSevereError(state,
    2139           0 :                                             cCurrentModuleObject + '=' + cAlphaArgs(1) + " invalid values " + cAlphaFieldNames(5) + "=[" +
    2140           0 :                                                 cAlphaArgs(5) + "\".");
    2141           0 :                             ShowContinueError(state, "..Values outside of range [0.0,3.0].");
    2142           0 :                             ErrorsFound = true;
    2143             :                         }
    2144             :                     }
    2145             :                     // check Overcool Control Ratio limits
    2146           0 :                     TempControlledZone(TempControlledZoneNum).ZoneOvercoolControlRatio = rNumericArgs(2);
    2147           0 :                     if (TempControlledZone(TempControlledZoneNum).ZoneOvercoolControlRatio < 0.0) {
    2148           0 :                         ShowSevereError(state,
    2149           0 :                                         format("{}={} invalid {}=[{:.2T}\" cannot be negative.",
    2150             :                                                cCurrentModuleObject,
    2151             :                                                cAlphaArgs(2),
    2152             :                                                cNumericFieldNames(2),
    2153           0 :                                                rNumericArgs(2)));
    2154           0 :                         ErrorsFound = true;
    2155             :                     }
    2156             :                 }
    2157             :             } else {
    2158           2 :                 for (Item = 1; Item <= TStatObjects(found).NumOfZones; ++Item) {
    2159           1 :                     TempControlledZoneNum = TStatObjects(found).TempControlledZoneStartPtr + Item - 1;
    2160           1 :                     TempControlledZone(TempControlledZoneNum).DehumidifyingSched = cAlphaArgs(2);
    2161           1 :                     TempControlledZone(TempControlledZoneNum).DehumidifyingSchedIndex = GetScheduleIndex(state, cAlphaArgs(2));
    2162           1 :                     if (TempControlledZone(TempControlledZoneNum).DehumidifyingSchedIndex == 0) {
    2163           0 :                         ShowSevereError(state,
    2164           0 :                                         cCurrentModuleObject + "=\"" + cAlphaArgs(1) + " invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) +
    2165             :                                             "\" not found.");
    2166           0 :                         ErrorsFound = true;
    2167             :                     }
    2168           1 :                     TempControlledZone(TempControlledZoneNum).ZoneOvercoolControl = true;
    2169           1 :                     if ((UtilityRoutines::SameString(cAlphaArgs(3), "None"))) {
    2170           0 :                         TempControlledZone(TempControlledZoneNum).ZoneOvercoolControl = false;
    2171             :                     }
    2172           1 :                     if (UtilityRoutines::SameString(cAlphaArgs(4), "Scheduled")) {
    2173           0 :                         TempControlledZone(TempControlledZoneNum).OvercoolCntrlModeScheduled = false;
    2174             :                     }
    2175           1 :                     if (Item == 1) {
    2176           3 :                         if ((!(UtilityRoutines::SameString(cAlphaArgs(4), "Scheduled"))) &&
    2177           2 :                             (!(UtilityRoutines::SameString(cAlphaArgs(4), "Constant")))) {
    2178           0 :                             ShowSevereError(state,
    2179           0 :                                             cCurrentModuleObject + '=' + cAlphaArgs(1) + " invalid " + cAlphaFieldNames(4) + "=\"" + cAlphaArgs(4) +
    2180             :                                                 "\".");
    2181           0 :                             ErrorsFound = true;
    2182             :                         }
    2183             :                     }
    2184           1 :                     TempControlledZone(TempControlledZoneNum).ZoneOvercoolConstRange = rNumericArgs(1);
    2185           1 :                     TempControlledZone(TempControlledZoneNum).ZoneOvercoolRangeSchedIndex = GetScheduleIndex(state, cAlphaArgs(6));
    2186           1 :                     if (Item == 1) {
    2187           2 :                         if ((TempControlledZone(TempControlledZoneNum).ZoneOvercoolRangeSchedIndex == 0) &&
    2188           1 :                             (TempControlledZone(TempControlledZoneNum).OvercoolCntrlModeScheduled)) { // throw error
    2189           0 :                             ShowSevereError(state,
    2190           0 :                                             cCurrentModuleObject + '=' + cAlphaArgs(1) + " invalid " + cAlphaFieldNames(5) + "=\"" + cAlphaArgs(5) +
    2191             :                                                 "\" not found.");
    2192           0 :                             ErrorsFound = true;
    2193             :                         }
    2194             :                     }
    2195             :                     // check validity of zone Overcool constant range
    2196           1 :                     if (Item == 1) {
    2197           1 :                         if ((TempControlledZone(TempControlledZoneNum).ZoneOvercoolConstRange < 0.0) &&
    2198           0 :                             (!(TempControlledZone(TempControlledZoneNum).OvercoolCntrlModeScheduled))) {
    2199           0 :                             ShowSevereError(state,
    2200           0 :                                             format("{}={} invalid {}=[{:.2T}\" cannot be negative.",
    2201             :                                                    cCurrentModuleObject,
    2202             :                                                    cAlphaArgs(1),
    2203             :                                                    cNumericFieldNames(1),
    2204           0 :                                                    rNumericArgs(1)));
    2205           0 :                             ErrorsFound = true;
    2206             :                         }
    2207             :                     }
    2208           1 :                     if (Item == 1) {
    2209           1 :                         if ((TempControlledZone(TempControlledZoneNum).ZoneOvercoolConstRange > 3.0) &&
    2210           0 :                             (!(TempControlledZone(TempControlledZoneNum).OvercoolCntrlModeScheduled))) {
    2211           0 :                             ShowSevereError(state,
    2212           0 :                                             format("{}={} invalid {}=[{:.2T}\" cannot > 3.0",
    2213             :                                                    cCurrentModuleObject,
    2214             :                                                    cAlphaArgs(1),
    2215             :                                                    cNumericFieldNames(1),
    2216           0 :                                                    rNumericArgs(1)));
    2217           0 :                             ErrorsFound = true;
    2218             :                         }
    2219             :                     }
    2220             :                     // check zone Overcool range schedule min/max values.
    2221           1 :                     if (Item == 1) {
    2222           1 :                         if (TempControlledZone(TempControlledZoneNum).OvercoolCntrlModeScheduled) {
    2223           0 :                             ValidZoneOvercoolRangeSched = CheckScheduleValueMinMax(
    2224           0 :                                 state, TempControlledZone(TempControlledZoneNum).ZoneOvercoolRangeSchedIndex, ">=", 0.0, "<=", 3.0);
    2225           0 :                             if (!ValidZoneOvercoolRangeSched) {
    2226           0 :                                 ShowSevereError(state,
    2227           0 :                                                 cCurrentModuleObject + '=' + cAlphaArgs(1) + " invalid values " + cAlphaFieldNames(5) + "=[" +
    2228           0 :                                                     cAlphaArgs(5) + "\".");
    2229           0 :                                 ShowContinueError(state, "..Values outside of range [0.0,3.0].");
    2230           0 :                                 ErrorsFound = true;
    2231             :                             }
    2232             :                         }
    2233             :                     }
    2234           1 :                     TempControlledZone(TempControlledZoneNum).ZoneOvercoolControlRatio = rNumericArgs(2);
    2235             :                     // check Overcool Control Ratio limits
    2236           1 :                     if (Item == 1) {
    2237           1 :                         if (TempControlledZone(TempControlledZoneNum).ZoneOvercoolControlRatio < 0.0) {
    2238           0 :                             ShowSevereError(state,
    2239           0 :                                             format("{}={} invalid {}=[{:.2T}\" cannot be negative.",
    2240             :                                                    cCurrentModuleObject,
    2241             :                                                    cAlphaArgs(2),
    2242             :                                                    cNumericFieldNames(2),
    2243           0 :                                                    rNumericArgs(2)));
    2244           0 :                             ErrorsFound = true;
    2245             :                         }
    2246             :                     }
    2247             : 
    2248             :                 } // TStat Objects Loop
    2249             :             }     // found thermostat reference
    2250             :         }         // loop over NumTempAndHumidityControlledZones
    2251             :     }             // NumTempAndHumidityControlledZones > 0
    2252             : 
    2253             :     // Staged thermostat control inputs start
    2254         771 :     cCurrentModuleObject = cZControlTypes(static_cast<int>(ZoneControlTypes::StagedDual));
    2255         771 :     NumStageControlledZones = inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    2256         771 :     if (NumStageControlledZones > 0) state.dataZoneCtrls->StagedTStatObjects.allocate(NumStageControlledZones);
    2257             : 
    2258             :     // Pre-scan for use of Zone lists in TStat statements (i.e. Global application of TStat)
    2259         771 :     state.dataZoneTempPredictorCorrector->NumStageCtrZone = 0;
    2260         776 :     for (Item = 1; Item <= NumStageControlledZones; ++Item) {
    2261           5 :         inputProcessor->getObjectItem(state,
    2262             :                                       cCurrentModuleObject,
    2263             :                                       Item,
    2264             :                                       cAlphaArgs,
    2265             :                                       NumAlphas,
    2266             :                                       rNumericArgs,
    2267             :                                       NumNums,
    2268             :                                       IOStat,
    2269             :                                       lNumericFieldBlanks,
    2270             :                                       lAlphaFieldBlanks,
    2271             :                                       cAlphaFieldNames,
    2272             :                                       cNumericFieldNames);
    2273           5 :         UtilityRoutines::IsNameEmpty(state, cAlphaArgs(1), cCurrentModuleObject, ErrorsFound);
    2274             : 
    2275           5 :         state.dataZoneCtrls->StagedTStatObjects(Item).Name = cAlphaArgs(1);
    2276           5 :         Item1 = UtilityRoutines::FindItemInList(cAlphaArgs(2), Zone);
    2277           5 :         ZLItem = 0;
    2278           5 :         if (Item1 == 0 && state.dataHeatBal->NumOfZoneLists > 0) ZLItem = UtilityRoutines::FindItemInList(cAlphaArgs(2), ZoneList);
    2279           5 :         if (Item1 > 0) {
    2280           4 :             state.dataZoneCtrls->StagedTStatObjects(Item).StageControlledZoneStartPtr = state.dataZoneTempPredictorCorrector->NumStageCtrZone + 1;
    2281           4 :             ++state.dataZoneTempPredictorCorrector->NumStageCtrZone;
    2282           4 :             state.dataZoneCtrls->StagedTStatObjects(Item).NumOfZones = 1;
    2283           4 :             state.dataZoneCtrls->StagedTStatObjects(Item).ZoneListActive = false;
    2284           4 :             state.dataZoneCtrls->StagedTStatObjects(Item).ZoneOrZoneListPtr = Item1;
    2285           1 :         } else if (ZLItem > 0) {
    2286           1 :             state.dataZoneCtrls->StagedTStatObjects(Item).TempControlledZoneStartPtr = state.dataZoneTempPredictorCorrector->NumStageCtrZone + 1;
    2287           1 :             state.dataZoneTempPredictorCorrector->NumStageCtrZone += ZoneList(ZLItem).NumOfZones;
    2288           1 :             state.dataZoneCtrls->StagedTStatObjects(Item).NumOfZones = ZoneList(ZLItem).NumOfZones;
    2289           1 :             state.dataZoneCtrls->StagedTStatObjects(Item).ZoneListActive = true;
    2290           1 :             state.dataZoneCtrls->StagedTStatObjects(Item).ZoneOrZoneListPtr = ZLItem;
    2291             :         } else {
    2292           0 :             ShowSevereError(
    2293           0 :                 state, cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) + "\" not found.");
    2294           0 :             ErrorsFound = true;
    2295             :         }
    2296             :     }
    2297             : 
    2298         771 :     if (ErrorsFound) {
    2299           0 :         ShowSevereError(state, "GetStagedDualSetpoint: Errors with invalid names in " + cCurrentModuleObject + " objects.");
    2300           0 :         ShowContinueError(state, "...These will not be read in.  Other errors may occur.");
    2301           0 :         state.dataZoneTempPredictorCorrector->NumStageCtrZone = 0;
    2302             :     }
    2303             : 
    2304         771 :     if (state.dataZoneTempPredictorCorrector->NumStageCtrZone > 0) {
    2305           2 :         StageControlledZone.allocate(state.dataZoneTempPredictorCorrector->NumStageCtrZone);
    2306           2 :         state.dataZoneCtrls->StageZoneLogic.dimension(NumOfZones, false);
    2307             : 
    2308           2 :         StageControlledZoneNum = 0;
    2309           7 :         for (Item = 1; Item <= NumStageControlledZones; ++Item) {
    2310           5 :             inputProcessor->getObjectItem(state,
    2311             :                                           cCurrentModuleObject,
    2312             :                                           Item,
    2313             :                                           cAlphaArgs,
    2314             :                                           NumAlphas,
    2315             :                                           rNumericArgs,
    2316             :                                           NumNums,
    2317             :                                           IOStat,
    2318             :                                           lNumericFieldBlanks,
    2319             :                                           lAlphaFieldBlanks,
    2320             :                                           cAlphaFieldNames,
    2321             :                                           cNumericFieldNames);
    2322          12 :             for (Item1 = 1; Item1 <= state.dataZoneCtrls->StagedTStatObjects(Item).NumOfZones; ++Item1) {
    2323           7 :                 ++StageControlledZoneNum;
    2324           7 :                 if (state.dataZoneCtrls->StagedTStatObjects(Item).ZoneListActive) {
    2325           3 :                     cAlphaArgs(2) =
    2326           3 :                         state.dataHeatBal->Zone(ZoneList(state.dataZoneCtrls->StagedTStatObjects(Item).ZoneOrZoneListPtr).Zone(Item1)).Name;
    2327             :                 }
    2328          14 :                 int ZoneAssigned = UtilityRoutines::FindItemInList(
    2329          14 :                     cAlphaArgs(2), StageControlledZone, &DataZoneControls::ZoneStagedControls::ZoneName, StageControlledZoneNum - 1);
    2330           7 :                 if (ZoneAssigned == 0) {
    2331           7 :                     StageControlledZone(StageControlledZoneNum).ZoneName = cAlphaArgs(2);
    2332           7 :                     StageControlledZone(StageControlledZoneNum).ActualZoneNum = UtilityRoutines::FindItemInList(cAlphaArgs(2), Zone);
    2333           7 :                     if (StageControlledZone(StageControlledZoneNum).ActualZoneNum == 0) {
    2334           0 :                         ShowSevereError(state,
    2335           0 :                                         cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) +
    2336             :                                             "\" not found.");
    2337           0 :                         ErrorsFound = true;
    2338             :                     } else {
    2339             :                         //           Zone(StageControlledZone(StageControlledZoneNum)%ActualZoneNum)%StageControlledZoneIndex =
    2340             :                         //           StageControlledZoneNum
    2341             :                     }
    2342           7 :                     state.dataZoneCtrls->StageZoneLogic(StageControlledZone(StageControlledZoneNum).ActualZoneNum) = true;
    2343             :                 } else {
    2344           0 :                     StageControlledZone(StageControlledZoneNum).ZoneName = cAlphaArgs(2); // for continuity
    2345           0 :                     ShowSevereError(state,
    2346           0 :                                     cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) +
    2347             :                                         "\" zone previously assigned.");
    2348           0 :                     ShowContinueError(state, "...Zone was previously assigned to Thermostat=\"" + StageControlledZone(ZoneAssigned).Name + "\".");
    2349           0 :                     ErrorsFound = true;
    2350           0 :                     continue;
    2351             :                 }
    2352             : 
    2353           7 :                 if (!state.dataZoneCtrls->StagedTStatObjects(Item).ZoneListActive) {
    2354           4 :                     StageControlledZone(StageControlledZoneNum).Name = cAlphaArgs(1);
    2355             :                 } else {
    2356          12 :                     CheckCreatedZoneItemName(
    2357             :                         state,
    2358             :                         RoutineName,
    2359             :                         cCurrentModuleObject,
    2360           3 :                         state.dataHeatBal->Zone(ZoneList(state.dataZoneCtrls->StagedTStatObjects(Item).ZoneOrZoneListPtr).Zone(Item1)).Name,
    2361           3 :                         ZoneList(state.dataZoneCtrls->StagedTStatObjects(Item).ZoneOrZoneListPtr).MaxZoneNameLength,
    2362           3 :                         state.dataZoneCtrls->StagedTStatObjects(Item).Name,
    2363             :                         StageControlledZone,
    2364             :                         StageControlledZoneNum - 1,
    2365           3 :                         StageControlledZone(StageControlledZoneNum).Name,
    2366             :                         errFlag);
    2367           3 :                     if (errFlag) ErrorsFound = true;
    2368             :                 }
    2369             : 
    2370           7 :                 StageControlledZone(StageControlledZoneNum).NumOfHeatStages = rNumericArgs(1);
    2371           7 :                 if (rNumericArgs(1) < 1 || rNumericArgs(1) > 4) {
    2372           0 :                     ShowSevereError(
    2373             :                         state,
    2374           0 :                         format("{}=\"{}\" invalid range {}=\"{:.0R}\"", cCurrentModuleObject, cAlphaArgs(1), cNumericFieldNames(1), rNumericArgs(1)));
    2375           0 :                     ShowContinueError(state, "..contains values outside of range [1,4].");
    2376           0 :                     ErrorsFound = true;
    2377             :                 }
    2378             : 
    2379           7 :                 StageControlledZone(StageControlledZoneNum).HeatSetBaseSchedName = cAlphaArgs(3);
    2380           7 :                 StageControlledZone(StageControlledZoneNum).HSBchedIndex = GetScheduleIndex(state, cAlphaArgs(3));
    2381           7 :                 if (Item1 == 1) { // only show error on first of several if zone list
    2382           5 :                     if (StageControlledZone(StageControlledZoneNum).HSBchedIndex == 0) {
    2383           0 :                         ShowSevereError(state,
    2384           0 :                                         cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(3) + "=\"" + cAlphaArgs(3) +
    2385             :                                             "\" not found.");
    2386           0 :                         ErrorsFound = true;
    2387             :                     }
    2388             :                 }
    2389             : 
    2390           7 :                 StageControlledZone(StageControlledZoneNum).HeatThroRange = rNumericArgs(2);
    2391           7 :                 if (rNumericArgs(1) < 0.0) {
    2392           0 :                     ShowSevereError(state,
    2393           0 :                                     format("{}=\"{}\" negative value is found at {}=\"{:.1R}\"",
    2394             :                                            cAlphaArgs(1),
    2395             :                                            cCurrentModuleObject,
    2396             :                                            cNumericFieldNames(2),
    2397           0 :                                            rNumericArgs(2)));
    2398           0 :                     ShowContinueError(state, ".. The minimum value is 0.");
    2399           0 :                     ErrorsFound = true;
    2400             :                 }
    2401             : 
    2402           7 :                 if (StageControlledZone(StageControlledZoneNum).NumOfHeatStages > 0) {
    2403           7 :                     StageControlledZone(StageControlledZoneNum).HeatTOffset.allocate(StageControlledZone(StageControlledZoneNum).NumOfHeatStages);
    2404          18 :                     for (i = 1; i <= StageControlledZone(StageControlledZoneNum).NumOfHeatStages; ++i) {
    2405          11 :                         StageControlledZone(StageControlledZoneNum).HeatTOffset(i) = rNumericArgs(2 + i);
    2406          11 :                         if (rNumericArgs(2 + i) > 0.0) {
    2407           0 :                             ShowSevereError(state,
    2408           0 :                                             cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" positive value is found at " +
    2409           0 :                                                 format("{}=\"{:.1R}\"", cNumericFieldNames(2 + i), rNumericArgs(2 + i)));
    2410           0 :                             ShowContinueError(state, ".. The maximum value is 0.");
    2411           0 :                             ErrorsFound = true;
    2412             :                         }
    2413          11 :                         if (lNumericFieldBlanks(2 + i)) {
    2414           0 :                             ShowSevereError(state,
    2415           0 :                                             cCurrentModuleObject + " object =" + cAlphaArgs(1) + ". The input of " + cNumericFieldNames(2 + i) +
    2416             :                                                 " is required, but a blank is found.");
    2417           0 :                             ErrorsFound = true;
    2418             :                         }
    2419          11 :                         if (i > 1) {
    2420           4 :                             if (rNumericArgs(2 + i) >= rNumericArgs(1 + i)) {
    2421           0 :                                 ShowSevereError(state,
    2422           0 :                                                 format(R"({}="{}" The value at {}="{:.1R}" has to be less than )",
    2423             :                                                        cCurrentModuleObject,
    2424             :                                                        cAlphaArgs(1),
    2425             :                                                        cNumericFieldNames(2 + i),
    2426           0 :                                                        rNumericArgs(2 + i)));
    2427           0 :                                 ShowContinueError(state, format("{}=\"{:.1R}", cNumericFieldNames(1 + i), rNumericArgs(1 + i)));
    2428           0 :                                 ErrorsFound = true;
    2429             :                             }
    2430             :                         }
    2431             :                     }
    2432             :                 }
    2433             : 
    2434           7 :                 StageControlledZone(StageControlledZoneNum).NumOfCoolStages = rNumericArgs(7);
    2435           7 :                 if (rNumericArgs(7) < 1 || rNumericArgs(7) > 4) {
    2436           0 :                     ShowSevereError(
    2437             :                         state,
    2438           0 :                         format("{}=\"{}\" invalid range {}=\"{:.0R}\"", cCurrentModuleObject, cAlphaArgs(1), cNumericFieldNames(7), rNumericArgs(7)));
    2439           0 :                     ShowContinueError(state, "..contains values outside of range [1,4].");
    2440           0 :                     ErrorsFound = true;
    2441             :                 }
    2442             : 
    2443           7 :                 StageControlledZone(StageControlledZoneNum).CoolSetBaseSchedName = cAlphaArgs(4);
    2444           7 :                 StageControlledZone(StageControlledZoneNum).CSBchedIndex = GetScheduleIndex(state, cAlphaArgs(4));
    2445           7 :                 if (Item1 == 1) { // only show error on first of several if zone list
    2446           5 :                     if (StageControlledZone(StageControlledZoneNum).CSBchedIndex == 0) {
    2447           0 :                         ShowSevereError(state,
    2448           0 :                                         cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(4) + "=\"" + cAlphaArgs(4) +
    2449             :                                             "\" not found.");
    2450           0 :                         ErrorsFound = true;
    2451             :                     }
    2452             :                 }
    2453             : 
    2454           7 :                 StageControlledZone(StageControlledZoneNum).CoolThroRange = rNumericArgs(8);
    2455           7 :                 if (rNumericArgs(8) < 0.0) {
    2456           0 :                     ShowSevereError(state,
    2457           0 :                                     format("{}=\"{}\" negative value is found at {}=\"{:.1R}\"",
    2458             :                                            cCurrentModuleObject,
    2459             :                                            cAlphaArgs(1),
    2460             :                                            cNumericFieldNames(8),
    2461           0 :                                            rNumericArgs(8)));
    2462           0 :                     ShowContinueError(state, ".. The minumum value is 0.");
    2463           0 :                     ErrorsFound = true;
    2464             :                 }
    2465             : 
    2466           7 :                 if (StageControlledZone(StageControlledZoneNum).NumOfCoolStages > 0) {
    2467           7 :                     StageControlledZone(StageControlledZoneNum).CoolTOffset.allocate(StageControlledZone(StageControlledZoneNum).NumOfCoolStages);
    2468          26 :                     for (i = 1; i <= StageControlledZone(StageControlledZoneNum).NumOfCoolStages; ++i) {
    2469          19 :                         StageControlledZone(StageControlledZoneNum).CoolTOffset(i) = rNumericArgs(8 + i);
    2470          19 :                         if (rNumericArgs(8 + i) < 0.0) {
    2471           0 :                             ShowSevereError(state,
    2472           0 :                                             format("{}=\"{}\" negative value is found at {}=\"{:.1R}\"",
    2473             :                                                    cCurrentModuleObject,
    2474             :                                                    cAlphaArgs(1),
    2475             :                                                    cNumericFieldNames(8 + i),
    2476           0 :                                                    rNumericArgs(8 + i)));
    2477           0 :                             ShowContinueError(state, ".. The minimum value is 0.");
    2478           0 :                             ErrorsFound = true;
    2479             :                         }
    2480          19 :                         if (lNumericFieldBlanks(8 + i)) {
    2481           0 :                             ShowSevereError(state,
    2482           0 :                                             cCurrentModuleObject + " object =" + cAlphaArgs(1) + ". The input of " + cNumericFieldNames(8 + i) +
    2483             :                                                 " is required, but a blank is found.");
    2484           0 :                             ErrorsFound = true;
    2485             :                         }
    2486          19 :                         if (i > 1) {
    2487          12 :                             if (rNumericArgs(8 + i) <= rNumericArgs(7 + i)) {
    2488           0 :                                 ShowSevereError(state,
    2489           0 :                                                 format("{}=\"{}\" The value at {}=\"{:.1R}\" has to be greater than ",
    2490             :                                                        cCurrentModuleObject,
    2491             :                                                        cAlphaArgs(1),
    2492             :                                                        cNumericFieldNames(8 + i),
    2493           0 :                                                        rNumericArgs(8 + i)));
    2494           0 :                                 ShowContinueError(state, format("{}=\"{:.1R}", cNumericFieldNames(7 + i), rNumericArgs(7 + i)));
    2495           0 :                                 ErrorsFound = true;
    2496             :                             }
    2497             :                         }
    2498             :                     }
    2499             :                 }
    2500             :             }
    2501             :         } // loop over NumStageControlledZones
    2502           5 :         if ((inputProcessor->getNumObjectsFound(state, "AirLoopHVAC:UnitaryHeatPump:AirToAir:MultiSpeed") == 0) &&
    2503           4 :             (inputProcessor->getNumObjectsFound(state, "AirLoopHVAC:UnitarySystem") == 0) &&
    2504           5 :             (inputProcessor->getNumObjectsFound(state, "SetpointManager:SingleZone:OneStageCooling") == 0) &&
    2505           2 :             (inputProcessor->getNumObjectsFound(state, "SetpointManager:SingleZone:OneStageHeating") == 0)) {
    2506           0 :             ShowWarningError(state, cCurrentModuleObject + " is applicable to only selected HVAC objects which are missing from input.");
    2507           0 :             ShowContinueError(state, "Model should include one or more of the following objects:  ");
    2508           0 :             ShowContinueError(state, "AirLoopHVAC:UnitaryHeatPump:AirToAir:MultiSpeed, AirLoopHVAC:UnitarySystem, ");
    2509           0 :             ShowContinueError(
    2510             :                 state, "SetpointManager:SingleZone:OneStageCooling, and/or SetpointManager:SingleZone:OneStageHeating. The simulation continues...");
    2511             :         }
    2512             :     } // NumStageControlledZones > 0
    2513             : 
    2514         771 :     if (ErrorsFound) {
    2515           0 :         ShowFatalError(state, "Errors getting Zone Control input data.  Preceding condition(s) cause termination.");
    2516             :     }
    2517         771 : }
    2518             : 
    2519           1 : void CalculateMonthlyRunningAverageDryBulb(EnergyPlusData &state, Array1D<Real64> &runningAverageASH, Array1D<Real64> &runningAverageCEN)
    2520             : {
    2521             :     // SUBROUTINE INFORMATION:
    2522             :     //       AUTHOR         Xuan Luo
    2523             :     //       DATE WRITTEN   January 2017
    2524             :     //       RE-ENGINEERED  na
    2525             : 
    2526             :     // PURPOSE OF THIS SUBROUTINE:
    2527             :     // This subroutine calculate the monthly running average dry bulb temperature;
    2528             : 
    2529             :     // Using/Aliasing
    2530             : 
    2531             :     using OutputReportTabular::GetColumnUsingTabs;
    2532             :     using OutputReportTabular::StrToReal;
    2533             : 
    2534             :     // SUBROUTINE PARAMETER DEFINITIONS:
    2535             : 
    2536             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2537             : 
    2538           2 :     std::string lineIn;
    2539           2 :     std::string lineAvg;
    2540           2 :     std::string epwLine;
    2541             : 
    2542             :     Real64 dryBulb;
    2543             :     Real64 avgDryBulb;
    2544             : 
    2545             :     int readStat;
    2546             :     int calcEndDay;
    2547             :     int calcStartDayASH;
    2548             :     int calcStartDayCEN;
    2549             : 
    2550             :     std::string::size_type pos;
    2551             :     int ind, i, j;
    2552             : 
    2553           2 :     Array1D<Real64> adaptiveTemp(state.dataWeatherManager->NumDaysInYear, 0.0);
    2554           2 :     Array1D<Real64> dailyDryTemp(state.dataWeatherManager->NumDaysInYear, 0.0);
    2555             : 
    2556           1 :     readStat = 0;
    2557           1 :     if (FileSystem::fileExists(state.files.inputWeatherFilePath.filePath)) {
    2558             :         // Read hourly dry bulb temperature first
    2559           2 :         auto epwFile = state.files.inputWeatherFilePath.open(state, "CalcThermalComfortAdaptive");
    2560          10 :         for (i = 1; i <= 9; ++i) { // Headers
    2561           9 :             epwFile.readLine();
    2562             :         }
    2563         366 :         for (i = 1; i <= state.dataWeatherManager->NumDaysInYear; ++i) {
    2564         365 :             avgDryBulb = 0.0;
    2565        9125 :             for (j = 1; j <= 24; ++j) {
    2566        8760 :                 epwLine = epwFile.readLine().data;
    2567       61320 :                 for (ind = 1; ind <= 6; ++ind) {
    2568       52560 :                     pos = index(epwLine, ',');
    2569       52560 :                     epwLine.erase(0, pos + 1);
    2570             :                 }
    2571        8760 :                 pos = index(epwLine, ',');
    2572        8760 :                 dryBulb = StrToReal(epwLine.substr(0, pos));
    2573        8760 :                 avgDryBulb += (dryBulb / 24.0);
    2574             :             }
    2575         365 :             dailyDryTemp(i) = avgDryBulb;
    2576             :         }
    2577           1 :         epwFile.close();
    2578             : 
    2579             :         // Calculate monthly running average dry bulb temperature.
    2580           1 :         int dayOfYear = 0;
    2581         731 :         while (dayOfYear < state.dataWeatherManager->NumDaysInYear) {
    2582         365 :             dayOfYear++;
    2583         365 :             calcEndDay = dayOfYear - 1;
    2584         365 :             calcStartDayASH = calcEndDay - 30;
    2585         365 :             calcStartDayCEN = calcEndDay - 7;
    2586             : 
    2587         365 :             if (calcStartDayASH > 0) {
    2588       10688 :                 for (i = calcStartDayASH; i <= calcStartDayASH + 30; i++) {
    2589       10354 :                     avgDryBulb = dailyDryTemp(i);
    2590       10354 :                     runningAverageASH(dayOfYear) = runningAverageASH(dayOfYear) + avgDryBulb;
    2591             :                 }
    2592         334 :                 runningAverageASH(dayOfYear) /= 30;
    2593             :             } else { // Do special things for wrapping the epw
    2594          31 :                 calcStartDayASH += state.dataWeatherManager->NumDaysInYear;
    2595         496 :                 for (i = 1; i <= calcEndDay; i++) {
    2596         465 :                     avgDryBulb = dailyDryTemp(i);
    2597         465 :                     runningAverageASH(dayOfYear) = runningAverageASH(dayOfYear) + avgDryBulb;
    2598             :                 }
    2599         496 :                 for (i = calcStartDayASH; i < state.dataWeatherManager->NumDaysInYear; i++) {
    2600         465 :                     avgDryBulb = dailyDryTemp(i);
    2601         465 :                     runningAverageASH(dayOfYear) = runningAverageASH(dayOfYear) + avgDryBulb;
    2602             :                 }
    2603          31 :                 runningAverageASH(dayOfYear) /= 30;
    2604             :             }
    2605             : 
    2606         365 :             if (calcStartDayCEN > 0) {
    2607        3213 :                 for (i = calcStartDayCEN; i <= calcStartDayCEN + 7; i++) {
    2608        2856 :                     avgDryBulb = dailyDryTemp(i);
    2609        2856 :                     runningAverageCEN(dayOfYear) = runningAverageCEN(dayOfYear) + avgDryBulb;
    2610             :                 }
    2611         357 :                 runningAverageCEN(dayOfYear) /= 7;
    2612             :             } else { // Do special things for wrapping the epw
    2613           8 :                 calcStartDayCEN += state.dataWeatherManager->NumDaysInYear;
    2614          36 :                 for (i = 1; i <= calcEndDay; i++) {
    2615          28 :                     avgDryBulb = dailyDryTemp(i);
    2616          28 :                     runningAverageCEN(dayOfYear) = runningAverageCEN(dayOfYear) + avgDryBulb;
    2617             :                 }
    2618          36 :                 for (i = calcStartDayCEN; i < state.dataWeatherManager->NumDaysInYear; i++) {
    2619          28 :                     avgDryBulb = dailyDryTemp(i);
    2620          28 :                     runningAverageCEN(dayOfYear) = runningAverageCEN(dayOfYear) + avgDryBulb;
    2621             :                 }
    2622           8 :                 runningAverageCEN(dayOfYear) /= 7;
    2623             :             }
    2624             :         }
    2625             :     } else {
    2626           0 :         ShowFatalError(state,
    2627           0 :                        "CalcThermalComfortAdaptive: Could not open file " + state.files.inputWeatherFilePath.filePath.string() +
    2628             :                            " for input (read). (File does not exist)");
    2629             :     }
    2630           1 : }
    2631             : 
    2632           1 : void CalculateAdaptiveComfortSetPointSchl(EnergyPlusData &state, Array1D<Real64> const &runningAverageASH, Array1D<Real64> const &runningAverageCEN)
    2633             : {
    2634             :     // SUBROUTINE INFORMATION:
    2635             :     //       AUTHOR         Xuan Luo
    2636             :     //       DATE WRITTEN   January 2017
    2637             :     //       RE-ENGINEERED  na
    2638             : 
    2639             :     // PURPOSE OF THIS SUBROUTINE:
    2640             :     // This subroutine calculates the zone operative temperature setpoint using adaptive comfort model.
    2641             : 
    2642             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2643           1 :     int constexpr summerDesignDayTypeIndex(9);
    2644           1 :     Real64 GrossApproxAvgDryBulbDesignDay(0.0);
    2645             : 
    2646           1 :     auto &AdapComfortDailySetPointSchedule = state.dataZoneTempPredictorCorrector->AdapComfortDailySetPointSchedule;
    2647           1 :     auto &AdapComfortSetPointSummerDesDay = state.dataZoneTempPredictorCorrector->AdapComfortSetPointSummerDesDay;
    2648             : 
    2649           3 :     for (size_t i = 1; i <= state.dataWeatherManager->DesDayInput.size(); i++) {
    2650             :         // Summer design day
    2651           2 :         if (state.dataWeatherManager->DesDayInput(i).DayType == summerDesignDayTypeIndex) {
    2652           1 :             GrossApproxAvgDryBulbDesignDay =
    2653           2 :                 (state.dataWeatherManager->DesDayInput(i).MaxDryBulb +
    2654           1 :                  (state.dataWeatherManager->DesDayInput(i).MaxDryBulb - state.dataWeatherManager->DesDayInput(i).DailyDBRange)) /
    2655             :                 2.0;
    2656           1 :             if (GrossApproxAvgDryBulbDesignDay > 10 && GrossApproxAvgDryBulbDesignDay < 33.5) {
    2657           1 :                 AdapComfortSetPointSummerDesDay[0] = 0.31 * GrossApproxAvgDryBulbDesignDay + 17.8;
    2658           1 :                 AdapComfortSetPointSummerDesDay[1] = 0.31 * GrossApproxAvgDryBulbDesignDay + 20.3;
    2659           1 :                 AdapComfortSetPointSummerDesDay[2] = 0.31 * GrossApproxAvgDryBulbDesignDay + 21.3;
    2660             :             }
    2661           1 :             if (GrossApproxAvgDryBulbDesignDay > 10 && GrossApproxAvgDryBulbDesignDay < 30) {
    2662           1 :                 AdapComfortSetPointSummerDesDay[3] = 0.33 * GrossApproxAvgDryBulbDesignDay + 18.8;
    2663           1 :                 AdapComfortSetPointSummerDesDay[4] = 0.33 * GrossApproxAvgDryBulbDesignDay + 20.8;
    2664             :                 ;
    2665           1 :                 AdapComfortSetPointSummerDesDay[5] = 0.33 * GrossApproxAvgDryBulbDesignDay + 21.8;
    2666             :                 ;
    2667           1 :                 AdapComfortSetPointSummerDesDay[6] = 0.33 * GrossApproxAvgDryBulbDesignDay + 22.8;
    2668             :                 ;
    2669             :             }
    2670             :         }
    2671             :     }
    2672             : 
    2673           1 :     AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveASH55_Central.allocate(state.dataWeatherManager->NumDaysInYear);
    2674           1 :     AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveASH55_Upper_90.allocate(state.dataWeatherManager->NumDaysInYear);
    2675           1 :     AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveASH55_Upper_80.allocate(state.dataWeatherManager->NumDaysInYear);
    2676           1 :     AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveCEN15251_Central.allocate(state.dataWeatherManager->NumDaysInYear);
    2677           1 :     AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveCEN15251_Upper_I.allocate(state.dataWeatherManager->NumDaysInYear);
    2678           1 :     AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveCEN15251_Upper_II.allocate(state.dataWeatherManager->NumDaysInYear);
    2679           1 :     AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveCEN15251_Upper_III.allocate(state.dataWeatherManager->NumDaysInYear);
    2680             : 
    2681             :     // Calculate the set points based on different models, set flag as -1 when running average temperature is not in the range.
    2682         366 :     for (int day = 1; day <= state.dataWeatherManager->NumDaysInYear; day++) {
    2683         365 :         if (runningAverageASH(day) > 10 && runningAverageASH(day) < 33.5) {
    2684         365 :             AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveASH55_Central(day) = 0.31 * runningAverageASH(day) + 17.8;
    2685         365 :             AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveASH55_Upper_90(day) = 0.31 * runningAverageASH(day) + 20.3;
    2686         365 :             AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveASH55_Upper_80(day) = 0.31 * runningAverageASH(day) + 21.3;
    2687             :         } else {
    2688           0 :             AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveASH55_Central(day) = -1;
    2689           0 :             AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveASH55_Upper_90(day) = -1;
    2690           0 :             AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveASH55_Upper_80(day) = -1;
    2691             :         }
    2692         365 :         if (runningAverageCEN(day) > 10 && runningAverageCEN(day) < 30) {
    2693         216 :             AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveCEN15251_Central(day) = 0.33 * runningAverageCEN(day) + 18.8;
    2694         216 :             AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveCEN15251_Upper_I(day) = 0.33 * runningAverageCEN(day) + 20.8;
    2695         216 :             AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveCEN15251_Upper_II(day) = 0.33 * runningAverageCEN(day) + 21.8;
    2696         216 :             AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveCEN15251_Upper_III(day) = 0.33 * runningAverageCEN(day) + 22.8;
    2697             :         } else {
    2698         149 :             AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveCEN15251_Central(day) = -1;
    2699         149 :             AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveCEN15251_Upper_I(day) = -1;
    2700         149 :             AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveCEN15251_Upper_II(day) = -1;
    2701         149 :             AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveCEN15251_Upper_III(day) = -1;
    2702             :         }
    2703             :     }
    2704           1 :     AdapComfortDailySetPointSchedule.initialized = true;
    2705           1 : }
    2706             : 
    2707    13440069 : void InitZoneAirSetPoints(EnergyPlusData &state)
    2708             : {
    2709             : 
    2710             :     // SUBROUTINE INFORMATION:
    2711             :     //       AUTHOR         Russell Taylor
    2712             :     //       DATE WRITTEN   September 1998
    2713             :     //       MODIFIED       November 2004, M. J. Witte additional report variables
    2714             :     //       MODIFIED       L.Gu, May 2006
    2715             :     //       RE-ENGINEERED  na
    2716             : 
    2717             :     // PURPOSE OF THIS SUBROUTINE:
    2718             :     // This subroutine initializes the data for the zone air setpoints.
    2719             : 
    2720             :     // METHODOLOGY EMPLOYED:
    2721             :     // Uses the status flags to trigger events.
    2722             : 
    2723             :     // SUBROUTINE PARAMETER DEFINITIONS:
    2724             :     static constexpr std::string_view RoutineName("InitZoneAirSetpoints: ");
    2725             : 
    2726             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2727             :     bool FirstSurfFlag;
    2728             :     int TRefFlag; // Flag for Reference Temperature process in Zones
    2729             : 
    2730    13440069 :     auto &ZoneList = state.dataHeatBal->ZoneList;
    2731    13440069 :     auto &TempControlledZone = state.dataZoneCtrls->TempControlledZone;
    2732    13440069 :     auto &TempZoneThermostatSetPoint = state.dataHeatBalFanSys->TempZoneThermostatSetPoint;
    2733    13440069 :     auto &TempControlType = state.dataHeatBalFanSys->TempControlType;
    2734    13440069 :     auto &TempControlTypeRpt = state.dataHeatBalFanSys->TempControlTypeRpt;
    2735    13440069 :     auto &ComfortControlledZone = state.dataZoneCtrls->ComfortControlledZone;
    2736    13440069 :     auto &ZoneThermostatSetPointLo = state.dataHeatBalFanSys->ZoneThermostatSetPointLo;
    2737    13440069 :     auto &ZoneThermostatSetPointHi = state.dataHeatBalFanSys->ZoneThermostatSetPointHi;
    2738    13440069 :     auto &NumOfZones = state.dataGlobal->NumOfZones;
    2739             : 
    2740    13440069 :     if (state.dataZoneTempPredictorCorrector->InitZoneAirSetPointsOneTimeFlag) {
    2741         771 :         TempZoneThermostatSetPoint.dimension(NumOfZones, 0.0);
    2742         771 :         state.dataHeatBalFanSys->AdapComfortCoolingSetPoint.dimension(NumOfZones, 0.0);
    2743         771 :         ZoneThermostatSetPointHi.dimension(NumOfZones, 0.0);
    2744         771 :         ZoneThermostatSetPointLo.dimension(NumOfZones, 0.0);
    2745         771 :         state.dataHeatBalFanSys->ZoneThermostatSetPointHiAver.dimension(NumOfZones, 0.0);
    2746         771 :         state.dataHeatBalFanSys->ZoneThermostatSetPointLoAver.dimension(NumOfZones, 0.0);
    2747             : 
    2748         771 :         state.dataHeatBalFanSys->LoadCorrectionFactor.dimension(NumOfZones, 0.0);
    2749         771 :         TempControlType.dimension(NumOfZones, DataHVACGlobals::ThermostatType::Uncontrolled);
    2750         771 :         TempControlTypeRpt.dimension(NumOfZones, 0);
    2751         771 :         if (state.dataZoneCtrls->NumComfortControlledZones > 0) {
    2752           1 :             state.dataHeatBalFanSys->ComfortControlType.dimension(NumOfZones, DataHVACGlobals::ThermostatType::Uncontrolled);
    2753           1 :             state.dataHeatBalFanSys->ComfortControlTypeRpt.dimension(NumOfZones, 0);
    2754           1 :             state.dataHeatBalFanSys->ZoneComfortControlsFanger.allocate(NumOfZones);
    2755             :         }
    2756         771 :         state.dataZoneEnergyDemand->Setback.dimension(NumOfZones, false);
    2757         771 :         state.dataZoneEnergyDemand->DeadBandOrSetback.dimension(NumOfZones, false);
    2758         771 :         state.dataZoneEnergyDemand->CurDeadBandOrSetback.dimension(NumOfZones, false);
    2759             : 
    2760         771 :         state.dataHeatBal->ZoneListSNLoadHeatEnergy.dimension(state.dataHeatBal->NumOfZoneLists, 0.0);
    2761         771 :         state.dataHeatBal->ZoneListSNLoadCoolEnergy.dimension(state.dataHeatBal->NumOfZoneLists, 0.0);
    2762         771 :         state.dataHeatBal->ZoneListSNLoadHeatRate.dimension(state.dataHeatBal->NumOfZoneLists, 0.0);
    2763         771 :         state.dataHeatBal->ZoneListSNLoadCoolRate.dimension(state.dataHeatBal->NumOfZoneLists, 0.0);
    2764             : 
    2765         771 :         state.dataHeatBal->ZoneGroupSNLoadHeatEnergy.dimension(state.dataHeatBal->NumOfZoneGroups, 0.0);
    2766         771 :         state.dataHeatBal->ZoneGroupSNLoadCoolEnergy.dimension(state.dataHeatBal->NumOfZoneGroups, 0.0);
    2767         771 :         state.dataHeatBal->ZoneGroupSNLoadHeatRate.dimension(state.dataHeatBal->NumOfZoneGroups, 0.0);
    2768         771 :         state.dataHeatBal->ZoneGroupSNLoadCoolRate.dimension(state.dataHeatBal->NumOfZoneGroups, 0.0);
    2769             : 
    2770             :         // Hybrid modeling
    2771         771 :         state.dataHeatBalFanSys->PreviousMeasuredZT1.dimension(NumOfZones, 0.0);
    2772         771 :         state.dataHeatBalFanSys->PreviousMeasuredZT2.dimension(NumOfZones, 0.0);
    2773         771 :         state.dataHeatBalFanSys->PreviousMeasuredZT3.dimension(NumOfZones, 0.0);
    2774         771 :         state.dataHeatBalFanSys->PreviousMeasuredHumRat1.dimension(NumOfZones, 0.0);
    2775         771 :         state.dataHeatBalFanSys->PreviousMeasuredHumRat2.dimension(NumOfZones, 0.0);
    2776         771 :         state.dataHeatBalFanSys->PreviousMeasuredHumRat3.dimension(NumOfZones, 0.0);
    2777             : 
    2778             :         // Allocate Derived Types
    2779         771 :         state.dataZoneEnergyDemand->ZoneSysEnergyDemand.allocate(NumOfZones);
    2780         771 :         state.dataZoneEnergyDemand->ZoneSysMoistureDemand.allocate(NumOfZones);
    2781         771 :         if (state.dataHeatBal->doSpaceHeatBalanceSimulation || state.dataHeatBal->doSpaceHeatBalanceSizing) {
    2782           1 :             state.dataZoneEnergyDemand->spaceSysEnergyDemand.allocate(state.dataGlobal->numSpaces);
    2783           1 :             state.dataZoneEnergyDemand->spaceSysMoistureDemand.allocate(state.dataGlobal->numSpaces);
    2784             :         }
    2785             : 
    2786        5585 :         for (int zoneNum = 1; zoneNum <= NumOfZones; ++zoneNum) {
    2787        4814 :             FirstSurfFlag = true;
    2788        9632 :             for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
    2789        4818 :                 auto &thisSpace = state.dataHeatBal->space(spaceNum);
    2790       47024 :                 for (int SurfNum = thisSpace.HTSurfaceFirst; SurfNum <= thisSpace.HTSurfaceLast; ++SurfNum) {
    2791       42206 :                     if (FirstSurfFlag) {
    2792        4814 :                         TRefFlag = state.dataSurface->SurfTAirRef(SurfNum);
    2793        4814 :                         FirstSurfFlag = false;
    2794             :                     }
    2795             :                     // for each particular zone, the reference air temperature(s) should be the same
    2796             :                     // (either mean air, bulk air, or supply air temp).
    2797       42206 :                     if (state.dataSurface->SurfTAirRef(SurfNum) != TRefFlag) {
    2798           0 :                         ShowWarningError(state,
    2799           0 :                                          "Different reference air temperatures for difference surfaces encountered in zone " +
    2800           0 :                                              state.dataHeatBal->Zone(zoneNum).Name);
    2801             :                     }
    2802             :                 }
    2803             :             }
    2804             :         }
    2805             : 
    2806             :         // CurrentModuleObject='Zone'
    2807        5585 :         for (int zoneNum = 1; zoneNum <= NumOfZones; ++zoneNum) {
    2808        4814 :             auto &thisZone = state.dataHeatBal->Zone(zoneNum);
    2809        4814 :             state.dataZoneTempPredictorCorrector->zoneHeatBalance(zoneNum).setUpOutputVars(state, DataStringGlobals::zonePrefix, thisZone.Name);
    2810        4814 :             if (state.dataHeatBal->doSpaceHeatBalanceSizing || state.dataHeatBal->doSpaceHeatBalanceSimulation) {
    2811          12 :                 for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
    2812          12 :                     state.dataZoneTempPredictorCorrector->spaceHeatBalance(spaceNum).setUpOutputVars(
    2813           6 :                         state, DataStringGlobals::spacePrefix, state.dataHeatBal->space(spaceNum).Name);
    2814             :                 }
    2815             :             }
    2816        4814 :             bool staged = false;
    2817        4814 :             if (allocated(state.dataZoneCtrls->StageZoneLogic)) {
    2818           8 :                 staged = state.dataZoneCtrls->StageZoneLogic(zoneNum);
    2819             :             }
    2820             :             // If not doSpaceHeatBalanceSimulation then meter zones, not spaces
    2821        4814 :             bool attachMeters = !state.dataHeatBal->doSpaceHeatBalanceSimulation;
    2822        9628 :             state.dataZoneEnergyDemand->ZoneSysEnergyDemand(zoneNum).setUpOutputVars(
    2823        4814 :                 state, DataStringGlobals::zonePrefix, thisZone.Name, staged, attachMeters, thisZone.Multiplier, thisZone.ListMultiplier);
    2824        4814 :             if (state.dataHeatBal->doSpaceHeatBalanceSizing || state.dataHeatBal->doSpaceHeatBalanceSimulation) {
    2825             :                 // If doSpaceHeatBalanceSimulation then meter spaces, not zones
    2826           6 :                 attachMeters = state.dataHeatBal->doSpaceHeatBalanceSimulation;
    2827          12 :                 for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
    2828          18 :                     state.dataZoneEnergyDemand->spaceSysEnergyDemand(spaceNum).setUpOutputVars(state,
    2829             :                                                                                                DataStringGlobals::spacePrefix,
    2830           6 :                                                                                                state.dataHeatBal->space(spaceNum).Name,
    2831             :                                                                                                staged,
    2832             :                                                                                                attachMeters,
    2833             :                                                                                                thisZone.Multiplier,
    2834           6 :                                                                                                thisZone.ListMultiplier);
    2835             :                 }
    2836             :             }
    2837        4814 :             state.dataZoneEnergyDemand->ZoneSysMoistureDemand(zoneNum).setUpOutputVars(state, DataStringGlobals::zonePrefix, thisZone.Name);
    2838        4814 :             if (state.dataHeatBal->doSpaceHeatBalanceSizing || state.dataHeatBal->doSpaceHeatBalanceSimulation) {
    2839          12 :                 for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
    2840          12 :                     state.dataZoneEnergyDemand->spaceSysMoistureDemand(spaceNum).setUpOutputVars(
    2841           6 :                         state, DataStringGlobals::spacePrefix, state.dataHeatBal->space(spaceNum).Name);
    2842             :                 }
    2843             :             }
    2844        9628 :             SetupOutputVariable(state,
    2845             :                                 "Zone Thermostat Air Temperature",
    2846             :                                 OutputProcessor::Unit::C,
    2847        4814 :                                 state.dataHeatBalFanSys->TempTstatAir(zoneNum),
    2848             :                                 OutputProcessor::SOVTimeStepType::System,
    2849             :                                 OutputProcessor::SOVStoreType::Average,
    2850        4814 :                                 thisZone.Name);
    2851        9628 :             SetupOutputVariable(state,
    2852             :                                 "Zone Thermostat Control Type",
    2853             :                                 OutputProcessor::Unit::None,
    2854             :                                 TempControlTypeRpt(zoneNum),
    2855             :                                 OutputProcessor::SOVTimeStepType::Zone,
    2856             :                                 OutputProcessor::SOVStoreType::Average,
    2857        4814 :                                 thisZone.Name);
    2858        9628 :             SetupOutputVariable(state,
    2859             :                                 "Zone Thermostat Heating Setpoint Temperature",
    2860             :                                 OutputProcessor::Unit::C,
    2861        4814 :                                 ZoneThermostatSetPointLo(zoneNum),
    2862             :                                 OutputProcessor::SOVTimeStepType::System,
    2863             :                                 OutputProcessor::SOVStoreType::Average,
    2864        4814 :                                 thisZone.Name);
    2865        9628 :             SetupOutputVariable(state,
    2866             :                                 "Zone Thermostat Cooling Setpoint Temperature",
    2867             :                                 OutputProcessor::Unit::C,
    2868        4814 :                                 ZoneThermostatSetPointHi(zoneNum),
    2869             :                                 OutputProcessor::SOVTimeStepType::System,
    2870             :                                 OutputProcessor::SOVStoreType::Average,
    2871        4814 :                                 thisZone.Name);
    2872        9628 :             SetupOutputVariable(state,
    2873             :                                 "Zone Adaptive Comfort Operative Temperature Set Point",
    2874             :                                 OutputProcessor::Unit::C,
    2875        4814 :                                 state.dataHeatBalFanSys->AdapComfortCoolingSetPoint(zoneNum),
    2876             :                                 OutputProcessor::SOVTimeStepType::Zone,
    2877             :                                 OutputProcessor::SOVStoreType::Average,
    2878        4814 :                                 thisZone.Name);
    2879        9628 :             SetupOutputVariable(state,
    2880             :                                 "Zone Predicted Sensible Load Room Air Correction Factor",
    2881             :                                 OutputProcessor::Unit::None,
    2882        4814 :                                 state.dataHeatBalFanSys->LoadCorrectionFactor(zoneNum),
    2883             :                                 OutputProcessor::SOVTimeStepType::System,
    2884             :                                 OutputProcessor::SOVStoreType::Average,
    2885        4814 :                                 thisZone.Name);
    2886             :         } // zoneNum
    2887             : 
    2888             :         // Thermal comfort control output
    2889         771 :         if (state.dataZoneCtrls->NumComfortControlledZones > 0) {
    2890             :             // CurrentModuleObject='ZoneControl:Thermostat:ThermalComfort'
    2891           2 :             for (int Loop = 1; Loop <= state.dataZoneCtrls->NumComfortControlledZones; ++Loop) {
    2892           1 :                 int zoneNum = ComfortControlledZone(Loop).ActualZoneNum;
    2893           1 :                 auto &thisZone = state.dataHeatBal->Zone(zoneNum);
    2894           3 :                 SetupOutputVariable(state,
    2895             :                                     "Zone Thermal Comfort Control Type",
    2896             :                                     OutputProcessor::Unit::None,
    2897           1 :                                     state.dataHeatBalFanSys->ComfortControlTypeRpt(zoneNum),
    2898             :                                     OutputProcessor::SOVTimeStepType::Zone,
    2899             :                                     OutputProcessor::SOVStoreType::Average,
    2900           1 :                                     thisZone.Name);
    2901           3 :                 SetupOutputVariable(state,
    2902             :                                     "Zone Thermal Comfort Control Fanger Low Setpoint PMV",
    2903             :                                     OutputProcessor::Unit::None,
    2904           1 :                                     state.dataHeatBalFanSys->ZoneComfortControlsFanger(zoneNum).LowPMV,
    2905             :                                     OutputProcessor::SOVTimeStepType::Zone,
    2906             :                                     OutputProcessor::SOVStoreType::Average,
    2907           1 :                                     thisZone.Name);
    2908           3 :                 SetupOutputVariable(state,
    2909             :                                     "Zone Thermal Comfort Control Fanger High Setpoint PMV",
    2910             :                                     OutputProcessor::Unit::None,
    2911           1 :                                     state.dataHeatBalFanSys->ZoneComfortControlsFanger(zoneNum).HighPMV,
    2912             :                                     OutputProcessor::SOVTimeStepType::Zone,
    2913             :                                     OutputProcessor::SOVStoreType::Average,
    2914           1 :                                     thisZone.Name);
    2915             :             }
    2916             :         }
    2917             : 
    2918             :         // CurrentModuleObject='ZoneList'
    2919         808 :         for (int Loop = 1; Loop <= state.dataHeatBal->NumOfZoneLists; ++Loop) {
    2920         111 :             SetupOutputVariable(state,
    2921             :                                 "Zone List Sensible Heating Energy",
    2922             :                                 OutputProcessor::Unit::J,
    2923          37 :                                 state.dataHeatBal->ZoneListSNLoadHeatEnergy(Loop),
    2924             :                                 OutputProcessor::SOVTimeStepType::System,
    2925             :                                 OutputProcessor::SOVStoreType::Summed,
    2926          74 :                                 ZoneList(Loop).Name);
    2927         111 :             SetupOutputVariable(state,
    2928             :                                 "Zone List Sensible Cooling Energy",
    2929             :                                 OutputProcessor::Unit::J,
    2930          37 :                                 state.dataHeatBal->ZoneListSNLoadCoolEnergy(Loop),
    2931             :                                 OutputProcessor::SOVTimeStepType::System,
    2932             :                                 OutputProcessor::SOVStoreType::Summed,
    2933          74 :                                 ZoneList(Loop).Name);
    2934         111 :             SetupOutputVariable(state,
    2935             :                                 "Zone List Sensible Heating Rate",
    2936             :                                 OutputProcessor::Unit::W,
    2937          37 :                                 state.dataHeatBal->ZoneListSNLoadHeatRate(Loop),
    2938             :                                 OutputProcessor::SOVTimeStepType::System,
    2939             :                                 OutputProcessor::SOVStoreType::Average,
    2940          74 :                                 ZoneList(Loop).Name);
    2941         111 :             SetupOutputVariable(state,
    2942             :                                 "Zone List Sensible Cooling Rate",
    2943             :                                 OutputProcessor::Unit::W,
    2944          37 :                                 state.dataHeatBal->ZoneListSNLoadCoolRate(Loop),
    2945             :                                 OutputProcessor::SOVTimeStepType::System,
    2946             :                                 OutputProcessor::SOVStoreType::Average,
    2947          74 :                                 ZoneList(Loop).Name);
    2948             :         } // Loop
    2949             : 
    2950             :         // CurrentModuleObject='ZoneGroup'
    2951         775 :         for (int Loop = 1; Loop <= state.dataHeatBal->NumOfZoneGroups; ++Loop) {
    2952          12 :             SetupOutputVariable(state,
    2953             :                                 "Zone Group Sensible Heating Energy",
    2954             :                                 OutputProcessor::Unit::J,
    2955           4 :                                 state.dataHeatBal->ZoneGroupSNLoadHeatEnergy(Loop),
    2956             :                                 OutputProcessor::SOVTimeStepType::System,
    2957             :                                 OutputProcessor::SOVStoreType::Summed,
    2958           8 :                                 state.dataHeatBal->ZoneGroup(Loop).Name);
    2959          12 :             SetupOutputVariable(state,
    2960             :                                 "Zone Group Sensible Cooling Energy",
    2961             :                                 OutputProcessor::Unit::J,
    2962           4 :                                 state.dataHeatBal->ZoneGroupSNLoadCoolEnergy(Loop),
    2963             :                                 OutputProcessor::SOVTimeStepType::System,
    2964             :                                 OutputProcessor::SOVStoreType::Summed,
    2965           8 :                                 state.dataHeatBal->ZoneGroup(Loop).Name);
    2966          12 :             SetupOutputVariable(state,
    2967             :                                 "Zone Group Sensible Heating Rate",
    2968             :                                 OutputProcessor::Unit::W,
    2969           4 :                                 state.dataHeatBal->ZoneGroupSNLoadHeatRate(Loop),
    2970             :                                 OutputProcessor::SOVTimeStepType::System,
    2971             :                                 OutputProcessor::SOVStoreType::Average,
    2972           8 :                                 state.dataHeatBal->ZoneGroup(Loop).Name);
    2973          12 :             SetupOutputVariable(state,
    2974             :                                 "Zone Group Sensible Cooling Rate",
    2975             :                                 OutputProcessor::Unit::W,
    2976           4 :                                 state.dataHeatBal->ZoneGroupSNLoadCoolRate(Loop),
    2977             :                                 OutputProcessor::SOVTimeStepType::System,
    2978             :                                 OutputProcessor::SOVStoreType::Average,
    2979           8 :                                 state.dataHeatBal->ZoneGroup(Loop).Name);
    2980             :         } // Loop
    2981             : 
    2982         771 :         state.dataZoneTempPredictorCorrector->InitZoneAirSetPointsOneTimeFlag = false;
    2983             :     }
    2984             : 
    2985             :     // Do the Begin Environment initializations
    2986    13440069 :     if (state.dataZoneTempPredictorCorrector->MyEnvrnFlag && state.dataGlobal->BeginEnvrnFlag) {
    2987       52491 :         for (auto &thisZoneHB : state.dataZoneTempPredictorCorrector->zoneHeatBalance) {
    2988       46273 :             thisZoneHB.beginEnvironmentInit(state);
    2989             :         }
    2990        6218 :         if (state.dataHeatBal->doSpaceHeatBalance) {
    2991          70 :             for (auto &thisSpaceHB : state.dataZoneTempPredictorCorrector->spaceHeatBalance) {
    2992          60 :                 thisSpaceHB.beginEnvironmentInit(state);
    2993             :             }
    2994             :         }
    2995        6218 :         TempZoneThermostatSetPoint = 0.0;
    2996        6218 :         state.dataHeatBalFanSys->AdapComfortCoolingSetPoint = 0.0;
    2997        6218 :         ZoneThermostatSetPointHi = 0.0;
    2998        6218 :         ZoneThermostatSetPointLo = 0.0;
    2999             : 
    3000        6218 :         state.dataHeatBalFanSys->LoadCorrectionFactor = 1.0;
    3001        6218 :         TempControlType = DataHVACGlobals::ThermostatType::Uncontrolled;
    3002       52491 :         for (auto &e : state.dataZoneEnergyDemand->ZoneSysEnergyDemand) {
    3003       46273 :             e.beginEnvironmentInit();
    3004             :         }
    3005       52491 :         for (auto &e : state.dataZoneEnergyDemand->ZoneSysMoistureDemand) {
    3006       46273 :             e.beginEnvironmentInit();
    3007             :         }
    3008        6218 :         if (state.dataHeatBal->doSpaceHeatBalance) {
    3009          70 :             for (auto &e : state.dataZoneEnergyDemand->spaceSysEnergyDemand) {
    3010          60 :                 e.beginEnvironmentInit();
    3011             :             }
    3012          70 :             for (auto &e : state.dataZoneEnergyDemand->spaceSysMoistureDemand) {
    3013          60 :                 e.beginEnvironmentInit();
    3014             :             }
    3015             :         }
    3016             : 
    3017        6218 :         state.dataZoneEnergyDemand->DeadBandOrSetback = false;
    3018             : 
    3019       52491 :         for (auto &e : state.dataHeatBal->Zone)
    3020       46273 :             e.NoHeatToReturnAir = false;
    3021        6218 :         state.dataHeatBalFanSys->PreviousMeasuredZT1 = 0.0;     // Hybrid modeling
    3022        6218 :         state.dataHeatBalFanSys->PreviousMeasuredZT2 = 0.0;     // Hybrid modeling
    3023        6218 :         state.dataHeatBalFanSys->PreviousMeasuredZT3 = 0.0;     // Hybrid modeling
    3024        6218 :         state.dataHeatBalFanSys->PreviousMeasuredHumRat1 = 0.0; // Hybrid modeling
    3025        6218 :         state.dataHeatBalFanSys->PreviousMeasuredHumRat2 = 0.0; // Hybrid modeling
    3026        6218 :         state.dataHeatBalFanSys->PreviousMeasuredHumRat3 = 0.0; // Hybrid modeling
    3027             : 
    3028        6218 :         state.dataZoneTempPredictorCorrector->MyEnvrnFlag = false;
    3029             :     }
    3030             : 
    3031    13440069 :     if (!state.dataGlobal->BeginEnvrnFlag) {
    3032    13384756 :         state.dataZoneTempPredictorCorrector->MyEnvrnFlag = true;
    3033             :     }
    3034             : 
    3035             :     // Do the Begin Day initializations
    3036    13440069 :     if (state.dataZoneTempPredictorCorrector->MyDayFlag && state.dataGlobal->BeginDayFlag) {
    3037       23416 :         state.dataZoneTempPredictorCorrector->MyDayFlag = false;
    3038             :     }
    3039             : 
    3040    13440069 :     if (!state.dataGlobal->BeginDayFlag) {
    3041    13295675 :         state.dataZoneTempPredictorCorrector->MyDayFlag = true;
    3042             :     }
    3043             : 
    3044    99142998 :     for (int Loop = 1; Loop <= state.dataZoneCtrls->NumTempControlledZones; ++Loop) {
    3045    85702929 :         if (state.dataZoneEquip->ZoneEquipInputsFilled && !state.dataZoneTempPredictorCorrector->ControlledZonesChecked) {
    3046        3982 :             if (!VerifyControlledZoneForThermostat(state, TempControlledZone(Loop).ZoneName)) {
    3047           0 :                 ShowSevereError(state,
    3048           0 :                                 format("{}Zone=\"{}\" has specified a Thermostatic control but is not a controlled zone.",
    3049             :                                        RoutineName,
    3050           0 :                                        TempControlledZone(Loop).ZoneName));
    3051           0 :                 ShowContinueError(state, "...must have a ZoneHVAC:EquipmentConnections specification for this zone.");
    3052           0 :                 state.dataZoneTempPredictorCorrector->ErrorsFound = true;
    3053             :             }
    3054             :         }
    3055             : 
    3056    85702929 :         if (TempControlledZone(Loop).ManageDemand) {
    3057           0 :             int ZoneNum = TempControlledZone(Loop).ActualZoneNum;
    3058             : 
    3059           0 :             switch (TempControlType(ZoneNum)) {
    3060           0 :             case DataHVACGlobals::ThermostatType::SingleHeating:
    3061           0 :                 if (TempZoneThermostatSetPoint(ZoneNum) > TempControlledZone(Loop).HeatingResetLimit) {
    3062           0 :                     TempZoneThermostatSetPoint(ZoneNum) = TempControlledZone(Loop).HeatingResetLimit;
    3063           0 :                     ZoneThermostatSetPointLo(ZoneNum) = TempZoneThermostatSetPoint(ZoneNum);
    3064             :                 }
    3065           0 :                 break;
    3066           0 :             case DataHVACGlobals::ThermostatType::SingleCooling:
    3067           0 :                 if (TempZoneThermostatSetPoint(ZoneNum) < TempControlledZone(Loop).CoolingResetLimit) {
    3068           0 :                     TempZoneThermostatSetPoint(ZoneNum) = TempControlledZone(Loop).CoolingResetLimit;
    3069           0 :                     ZoneThermostatSetPointHi(ZoneNum) = TempZoneThermostatSetPoint(ZoneNum);
    3070             :                 }
    3071           0 :                 break;
    3072           0 :             case DataHVACGlobals::ThermostatType::SingleHeatCool:
    3073           0 :                 if ((TempZoneThermostatSetPoint(ZoneNum) > TempControlledZone(Loop).HeatingResetLimit) ||
    3074           0 :                     (TempZoneThermostatSetPoint(ZoneNum) < TempControlledZone(Loop).CoolingResetLimit)) {
    3075             : 
    3076           0 :                     TempControlType(ZoneNum) = DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand;
    3077           0 :                     TempControlTypeRpt(ZoneNum) = static_cast<int>(TempControlType(ZoneNum));
    3078           0 :                     ZoneThermostatSetPointLo(ZoneNum) = TempZoneThermostatSetPoint(ZoneNum);
    3079           0 :                     ZoneThermostatSetPointHi(ZoneNum) = TempZoneThermostatSetPoint(ZoneNum);
    3080             : 
    3081           0 :                     if (ZoneThermostatSetPointLo(ZoneNum) > TempControlledZone(Loop).HeatingResetLimit)
    3082           0 :                         ZoneThermostatSetPointLo(ZoneNum) = TempControlledZone(Loop).HeatingResetLimit;
    3083           0 :                     if (ZoneThermostatSetPointHi(ZoneNum) < TempControlledZone(Loop).CoolingResetLimit)
    3084           0 :                         ZoneThermostatSetPointHi(ZoneNum) = TempControlledZone(Loop).CoolingResetLimit;
    3085             :                 }
    3086           0 :                 break;
    3087           0 :             case DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand:
    3088           0 :                 if (ZoneThermostatSetPointLo(ZoneNum) > TempControlledZone(Loop).HeatingResetLimit)
    3089           0 :                     ZoneThermostatSetPointLo(ZoneNum) = TempControlledZone(Loop).HeatingResetLimit;
    3090           0 :                 if (ZoneThermostatSetPointHi(ZoneNum) < TempControlledZone(Loop).CoolingResetLimit)
    3091           0 :                     ZoneThermostatSetPointHi(ZoneNum) = TempControlledZone(Loop).CoolingResetLimit;
    3092           0 :                 break;
    3093           0 :             default:
    3094           0 :                 break;
    3095             :             }
    3096             :         }
    3097             :     }
    3098             : 
    3099    13450491 :     for (int Loop = 1; Loop <= state.dataZoneCtrls->NumComfortControlledZones; ++Loop) {
    3100       10422 :         if (state.dataZoneEquip->ZoneEquipInputsFilled && !state.dataZoneTempPredictorCorrector->ControlledZonesChecked) {
    3101           1 :             if (!VerifyControlledZoneForThermostat(state, ComfortControlledZone(Loop).ZoneName)) {
    3102           0 :                 ShowSevereError(state,
    3103           0 :                                 format("{}Zone=\"{}\" has specified a Comfort control but is not a controlled zone.",
    3104             :                                        RoutineName,
    3105           0 :                                        ComfortControlledZone(Loop).ZoneName));
    3106           0 :                 ShowContinueError(state, "...must have a ZoneHVAC:EquipmentConnections specification for this zone.");
    3107           0 :                 state.dataZoneTempPredictorCorrector->ErrorsFound = true;
    3108             :             }
    3109             :         }
    3110       10422 :         if (ComfortControlledZone(Loop).ManageDemand) {
    3111           0 :             int ZoneNum = ComfortControlledZone(Loop).ActualZoneNum;
    3112             : 
    3113           0 :             switch (state.dataHeatBalFanSys->ComfortControlType(ZoneNum)) {
    3114           0 :             case DataHVACGlobals::ThermostatType::SingleHeating:
    3115           0 :                 if (TempZoneThermostatSetPoint(ZoneNum) >= ComfortControlledZone(Loop).HeatingResetLimit) {
    3116           0 :                     TempZoneThermostatSetPoint(ZoneNum) = ComfortControlledZone(Loop).HeatingResetLimit;
    3117           0 :                     ZoneThermostatSetPointLo(ZoneNum) = TempZoneThermostatSetPoint(ZoneNum);
    3118           0 :                     TempControlType(ZoneNum) = DataHVACGlobals::ThermostatType::SingleHeating;
    3119           0 :                     TempControlTypeRpt(ZoneNum) = static_cast<int>(TempControlType(ZoneNum));
    3120             :                 }
    3121           0 :                 break;
    3122           0 :             case DataHVACGlobals::ThermostatType::SingleCooling:
    3123           0 :                 if (TempZoneThermostatSetPoint(ZoneNum) <= ComfortControlledZone(Loop).CoolingResetLimit) {
    3124           0 :                     TempZoneThermostatSetPoint(ZoneNum) = ComfortControlledZone(Loop).CoolingResetLimit;
    3125           0 :                     ZoneThermostatSetPointHi(ZoneNum) = TempZoneThermostatSetPoint(ZoneNum);
    3126           0 :                     TempControlType(ZoneNum) = DataHVACGlobals::ThermostatType::SingleCooling;
    3127           0 :                     TempControlTypeRpt(ZoneNum) = static_cast<int>(TempControlType(ZoneNum));
    3128             :                 }
    3129           0 :                 break;
    3130           0 :             case DataHVACGlobals::ThermostatType::SingleHeatCool:
    3131           0 :                 if ((TempZoneThermostatSetPoint(ZoneNum) >= ComfortControlledZone(Loop).HeatingResetLimit) ||
    3132           0 :                     (TempZoneThermostatSetPoint(ZoneNum) <= ComfortControlledZone(Loop).CoolingResetLimit)) {
    3133             : 
    3134           0 :                     TempControlType(ZoneNum) = DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand;
    3135           0 :                     TempControlTypeRpt(ZoneNum) = static_cast<int>(TempControlType(ZoneNum));
    3136           0 :                     ZoneThermostatSetPointLo(ZoneNum) = TempZoneThermostatSetPoint(ZoneNum);
    3137           0 :                     ZoneThermostatSetPointHi(ZoneNum) = TempZoneThermostatSetPoint(ZoneNum);
    3138             : 
    3139           0 :                     if (ZoneThermostatSetPointLo(ZoneNum) >= ComfortControlledZone(Loop).HeatingResetLimit)
    3140           0 :                         ZoneThermostatSetPointLo(ZoneNum) = ComfortControlledZone(Loop).HeatingResetLimit;
    3141           0 :                     if (ZoneThermostatSetPointHi(ZoneNum) <= ComfortControlledZone(Loop).CoolingResetLimit)
    3142           0 :                         ZoneThermostatSetPointHi(ZoneNum) = ComfortControlledZone(Loop).CoolingResetLimit;
    3143             :                 }
    3144           0 :                 break;
    3145           0 :             case DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand:
    3146           0 :                 TempControlType(ZoneNum) = DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand;
    3147           0 :                 TempControlTypeRpt(ZoneNum) = static_cast<int>(TempControlType(ZoneNum));
    3148           0 :                 if (ZoneThermostatSetPointLo(ZoneNum) >= ComfortControlledZone(Loop).HeatingResetLimit)
    3149           0 :                     ZoneThermostatSetPointLo(ZoneNum) = ComfortControlledZone(Loop).HeatingResetLimit;
    3150           0 :                 if (ZoneThermostatSetPointHi(ZoneNum) <= ComfortControlledZone(Loop).CoolingResetLimit)
    3151           0 :                     ZoneThermostatSetPointHi(ZoneNum) = ComfortControlledZone(Loop).CoolingResetLimit;
    3152           0 :                 break;
    3153           0 :             default:
    3154           0 :                 break;
    3155             :             }
    3156             :         } // Demand manager
    3157             :     }
    3158             : 
    3159    13440069 :     if (state.dataZoneTempPredictorCorrector->ErrorsFound) {
    3160           0 :         ShowFatalError(state, "InitZoneAirSetpoints - program terminates due to previous condition.");
    3161             :     }
    3162             : 
    3163    13440069 :     if (state.dataZoneEquip->ZoneEquipInputsFilled) {
    3164    13439815 :         state.dataZoneTempPredictorCorrector->ControlledZonesChecked = true;
    3165             :     }
    3166    13440069 : }
    3167             : 
    3168       46333 : void ZoneSpaceHeatBalanceData::beginEnvironmentInit(EnergyPlusData &state)
    3169             : {
    3170      231665 :     for (int i = 0; i <= 3; ++i) {
    3171      185332 :         this->ZTM[i] = 0.0;
    3172      185332 :         this->WPrevZoneTS[i] = state.dataEnvrn->OutHumRat;
    3173      185332 :         this->DSWPrevZoneTS[i] = state.dataEnvrn->OutHumRat;
    3174      185332 :         this->WPrevZoneTSTemp[i] = 0.0;
    3175             :     }
    3176       46333 :     this->WZoneTimeMinusP = state.dataEnvrn->OutHumRat;
    3177       46333 :     this->ZoneW1 = state.dataEnvrn->OutHumRat;
    3178       46333 :     this->ZoneWMX = state.dataEnvrn->OutHumRat;
    3179       46333 :     this->ZoneWM2 = state.dataEnvrn->OutHumRat;
    3180       46333 :     this->ZoneAirHumRatTemp = 0.0;
    3181       46333 :     this->TempIndZnLd = 0.0;
    3182       46333 :     this->TempDepZnLd = 0.0;
    3183       46333 :     this->ZoneAirRelHum = 0.0;
    3184       46333 :     this->AirPowerCap = 0.0;
    3185       46333 :     this->ZoneT1 = 0.0;
    3186       46333 : }
    3187             : 
    3188        4820 : void ZoneSpaceHeatBalanceData::setUpOutputVars(EnergyPlusData &state, std::string_view prefix, std::string_view name)
    3189             : {
    3190       14460 :     SetupOutputVariable(state,
    3191        9640 :                         format("{} Air Temperature", prefix),
    3192             :                         OutputProcessor::Unit::C,
    3193             :                         this->ZT,
    3194             :                         OutputProcessor::SOVTimeStepType::System,
    3195             :                         OutputProcessor::SOVStoreType::Average,
    3196             :                         name);
    3197       14460 :     SetupOutputVariable(state,
    3198        9640 :                         format("{} Air Humidity Ratio", prefix),
    3199             :                         OutputProcessor::Unit::None,
    3200             :                         this->ZoneAirHumRat,
    3201             :                         OutputProcessor::SOVTimeStepType::System,
    3202             :                         OutputProcessor::SOVStoreType::Average,
    3203             :                         name);
    3204       14460 :     SetupOutputVariable(state,
    3205        9640 :                         format("{} Air Relative Humidity", prefix),
    3206             :                         OutputProcessor::Unit::Perc,
    3207             :                         this->ZoneAirRelHum,
    3208             :                         OutputProcessor::SOVTimeStepType::System,
    3209             :                         OutputProcessor::SOVStoreType::Average,
    3210             :                         name);
    3211        4820 : }
    3212             : 
    3213     3623998 : void PredictSystemLoads(EnergyPlusData &state,
    3214             :                         bool const ShortenTimeStepSys,
    3215             :                         bool const UseZoneTimeStepHistory, // if true then use zone timestep history, if false use system time step
    3216             :                         Real64 const PriorTimeStep         // the old value for timestep length is passed for possible use in interpolating
    3217             : )
    3218             : {
    3219             : 
    3220             :     // SUBROUTINE INFORMATION:
    3221             :     //       AUTHOR         Russ Taylor
    3222             :     //       DATE WRITTEN   May 1997
    3223             :     //       MODIFIED       na
    3224             :     //       RE-ENGINEERED  July 2003 (Peter Graham Ellis)
    3225             : 
    3226             :     // PURPOSE OF THIS SUBROUTINE:
    3227             :     // This subroutine is responsible for determining
    3228             :     // how much of each type of energy every zone requires.
    3229             :     // In effect, this subroutine defines and simulates all
    3230             :     // the system types and in the case of hybrid systems
    3231             :     // which use more than one type of energy must determine
    3232             :     // how to apportion the load. An example of a hybrid system
    3233             :     // is a water loop heat pump with supplemental air.  In
    3234             :     // this case, a zone will require water from the loop and
    3235             :     // cooled or heated air from the air system. A simpler
    3236             :     // example would be a VAV system with baseboard heaters.
    3237             : 
    3238             :     //  Basic Air System Types
    3239             :     //  1) Constant Volume Single Duct
    3240             :     //  2) Variable Volume Single Duct
    3241             :     //  3) Constant Volume Dual Duct
    3242             :     //  4) Variable Volume Dual Duct
    3243             : 
    3244             :     // METHODOLOGY EMPLOYED:
    3245             :     // 0.  Determine if simulation has downstepped and readjust history and revert node results
    3246             :     // 1.  Determine zone load - this is zone temperature dependent
    3247             :     // 2.  Determine balance point - the temperature at which the
    3248             :     //     zone load is balanced by the system output. The way the
    3249             :     //     balance point is determined will be different depending on
    3250             :     //     the type of system being simulated.
    3251             :     // 3.  Calculate zone energy requirements
    3252             : 
    3253             :     // Staged thermostat setpoint
    3254     3623998 :     if (state.dataZoneTempPredictorCorrector->NumStageCtrZone > 0) {
    3255      128021 :         for (int RelativeZoneNum = 1; RelativeZoneNum <= state.dataZoneTempPredictorCorrector->NumStageCtrZone; ++RelativeZoneNum) {
    3256      101418 :             auto &thisStageControlZone = state.dataZoneCtrls->StageControlledZone(RelativeZoneNum);
    3257      101418 :             int ActualZoneNum = thisStageControlZone.ActualZoneNum;
    3258      101418 :             auto &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ActualZoneNum);
    3259      101418 :             auto &thisZoneThermostatSetPointLo = state.dataHeatBalFanSys->ZoneThermostatSetPointLo(ActualZoneNum);
    3260      101418 :             auto &thisZoneThermostatSetPointHi = state.dataHeatBalFanSys->ZoneThermostatSetPointHi(ActualZoneNum);
    3261      101418 :             Real64 ZoneT = thisZoneHB.MAT; // Zone temperature at previous time step
    3262      101418 :             if (ShortenTimeStepSys) ZoneT = thisZoneHB.XMPT;
    3263      101418 :             thisStageControlZone.HeatSetPoint = ScheduleManager::GetCurrentScheduleValue(state, thisStageControlZone.HSBchedIndex);
    3264      101418 :             thisStageControlZone.CoolSetPoint = ScheduleManager::GetCurrentScheduleValue(state, thisStageControlZone.CSBchedIndex);
    3265      101418 :             if (thisStageControlZone.HeatSetPoint >= thisStageControlZone.CoolSetPoint) {
    3266           0 :                 ++thisStageControlZone.StageErrCount;
    3267           0 :                 if (thisStageControlZone.StageErrCount < 2) {
    3268           0 :                     ShowWarningError(state,
    3269           0 :                                      "ZoneControl:Thermostat:StagedDualSetpoint: The heating setpoint is equal to or above the cooling setpoint in " +
    3270             :                                          thisStageControlZone.Name);
    3271           0 :                     ShowContinueError(state, "The zone heating setpoint is set to the cooling setpoint - 0.1C.");
    3272           0 :                     ShowContinueErrorTimeStamp(state, "Occurrence info:");
    3273             :                 } else {
    3274           0 :                     ShowRecurringWarningErrorAtEnd(state,
    3275             :                                                    "The heating setpoint is still above the cooling setpoint",
    3276             :                                                    thisStageControlZone.StageErrIndex,
    3277             :                                                    thisStageControlZone.HeatSetPoint,
    3278             :                                                    thisStageControlZone.HeatSetPoint);
    3279             :                 }
    3280           0 :                 thisStageControlZone.HeatSetPoint = thisStageControlZone.CoolSetPoint - 0.1; //???????????
    3281             :             }
    3282             :             // Determine either cooling or heating
    3283      101418 :             if (thisStageControlZone.CoolSetPoint < ZoneT) { // Cooling
    3284       19883 :                 Real64 SetpointOffset = ZoneT - thisStageControlZone.CoolSetPoint;
    3285       19883 :                 int Itemp = 0;
    3286       71665 :                 for (int I = 1; I <= thisStageControlZone.NumOfCoolStages; ++I) {
    3287       51782 :                     if (SetpointOffset >= thisStageControlZone.CoolTOffset(I)) {
    3288       31791 :                         Itemp = -I;
    3289             :                     }
    3290             :                 }
    3291       19883 :                 state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ActualZoneNum).StageNum = Itemp;
    3292       19883 :                 if (SetpointOffset >= 0.5 * thisStageControlZone.CoolThroRange) {
    3293        7712 :                     thisZoneThermostatSetPointHi = thisStageControlZone.CoolSetPoint - 0.5 * thisStageControlZone.CoolThroRange;
    3294             :                 } else {
    3295       12171 :                     thisZoneThermostatSetPointHi = thisStageControlZone.CoolSetPoint + 0.5 * thisStageControlZone.CoolThroRange;
    3296             :                 }
    3297       19883 :                 thisZoneThermostatSetPointLo = thisZoneThermostatSetPointHi;
    3298       81535 :             } else if (thisStageControlZone.HeatSetPoint > ZoneT) { // heating
    3299       37138 :                 Real64 SetpointOffset = ZoneT - thisStageControlZone.HeatSetPoint;
    3300       37138 :                 int Itemp = 0;
    3301       86581 :                 for (int I = 1; I <= thisStageControlZone.NumOfHeatStages; ++I) {
    3302       49443 :                     if (std::abs(SetpointOffset) >= std::abs(thisStageControlZone.HeatTOffset(I))) {
    3303       46662 :                         Itemp = I;
    3304             :                     }
    3305             :                 }
    3306       37138 :                 state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ActualZoneNum).StageNum = Itemp;
    3307       37138 :                 if (std::abs(SetpointOffset) >= 0.5 * thisStageControlZone.CoolThroRange) {
    3308       25336 :                     thisZoneThermostatSetPointLo = thisStageControlZone.HeatSetPoint + 0.5 * thisStageControlZone.HeatThroRange;
    3309             :                 } else {
    3310       11802 :                     thisZoneThermostatSetPointLo = thisStageControlZone.HeatSetPoint - 0.5 * thisStageControlZone.HeatThroRange;
    3311             :                 }
    3312       37138 :                 thisZoneThermostatSetPointHi = thisZoneThermostatSetPointLo;
    3313             :             } else {
    3314       44397 :                 thisZoneThermostatSetPointHi = thisStageControlZone.CoolSetPoint + 0.5 * thisStageControlZone.CoolThroRange;
    3315       44397 :                 thisZoneThermostatSetPointLo = thisStageControlZone.HeatSetPoint - 0.5 * thisStageControlZone.HeatThroRange;
    3316       44397 :                 state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ActualZoneNum).StageNum = 0;
    3317             :             }
    3318             :             // SpaceHB TODO: For now, set space stagenum to zone stagenum - later need to see what space the thermostat is in
    3319      101418 :             if (state.dataHeatBal->doSpaceHeatBalance) {
    3320           0 :                 for (int spaceNum : state.dataHeatBal->Zone(ActualZoneNum).spaceIndexes) {
    3321           0 :                     state.dataZoneEnergyDemand->spaceSysEnergyDemand(spaceNum).StageNum =
    3322           0 :                         state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ActualZoneNum).StageNum;
    3323             :                 }
    3324             :             }
    3325             :         }
    3326             :     }
    3327             : 
    3328             :     // Setpoint revision for onoff thermostat
    3329     3623998 :     if (state.dataZoneTempPredictorCorrector->NumOnOffCtrZone > 0) {
    3330      140541 :         Real64 TempTole = 0.02;
    3331             :         Real64 Tprev;
    3332      281082 :         for (int RelativeZoneNum = 1; RelativeZoneNum <= state.dataZoneCtrls->NumTempControlledZones; ++RelativeZoneNum) {
    3333      140541 :             auto &thisTempControlledZone = state.dataZoneCtrls->TempControlledZone(RelativeZoneNum);
    3334      140541 :             if (thisTempControlledZone.DeltaTCutSet > 0.0) {
    3335      140541 :                 if (ShortenTimeStepSys) {
    3336       24968 :                     thisTempControlledZone.HeatModeLast = thisTempControlledZone.HeatModeLastSave;
    3337       24968 :                     thisTempControlledZone.CoolModeLast = thisTempControlledZone.CoolModeLastSave;
    3338             :                 } else {
    3339      115573 :                     thisTempControlledZone.HeatModeLastSave = thisTempControlledZone.HeatModeLast;
    3340      115573 :                     thisTempControlledZone.CoolModeLastSave = thisTempControlledZone.CoolModeLast;
    3341             :                 }
    3342      140541 :                 auto &thisTempZoneThermostatSetPoint = state.dataHeatBalFanSys->TempZoneThermostatSetPoint(thisTempControlledZone.ActualZoneNum);
    3343      140541 :                 auto &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(thisTempControlledZone.ActualZoneNum);
    3344      140541 :                 auto &thisZoneThermostatSetPointLo = state.dataHeatBalFanSys->ZoneThermostatSetPointLo(thisTempControlledZone.ActualZoneNum);
    3345      140541 :                 auto &thisZoneThermostatSetPointHi = state.dataHeatBalFanSys->ZoneThermostatSetPointHi(thisTempControlledZone.ActualZoneNum);
    3346             : 
    3347      140541 :                 thisTempControlledZone.CoolOffFlag = false;
    3348      140541 :                 thisTempControlledZone.HeatOffFlag = false;
    3349      140541 :                 if (state.dataHeatBal->ZoneAirSolutionAlgo == DataHeatBalance::SolutionAlgo::ThirdOrder) {
    3350      140541 :                     Tprev = thisZoneHB.MAT;
    3351      140541 :                     if (ShortenTimeStepSys) Tprev = thisZoneHB.XMPT;
    3352             :                 } else {
    3353           0 :                     Tprev = thisZoneHB.ZoneT1;
    3354             :                 }
    3355             : 
    3356      140541 :                 switch (state.dataHeatBalFanSys->TempControlType(thisTempControlledZone.ActualZoneNum)) {
    3357           0 :                 case DataHVACGlobals::ThermostatType::SingleHeating:
    3358           0 :                     thisTempZoneThermostatSetPoint = thisTempControlledZone.ZoneThermostatSetPointLo;
    3359           0 :                     thisZoneThermostatSetPointLo = thisTempControlledZone.ZoneThermostatSetPointLo;
    3360           0 :                     if (Tprev < thisTempControlledZone.ZoneThermostatSetPointLo + TempTole) {
    3361           0 :                         thisTempZoneThermostatSetPoint = thisTempControlledZone.ZoneThermostatSetPointLo + thisTempControlledZone.DeltaTCutSet;
    3362           0 :                         thisZoneThermostatSetPointLo = thisTempZoneThermostatSetPoint;
    3363           0 :                     } else if (Tprev > thisTempControlledZone.ZoneThermostatSetPointLo &&
    3364           0 :                                (Tprev < thisTempControlledZone.ZoneThermostatSetPointLo + thisTempControlledZone.DeltaTCutSet - TempTole)) {
    3365           0 :                         thisTempZoneThermostatSetPoint = thisTempControlledZone.ZoneThermostatSetPointLo + thisTempControlledZone.DeltaTCutSet;
    3366           0 :                         thisZoneThermostatSetPointLo = thisTempZoneThermostatSetPoint;
    3367             :                     } else {
    3368           0 :                         thisTempControlledZone.HeatOffFlag = true;
    3369             :                     }
    3370           0 :                     if (thisTempControlledZone.HeatModeLast && Tprev > thisTempControlledZone.ZoneThermostatSetPointLo) {
    3371           0 :                         thisTempZoneThermostatSetPoint = thisTempControlledZone.ZoneThermostatSetPointLo;
    3372           0 :                         thisZoneThermostatSetPointLo = thisTempControlledZone.ZoneThermostatSetPointLo;
    3373           0 :                         thisTempControlledZone.HeatOffFlag = true;
    3374             :                     }
    3375           0 :                     break;
    3376           0 :                 case DataHVACGlobals::ThermostatType::SingleCooling:
    3377           0 :                     thisTempZoneThermostatSetPoint = thisTempControlledZone.ZoneThermostatSetPointHi;
    3378           0 :                     thisZoneThermostatSetPointHi = thisTempControlledZone.ZoneThermostatSetPointHi;
    3379           0 :                     if (Tprev > thisTempControlledZone.ZoneThermostatSetPointHi - TempTole) {
    3380           0 :                         thisTempZoneThermostatSetPoint = thisTempControlledZone.ZoneThermostatSetPointHi - thisTempControlledZone.DeltaTCutSet;
    3381           0 :                         thisZoneThermostatSetPointHi = thisTempZoneThermostatSetPoint;
    3382           0 :                     } else if (Tprev < thisTempControlledZone.ZoneThermostatSetPointHi &&
    3383           0 :                                Tprev > thisTempControlledZone.ZoneThermostatSetPointHi - thisTempControlledZone.DeltaTCutSet + TempTole) {
    3384           0 :                         thisTempZoneThermostatSetPoint = thisTempControlledZone.ZoneThermostatSetPointHi - thisTempControlledZone.DeltaTCutSet;
    3385           0 :                         thisZoneThermostatSetPointHi = thisTempZoneThermostatSetPoint;
    3386             :                     } else {
    3387           0 :                         thisTempControlledZone.CoolOffFlag = true;
    3388             :                     }
    3389           0 :                     if (thisTempControlledZone.CoolModeLast && Tprev < thisTempControlledZone.ZoneThermostatSetPointHi) {
    3390           0 :                         thisTempZoneThermostatSetPoint = thisTempControlledZone.ZoneThermostatSetPointHi;
    3391           0 :                         thisZoneThermostatSetPointHi = thisTempControlledZone.ZoneThermostatSetPointHi;
    3392           0 :                         thisTempControlledZone.CoolOffFlag = true;
    3393             :                     }
    3394           0 :                     break;
    3395      140541 :                 case DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand:
    3396      140541 :                     thisZoneThermostatSetPointHi = thisTempControlledZone.ZoneThermostatSetPointHi;
    3397      140541 :                     thisZoneThermostatSetPointLo = thisTempControlledZone.ZoneThermostatSetPointLo;
    3398      140541 :                     if (Tprev > thisTempControlledZone.ZoneThermostatSetPointHi - TempTole) {
    3399       11704 :                         thisZoneThermostatSetPointHi = thisTempControlledZone.ZoneThermostatSetPointHi - thisTempControlledZone.DeltaTCutSet;
    3400      257674 :                     } else if (Tprev < thisTempControlledZone.ZoneThermostatSetPointHi &&
    3401      128837 :                                Tprev > thisTempControlledZone.ZoneThermostatSetPointHi - thisTempControlledZone.DeltaTCutSet + TempTole) {
    3402       68814 :                         thisZoneThermostatSetPointHi = thisTempControlledZone.ZoneThermostatSetPointHi - thisTempControlledZone.DeltaTCutSet;
    3403             :                     } else {
    3404       60023 :                         thisTempControlledZone.CoolOffFlag = true;
    3405             :                     }
    3406      140541 :                     if (thisTempControlledZone.CoolModeLast && Tprev < thisTempControlledZone.ZoneThermostatSetPointHi) {
    3407       87058 :                         thisZoneThermostatSetPointHi = thisTempControlledZone.ZoneThermostatSetPointHi;
    3408       87058 :                         thisTempControlledZone.CoolOffFlag = true;
    3409             :                     }
    3410             : 
    3411      140541 :                     if (Tprev < thisTempControlledZone.ZoneThermostatSetPointLo + TempTole) {
    3412       14786 :                         thisZoneThermostatSetPointLo = thisTempControlledZone.ZoneThermostatSetPointLo + thisTempControlledZone.DeltaTCutSet;
    3413      251510 :                     } else if (Tprev > thisTempControlledZone.ZoneThermostatSetPointLo &&
    3414      125755 :                                (Tprev < thisTempControlledZone.ZoneThermostatSetPointLo + thisTempControlledZone.DeltaTCutSet - TempTole)) {
    3415       23503 :                         thisZoneThermostatSetPointLo = thisTempControlledZone.ZoneThermostatSetPointLo + thisTempControlledZone.DeltaTCutSet;
    3416             :                     } else {
    3417      102252 :                         thisTempControlledZone.HeatOffFlag = true;
    3418             :                     }
    3419      140541 :                     if (thisTempControlledZone.HeatModeLast && Tprev > thisTempControlledZone.ZoneThermostatSetPointLo) {
    3420       94415 :                         thisZoneThermostatSetPointLo = thisTempControlledZone.ZoneThermostatSetPointLo;
    3421       94415 :                         thisTempControlledZone.HeatOffFlag = true;
    3422             :                     }
    3423             :                     // check setpoint for both and provde an error message
    3424      140541 :                     if (thisZoneThermostatSetPointLo >= thisZoneThermostatSetPointHi) {
    3425           0 :                         ShowSevereError(state,
    3426             :                                         "DualSetPointWithDeadBand: When Temperature Difference Between Cutout And Setpoint is applied, the heating "
    3427             :                                         "setpoint is greater than the cooling setpoint. ");
    3428           0 :                         ShowContinueErrorTimeStamp(state, "occurs in Zone=" + state.dataHeatBal->Zone(thisTempControlledZone.ActualZoneNum).Name);
    3429           0 :                         ShowContinueError(state, format("Zone Heating ThermostatSetPoint={:.2R}", thisZoneThermostatSetPointLo));
    3430           0 :                         ShowContinueError(state, format("Zone Cooling ThermostatSetPoint={:.2R}", thisZoneThermostatSetPointHi));
    3431           0 :                         ShowFatalError(state, "Program terminates due to above conditions.");
    3432             :                     }
    3433      140541 :                     break;
    3434           0 :                 default:
    3435           0 :                     break;
    3436             :                 }
    3437             :             }
    3438             :         }
    3439             :     }
    3440             : 
    3441    31553517 :     for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
    3442    27929519 :         state.dataZoneTempPredictorCorrector->zoneHeatBalance(zoneNum).predictSystemLoad(
    3443             :             state, ShortenTimeStepSys, UseZoneTimeStepHistory, PriorTimeStep, zoneNum);
    3444    27929519 :         if (state.dataHeatBal->doSpaceHeatBalance) {
    3445       60024 :             for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
    3446       30012 :                 state.dataZoneTempPredictorCorrector->spaceHeatBalance(spaceNum).predictSystemLoad(
    3447             :                     state, ShortenTimeStepSys, UseZoneTimeStepHistory, PriorTimeStep, zoneNum, spaceNum);
    3448             :             }
    3449             :         }
    3450             :     }
    3451     3623998 :     if (state.dataZoneTempPredictorCorrector->NumOnOffCtrZone > 0) {
    3452      281082 :         for (int RelativeZoneNum = 1; RelativeZoneNum <= state.dataZoneCtrls->NumTempControlledZones; ++RelativeZoneNum) {
    3453      140541 :             auto &thisTempControlledZone = state.dataZoneCtrls->TempControlledZone(RelativeZoneNum);
    3454      140541 :             if (thisTempControlledZone.DeltaTCutSet > 0.0) {
    3455      140541 :                 int ZoneNum = thisTempControlledZone.ActualZoneNum;
    3456      140541 :                 if (thisTempControlledZone.CoolOffFlag && state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).TotalOutputRequired >= 0.0) {
    3457       84583 :                     thisTempControlledZone.CoolModeLast = true;
    3458             :                 } else {
    3459       55958 :                     thisTempControlledZone.CoolModeLast = false;
    3460             :                 }
    3461      140541 :                 if (thisTempControlledZone.HeatOffFlag && state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).TotalOutputRequired <= 0.0) {
    3462       94398 :                     thisTempControlledZone.HeatModeLast = true;
    3463             :                 } else {
    3464       46143 :                     thisTempControlledZone.HeatModeLast = false;
    3465             :                 }
    3466             :             }
    3467             :         }
    3468             :     }
    3469     3623998 : }
    3470    27959531 : void ZoneSpaceHeatBalanceData::predictSystemLoad(
    3471             :     EnergyPlusData &state,
    3472             :     bool const shortenTimeStepSys,
    3473             :     bool const useZoneTimeStepHistory, // if true then use zone timestep history, if false use system time step
    3474             :     Real64 const priorTimeStep,        // the old value for timestep length is passed for possible use in interpolating
    3475             :     int zoneNum,
    3476             :     int spaceNum)
    3477             : {
    3478    27959531 :     assert(zoneNum > 0);
    3479    27959531 :     this->updateTemperatures(state, shortenTimeStepSys, useZoneTimeStepHistory, priorTimeStep, zoneNum, spaceNum);
    3480             : 
    3481    27959531 :     Real64 volume = 0.0;
    3482    27959531 :     if (spaceNum > 0) {
    3483       30012 :         volume = state.dataHeatBal->space(spaceNum).Volume;
    3484             :     } else {
    3485    27929519 :         volume = state.dataHeatBal->Zone(zoneNum).Volume;
    3486             :     }
    3487    83878593 :     this->AirPowerCap = volume * state.dataHeatBal->Zone(zoneNum).ZoneVolCapMultpSens *
    3488    83878593 :                         Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, this->MAT, this->ZoneAirHumRat) *
    3489    55919062 :                         Psychrometrics::PsyCpAirFnW(this->ZoneAirHumRat) / (state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour);
    3490    27959531 :     Real64 RAFNFrac = 0.0;
    3491             : 
    3492             :     // Calculate the various heat balance sums
    3493             : 
    3494             :     // NOTE: SumSysMCp and SumSysMCpT are not used in the predict step
    3495    27959531 :     this->calcZoneOrSpaceSums(state, false, zoneNum, spaceNum);
    3496             : 
    3497             :     // Sum all convective internal gains except for people: SumIntGainExceptPeople
    3498    27959531 :     if (spaceNum == 0 && state.dataHybridModel->FlagHybridModel_PC) {
    3499        8216 :         this->SumIntGainExceptPeople = 0.0;
    3500        8216 :         this->SumIntGainExceptPeople = InternalHeatGains::SumAllInternalConvectionGainsExceptPeople(state, zoneNum);
    3501             :     }
    3502             : 
    3503    27959531 :     this->TempDepCoef = this->SumHA + this->SumMCp;
    3504    27959531 :     this->TempIndCoef = this->SumIntGain + this->SumHATsurf - this->SumHATref + this->SumMCpT + this->SysDepZoneLoadsLagged;
    3505    27959531 :     this->TempHistoryTerm = this->AirPowerCap * (3.0 * this->ZTM[0] - (3.0 / 2.0) * this->ZTM[1] + (1.0 / 3.0) * this->ZTM[2]);
    3506    27959531 :     this->TempDepZnLd = (11.0 / 6.0) * this->AirPowerCap + this->TempDepCoef;
    3507    27959531 :     this->TempIndZnLd = this->TempHistoryTerm + this->TempIndCoef;
    3508    27959531 :     if (state.dataRoomAirMod->anyNonMixingRoomAirModel) {
    3509      162216 :         if (state.dataRoomAirMod->AirModel(zoneNum).AirModelType == DataRoomAirModel::RoomAirModel::AirflowNetwork) {
    3510             :             // RoomAirflowNetworkModel - make dynamic term independent of TimeStepSys
    3511        7689 :             auto &thisRoomAirflowNetworkZoneInfo = state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum);
    3512        7689 :             if (thisRoomAirflowNetworkZoneInfo.IsUsed) {
    3513        7689 :                 int RoomAirNode = thisRoomAirflowNetworkZoneInfo.ControlAirNodeID;
    3514        7689 :                 RoomAirModelAirflowNetwork::LoadPredictionRoomAirModelAirflowNetwork(state, zoneNum, RoomAirNode);
    3515        7689 :                 this->TempDepCoef =
    3516        7689 :                     thisRoomAirflowNetworkZoneInfo.Node(RoomAirNode).SumHA + thisRoomAirflowNetworkZoneInfo.Node(RoomAirNode).SumLinkMCp;
    3517       23067 :                 this->TempIndCoef = thisRoomAirflowNetworkZoneInfo.Node(RoomAirNode).SumIntSensibleGain +
    3518       15378 :                                     thisRoomAirflowNetworkZoneInfo.Node(RoomAirNode).SumHATsurf -
    3519       15378 :                                     thisRoomAirflowNetworkZoneInfo.Node(RoomAirNode).SumHATref +
    3520       15378 :                                     thisRoomAirflowNetworkZoneInfo.Node(RoomAirNode).SumLinkMCpT +
    3521        7689 :                                     thisRoomAirflowNetworkZoneInfo.Node(RoomAirNode).SysDepZoneLoadsLagged;
    3522       23067 :                 this->AirPowerCap = thisRoomAirflowNetworkZoneInfo.Node(RoomAirNode).AirVolume *
    3523       23067 :                                     state.dataHeatBal->Zone(zoneNum).ZoneVolCapMultpSens * thisRoomAirflowNetworkZoneInfo.Node(RoomAirNode).RhoAir *
    3524       15378 :                                     thisRoomAirflowNetworkZoneInfo.Node(RoomAirNode).CpAir /
    3525        7689 :                                     (state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour);
    3526        7689 :                 this->TempHistoryTerm = this->AirPowerCap * (3.0 * this->ZTM[0] - (3.0 / 2.0) * this->ZTM[1] + (1.0 / 3.0) * this->ZTM[2]);
    3527        7689 :                 this->TempDepZnLd = (11.0 / 6.0) * this->AirPowerCap + this->TempDepCoef;
    3528        7689 :                 this->TempIndZnLd = this->TempHistoryTerm + this->TempIndCoef;
    3529        7689 :                 if (thisRoomAirflowNetworkZoneInfo.Node(RoomAirNode).HasHVACAssigned)
    3530        7689 :                     RAFNFrac = thisRoomAirflowNetworkZoneInfo.Node(RoomAirNode).HVAC(1).SupplyFraction;
    3531             :             }
    3532             :         }
    3533             :     }
    3534             : 
    3535             :     // Exact solution or Euler method
    3536    27959531 :     state.dataHVACGlobal->ShortenTimeStepSysRoomAir = false;
    3537    27959531 :     if (state.dataHeatBal->ZoneAirSolutionAlgo != DataHeatBalance::SolutionAlgo::ThirdOrder) {
    3538    12381078 :         if (shortenTimeStepSys && state.dataHVACGlobal->TimeStepSys < state.dataGlobal->TimeStepZone) {
    3539     1533526 :             if (state.dataHVACGlobal->PreviousTimeStep < state.dataGlobal->TimeStepZone) {
    3540     1243677 :                 this->ZoneT1 = this->ZoneTM2;
    3541     1243677 :                 this->ZoneW1 = this->ZoneWM2;
    3542     1243677 :                 if (state.dataRoomAirMod->AirModel(zoneNum).AirModelType == DataRoomAirModel::RoomAirModel::AirflowNetwork) {
    3543           0 :                     auto &thisRoomAirflowNetworkZoneInfo = state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum);
    3544           0 :                     for (int LoopNode = 1; LoopNode <= thisRoomAirflowNetworkZoneInfo.NumOfAirNodes; ++LoopNode) {
    3545           0 :                         thisRoomAirflowNetworkZoneInfo.Node(LoopNode).AirTempT1 = thisRoomAirflowNetworkZoneInfo.Node(LoopNode).AirTempTM2;
    3546           0 :                         thisRoomAirflowNetworkZoneInfo.Node(LoopNode).HumRatW1 = thisRoomAirflowNetworkZoneInfo.Node(LoopNode).HumRatWM2;
    3547             :                     }
    3548             :                 }
    3549             :             } else {
    3550      289849 :                 this->ZoneT1 = this->ZoneTMX;
    3551      289849 :                 this->ZoneW1 = this->ZoneWMX;
    3552      289849 :                 if (state.dataRoomAirMod->AirModel(zoneNum).AirModelType == DataRoomAirModel::RoomAirModel::AirflowNetwork) {
    3553           0 :                     auto &thisRoomAirflowNetworkZoneInfo = state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum);
    3554           0 :                     for (int LoopNode = 1; LoopNode <= thisRoomAirflowNetworkZoneInfo.NumOfAirNodes; ++LoopNode) {
    3555           0 :                         thisRoomAirflowNetworkZoneInfo.Node(LoopNode).AirTempT1 = thisRoomAirflowNetworkZoneInfo.Node(LoopNode).AirTempTMX;
    3556           0 :                         thisRoomAirflowNetworkZoneInfo.Node(LoopNode).HumRatW1 = thisRoomAirflowNetworkZoneInfo.Node(LoopNode).HumRatWMX;
    3557             :                     }
    3558             :                 }
    3559             :             }
    3560     1533526 :             state.dataHVACGlobal->ShortenTimeStepSysRoomAir = true;
    3561             :         } else {
    3562    10847552 :             this->ZoneT1 = this->ZT;
    3563    10847552 :             this->ZoneW1 = this->ZoneAirHumRat;
    3564    10847552 :             if (state.dataRoomAirMod->AirModel(zoneNum).AirModelType == DataRoomAirModel::RoomAirModel::AirflowNetwork) {
    3565           0 :                 auto &thisRoomAirflowNetworkZoneInfo = state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum);
    3566           0 :                 for (int LoopNode = 1; LoopNode <= thisRoomAirflowNetworkZoneInfo.NumOfAirNodes; ++LoopNode) {
    3567           0 :                     thisRoomAirflowNetworkZoneInfo.Node(LoopNode).AirTempT1 = thisRoomAirflowNetworkZoneInfo.Node(LoopNode).AirTemp;
    3568           0 :                     thisRoomAirflowNetworkZoneInfo.Node(LoopNode).HumRatW1 = thisRoomAirflowNetworkZoneInfo.Node(LoopNode).HumRat;
    3569             :                 }
    3570             :             }
    3571             :         }
    3572    12381078 :         this->TempDepZnLd = this->TempDepCoef;
    3573    12381078 :         this->TempIndZnLd = this->TempIndCoef;
    3574             :     }
    3575             : 
    3576             :     // Calculate the predicted zone load to be provided by the system with the given desired zone air temperature
    3577    27959531 :     this->calcPredictedSystemLoad(state, RAFNFrac, zoneNum, spaceNum);
    3578             : 
    3579             :     // Calculate the predicted zone load to be provided by the system with the given desired humidity ratio
    3580    27959531 :     this->calcPredictedHumidityRatio(state, RAFNFrac, zoneNum, spaceNum);
    3581    27959531 : }
    3582             : 
    3583     2568551 : void CalcZoneAirTempSetPoints(EnergyPlusData &state)
    3584             : {
    3585             : 
    3586             :     // SUBROUTINE INFORMATION:
    3587             :     //       AUTHOR         Russ Taylor
    3588             :     //       DATE WRITTEN   Nov 1997
    3589             :     //       MODIFIED       Aug 2013, Xiufeng Pang (XP) - Added code for updating set points during
    3590             :     //                      optimum start period
    3591             :     //       RE-ENGINEERED  na
    3592             : 
    3593             :     // PURPOSE OF THIS SUBROUTINE:
    3594             :     // This routine sets what the setpoints for each controlled zone should be based on schedules.
    3595             :     // This is called each time step.
    3596             : 
    3597             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    3598             :     int RelativeZoneNum;
    3599             :     int ActualZoneNum;
    3600             :     int TempControlSchedIndex;
    3601             :     int SetPointTempSchedIndexHot;
    3602             :     int SetPointTempSchedIndexCold;
    3603             :     int SchedNameIndex;
    3604     5137102 :     Array2D<Real64> DaySPValues; // Day room temp setpoint values - for optimum start
    3605             :     int OccStartTime;            // Occupancy start time - for optimum start
    3606             :     Real64 DeltaT;               // Temperature difference between cutout and setpoint
    3607             : 
    3608     2568551 :     auto &Zone = state.dataHeatBal->Zone;
    3609     2568551 :     auto &TempControlledZone = state.dataZoneCtrls->TempControlledZone;
    3610     2568551 :     auto &TempZoneThermostatSetPoint = state.dataHeatBalFanSys->TempZoneThermostatSetPoint;
    3611     2568551 :     auto &TempControlType = state.dataHeatBalFanSys->TempControlType;
    3612     2568551 :     auto &TempControlTypeRpt = state.dataHeatBalFanSys->TempControlTypeRpt;
    3613     2568551 :     auto &ZoneThermostatSetPointLo = state.dataHeatBalFanSys->ZoneThermostatSetPointLo;
    3614     2568551 :     auto &ZoneThermostatSetPointHi = state.dataHeatBalFanSys->ZoneThermostatSetPointHi;
    3615     2568551 :     auto &NumOfZones = state.dataGlobal->NumOfZones;
    3616             : 
    3617     2568551 :     TempControlType = DataHVACGlobals::ThermostatType::Uncontrolled; // Default
    3618             : 
    3619             :     // Place holder for occupied heating and cooling set points - for optimum start
    3620     2568551 :     if (!allocated(state.dataZoneCtrls->OccRoomTSetPointHeat)) {
    3621         771 :         state.dataZoneCtrls->OccRoomTSetPointHeat.allocate(NumOfZones);
    3622             :     }
    3623     2568551 :     if (!allocated(state.dataZoneCtrls->OccRoomTSetPointCool)) {
    3624         771 :         state.dataZoneCtrls->OccRoomTSetPointCool.allocate(NumOfZones);
    3625             :     }
    3626     2568551 :     state.dataZoneCtrls->OccRoomTSetPointHeat = 0.0;
    3627     2568551 :     state.dataZoneCtrls->OccRoomTSetPointCool = 100.0;
    3628     2568551 :     DeltaT = 0.0;
    3629             : 
    3630    18204603 :     for (RelativeZoneNum = 1; RelativeZoneNum <= state.dataZoneCtrls->NumTempControlledZones; ++RelativeZoneNum) {
    3631             : 
    3632             :         // What if this zone not controlled???
    3633    15636052 :         ActualZoneNum = TempControlledZone(RelativeZoneNum).ActualZoneNum;
    3634    15636052 :         TempControlSchedIndex = TempControlledZone(RelativeZoneNum).CTSchedIndex;
    3635    15636052 :         TempControlType(ActualZoneNum) =
    3636    15636052 :             static_cast<DataHVACGlobals::ThermostatType>(ScheduleManager::GetCurrentScheduleValue(state, TempControlSchedIndex));
    3637    15636052 :         TempControlTypeRpt(ActualZoneNum) = static_cast<int>(TempControlType(ActualZoneNum));
    3638             :         // Error detection for these values is done in the Get routine
    3639             : 
    3640    15636052 :         switch (TempControlType(ActualZoneNum)) {
    3641        2034 :         case DataHVACGlobals::ThermostatType::Uncontrolled:
    3642        2034 :             break;
    3643     1702443 :         case DataHVACGlobals::ThermostatType::SingleHeating:
    3644     1702443 :             SchedNameIndex = TempControlledZone(RelativeZoneNum).SchIndx_SingleHeatSetPoint;
    3645     1702443 :             TempZoneThermostatSetPoint(ActualZoneNum) = ScheduleManager::GetCurrentScheduleValue(state, SchedNameIndex);
    3646     1702443 :             TempControlledZone(RelativeZoneNum).ZoneThermostatSetPointLo = TempZoneThermostatSetPoint(ActualZoneNum);
    3647             : 
    3648     1702443 :             AdjustAirSetPointsforOpTempCntrl(state, RelativeZoneNum, ActualZoneNum, TempZoneThermostatSetPoint(ActualZoneNum));
    3649     1702443 :             ZoneThermostatSetPointLo(ActualZoneNum) = TempZoneThermostatSetPoint(ActualZoneNum);
    3650     1702443 :             break;
    3651     1705748 :         case DataHVACGlobals::ThermostatType::SingleCooling:
    3652     1705748 :             SchedNameIndex = TempControlledZone(RelativeZoneNum).SchIndx_SingleCoolSetPoint;
    3653     1705748 :             TempZoneThermostatSetPoint(ActualZoneNum) = ScheduleManager::GetCurrentScheduleValue(state, SchedNameIndex);
    3654     1705748 :             TempControlledZone(RelativeZoneNum).ZoneThermostatSetPointHi = TempZoneThermostatSetPoint(ActualZoneNum);
    3655             : 
    3656             :             // Added Jan 17 (X. Luo)
    3657             :             // Adjust operative temperature based on adaptive comfort model
    3658     1705748 :             if ((TempControlledZone(RelativeZoneNum).AdaptiveComfortTempControl)) {
    3659        6750 :                 AdjustOperativeSetPointsforAdapComfort(state, RelativeZoneNum, TempZoneThermostatSetPoint(ActualZoneNum));
    3660        6750 :                 state.dataHeatBalFanSys->AdapComfortCoolingSetPoint(ActualZoneNum) = TempZoneThermostatSetPoint(ActualZoneNum);
    3661             :             }
    3662             : 
    3663     1705748 :             AdjustAirSetPointsforOpTempCntrl(state, RelativeZoneNum, ActualZoneNum, TempZoneThermostatSetPoint(ActualZoneNum));
    3664     1705748 :             ZoneThermostatSetPointHi(ActualZoneNum) = TempZoneThermostatSetPoint(ActualZoneNum);
    3665             : 
    3666     1705748 :             AdjustCoolingSetPointforTempAndHumidityControl(state, RelativeZoneNum, ActualZoneNum);
    3667     1705748 :             break;
    3668       79254 :         case DataHVACGlobals::ThermostatType::SingleHeatCool:
    3669             : 
    3670       79254 :             SchedNameIndex = TempControlledZone(RelativeZoneNum).SchIndx_SingleHeatCoolSetPoint;
    3671             : 
    3672       79254 :             TempZoneThermostatSetPoint(ActualZoneNum) = ScheduleManager::GetCurrentScheduleValue(state, SchedNameIndex);
    3673             : 
    3674             :             // Added Jan 17 (X. Luo)
    3675             :             // Adjust operative temperature based on adaptive comfort model
    3676       79254 :             if ((TempControlledZone(RelativeZoneNum).AdaptiveComfortTempControl)) {
    3677           0 :                 AdjustOperativeSetPointsforAdapComfort(state, RelativeZoneNum, TempZoneThermostatSetPoint(ActualZoneNum));
    3678           0 :                 state.dataHeatBalFanSys->AdapComfortCoolingSetPoint(ActualZoneNum) = TempZoneThermostatSetPoint(ActualZoneNum);
    3679             :             }
    3680             : 
    3681       79254 :             AdjustAirSetPointsforOpTempCntrl(state, RelativeZoneNum, ActualZoneNum, TempZoneThermostatSetPoint(ActualZoneNum));
    3682             : 
    3683       79254 :             ZoneThermostatSetPointHi(ActualZoneNum) = TempZoneThermostatSetPoint(ActualZoneNum);
    3684       79254 :             ZoneThermostatSetPointLo(ActualZoneNum) = TempZoneThermostatSetPoint(ActualZoneNum);
    3685             : 
    3686             :             // Change the room set point to occupied set point during optimum start period--------------
    3687             : 
    3688       79254 :             if (allocated(state.dataHVACGlobal->OptStartData.OptStartFlag)) {
    3689           0 :                 if (!allocated(DaySPValues)) {
    3690           0 :                     DaySPValues.allocate(state.dataGlobal->NumOfTimeStepInHour, 24);
    3691             :                 }
    3692           0 :                 if (state.dataHVACGlobal->OptStartData.ActualZoneNum(ActualZoneNum) == ActualZoneNum) {
    3693           0 :                     ScheduleManager::GetScheduleValuesForDay(state, SetPointTempSchedIndexCold, DaySPValues);
    3694           0 :                     OccStartTime = CEILING(state.dataHVACGlobal->OptStartData.OccStartTime(ActualZoneNum)) + 1;
    3695           0 :                     TempZoneThermostatSetPoint(ActualZoneNum) = DaySPValues(1, OccStartTime);
    3696             :                 }
    3697             : 
    3698           0 :                 if (state.dataHVACGlobal->OptStartData.OptStartFlag(ActualZoneNum)) {
    3699           0 :                     ZoneThermostatSetPointHi(ActualZoneNum) = TempZoneThermostatSetPoint(ActualZoneNum);
    3700           0 :                     ZoneThermostatSetPointLo(ActualZoneNum) = TempZoneThermostatSetPoint(ActualZoneNum);
    3701             :                 }
    3702             :             }
    3703             :             //--------------------------------------------------------------------------------------------
    3704       79254 :             break;
    3705    12146573 :         case DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand:
    3706    12146573 :             SetPointTempSchedIndexHot = TempControlledZone(RelativeZoneNum).SchIndx_DualSetPointWDeadBandHeat;
    3707    12146573 :             SetPointTempSchedIndexCold = TempControlledZone(RelativeZoneNum).SchIndx_DualSetPointWDeadBandCool;
    3708             : 
    3709    12146573 :             ZoneThermostatSetPointHi(ActualZoneNum) = ScheduleManager::GetCurrentScheduleValue(state, SetPointTempSchedIndexCold);
    3710    12146573 :             TempControlledZone(RelativeZoneNum).ZoneThermostatSetPointHi = ZoneThermostatSetPointHi(ActualZoneNum);
    3711             : 
    3712             :             // Added Jan 17 (X. Luo)
    3713             :             // Adjust operative temperature based on adaptive comfort model
    3714    12146573 :             if ((TempControlledZone(RelativeZoneNum).AdaptiveComfortTempControl)) {
    3715          15 :                 AdjustOperativeSetPointsforAdapComfort(state, RelativeZoneNum, ZoneThermostatSetPointHi(ActualZoneNum));
    3716          15 :                 state.dataHeatBalFanSys->AdapComfortCoolingSetPoint(ActualZoneNum) = ZoneThermostatSetPointHi(ActualZoneNum);
    3717             :             }
    3718             : 
    3719    12146573 :             AdjustAirSetPointsforOpTempCntrl(state, RelativeZoneNum, ActualZoneNum, ZoneThermostatSetPointHi(ActualZoneNum));
    3720             : 
    3721    12146573 :             ZoneThermostatSetPointLo(ActualZoneNum) = ScheduleManager::GetCurrentScheduleValue(state, SetPointTempSchedIndexHot);
    3722    12146573 :             TempControlledZone(RelativeZoneNum).ZoneThermostatSetPointLo = ZoneThermostatSetPointLo(ActualZoneNum);
    3723    12146573 :             AdjustAirSetPointsforOpTempCntrl(state, RelativeZoneNum, ActualZoneNum, ZoneThermostatSetPointLo(ActualZoneNum));
    3724             : 
    3725             :             // Change the room set point to occupied set point during optimum start period--------------
    3726             : 
    3727    12146573 :             if (allocated(state.dataHVACGlobal->OptStartData.OptStartFlag)) {
    3728       36848 :                 if (!allocated(DaySPValues)) {
    3729        2303 :                     DaySPValues.allocate(state.dataGlobal->NumOfTimeStepInHour, 24);
    3730             :                 }
    3731       36848 :                 if (state.dataHVACGlobal->OptStartData.ActualZoneNum(ActualZoneNum) == ActualZoneNum) {
    3732       11515 :                     ScheduleManager::GetScheduleValuesForDay(state, SetPointTempSchedIndexCold, DaySPValues);
    3733       11515 :                     OccStartTime = CEILING(state.dataHVACGlobal->OptStartData.OccStartTime(ActualZoneNum)) + 1;
    3734       11515 :                     state.dataZoneCtrls->OccRoomTSetPointCool(ActualZoneNum) = DaySPValues(1, OccStartTime);
    3735       11515 :                     ScheduleManager::GetScheduleValuesForDay(state, SetPointTempSchedIndexHot, DaySPValues);
    3736       11515 :                     state.dataZoneCtrls->OccRoomTSetPointHeat(ActualZoneNum) = DaySPValues(1, OccStartTime);
    3737             :                 }
    3738             : 
    3739       36848 :                 if (state.dataHVACGlobal->OptStartData.OptStartFlag(ActualZoneNum)) {
    3740        1740 :                     ZoneThermostatSetPointHi(ActualZoneNum) = state.dataZoneCtrls->OccRoomTSetPointCool(ActualZoneNum);
    3741        1740 :                     ZoneThermostatSetPointLo(ActualZoneNum) = state.dataZoneCtrls->OccRoomTSetPointHeat(ActualZoneNum);
    3742             :                 }
    3743             :             }
    3744             :             //--------------------------------------------------------------------------------------------
    3745             : 
    3746    12146573 :             AdjustCoolingSetPointforTempAndHumidityControl(state, RelativeZoneNum, ActualZoneNum);
    3747    12146573 :             break;
    3748           0 :         default:
    3749           0 :             ShowSevereError(state,
    3750           0 :                             format("CalcZoneAirTempSetpoints: Illegal control type for Zone={}, Found value={}, in Schedule={}",
    3751           0 :                                    Zone(ActualZoneNum).Name,
    3752             :                                    TempControlType(ActualZoneNum),
    3753           0 :                                    TempControlledZone(RelativeZoneNum).ControlTypeSchedName));
    3754             : 
    3755           0 :             break;
    3756             :         }
    3757             : 
    3758             :         // Apply offset for faulty therostats
    3759    15640660 :         if ((state.dataFaultsMgr->NumFaultyThermostat > 0) && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) &&
    3760        4608 :             (!state.dataGlobal->KickOffSimulation)) {
    3761             :             //  loop through the FaultsThermostatOffset objects to find the one for the zone
    3762       34848 :             for (int iFault = 1; iFault <= state.dataFaultsMgr->NumFaultyThermostat; ++iFault) {
    3763             : 
    3764       34848 :                 if (UtilityRoutines::SameString(TempControlledZone(RelativeZoneNum).Name,
    3765       34848 :                                                 state.dataFaultsMgr->FaultsThermostatOffset(iFault).FaultyThermostatName)) {
    3766             : 
    3767             :                     // Check fault availability schedules
    3768        4608 :                     if (ScheduleManager::GetCurrentScheduleValue(state, state.dataFaultsMgr->FaultsThermostatOffset(iFault).AvaiSchedPtr) > 0.0) {
    3769             : 
    3770             :                         // Check fault severity schedules to update the reference thermostat offset
    3771        4608 :                         double rSchVal = 1.0;
    3772             :                         double offsetUpdated;
    3773        4608 :                         if (state.dataFaultsMgr->FaultsThermostatOffset(iFault).SeveritySchedPtr >= 0) {
    3774           0 :                             rSchVal =
    3775           0 :                                 ScheduleManager::GetCurrentScheduleValue(state, state.dataFaultsMgr->FaultsThermostatOffset(iFault).SeveritySchedPtr);
    3776             :                         }
    3777        4608 :                         offsetUpdated = rSchVal * state.dataFaultsMgr->FaultsThermostatOffset(iFault).Offset;
    3778             : 
    3779             :                         // Positive offset means the sensor reading is higher than the actual value
    3780        4608 :                         TempZoneThermostatSetPoint(ActualZoneNum) -= offsetUpdated;
    3781        4608 :                         ZoneThermostatSetPointLo(ActualZoneNum) -= offsetUpdated;
    3782        4608 :                         ZoneThermostatSetPointHi(ActualZoneNum) -= offsetUpdated;
    3783             :                     }
    3784             : 
    3785             :                     // Stop searching the FaultsThermostatOffset object for the zone
    3786        4608 :                     break;
    3787             :                 }
    3788             :             }
    3789             :         }
    3790             :     }
    3791             : 
    3792     2568551 :     if (state.dataZoneCtrls->NumComfortControlledZones > 0) CalcZoneAirComfortSetPoints(state);
    3793     2568551 :     OverrideAirSetPointsforEMSCntrl(state);
    3794     2568551 : }
    3795             : 
    3796    27959531 : void ZoneSpaceHeatBalanceData::calcPredictedHumidityRatio(EnergyPlusData &state, Real64 const RAFNFrac, int const zoneNum, int const spaceNum)
    3797             : {
    3798             : 
    3799             :     // SUBROUTINE INFORMATION:
    3800             :     //       AUTHOR         Richard J. Liesen
    3801             :     //       DATE WRITTEN   May 2001
    3802             : 
    3803             :     // PURPOSE OF THIS SUBROUTINE:
    3804             :     // This subroutine does the prediction step for humidity control
    3805             : 
    3806             :     // METHODOLOGY EMPLOYED:
    3807             :     // This solves for the required system moisture required to try and achieve the desired
    3808             :     // Humidity Ratio in the Zone
    3809             : 
    3810             :     // REFERENCES:
    3811             :     // Routine FinalZnCalcs - FINAL ZONE CALCULATIONS, authored by Dale Herron
    3812             :     // for BLAST.
    3813             : 
    3814             :     static constexpr std::string_view RoutineName("calcPredictedHumidityRatio");
    3815             : 
    3816    27959531 :     Real64 ZoneRHHumidifyingSetPoint = 0.0;   // Zone humidifying set point (%)
    3817    27959531 :     Real64 ZoneRHDehumidifyingSetPoint = 0.0; // Zone dehumidifying set point (%)
    3818             : 
    3819    27959531 :     auto &thisZone = state.dataHeatBal->Zone(zoneNum);
    3820    27959531 :     bool SingleSetPoint = false; // This determines whether both setpoint are equal or not
    3821             : 
    3822             :     // Check to see if this is a "humidity controlled zone"
    3823    27959531 :     bool ControlledHumidZoneFlag = false;
    3824             :     // Check all the controlled zones to see if it matches the zone simulated
    3825    27959531 :     if (thisZone.humidityControlZoneIndex > 0) {
    3826     1004382 :         auto &humidityControlZone = state.dataZoneCtrls->HumidityControlZone(thisZone.humidityControlZoneIndex);
    3827     1004382 :         assert(humidityControlZone.ActualZoneNum == zoneNum);
    3828     1004382 :         ZoneRHHumidifyingSetPoint = ScheduleManager::GetCurrentScheduleValue(state, humidityControlZone.HumidifyingSchedIndex);
    3829     1004382 :         ZoneRHDehumidifyingSetPoint = ScheduleManager::GetCurrentScheduleValue(state, humidityControlZone.DehumidifyingSchedIndex);
    3830             : 
    3831             :         // Apply EMS values to overwrite the humidistat values
    3832     1004382 :         if (humidityControlZone.EMSOverrideHumidifySetPointOn) {
    3833           0 :             ZoneRHHumidifyingSetPoint = humidityControlZone.EMSOverrideHumidifySetPointValue;
    3834             :         }
    3835     1004382 :         if (humidityControlZone.EMSOverrideDehumidifySetPointOn) {
    3836           0 :             ZoneRHDehumidifyingSetPoint = humidityControlZone.EMSOverrideDehumidifySetPointValue;
    3837             :         }
    3838             : 
    3839             :         // Apply offsets for faulty humidistats
    3840     1005018 :         if ((state.dataFaultsMgr->NumFaultyHumidistat > 0) && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) &&
    3841         636 :             (!state.dataGlobal->KickOffSimulation)) {
    3842             : 
    3843             :             //  loop through the FaultsHumidistatOffset objects to find the one for the zone
    3844         636 :             for (int iFault = 1; iFault <= state.dataFaultsMgr->NumFaultyHumidistat; ++iFault) {
    3845             : 
    3846         636 :                 if (UtilityRoutines::SameString(humidityControlZone.ControlName,
    3847         636 :                                                 state.dataFaultsMgr->FaultsHumidistatOffset(iFault).FaultyHumidistatName)) {
    3848             : 
    3849         636 :                     if (UtilityRoutines::SameString(state.dataFaultsMgr->FaultsHumidistatOffset(iFault).FaultyHumidistatType,
    3850         636 :                                                     "ThermostatOffsetDependent")) {
    3851             :                         // For Humidistat Offset Type I: ThermostatOffsetDependent
    3852             : 
    3853         316 :                         bool IsThermostatFound = false;
    3854         316 :                         double offsetThermostat = 0.0;
    3855         316 :                         double offsetZoneRHHumidifyingSetPoint = 0.0;
    3856         316 :                         double offsetZoneRHDehumidifyingSetPoint = 0.0;
    3857             :                         double faultZoneWHumidifyingSetPoint;
    3858             :                         double faultZoneWDehumidifyingSetPoint;
    3859             : 
    3860             :                         // Get the offset value of the corresponding thermostat fault object
    3861         316 :                         if (state.dataFaultsMgr->NumFaultyThermostat > 0) {
    3862             : 
    3863             :                             //  loop through the FaultsThermostatOffset objects to find the one causes the Humidistat Offset
    3864         316 :                             for (int iFaultThermo = 1; iFaultThermo <= state.dataFaultsMgr->NumFaultyThermostat; ++iFaultThermo) {
    3865             : 
    3866         316 :                                 if (UtilityRoutines::SameString(state.dataFaultsMgr->FaultsHumidistatOffset(iFault).FaultyThermostatName,
    3867         316 :                                                                 state.dataFaultsMgr->FaultsThermostatOffset(iFaultThermo).Name)) {
    3868         316 :                                     IsThermostatFound = true;
    3869             : 
    3870             :                                     // Check fault availability schedules
    3871         632 :                                     if (ScheduleManager::GetCurrentScheduleValue(
    3872         632 :                                             state, state.dataFaultsMgr->FaultsThermostatOffset(iFaultThermo).AvaiSchedPtr) > 0.0) {
    3873             : 
    3874             :                                         // Check fault severity schedules to update the reference thermostat offset
    3875         316 :                                         double rSchVal = 1.0;
    3876         316 :                                         if (state.dataFaultsMgr->FaultsThermostatOffset(iFaultThermo).SeveritySchedPtr >= 0) {
    3877           0 :                                             rSchVal = ScheduleManager::GetCurrentScheduleValue(
    3878           0 :                                                 state, state.dataFaultsMgr->FaultsThermostatOffset(iFaultThermo).SeveritySchedPtr);
    3879             :                                         }
    3880         316 :                                         offsetThermostat = rSchVal * state.dataFaultsMgr->FaultsThermostatOffset(iFaultThermo).Offset;
    3881             :                                     }
    3882             : 
    3883             :                                     // Stop searching the FaultsThermostatOffset object for the Humidistat Offset
    3884         316 :                                     break;
    3885             :                                 }
    3886             :                             }
    3887             :                         }
    3888             : 
    3889             :                         // The FaultsThermostatOffset specified in the FaultHumidistatOffset is not found
    3890         316 :                         if (!IsThermostatFound) {
    3891           0 :                             ShowSevereError(state,
    3892           0 :                                             "FaultModel:HumidistatOffset = \"" + state.dataFaultsMgr->FaultsHumidistatOffset(iFault).Name +
    3893           0 :                                                 "\" invalid Reference Humidistat Offset Name = \"" +
    3894           0 :                                                 state.dataFaultsMgr->FaultsHumidistatOffset(iFault).FaultyThermostatName + "\" not found.");
    3895           0 :                             ShowFatalError(state, "Errors getting FaultModel input data.  Preceding condition(s) cause termination.");
    3896             :                         }
    3897             : 
    3898         316 :                         if (offsetThermostat != 0.0) {
    3899             :                             // Calculate the humidistat offset value from the thermostat offset value
    3900         632 :                             faultZoneWHumidifyingSetPoint = Psychrometrics::PsyWFnTdbRhPb(
    3901         632 :                                 state, (this->MAT + offsetThermostat), (ZoneRHHumidifyingSetPoint / 100.0), state.dataEnvrn->OutBaroPress);
    3902         632 :                             faultZoneWDehumidifyingSetPoint = Psychrometrics::PsyWFnTdbRhPb(
    3903         632 :                                 state, (this->MAT + offsetThermostat), (ZoneRHDehumidifyingSetPoint / 100.0), state.dataEnvrn->OutBaroPress);
    3904         316 :                             offsetZoneRHHumidifyingSetPoint =
    3905         316 :                                 ZoneRHHumidifyingSetPoint -
    3906         632 :                                 Psychrometrics::PsyRhFnTdbWPb(state, this->MAT, faultZoneWHumidifyingSetPoint, state.dataEnvrn->OutBaroPress) * 100.0;
    3907         316 :                             offsetZoneRHDehumidifyingSetPoint =
    3908         316 :                                 ZoneRHDehumidifyingSetPoint -
    3909         632 :                                 Psychrometrics::PsyRhFnTdbWPb(state, this->MAT, faultZoneWDehumidifyingSetPoint, state.dataEnvrn->OutBaroPress) *
    3910             :                                     100.0;
    3911             : 
    3912             :                             // Apply the calculated humidistat offset value
    3913             :                             // Positive offset means the sensor reading is higher than the actual value
    3914         316 :                             ZoneRHHumidifyingSetPoint -= offsetZoneRHHumidifyingSetPoint;
    3915         316 :                             ZoneRHDehumidifyingSetPoint -= offsetZoneRHDehumidifyingSetPoint;
    3916             : 
    3917             :                             // constrain value to something reasonable
    3918         316 :                             ZoneRHHumidifyingSetPoint = min(100.0, max(0.0, ZoneRHHumidifyingSetPoint));
    3919         316 :                             ZoneRHDehumidifyingSetPoint = min(100.0, max(0.0, ZoneRHDehumidifyingSetPoint));
    3920             :                         }
    3921             : 
    3922             :                     } else {
    3923             :                         // For Humidistat Offset Type II: ThermostatOffsetIndependent
    3924             : 
    3925             :                         // Check fault availability schedules
    3926         320 :                         if (ScheduleManager::GetCurrentScheduleValue(state, state.dataFaultsMgr->FaultsHumidistatOffset(iFault).AvaiSchedPtr) > 0.0) {
    3927             : 
    3928             :                             // Check fault severity schedules to update the reference humidistat offset
    3929         320 :                             double rSchVal = 1.0;
    3930             :                             double offsetUpdated;
    3931         320 :                             if (state.dataFaultsMgr->FaultsHumidistatOffset(iFault).SeveritySchedPtr >= 0) {
    3932           0 :                                 rSchVal = ScheduleManager::GetCurrentScheduleValue(
    3933           0 :                                     state, state.dataFaultsMgr->FaultsHumidistatOffset(iFault).SeveritySchedPtr);
    3934             :                             }
    3935         320 :                             offsetUpdated = rSchVal * state.dataFaultsMgr->FaultsHumidistatOffset(iFault).Offset;
    3936             : 
    3937             :                             // Positive offset means the sensor reading is higher than the actual value
    3938         320 :                             ZoneRHHumidifyingSetPoint -= offsetUpdated;
    3939         320 :                             ZoneRHDehumidifyingSetPoint -= offsetUpdated;
    3940             : 
    3941             :                             // constrain value to something reasonable
    3942         320 :                             ZoneRHHumidifyingSetPoint = min(100.0, max(0.0, ZoneRHHumidifyingSetPoint));
    3943         320 :                             ZoneRHDehumidifyingSetPoint = min(100.0, max(0.0, ZoneRHDehumidifyingSetPoint));
    3944             :                         }
    3945             :                     }
    3946         636 :                     break;
    3947             :                 }
    3948             :             }
    3949             :         }
    3950             : 
    3951             :         // Run-time error check
    3952     1004382 :         if (ZoneRHHumidifyingSetPoint > ZoneRHDehumidifyingSetPoint) {
    3953           0 :             if (humidityControlZone.ErrorIndex == 0) {
    3954           0 :                 ShowWarningMessage(state,
    3955           0 :                                    "HUMIDISTAT: The humidifying setpoint is above the dehumidifying setpoint in " + humidityControlZone.ControlName);
    3956           0 :                 ShowContinueError(state, "The zone humidifying setpoint is set to the dehumidifying setpoint.");
    3957           0 :                 ShowContinueErrorTimeStamp(state, "Occurrence info:");
    3958             :             }
    3959           0 :             ShowRecurringWarningErrorAtEnd(state,
    3960             :                                            "The humidifying setpoint is still above the dehumidifying setpoint",
    3961             :                                            humidityControlZone.ErrorIndex,
    3962             :                                            ZoneRHHumidifyingSetPoint,
    3963             :                                            ZoneRHHumidifyingSetPoint);
    3964           0 :             ZoneRHHumidifyingSetPoint = ZoneRHDehumidifyingSetPoint;
    3965             :         }
    3966     1004382 :         if (ZoneRHHumidifyingSetPoint == ZoneRHDehumidifyingSetPoint) SingleSetPoint = true;
    3967     1004382 :         ControlledHumidZoneFlag = true;
    3968             : 
    3969             :     } // HumidControlledZoneNum
    3970             : 
    3971             :     // if zone latent sizing is requested but no humidistat exists
    3972    27959531 :     if (state.dataGlobal->DoingSizing && !ControlledHumidZoneFlag && state.dataHeatBal->DoLatentSizing) {
    3973       43524 :         for (size_t zoneEqConfigNum = 1; zoneEqConfigNum <= state.dataZoneEquip->ZoneEquipConfig.size(); ++zoneEqConfigNum) {
    3974       43524 :             auto &zoneEqConfig = state.dataZoneEquip->ZoneEquipConfig(zoneEqConfigNum);
    3975       43524 :             if (!zoneEqConfig.IsControlled) continue;
    3976             :             int ZoneSizNum =
    3977       23826 :                 UtilityRoutines::FindItemInList(zoneEqConfig.ZoneName, state.dataSize->ZoneSizingInput, &DataSizing::ZoneSizingInputData::ZoneName);
    3978             :             // should use the first Sizing:Zone object if not found
    3979       23826 :             if (ZoneSizNum == 0 && !state.dataSize->ZoneSizingInput.empty()) ZoneSizNum = 1;
    3980       23826 :             if (ZoneSizNum > 0) {
    3981       23826 :                 auto &zoneSizingInput = state.dataSize->ZoneSizingInput(ZoneSizNum);
    3982       23826 :                 if (zoneSizingInput.zoneLatentSizing) {
    3983       47652 :                     ZoneRHDehumidifyingSetPoint = (zoneSizingInput.zoneRHDehumidifySchIndex)
    3984       23826 :                                                       ? ScheduleManager::GetCurrentScheduleValue(state, zoneSizingInput.zoneRHDehumidifySchIndex)
    3985             :                                                       : zoneSizingInput.zoneRHDehumidifySetPoint;
    3986       47652 :                     ZoneRHHumidifyingSetPoint = (zoneSizingInput.zoneRHHumidifySchIndex)
    3987       23826 :                                                     ? ScheduleManager::GetCurrentScheduleValue(state, zoneSizingInput.zoneRHHumidifySchIndex)
    3988             :                                                     : zoneSizingInput.zoneRHHumidifySetPoint;
    3989       23826 :                     if (ZoneRHHumidifyingSetPoint > ZoneRHDehumidifyingSetPoint) ZoneRHHumidifyingSetPoint = ZoneRHDehumidifyingSetPoint;
    3990       23826 :                     if (ZoneRHHumidifyingSetPoint == ZoneRHDehumidifyingSetPoint) SingleSetPoint = true;
    3991       23826 :                     ControlledHumidZoneFlag = true;
    3992             :                 }
    3993             :             }
    3994       23826 :             break;
    3995             :         }
    3996             :     }
    3997             : 
    3998    27959531 :     Real64 LoadToHumidifySetPoint = 0.0;   // Moisture load at humidifying set point
    3999    27959531 :     Real64 LoadToDehumidifySetPoint = 0.0; // Moisture load at dehumidifying set point
    4000    27959531 :     Real64 totalOutputRequired = 0.0;
    4001    27959531 :     if (ControlledHumidZoneFlag) {
    4002             : 
    4003             :         // Calculate hourly humidity ratio from infiltration + humidity added from latent load
    4004             :         // to determine system added/subtracted moisture.
    4005             :         Real64 LatentGain =
    4006     1028208 :             this->ZoneLatentGain + state.dataHeatBalFanSys->SumLatentHTRadSys(zoneNum) + state.dataHeatBalFanSys->SumLatentPool(zoneNum);
    4007             : 
    4008     1028208 :         Real64 SysTimeStepInSeconds = DataGlobalConstants::SecInHour * state.dataHVACGlobal->TimeStepSys;
    4009             : 
    4010             :         // Calculate the coefficients for the 3rd Order derivative for final
    4011             :         // zone humidity ratio.  The A, B, C coefficients are analogous to the heat balance.
    4012             :         // SumHmARaW and SumHmARa will be used with the Moisture Balance on the building elements and
    4013             :         // are currently set to zero when the CTF only version is used.
    4014             : 
    4015             :         // The density of air and latent heat of vaporization are calculated as functions.
    4016     1028208 :         Real64 RhoAir = Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, this->ZT, this->ZoneAirHumRat, RoutineName);
    4017     1028208 :         Real64 H2OHtOfVap = Psychrometrics::PsyHgAirFnWTdb(this->ZoneAirHumRat, this->ZT);
    4018             : 
    4019             :         // Assume that the system will have flow
    4020     1028208 :         Real64 A = 0.0;
    4021     1028208 :         Real64 B = 0.0;
    4022     1028208 :         Real64 C = 0.0;
    4023     2056416 :         if (state.afn->multizone_always_simulated ||
    4024      986677 :             (state.afn->simulation_control.type == AirflowNetwork::ControlType::MultizoneWithDistributionOnlyDuringFanOperation &&
    4025           0 :              state.afn->AirflowNetworkFanActivated)) {
    4026             :             // Multizone airflow calculated in AirflowNetwork
    4027       41531 :             B = (LatentGain / H2OHtOfVap) + state.afn->exchangeData(zoneNum).SumMHrW + state.afn->exchangeData(zoneNum).SumMMHrW + this->SumHmARaW;
    4028       41531 :             A = state.afn->exchangeData(zoneNum).SumMHr + state.afn->exchangeData(zoneNum).SumMMHr + this->SumHmARa;
    4029             :         } else {
    4030     2960031 :             B = (LatentGain / H2OHtOfVap) + ((this->OAMFL + this->VAMFL + this->CTMFL) * state.dataEnvrn->OutHumRat) + this->EAMFLxHumRat +
    4031     1973354 :                 this->SumHmARaW + this->MixingMassFlowXHumRat + this->MDotOA * state.dataEnvrn->OutHumRat;
    4032      986677 :             A = this->OAMFL + this->VAMFL + this->EAMFL + this->CTMFL + this->SumHmARa + this->MixingMassFlowZone + this->MDotOA;
    4033             :         }
    4034     1028208 :         Real64 volume = 0.0;
    4035     1028208 :         if (spaceNum > 0) {
    4036           0 :             volume = state.dataHeatBal->space(spaceNum).Volume;
    4037             :         } else {
    4038     1028208 :             volume = thisZone.Volume;
    4039             :         }
    4040     1028208 :         C = RhoAir * volume * thisZone.ZoneVolCapMultpMoist / SysTimeStepInSeconds;
    4041             : 
    4042     1028208 :         if (state.dataRoomAirMod->AirModel(zoneNum).AirModelType == DataRoomAirModel::RoomAirModel::AirflowNetwork) {
    4043           0 :             auto &roomAFNInfo = state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum);
    4044           0 :             int RoomAirNode = roomAFNInfo.ControlAirNodeID;
    4045           0 :             H2OHtOfVap = Psychrometrics::PsyHgAirFnWTdb(roomAFNInfo.Node(RoomAirNode).HumRat, roomAFNInfo.Node(RoomAirNode).AirTemp);
    4046           0 :             A = roomAFNInfo.Node(RoomAirNode).SumLinkM + roomAFNInfo.Node(RoomAirNode).SumHmARa;
    4047           0 :             B = (roomAFNInfo.Node(RoomAirNode).SumIntLatentGain / H2OHtOfVap) + roomAFNInfo.Node(RoomAirNode).SumLinkMW +
    4048           0 :                 roomAFNInfo.Node(RoomAirNode).SumHmARaW;
    4049           0 :             C = roomAFNInfo.Node(RoomAirNode).RhoAir * roomAFNInfo.Node(RoomAirNode).AirVolume * thisZone.ZoneVolCapMultpMoist /
    4050           0 :                 (DataGlobalConstants::SecInHour * state.dataHVACGlobal->TimeStepSys);
    4051             :         }
    4052             : 
    4053             :         // Use a 3rd Order derivative to predict zone moisture addition or removal and
    4054             :         // smooth the changes using the zone air capacitance.  Positive values of Moist Load means that
    4055             :         // this amount of moisture must be added to the zone to reach the setpoint.  Negative values represent
    4056             :         // the amount of moisture that must be removed by the system.
    4057             :         // MoistLoadHumidSetPoint = massflow * HumRat = kgDryAir/s * kgWater/kgDryAir = kgWater/s
    4058             :         Real64 WZoneSetPoint =
    4059     1028208 :             Psychrometrics::PsyWFnTdbRhPb(state, this->ZT, (ZoneRHHumidifyingSetPoint / 100.0), state.dataEnvrn->OutBaroPress, RoutineName);
    4060     1028208 :         Real64 exp_700_A_C(0.0);
    4061     1028208 :         if (state.dataHeatBal->ZoneAirSolutionAlgo == DataHeatBalance::SolutionAlgo::ThirdOrder) {
    4062      911700 :             LoadToHumidifySetPoint =
    4063     1823400 :                 ((11.0 / 6.0) * C + A) * WZoneSetPoint -
    4064      911700 :                 (B + C * (3.0 * this->WPrevZoneTSTemp[0] - (3.0 / 2.0) * this->WPrevZoneTSTemp[1] + (1.0 / 3.0) * this->WPrevZoneTSTemp[2]));
    4065             :             // Exact solution
    4066      116508 :         } else if (state.dataHeatBal->ZoneAirSolutionAlgo == DataHeatBalance::SolutionAlgo::AnalyticalSolution) {
    4067      116508 :             if (A == 0.0) { // B=0
    4068       14018 :                 LoadToHumidifySetPoint = C * (WZoneSetPoint - this->ZoneW1) - B;
    4069             :             } else {
    4070      102490 :                 exp_700_A_C = std::exp(min(700.0, -A / C)); // Tuned Save expensive value
    4071      102490 :                 LoadToHumidifySetPoint = A * (WZoneSetPoint - this->ZoneW1 * exp_700_A_C) / (1.0 - exp_700_A_C) - B;
    4072             :             }
    4073           0 :         } else if (state.dataHeatBal->ZoneAirSolutionAlgo == DataHeatBalance::SolutionAlgo::EulerMethod) {
    4074           0 :             LoadToHumidifySetPoint = C * (WZoneSetPoint - this->ZoneW1) + A * WZoneSetPoint - B;
    4075             :         }
    4076     1028208 :         if (RAFNFrac > 0.0) LoadToHumidifySetPoint = LoadToHumidifySetPoint / RAFNFrac;
    4077     1028208 :         WZoneSetPoint =
    4078     1028208 :             Psychrometrics::PsyWFnTdbRhPb(state, this->ZT, (ZoneRHDehumidifyingSetPoint / 100.0), state.dataEnvrn->OutBaroPress, RoutineName);
    4079     1028208 :         if (state.dataHeatBal->ZoneAirSolutionAlgo == DataHeatBalance::SolutionAlgo::ThirdOrder) {
    4080      911700 :             LoadToDehumidifySetPoint =
    4081     1823400 :                 ((11.0 / 6.0) * C + A) * WZoneSetPoint -
    4082      911700 :                 (B + C * (3.0 * this->WPrevZoneTSTemp[0] - (3.0 / 2.0) * this->WPrevZoneTSTemp[1] + (1.0 / 3.0) * this->WPrevZoneTSTemp[2]));
    4083             :             // Exact solution
    4084      116508 :         } else if (state.dataHeatBal->ZoneAirSolutionAlgo == DataHeatBalance::SolutionAlgo::AnalyticalSolution) {
    4085      116508 :             if (A == 0.0) { // B=0
    4086       14018 :                 LoadToDehumidifySetPoint = C * (WZoneSetPoint - this->ZoneW1) - B;
    4087             :             } else {
    4088      102490 :                 LoadToDehumidifySetPoint = A * (WZoneSetPoint - this->ZoneW1 * exp_700_A_C) / (1.0 - exp_700_A_C) - B; // exp_700_A_C set above
    4089             :             }
    4090           0 :         } else if (state.dataHeatBal->ZoneAirSolutionAlgo == DataHeatBalance::SolutionAlgo::EulerMethod) {
    4091           0 :             LoadToDehumidifySetPoint = C * (WZoneSetPoint - this->ZoneW1) + A * WZoneSetPoint - B;
    4092             :         }
    4093     1028208 :         if (RAFNFrac > 0.0) LoadToDehumidifySetPoint = LoadToDehumidifySetPoint / RAFNFrac;
    4094             : 
    4095             :         // The load is added to the TotalOutputRequired as in the Temperature Predictor.  There is also the remaining
    4096             :         // output variable for those who will use this for humidity control and stored in DataZoneEnergyDemands with the
    4097             :         // analogous temperature terms.
    4098             : 
    4099     1028208 :         if (SingleSetPoint) {
    4100      648032 :             totalOutputRequired = LoadToHumidifySetPoint;
    4101             :         } else {
    4102      380176 :             if (LoadToHumidifySetPoint > 0.0 && LoadToDehumidifySetPoint > 0.0) {
    4103       76045 :                 totalOutputRequired = LoadToHumidifySetPoint;
    4104      304131 :             } else if (LoadToHumidifySetPoint < 0.0 && LoadToDehumidifySetPoint < 0.0) {
    4105      116093 :                 totalOutputRequired = LoadToDehumidifySetPoint;
    4106      188038 :             } else if (LoadToHumidifySetPoint <= 0.0 && LoadToDehumidifySetPoint >= 0.0) { // deadband includes zero loads
    4107      188038 :                 totalOutputRequired = 0.0;
    4108             :             } else { // this should never occur!
    4109           0 :                 ShowSevereError(
    4110             :                     state, "Humidistat: Unanticipated combination of humidifying and dehumidifying loads - report to EnergyPlus Development Team");
    4111           0 :                 ShowContinueErrorTimeStamp(state, format("occurs in Zone = {}", thisZone.Name));
    4112           0 :                 ShowContinueError(
    4113             :                     state,
    4114           0 :                     format("LoadToHumidifySetPoint={:.5R}, LoadToDehumidifySetPoint={:.5R}", LoadToHumidifySetPoint, LoadToDehumidifySetPoint));
    4115           0 :                 ShowContinueError(state, format("Zone RH Humidifying Set-point={:.1R}", ZoneRHHumidifyingSetPoint));
    4116           0 :                 ShowContinueError(state, format("Zone RH Dehumidifying Set-point={:.2R}", ZoneRHDehumidifyingSetPoint));
    4117           0 :                 ShowFatalError(state, "Program terminates due to above conditions.");
    4118             :             }
    4119             :         }
    4120             :     }
    4121             : 
    4122             :     // Apply zone multipliers as needed or set to zero
    4123    27959531 :     if (spaceNum > 0) {
    4124       30012 :         auto &thisspaceSysMoistureDemand = state.dataZoneEnergyDemand->spaceSysMoistureDemand(spaceNum);
    4125       30012 :         if (ControlledHumidZoneFlag) {
    4126           0 :             thisspaceSysMoistureDemand.reportMoistLoadsZoneMultiplier(
    4127             :                 state, zoneNum, totalOutputRequired, LoadToHumidifySetPoint, LoadToDehumidifySetPoint);
    4128             :         } else {
    4129       30012 :             thisspaceSysMoistureDemand.TotalOutputRequired = 0.0;
    4130       30012 :             thisspaceSysMoistureDemand.OutputRequiredToDehumidifyingSP = 0.0;
    4131       30012 :             thisspaceSysMoistureDemand.OutputRequiredToHumidifyingSP = 0.0;
    4132             :         }
    4133             :     } else {
    4134    27929519 :         auto &thisZoneSysMoistureDemand = state.dataZoneEnergyDemand->ZoneSysMoistureDemand(zoneNum);
    4135    27929519 :         if (ControlledHumidZoneFlag) {
    4136     1028208 :             thisZoneSysMoistureDemand.reportMoistLoadsZoneMultiplier(
    4137             :                 state, zoneNum, totalOutputRequired, LoadToHumidifySetPoint, LoadToDehumidifySetPoint);
    4138             :         } else {
    4139    26901311 :             thisZoneSysMoistureDemand.TotalOutputRequired = 0.0;
    4140    26901311 :             thisZoneSysMoistureDemand.OutputRequiredToDehumidifyingSP = 0.0;
    4141    26901311 :             thisZoneSysMoistureDemand.OutputRequiredToHumidifyingSP = 0.0;
    4142             :         }
    4143             :     }
    4144    27959531 : }
    4145             : 
    4146     3623760 : Real64 correctZoneAirTemps(EnergyPlusData &state,
    4147             :                            bool useZoneTimeStepHistory // if true then use zone timestep history, if false use system time step history
    4148             : )
    4149             : {
    4150     3623760 :     Real64 maxTempChange = DataPrecisionGlobals::constant_zero; // Max absolute air temperature change between previous and current timestep
    4151    31551851 :     for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
    4152    27928091 :         Real64 zoneTempChange = state.dataZoneTempPredictorCorrector->zoneHeatBalance(zoneNum).correctAirTemp(state, useZoneTimeStepHistory, zoneNum);
    4153    27928091 :         if (state.dataHeatBal->doSpaceHeatBalance) {
    4154       60024 :             for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
    4155             :                 Real64 spaceTempChange =
    4156       30012 :                     state.dataZoneTempPredictorCorrector->spaceHeatBalance(spaceNum).correctAirTemp(state, useZoneTimeStepHistory, zoneNum, spaceNum);
    4157       30012 :                 maxTempChange = max(maxTempChange, spaceTempChange);
    4158             :             }
    4159             :         }
    4160    27928091 :         maxTempChange = max(maxTempChange, zoneTempChange);
    4161             :     }
    4162     3623760 :     return maxTempChange;
    4163             : }
    4164             : 
    4165    27958103 : Real64 ZoneSpaceHeatBalanceData::correctAirTemp(
    4166             :     EnergyPlusData &state,
    4167             :     bool const useZoneTimeStepHistory, // if true then use zone timestep history, if false use system time step history
    4168             :     int const zoneNum,
    4169             :     int const spaceNum)
    4170             : {
    4171             : 
    4172             :     // SUBROUTINE INFORMATION:
    4173             :     //       AUTHOR         Russell Taylor
    4174             :     //       MODIFIED       November 1999, LKL; November 2016 Sang Hoon Lee, Tianzhen Hong, Rongpeng Zhang;
    4175             :     //       RE-ENGINEERED  July 2003 (Peter Graham Ellis)
    4176             :     //                      February 2008 (Brent Griffith reworked history )
    4177             : 
    4178             :     // PURPOSE OF THIS SUBROUTINE:
    4179             :     // This subroutine updates the zone air temperature and modifies the system
    4180             :     // time step.
    4181             : 
    4182             :     static constexpr std::string_view RoutineName("correctAirTemp");
    4183             : 
    4184    27958103 :     Real64 tempChange = DataPrecisionGlobals::constant_zero; // Zone or space air temperature change between previous and current timestep
    4185             : 
    4186    27958103 :     assert(zoneNum > 0);
    4187    27958103 :     auto &thisZone = state.dataHeatBal->Zone(zoneNum);
    4188             : 
    4189             :     // Update zone temperatures
    4190             : 
    4191    27958103 :     Real64 ZoneMult = thisZone.Multiplier * thisZone.ListMultiplier;
    4192             : 
    4193             :     // update the variables actually used in the balance equations.
    4194    27958103 :     if (!useZoneTimeStepHistory) {
    4195     9488450 :         this->ZTM = this->DSXMAT;
    4196     9488450 :         this->WPrevZoneTSTemp = this->DSWPrevZoneTS;
    4197             :     } else {
    4198    18469653 :         this->ZTM = this->XMAT;
    4199    18469653 :         this->WPrevZoneTSTemp = this->WPrevZoneTS;
    4200             :     }
    4201             : 
    4202    27958103 :     Real64 volume = 0.0;
    4203    27958103 :     if (spaceNum > 0) {
    4204       30012 :         volume = state.dataHeatBal->space(spaceNum).Volume;
    4205             :     } else {
    4206    27928091 :         volume = thisZone.Volume;
    4207             :     }
    4208    83874309 :     this->AirPowerCap = volume * thisZone.ZoneVolCapMultpSens *
    4209    55916206 :                         Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, this->MAT, this->ZoneAirHumRat, RoutineName) *
    4210    55916206 :                         Psychrometrics::PsyCpAirFnW(this->ZoneAirHumRat) / (state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour);
    4211             : 
    4212             :     // SpaceHB TODO: For now, room air model is only for zones
    4213    27958103 :     if (spaceNum == 0) {
    4214    27928091 :         RoomAirModelManager::ManageAirModel(state, zoneNum);
    4215             :     }
    4216             : 
    4217             :     // Calculate the various heat balance sums
    4218    27958103 :     this->calcZoneOrSpaceSums(state, true, zoneNum, spaceNum);
    4219             : 
    4220             :     // Sum all convective internal gains except for people: SumIntGainExceptPeople
    4221    27958103 :     if (state.dataHybridModel->FlagHybridModel_PC) {
    4222             :         // TODO: For now, don't do space heat balance with hybrid model
    4223        8216 :         this->SumIntGainExceptPeople = InternalHeatGains::SumAllInternalConvectionGainsExceptPeople(state, zoneNum);
    4224             :     }
    4225             : 
    4226             :     //    ZoneTempHistoryTerm = (3.0D0 * ZTM1(zoneNum) - (3.0D0/2.0D0) * ZTM2(zoneNum) + (1.0D0/3.0D0) * ZTM3(zoneNum))
    4227    27958103 :     int ZoneNodeNum = thisZone.SystemZoneNodeNumber;
    4228    27958103 :     if (spaceNum > 0) {
    4229       30012 :         ZoneNodeNum = state.dataHeatBal->space(spaceNum).SystemZoneNodeNumber;
    4230             :     }
    4231             : 
    4232    27958103 :     Real64 SNLoad = 0.0;
    4233             : 
    4234    27958103 :     if (ZoneNodeNum > 0) { // This zone is controlled by a zone equipment configuration or zone plenum
    4235    24932253 :         auto &thisSystemNode = state.dataLoopNodes->Node(ZoneNodeNum);
    4236             : 
    4237             :         // Heat balance coefficients for controlled zone, i.e. with system air flow
    4238    24932253 :         this->TempDepCoef = this->SumHA + this->SumMCp + this->SumSysMCp;
    4239    49864506 :         this->TempIndCoef = this->SumIntGain + this->SumHATsurf - this->SumHATref + this->SumMCpT + this->SumSysMCpT +
    4240    24932253 :                             (this->NonAirSystemResponse / ZoneMult + this->SysDepZoneLoadsLagged);
    4241             : 
    4242    24932253 :         if (state.afn->distribution_simulated) {
    4243      244623 :             this->TempIndCoef += state.afn->exchangeData(zoneNum).TotalSen;
    4244             :         }
    4245             : 
    4246             :         // Solve for zone air temperature
    4247    24932253 :         switch (state.dataHeatBal->ZoneAirSolutionAlgo) {
    4248    13465732 :         case DataHeatBalance::SolutionAlgo::ThirdOrder: {
    4249    26931464 :             this->ZT = (this->TempIndCoef + this->AirPowerCap * (3.0 * this->ZTM[0] - (3.0 / 2.0) * this->ZTM[1] + (1.0 / 3.0) * this->ZTM[2])) /
    4250    13465732 :                        ((11.0 / 6.0) * this->AirPowerCap + this->TempDepCoef);
    4251    13465732 :         } break;
    4252    11434919 :         case DataHeatBalance::SolutionAlgo::AnalyticalSolution: {
    4253    11434919 :             if (this->TempDepCoef == 0.0) { // B=0
    4254           0 :                 this->ZT = this->ZoneT1 + this->TempIndCoef / this->AirPowerCap;
    4255             :             } else {
    4256    22869838 :                 this->ZT = (this->ZoneT1 - this->TempIndCoef / this->TempDepCoef) * std::exp(min(700.0, -this->TempDepCoef / this->AirPowerCap)) +
    4257    11434919 :                            this->TempIndCoef / this->TempDepCoef;
    4258             :             }
    4259    11434919 :         } break;
    4260       31602 :         case DataHeatBalance::SolutionAlgo::EulerMethod: {
    4261       31602 :             this->ZT = (this->AirPowerCap * this->ZoneT1 + this->TempIndCoef) / (this->AirPowerCap + this->TempDepCoef);
    4262       31602 :         } break;
    4263           0 :         default:
    4264           0 :             break;
    4265             :         }
    4266             :         // Update zone node temperature and thermostat temperature unless already updated in Room Air Model,
    4267             :         // calculate load correction factor
    4268    24932253 :         if (!state.dataRoomAirMod->anyNonMixingRoomAirModel) {
    4269             :             // Fully mixed
    4270    24823080 :             thisSystemNode.Temp = this->ZT;
    4271             :             // SpaceHB TODO: What to do here if this is for space
    4272    24823080 :             if (spaceNum == 0) {
    4273    24796292 :                 state.dataHeatBalFanSys->TempTstatAir(zoneNum) = this->ZT;
    4274             :             }
    4275    24823080 :             state.dataHeatBalFanSys->LoadCorrectionFactor(zoneNum) = 1.0;
    4276             :         } else {
    4277      109173 :             auto &thisAirModel = state.dataRoomAirMod->AirModel(zoneNum);
    4278      109173 :             if ((thisAirModel.AirModelType == DataRoomAirModel::RoomAirModel::Mixing) || (!thisAirModel.SimAirModel)) {
    4279             :                 // Fully mixed
    4280       41888 :                 thisSystemNode.Temp = this->ZT;
    4281             :                 // SpaceHB TODO: What to do here if this is for space
    4282       41888 :                 if (spaceNum == 0) {
    4283       41888 :                     state.dataHeatBalFanSys->TempTstatAir(zoneNum) = this->ZT;
    4284             :                 }
    4285       41888 :                 state.dataHeatBalFanSys->LoadCorrectionFactor(zoneNum) = 1.0;
    4286       67285 :             } else if (state.dataRoomAirMod->IsZoneDV(zoneNum) || state.dataRoomAirMod->IsZoneUI(zoneNum)) {
    4287             :                 // UCSDDV: Not fully mixed - calculate factor to correct load for fully mixed assumption
    4288             :                 // Space HB TODO: Space HB doesn't mix with DV etc.
    4289       13412 :                 if (this->SumSysMCp > DataHVACGlobals::SmallMassFlow) {
    4290       12551 :                     Real64 TempSupplyAir = this->SumSysMCpT / this->SumSysMCp; // Non-negligible flow, calculate supply air temperature
    4291       12551 :                     if (std::abs(TempSupplyAir - this->ZT) > state.dataHeatBal->TempConvergTol) {
    4292       12283 :                         state.dataHeatBalFanSys->LoadCorrectionFactor(zoneNum) = (TempSupplyAir - thisSystemNode.Temp) / (TempSupplyAir - this->ZT);
    4293             :                         // constrain value to something reasonable
    4294       12283 :                         state.dataHeatBalFanSys->LoadCorrectionFactor(zoneNum) = max(-3.0, state.dataHeatBalFanSys->LoadCorrectionFactor(zoneNum));
    4295       12283 :                         state.dataHeatBalFanSys->LoadCorrectionFactor(zoneNum) = min(3.0, state.dataHeatBalFanSys->LoadCorrectionFactor(zoneNum));
    4296             : 
    4297             :                     } else {
    4298         268 :                         state.dataHeatBalFanSys->LoadCorrectionFactor(zoneNum) = 1.0; // Indeterminate
    4299             :                     }
    4300             :                 } else {
    4301             :                     // Negligible flow, assume mixed - reasonable lagged starting value for first step time with significant flow
    4302         861 :                     state.dataHeatBalFanSys->LoadCorrectionFactor(zoneNum) = 1.0;
    4303             :                 }
    4304       70234 :             } else if (thisAirModel.SimAirModel && ((thisAirModel.AirModelType == DataRoomAirModel::RoomAirModel::UserDefined) ||
    4305       16361 :                                                     (thisAirModel.AirModelType == DataRoomAirModel::RoomAirModel::Mundt))) {
    4306       46184 :                 if (this->SumSysMCp > DataHVACGlobals::SmallMassFlow) {
    4307       45833 :                     Real64 TempSupplyAir = this->SumSysMCpT / this->SumSysMCp; // Non-negligible flow, calculate supply air temperature
    4308       45833 :                     if (std::abs(TempSupplyAir - this->ZT) > state.dataHeatBal->TempConvergTol) {
    4309       45829 :                         state.dataHeatBalFanSys->LoadCorrectionFactor(zoneNum) = (TempSupplyAir - thisSystemNode.Temp) / (TempSupplyAir - this->ZT);
    4310             :                         // constrain value
    4311       45829 :                         state.dataHeatBalFanSys->LoadCorrectionFactor(zoneNum) = max(-3.0, state.dataHeatBalFanSys->LoadCorrectionFactor(zoneNum));
    4312       45829 :                         state.dataHeatBalFanSys->LoadCorrectionFactor(zoneNum) = min(3.0, state.dataHeatBalFanSys->LoadCorrectionFactor(zoneNum));
    4313             : 
    4314             :                     } else {
    4315           4 :                         state.dataHeatBalFanSys->LoadCorrectionFactor(zoneNum) = 1.0; // Indeterminate
    4316             :                     }
    4317             :                 } else {
    4318             :                     // Negligible flow, assume mixed - reasonable lagged starting value for first step time with significant flow
    4319         351 :                     state.dataHeatBalFanSys->LoadCorrectionFactor(zoneNum) = 1.0;
    4320       46184 :                 }
    4321        7689 :             } else if (thisAirModel.AirModelType == DataRoomAirModel::RoomAirModel::AirflowNetwork) {
    4322             :                 // Zone node used in the RoomAirflowNetwork model
    4323       15378 :                 this->ZT = state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum)
    4324        7689 :                                .Node(state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum).ControlAirNodeID)
    4325        7689 :                                .AirTemp;
    4326        7689 :                 thisSystemNode.Temp = this->ZT;
    4327             :                 // SpaceHB TODO: What to do here if this is for space
    4328        7689 :                 if (spaceNum == 0) {
    4329        7689 :                     state.dataHeatBalFanSys->TempTstatAir(zoneNum) = this->ZT;
    4330             :                 }
    4331        7689 :                 state.dataHeatBalFanSys->LoadCorrectionFactor(zoneNum) = 1.0;
    4332             :             } else {
    4333           0 :                 thisSystemNode.Temp = this->ZT;
    4334             :                 // SpaceHB TODO: What to do here if this is for space
    4335           0 :                 if (spaceNum == 0) {
    4336           0 :                     state.dataHeatBalFanSys->TempTstatAir(zoneNum) = this->ZT;
    4337             :                 }
    4338           0 :                 state.dataHeatBalFanSys->LoadCorrectionFactor(zoneNum) = 1.0;
    4339             :             }
    4340             :         }
    4341             : 
    4342             :         // Sensible load is the enthalpy into the zone minus the enthalpy that leaves the zone.
    4343    24932253 :         Real64 CpAir = Psychrometrics::PsyCpAirFnW(this->ZoneAirHumRat);
    4344    24932253 :         Real64 ZoneEnthalpyIn = this->SumSysMCpT;
    4345             : 
    4346             :         // SNLOAD is the single zone load, without Zone Multiplier or Zone List Multiplier
    4347    49864506 :         SNLoad = ZoneEnthalpyIn - (thisSystemNode.MassFlowRate / ZoneMult) * CpAir * thisSystemNode.Temp + this->NonAirSystemResponse / ZoneMult +
    4348    24932253 :                  this->SysDepZoneLoadsLagged;
    4349             : 
    4350             :     } else {
    4351             : 
    4352             :         // Heat balance coefficients for uncontrolled zone, i.e. without system air flow
    4353     3025850 :         this->TempDepCoef = this->SumHA + this->SumMCp;
    4354     3025850 :         this->TempIndCoef = this->SumIntGain + this->SumHATsurf - this->SumHATref + this->SumMCpT;
    4355             : 
    4356     3025850 :         if (state.afn->distribution_simulated) {
    4357      157822 :             this->TempIndCoef += state.afn->exchangeData(zoneNum).TotalSen;
    4358             :         }
    4359             : 
    4360             :         // Solve for zone air temperature
    4361     3025850 :         switch (state.dataHeatBal->ZoneAirSolutionAlgo) {
    4362     2111293 :         case DataHeatBalance::SolutionAlgo::ThirdOrder: {
    4363     4222586 :             this->ZT = (this->TempIndCoef + this->AirPowerCap * (3.0 * this->ZTM[0] - (3.0 / 2.0) * this->ZTM[1] + (1.0 / 3.0) * this->ZTM[2])) /
    4364     2111293 :                        ((11.0 / 6.0) * this->AirPowerCap + this->TempDepCoef);
    4365             :             // Exact solution
    4366     2111293 :         } break;
    4367      907949 :         case DataHeatBalance::SolutionAlgo::AnalyticalSolution: {
    4368      907949 :             if (this->TempDepCoef == 0.0) { // B=0
    4369           0 :                 this->ZT = this->ZoneT1 + this->TempIndCoef / this->AirPowerCap;
    4370             :             } else {
    4371     1815898 :                 this->ZT = (this->ZoneT1 - this->TempIndCoef / this->TempDepCoef) * std::exp(min(700.0, -this->TempDepCoef / this->AirPowerCap)) +
    4372      907949 :                            this->TempIndCoef / this->TempDepCoef;
    4373             :             }
    4374      907949 :         } break;
    4375        6608 :         case DataHeatBalance::SolutionAlgo::EulerMethod: {
    4376        6608 :             this->ZT = (this->AirPowerCap * this->ZoneT1 + this->TempIndCoef) / (this->AirPowerCap + this->TempDepCoef);
    4377        6608 :         } break;
    4378           0 :         default:
    4379           0 :             break;
    4380             :         }
    4381             : 
    4382             :         // SpaceHB TODO: For now, room air model is only for zones
    4383     3025850 :         if (spaceNum == 0 && state.dataRoomAirMod->anyNonMixingRoomAirModel) {
    4384       53043 :             if (state.dataRoomAirMod->AirModel(zoneNum).AirModelType == DataRoomAirModel::RoomAirModel::AirflowNetwork) {
    4385           0 :                 this->ZT = state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum)
    4386           0 :                                .Node(state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum).ControlAirNodeID)
    4387           0 :                                .AirTemp;
    4388             :             }
    4389             :         }
    4390             : 
    4391             :         // No sensible load
    4392     3025850 :         SNLoad = 0.0;
    4393             :     }
    4394             : 
    4395             :     // Hybrid modeling start
    4396             :     // SpaceHB TODO: For now, hybrid model is only for zones
    4397    27958103 :     if (spaceNum == 0 && state.dataHybridModel->FlagHybridModel) {
    4398       85456 :         if ((state.dataHybridModel->HybridModelZone(zoneNum).InfiltrationCalc_T ||
    4399       44074 :              state.dataHybridModel->HybridModelZone(zoneNum).InternalThermalMassCalc_T ||
    4400       32382 :              state.dataHybridModel->HybridModelZone(zoneNum).PeopleCountCalc_T) &&
    4401       44936 :             (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing)) {
    4402        1500 :             InverseModelTemperature(state,
    4403             :                                     zoneNum,
    4404             :                                     this->SumIntGain,
    4405             :                                     this->SumIntGainExceptPeople,
    4406             :                                     this->SumHA,
    4407             :                                     this->SumHATsurf,
    4408             :                                     this->SumHATref,
    4409             :                                     this->SumMCp,
    4410             :                                     this->SumMCpT,
    4411             :                                     this->SumSysMCp,
    4412             :                                     this->SumSysMCpT,
    4413             :                                     this->AirPowerCap);
    4414             :         }
    4415             :     }
    4416             : 
    4417    27958103 :     this->MAT = this->ZT;
    4418             : 
    4419             :     // Determine sensible load heating/cooling rate and energy
    4420    27958103 :     if (spaceNum > 0) {
    4421       30012 :         state.dataZoneEnergyDemand->spaceSysEnergyDemand(spaceNum).reportZoneAirSystemSensibleLoads(state, SNLoad);
    4422             :     } else {
    4423    27928091 :         state.dataZoneEnergyDemand->ZoneSysEnergyDemand(zoneNum).reportZoneAirSystemSensibleLoads(state, SNLoad);
    4424             :     }
    4425             : 
    4426             :     // Final humidity calcs
    4427    27958103 :     this->correctHumRat(state, zoneNum, spaceNum);
    4428             : 
    4429    27958103 :     this->ZoneAirHumRat = this->ZoneAirHumRatTemp;
    4430    27958103 :     this->ZoneAirRelHum = 100.0 * Psychrometrics::PsyRhFnTdbWPb(state, this->ZT, this->ZoneAirHumRat, state.dataEnvrn->OutBaroPress, RoutineName);
    4431             : 
    4432             :     // tempChange is used by HVACManager to determine if the timestep needs to be shortened.
    4433    27958103 :     bool isMixed = true;
    4434             :     // SpaceHB TODO: For now, room air model is only for zones
    4435    27958103 :     if (spaceNum == 0 && state.dataRoomAirMod->anyNonMixingRoomAirModel) {
    4436      465504 :         isMixed = !((state.dataRoomAirMod->IsZoneDV(zoneNum) && !state.dataRoomAirMod->ZoneDVMixedFlag(zoneNum)) ||
    4437      173493 :                     (state.dataRoomAirMod->IsZoneUI(zoneNum) && !state.dataRoomAirMod->ZoneUFMixedFlag(zoneNum)));
    4438             :     }
    4439    27958103 :     switch (state.dataHeatBal->ZoneAirSolutionAlgo) {
    4440    15577025 :     case DataHeatBalance::SolutionAlgo::ThirdOrder: {
    4441    15577025 :         if (isMixed) {
    4442    15563613 :             tempChange = max(tempChange, std::abs(this->ZT - this->ZTM[0]));
    4443             :         } else {
    4444       26824 :             tempChange = max(tempChange,
    4445       13412 :                              max(std::abs(state.dataRoomAirMod->ZTOC(zoneNum) - state.dataRoomAirMod->ZTM1OC(zoneNum)),
    4446       13412 :                                  std::abs(state.dataRoomAirMod->ZTMX(zoneNum) - state.dataRoomAirMod->ZTM1MX(zoneNum))));
    4447             :         }
    4448    15577025 :     } break;
    4449    12381078 :     case DataHeatBalance::SolutionAlgo::AnalyticalSolution:
    4450             :     case DataHeatBalance::SolutionAlgo::EulerMethod: {
    4451    12381078 :         if (isMixed) {
    4452    12379649 :             tempChange = max(tempChange, std::abs(this->ZT - this->ZoneT1));
    4453             :         } else {
    4454        2858 :             tempChange = max(tempChange,
    4455        1429 :                              max(std::abs(state.dataRoomAirMod->ZTOC(zoneNum) - state.dataRoomAirMod->Zone1OC(zoneNum)),
    4456        1429 :                                  std::abs(state.dataRoomAirMod->ZTMX(zoneNum) - state.dataRoomAirMod->Zone1MX(zoneNum))));
    4457             :         }
    4458    12381078 :     } break;
    4459           0 :     default:
    4460           0 :         break;
    4461             :     }
    4462             : 
    4463   279581030 :     CalcZoneComponentLoadSums(state,
    4464             :                               zoneNum,
    4465             :                               this->TempDepCoef,
    4466             :                               this->TempIndCoef,
    4467    27958103 :                               state.dataHeatBal->ZnAirRpt(zoneNum).SumIntGains,
    4468    27958103 :                               state.dataHeatBal->ZnAirRpt(zoneNum).SumHADTsurfs,
    4469    27958103 :                               state.dataHeatBal->ZnAirRpt(zoneNum).SumMCpDTzones,
    4470    27958103 :                               state.dataHeatBal->ZnAirRpt(zoneNum).SumMCpDtInfil,
    4471    27958103 :                               state.dataHeatBal->ZnAirRpt(zoneNum).SumMCpDTsystem,
    4472    27958103 :                               state.dataHeatBal->ZnAirRpt(zoneNum).SumNonAirSystem,
    4473    27958103 :                               state.dataHeatBal->ZnAirRpt(zoneNum).CzdTdt,
    4474    27958103 :                               state.dataHeatBal->ZnAirRpt(zoneNum).imBalance,
    4475    27958103 :                               state.dataHeatBal->ZnAirRpt(zoneNum).SumEnthalpyM,
    4476    27958103 :                               state.dataHeatBal->ZnAirRpt(zoneNum).SumEnthalpyH);
    4477    27958103 :     return tempChange;
    4478             : }
    4479             : 
    4480     2568313 : void PushZoneTimestepHistories(EnergyPlusData &state)
    4481             : {
    4482             : 
    4483             :     // SUBROUTINE INFORMATION:
    4484             :     //       AUTHOR         Brent Griffith
    4485             :     //       DATE WRITTEN   February 2008
    4486             : 
    4487             :     // PURPOSE OF THIS SUBROUTINE:
    4488             :     // push histories for timestep advancing
    4489             : 
    4490    21013702 :     for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
    4491    18445389 :         state.dataZoneTempPredictorCorrector->zoneHeatBalance(zoneNum).pushZoneTimestepHistory(state, zoneNum);
    4492    18445389 :         if (state.dataHeatBal->doSpaceHeatBalance) {
    4493       48528 :             for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
    4494       24264 :                 state.dataZoneTempPredictorCorrector->spaceHeatBalance(spaceNum).pushZoneTimestepHistory(state, zoneNum, spaceNum);
    4495             :             }
    4496             :         }
    4497             :     }
    4498     2568313 : }
    4499             : 
    4500    18469653 : void ZoneSpaceHeatBalanceData::pushZoneTimestepHistory(EnergyPlusData &state, int const zoneNum, int const spaceNum)
    4501             : {
    4502             : 
    4503    18469653 :     constexpr std::string_view routineName("pushTimestepHistories");
    4504    18469653 :     assert(zoneNum > 0);
    4505             : 
    4506    18469653 :     auto &thisAirModel = state.dataRoomAirMod->AirModel(zoneNum);
    4507             : 
    4508             :     // Push the temperature and humidity ratio histories
    4509             : 
    4510    73878612 :     for (int iHistory = 3; iHistory >= 1; --iHistory) {
    4511    55408959 :         this->XMAT[iHistory] = this->XMAT[iHistory - 1];
    4512    55408959 :         this->WPrevZoneTS[iHistory] = this->WPrevZoneTS[iHistory - 1];
    4513             :     }
    4514    18469653 :     this->XMAT[0] = this->ZTAV; // using average for whole zone time step.
    4515    18469653 :     this->XMPT = this->ZT;
    4516    18469653 :     this->WPrevZoneTS[0] = this->ZoneAirHumRatAvg; // using average for whole zone time step.
    4517    18469653 :     this->ZoneAirHumRat = this->ZoneAirHumRatTemp;
    4518    18469653 :     this->WZoneTimeMinusP = this->ZoneAirHumRatTemp;
    4519    18469653 :     this->ZoneAirRelHum = 100.0 * Psychrometrics::PsyRhFnTdbWPb(state, this->ZT, this->ZoneAirHumRat, state.dataEnvrn->OutBaroPress, routineName);
    4520             : 
    4521             :     // SpaceHB TODO: For now, room air model is only for zones
    4522    18469653 :     if (spaceNum == 0) {
    4523    36877866 :         if (thisAirModel.AirModelType == DataRoomAirModel::RoomAirModel::UCSDDV ||
    4524    36862248 :             thisAirModel.AirModelType == DataRoomAirModel::RoomAirModel::UCSDUFI ||
    4525    18429771 :             thisAirModel.AirModelType == DataRoomAirModel::RoomAirModel::UCSDUFE) {
    4526       26442 :             state.dataRoomAirMod->XM4TFloor(zoneNum) = state.dataRoomAirMod->XM3TFloor(zoneNum);
    4527       26442 :             state.dataRoomAirMod->XM3TFloor(zoneNum) = state.dataRoomAirMod->XM2TFloor(zoneNum);
    4528       26442 :             state.dataRoomAirMod->XM2TFloor(zoneNum) = state.dataRoomAirMod->XMATFloor(zoneNum);
    4529       26442 :             state.dataRoomAirMod->XMATFloor(zoneNum) = state.dataRoomAirMod->ZTFloor(zoneNum);
    4530       26442 :             state.dataRoomAirMod->MATFloor(zoneNum) = state.dataRoomAirMod->ZTFloor(zoneNum);
    4531             : 
    4532       26442 :             state.dataRoomAirMod->XM4TOC(zoneNum) = state.dataRoomAirMod->XM3TOC(zoneNum);
    4533       26442 :             state.dataRoomAirMod->XM3TOC(zoneNum) = state.dataRoomAirMod->XM2TOC(zoneNum);
    4534       26442 :             state.dataRoomAirMod->XM2TOC(zoneNum) = state.dataRoomAirMod->XMATOC(zoneNum);
    4535       26442 :             state.dataRoomAirMod->XMATOC(zoneNum) = state.dataRoomAirMod->ZTOC(zoneNum);
    4536       26442 :             state.dataRoomAirMod->MATOC(zoneNum) = state.dataRoomAirMod->ZTOC(zoneNum);
    4537             : 
    4538       26442 :             state.dataRoomAirMod->XM4TMX(zoneNum) = state.dataRoomAirMod->XM3TMX(zoneNum);
    4539       26442 :             state.dataRoomAirMod->XM3TMX(zoneNum) = state.dataRoomAirMod->XM2TMX(zoneNum);
    4540       26442 :             state.dataRoomAirMod->XM2TMX(zoneNum) = state.dataRoomAirMod->XMATMX(zoneNum);
    4541       26442 :             state.dataRoomAirMod->XMATMX(zoneNum) = state.dataRoomAirMod->ZTMX(zoneNum);
    4542       26442 :             state.dataRoomAirMod->MATMX(zoneNum) = state.dataRoomAirMod->ZTMX(zoneNum);
    4543             :         }
    4544             : 
    4545             :         // for RoomAirflowNetwork model
    4546    18445389 :         if (thisAirModel.AirModelType == DataRoomAirModel::RoomAirModel::AirflowNetwork) {
    4547       41433 :             for (int LoopNode = 1; LoopNode <= state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum).NumOfAirNodes; ++LoopNode) {
    4548       35514 :                 auto &roomAirflowNetworkZoneInfo = state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum).Node(LoopNode);
    4549       35514 :                 roomAirflowNetworkZoneInfo.AirTempX4 = roomAirflowNetworkZoneInfo.AirTempX3;
    4550       35514 :                 roomAirflowNetworkZoneInfo.AirTempX3 = roomAirflowNetworkZoneInfo.AirTempX2;
    4551       35514 :                 roomAirflowNetworkZoneInfo.AirTempX2 = roomAirflowNetworkZoneInfo.AirTempX1;
    4552       35514 :                 roomAirflowNetworkZoneInfo.AirTempX1 = roomAirflowNetworkZoneInfo.AirTemp;
    4553             : 
    4554       35514 :                 roomAirflowNetworkZoneInfo.HumRatX4 = roomAirflowNetworkZoneInfo.HumRatX3;
    4555       35514 :                 roomAirflowNetworkZoneInfo.HumRatX3 = roomAirflowNetworkZoneInfo.HumRatX2;
    4556       35514 :                 roomAirflowNetworkZoneInfo.HumRatX2 = roomAirflowNetworkZoneInfo.HumRatX1;
    4557       35514 :                 roomAirflowNetworkZoneInfo.HumRatX1 = roomAirflowNetworkZoneInfo.HumRat;
    4558             :             }
    4559             :         }
    4560             :     }
    4561             : 
    4562    18469653 :     if (state.dataHeatBal->ZoneAirSolutionAlgo != DataHeatBalance::SolutionAlgo::ThirdOrder) {
    4563     6819450 :         this->ZoneTM2 = this->ZoneTMX;
    4564     6819450 :         this->ZoneTMX = this->ZTAV; // using average for whole zone time step.
    4565     6819450 :         this->ZoneWM2 = this->ZoneWMX;
    4566     6819450 :         this->ZoneWMX = this->ZoneAirHumRatAvg; // using average for whole zone time step.
    4567             :         // SpaceHB TODO: For now, room air model is only for zones
    4568     6819450 :         if (spaceNum == 0) {
    4569    13633122 :             if (thisAirModel.AirModelType == DataRoomAirModel::RoomAirModel::UCSDDV ||
    4570    13627344 :                 thisAirModel.AirModelType == DataRoomAirModel::RoomAirModel::UCSDUFI ||
    4571     6813672 :                 thisAirModel.AirModelType == DataRoomAirModel::RoomAirModel::UCSDUFE) {
    4572        5778 :                 state.dataRoomAirMod->ZoneM2Floor(zoneNum) = state.dataRoomAirMod->ZoneMXFloor(zoneNum);
    4573        5778 :                 state.dataRoomAirMod->ZoneMXFloor(zoneNum) = state.dataRoomAirMod->ZTFloor(zoneNum); // using average for whole zone time step.
    4574        5778 :                 state.dataRoomAirMod->ZoneM2OC(zoneNum) = state.dataRoomAirMod->ZoneMXOC(zoneNum);
    4575        5778 :                 state.dataRoomAirMod->ZoneMXOC(zoneNum) = state.dataRoomAirMod->ZTOC(zoneNum); // using average for whole zone time step.
    4576        5778 :                 state.dataRoomAirMod->ZoneM2MX(zoneNum) = state.dataRoomAirMod->ZoneMXMX(zoneNum);
    4577        5778 :                 state.dataRoomAirMod->ZoneMXMX(zoneNum) = state.dataRoomAirMod->ZTMX(zoneNum); // using average for whole zone time step.
    4578             :             }
    4579             : 
    4580     6819450 :             if (thisAirModel.AirModelType == DataRoomAirModel::RoomAirModel::AirflowNetwork) {
    4581           0 :                 for (int LoopNode = 1; LoopNode <= state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum).NumOfAirNodes; ++LoopNode) {
    4582           0 :                     auto &roomAirflowNetworkZoneInfo = state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum).Node(LoopNode);
    4583           0 :                     roomAirflowNetworkZoneInfo.AirTempTM2 = roomAirflowNetworkZoneInfo.AirTempTMX;
    4584           0 :                     roomAirflowNetworkZoneInfo.AirTempTMX = roomAirflowNetworkZoneInfo.AirTemp;
    4585             : 
    4586           0 :                     roomAirflowNetworkZoneInfo.HumRatWM2 = roomAirflowNetworkZoneInfo.HumRatWMX;
    4587           0 :                     roomAirflowNetworkZoneInfo.HumRatWMX = roomAirflowNetworkZoneInfo.HumRat;
    4588             :                 }
    4589             :             }
    4590             :         }
    4591             :     }
    4592    18469653 : }
    4593             : 
    4594     1055447 : void PushSystemTimestepHistories(EnergyPlusData &state)
    4595             : {
    4596             : 
    4597             :     // SUBROUTINE INFORMATION:
    4598             :     //       AUTHOR         Brent Griffith
    4599             :     //       DATE WRITTEN   April 2008
    4600             : 
    4601             :     // PURPOSE OF THIS SUBROUTINE:
    4602             :     // Push the temperature and humidity ratio histories back in time
    4603             : 
    4604    10538149 :     for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
    4605     9482702 :         state.dataZoneTempPredictorCorrector->zoneHeatBalance(zoneNum).pushSystemTimestepHistory(state, zoneNum);
    4606     9482702 :         if (state.dataHeatBal->doSpaceHeatBalance) {
    4607       11496 :             for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
    4608        5748 :                 state.dataZoneTempPredictorCorrector->spaceHeatBalance(spaceNum).pushSystemTimestepHistory(state, zoneNum, spaceNum);
    4609             :             }
    4610             :         }
    4611             :     }
    4612     1055447 : }
    4613             : 
    4614     9488450 : void ZoneSpaceHeatBalanceData::pushSystemTimestepHistory(EnergyPlusData &state, int const zoneNum, int const spaceNum)
    4615             : {
    4616     9488450 :     assert(zoneNum > 0);
    4617    37953800 :     for (int iHistory = 3; iHistory >= 1; --iHistory) {
    4618    28465350 :         this->DSXMAT[iHistory] = this->DSXMAT[iHistory - 1];
    4619    28465350 :         this->DSWPrevZoneTS[iHistory] = this->DSWPrevZoneTS[iHistory - 1];
    4620             :     }
    4621     9488450 :     this->DSXMAT[0] = this->MAT;
    4622     9488450 :     this->DSWPrevZoneTS[0] = this->ZoneAirHumRat;
    4623             : 
    4624             :     // SpaceHB TODO: For now, room air model is only for zones
    4625     9488450 :     if (spaceNum == 0 && state.dataRoomAirMod->anyNonMixingRoomAirModel) {
    4626       35274 :         if (state.dataRoomAirMod->IsZoneDV(zoneNum) || state.dataRoomAirMod->IsZoneUI(zoneNum)) {
    4627        6162 :             state.dataRoomAirMod->DSXM4TFloor(zoneNum) = state.dataRoomAirMod->DSXM3TFloor(zoneNum);
    4628        6162 :             state.dataRoomAirMod->DSXM3TFloor(zoneNum) = state.dataRoomAirMod->DSXM2TFloor(zoneNum);
    4629        6162 :             state.dataRoomAirMod->DSXM2TFloor(zoneNum) = state.dataRoomAirMod->DSXMATFloor(zoneNum);
    4630        6162 :             state.dataRoomAirMod->DSXMATFloor(zoneNum) = state.dataRoomAirMod->MATFloor(zoneNum);
    4631             : 
    4632        6162 :             state.dataRoomAirMod->DSXM4TOC(zoneNum) = state.dataRoomAirMod->DSXM3TOC(zoneNum);
    4633        6162 :             state.dataRoomAirMod->DSXM3TOC(zoneNum) = state.dataRoomAirMod->DSXM2TOC(zoneNum);
    4634        6162 :             state.dataRoomAirMod->DSXM2TOC(zoneNum) = state.dataRoomAirMod->DSXMATOC(zoneNum);
    4635        6162 :             state.dataRoomAirMod->DSXMATOC(zoneNum) = state.dataRoomAirMod->MATOC(zoneNum);
    4636             : 
    4637        6162 :             state.dataRoomAirMod->DSXM4TMX(zoneNum) = state.dataRoomAirMod->DSXM3TMX(zoneNum);
    4638        6162 :             state.dataRoomAirMod->DSXM3TMX(zoneNum) = state.dataRoomAirMod->DSXM2TMX(zoneNum);
    4639        6162 :             state.dataRoomAirMod->DSXM2TMX(zoneNum) = state.dataRoomAirMod->DSXMATMX(zoneNum);
    4640        6162 :             state.dataRoomAirMod->DSXMATMX(zoneNum) = state.dataRoomAirMod->MATMX(zoneNum);
    4641             :         }
    4642       35274 :         if (state.dataRoomAirMod->AirModel(zoneNum).AirModelType == DataRoomAirModel::RoomAirModel::AirflowNetwork) {
    4643       12390 :             for (int LoopNode = 1; LoopNode <= state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum).NumOfAirNodes; ++LoopNode) {
    4644       10620 :                 auto &roomAirflowNetworkZoneInfo = state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum).Node(LoopNode);
    4645       10620 :                 roomAirflowNetworkZoneInfo.AirTempDSX4 = roomAirflowNetworkZoneInfo.AirTempDSX3;
    4646       10620 :                 roomAirflowNetworkZoneInfo.AirTempDSX3 = roomAirflowNetworkZoneInfo.AirTempDSX2;
    4647       10620 :                 roomAirflowNetworkZoneInfo.AirTempDSX2 = roomAirflowNetworkZoneInfo.AirTempDSX1;
    4648       10620 :                 roomAirflowNetworkZoneInfo.AirTempDSX1 = roomAirflowNetworkZoneInfo.AirTemp;
    4649             : 
    4650       10620 :                 roomAirflowNetworkZoneInfo.HumRatDSX4 = roomAirflowNetworkZoneInfo.HumRatDSX3;
    4651       10620 :                 roomAirflowNetworkZoneInfo.HumRatDSX3 = roomAirflowNetworkZoneInfo.HumRatDSX2;
    4652       10620 :                 roomAirflowNetworkZoneInfo.HumRatDSX2 = roomAirflowNetworkZoneInfo.HumRatDSX1;
    4653       10620 :                 roomAirflowNetworkZoneInfo.HumRatDSX1 = roomAirflowNetworkZoneInfo.HumRat;
    4654             :             }
    4655             :         }
    4656             :     }
    4657             : 
    4658     9488450 :     if (state.dataHeatBal->ZoneAirSolutionAlgo != DataHeatBalance::SolutionAlgo::ThirdOrder) {
    4659     5561628 :         this->ZoneTM2 = this->ZoneTMX;
    4660     5561628 :         this->ZoneTMX = this->MAT; // using average for whole zone time step.
    4661     5561628 :         this->ZoneWM2 = this->ZoneWMX;
    4662     5561628 :         this->ZoneWMX = this->ZoneAirHumRatTemp; // using average for whole zone time step.
    4663             : 
    4664             :         // SpaceHB TODO: For now, room air model is only for zones
    4665     5561628 :         if (spaceNum == 0) {
    4666    16684054 :             if (state.dataRoomAirMod->AirModel(zoneNum).AirModelType == DataRoomAirModel::RoomAirModel::UCSDDV ||
    4667    11122426 :                 state.dataRoomAirMod->AirModel(zoneNum).AirModelType == DataRoomAirModel::RoomAirModel::UCSDUFI ||
    4668     5560798 :                 state.dataRoomAirMod->AirModel(zoneNum).AirModelType == DataRoomAirModel::RoomAirModel::UCSDUFE) {
    4669         830 :                 state.dataRoomAirMod->ZoneM2Floor(zoneNum) = state.dataRoomAirMod->ZoneMXFloor(zoneNum);
    4670         830 :                 state.dataRoomAirMod->ZoneMXFloor(zoneNum) = state.dataRoomAirMod->ZTFloor(zoneNum); // using average for whole zone time step.
    4671         830 :                 state.dataRoomAirMod->ZoneM2OC(zoneNum) = state.dataRoomAirMod->ZoneMXOC(zoneNum);
    4672         830 :                 state.dataRoomAirMod->ZoneMXOC(zoneNum) = state.dataRoomAirMod->ZTOC(zoneNum); // using average for whole zone time step.
    4673         830 :                 state.dataRoomAirMod->ZoneM2MX(zoneNum) = state.dataRoomAirMod->ZoneMXMX(zoneNum);
    4674         830 :                 state.dataRoomAirMod->ZoneMXMX(zoneNum) = state.dataRoomAirMod->ZTMX(zoneNum); // using average for whole zone time step.
    4675             :             }
    4676     5561628 :             if (state.dataRoomAirMod->AirModel(zoneNum).AirModelType == DataRoomAirModel::RoomAirModel::AirflowNetwork) {
    4677           0 :                 for (int LoopNode = 1; LoopNode <= state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum).NumOfAirNodes; ++LoopNode) {
    4678           0 :                     auto &roomAirflowNetworkZoneInfo = state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum).Node(LoopNode);
    4679           0 :                     roomAirflowNetworkZoneInfo.AirTempTM2 = roomAirflowNetworkZoneInfo.AirTempTMX;
    4680           0 :                     roomAirflowNetworkZoneInfo.AirTempTMX = roomAirflowNetworkZoneInfo.AirTemp;
    4681             : 
    4682           0 :                     roomAirflowNetworkZoneInfo.HumRatWM2 = roomAirflowNetworkZoneInfo.HumRatWMX;
    4683           0 :                     roomAirflowNetworkZoneInfo.HumRatWMX = roomAirflowNetworkZoneInfo.HumRat;
    4684             :                 }
    4685             :             }
    4686             :         }
    4687             :     }
    4688     9488450 : }
    4689             : 
    4690           0 : void RevertZoneTimestepHistories(EnergyPlusData &state)
    4691             : {
    4692             :     // SUBROUTINE INFORMATION:
    4693             :     //       AUTHOR         Brent Griffith
    4694             :     //       DATE WRITTEN   February 2008
    4695             : 
    4696             :     // PURPOSE OF THIS SUBROUTINE:
    4697             :     // Revert the temperature and humidity ratio histories
    4698             : 
    4699           0 :     for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
    4700           0 :         state.dataZoneTempPredictorCorrector->zoneHeatBalance(zoneNum).revertZoneTimestepHistory(state, zoneNum);
    4701           0 :         if (state.dataHeatBal->doSpaceHeatBalance) {
    4702           0 :             for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
    4703           0 :                 state.dataZoneTempPredictorCorrector->spaceHeatBalance(spaceNum).revertZoneTimestepHistory(state, zoneNum, spaceNum);
    4704             :             }
    4705             :         }
    4706             :     }
    4707           0 : }
    4708             : 
    4709           0 : void ZoneSpaceHeatBalanceData::revertZoneTimestepHistory(EnergyPlusData &state, int const zoneNum, int const spaceNum)
    4710             : {
    4711           0 :     assert(zoneNum > 0);
    4712             : 
    4713           0 :     for (int iHistory = 0; iHistory <= 2; ++iHistory) {
    4714           0 :         this->XMAT[iHistory] = this->XMAT[iHistory + 1];
    4715           0 :         this->WPrevZoneTS[iHistory] = this->WPrevZoneTS[iHistory + 1];
    4716             :     }
    4717             : 
    4718             :     // SpaceHB TODO: For now, room air model is only for zones
    4719           0 :     if (spaceNum == 0) {
    4720           0 :         if (state.dataRoomAirMod->AirModel(zoneNum).AirModelType == DataRoomAirModel::RoomAirModel::UCSDDV ||
    4721           0 :             state.dataRoomAirMod->AirModel(zoneNum).AirModelType == DataRoomAirModel::RoomAirModel::UCSDUFI ||
    4722           0 :             state.dataRoomAirMod->AirModel(zoneNum).AirModelType == DataRoomAirModel::RoomAirModel::UCSDUFE) {
    4723             : 
    4724           0 :             state.dataRoomAirMod->XMATFloor(zoneNum) = state.dataRoomAirMod->XM2TFloor(zoneNum);
    4725           0 :             state.dataRoomAirMod->XM2TFloor(zoneNum) = state.dataRoomAirMod->XM3TFloor(zoneNum);
    4726           0 :             state.dataRoomAirMod->XM3TFloor(zoneNum) = state.dataRoomAirMod->XM4TFloor(zoneNum);
    4727             : 
    4728           0 :             state.dataRoomAirMod->XMATOC(zoneNum) = state.dataRoomAirMod->XM2TOC(zoneNum);
    4729           0 :             state.dataRoomAirMod->XM2TOC(zoneNum) = state.dataRoomAirMod->XM3TOC(zoneNum);
    4730           0 :             state.dataRoomAirMod->XM3TOC(zoneNum) = state.dataRoomAirMod->XM4TOC(zoneNum);
    4731             : 
    4732           0 :             state.dataRoomAirMod->XMATMX(zoneNum) = state.dataRoomAirMod->XM2TMX(zoneNum);
    4733           0 :             state.dataRoomAirMod->XM2TMX(zoneNum) = state.dataRoomAirMod->XM3TMX(zoneNum);
    4734           0 :             state.dataRoomAirMod->XM3TMX(zoneNum) = state.dataRoomAirMod->XM4TMX(zoneNum);
    4735             :         }
    4736             : 
    4737           0 :         if (state.dataRoomAirMod->AirModel(zoneNum).AirModelType == DataRoomAirModel::RoomAirModel::AirflowNetwork) {
    4738           0 :             for (int LoopNode = 1; LoopNode <= state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum).NumOfAirNodes; ++LoopNode) {
    4739           0 :                 auto &roomAirflowNetworkZoneInfo = state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum).Node(LoopNode);
    4740           0 :                 roomAirflowNetworkZoneInfo.AirTempX1 = roomAirflowNetworkZoneInfo.AirTempX2;
    4741           0 :                 roomAirflowNetworkZoneInfo.AirTempX2 = roomAirflowNetworkZoneInfo.AirTempX3;
    4742           0 :                 roomAirflowNetworkZoneInfo.AirTempX3 = roomAirflowNetworkZoneInfo.AirTempX4;
    4743             : 
    4744           0 :                 roomAirflowNetworkZoneInfo.HumRatX1 = roomAirflowNetworkZoneInfo.HumRatX2;
    4745           0 :                 roomAirflowNetworkZoneInfo.HumRatX2 = roomAirflowNetworkZoneInfo.HumRatX3;
    4746           0 :                 roomAirflowNetworkZoneInfo.HumRatX3 = roomAirflowNetworkZoneInfo.HumRatX4;
    4747             :             }
    4748             :         }
    4749             :     }
    4750           0 : }
    4751             : 
    4752    27958103 : void ZoneSpaceHeatBalanceData::correctHumRat(EnergyPlusData &state, int const zoneNum, int const spaceNum)
    4753             : {
    4754             : 
    4755             :     // SUBROUTINE INFORMATION:
    4756             :     //       AUTHOR         Richard Liesen
    4757             :     //       DATE WRITTEN   2000
    4758             :     // REFERENCES: Routine FinalZnCalcs - FINAL ZONE CALCULATIONS, authored by Dale Herron for BLAST.
    4759             : 
    4760    27958103 :     assert(zoneNum > 0);
    4761             :     static constexpr std::string_view RoutineName("correctHumRat");
    4762             : 
    4763    27958103 :     Real64 MoistureMassFlowRate = 0.0;
    4764    27958103 :     Real64 ZoneMassFlowRate = 0.0;
    4765    27958103 :     auto &zone = state.dataHeatBal->Zone(zoneNum);
    4766    27958103 :     int ZoneMult = zone.Multiplier * zone.ListMultiplier;
    4767    27958103 :     bool ControlledZoneAirFlag = zone.IsControlled;
    4768    27958103 :     bool ZoneRetPlenumAirFlag = zone.IsReturnPlenum;
    4769    27958103 :     bool ZoneSupPlenumAirFlag = zone.IsSupplyPlenum;
    4770             : 
    4771    27958103 :     if (ControlledZoneAirFlag) { // If there is system flow then calculate the flow rates
    4772    23861098 :         auto &zoneEquipConfig = state.dataZoneEquip->ZoneEquipConfig(zoneNum);
    4773             :         // Calculate moisture flow rate into each zone
    4774    48058619 :         for (int NodeNum = 1; NodeNum <= zoneEquipConfig.NumInletNodes; ++NodeNum) {
    4775    24197521 :             auto &inletNode = state.dataLoopNodes->Node(zoneEquipConfig.InletNode(NodeNum));
    4776    24197521 :             MoistureMassFlowRate += (inletNode.MassFlowRate * inletNode.HumRat) / ZoneMult;
    4777    24197521 :             ZoneMassFlowRate += inletNode.MassFlowRate / ZoneMult;
    4778             :         }
    4779             : 
    4780             :         // Do the calculations for the plenum zone
    4781     4097005 :     } else if (ZoneRetPlenumAirFlag) {
    4782     1051397 :         int ZoneRetPlenumNum = zone.PlenumCondNum;
    4783     1051397 :         auto &zoneRetPlenCond = state.dataZonePlenum->ZoneRetPlenCond(ZoneRetPlenumNum);
    4784     6087908 :         for (int NodeNum = 1; NodeNum <= zoneRetPlenCond.NumInletNodes; ++NodeNum) {
    4785     5036511 :             auto &inletNode = state.dataLoopNodes->Node(zoneRetPlenCond.InletNode(NodeNum));
    4786     5036511 :             MoistureMassFlowRate += (inletNode.MassFlowRate * inletNode.HumRat) / ZoneMult;
    4787     5036511 :             ZoneMassFlowRate += inletNode.MassFlowRate / ZoneMult;
    4788             :         }
    4789             :         // add in the leak flow
    4790     6046913 :         for (int ADUListIndex = 1; ADUListIndex <= zoneRetPlenCond.NumADUs; ++ADUListIndex) {
    4791     4995516 :             int ADUNum = zoneRetPlenCond.ADUIndex(ADUListIndex);
    4792     4995516 :             auto &airDistUnit = state.dataDefineEquipment->AirDistUnit(ADUNum);
    4793     4995516 :             if (airDistUnit.UpStreamLeak) {
    4794      108695 :                 int ADUInNode = airDistUnit.InletNodeNum;
    4795      108695 :                 MoistureMassFlowRate += (airDistUnit.MassFlowRateUpStrLk * state.dataLoopNodes->Node(ADUInNode).HumRat) / ZoneMult;
    4796      108695 :                 ZoneMassFlowRate += airDistUnit.MassFlowRateUpStrLk / ZoneMult;
    4797             :             }
    4798     4995516 :             if (airDistUnit.DownStreamLeak) {
    4799      108695 :                 int ADUOutNode = airDistUnit.OutletNodeNum;
    4800      108695 :                 MoistureMassFlowRate += (airDistUnit.MassFlowRateDnStrLk * state.dataLoopNodes->Node(ADUOutNode).HumRat) / ZoneMult;
    4801      108695 :                 ZoneMassFlowRate += airDistUnit.MassFlowRateDnStrLk / ZoneMult;
    4802             :             }
    4803             :         }
    4804             : 
    4805     3045608 :     } else if (ZoneSupPlenumAirFlag) {
    4806       19758 :         int ZoneSupPlenumNum = zone.PlenumCondNum;
    4807       19758 :         auto &inletNode = state.dataLoopNodes->Node(state.dataZonePlenum->ZoneSupPlenCond(ZoneSupPlenumNum).InletNode);
    4808       19758 :         MoistureMassFlowRate += (inletNode.MassFlowRate * inletNode.HumRat) / ZoneMult;
    4809       19758 :         ZoneMassFlowRate += inletNode.MassFlowRate / ZoneMult;
    4810             :     }
    4811             : 
    4812             :     // Calculate hourly humidity ratio from infiltration + humidity added from latent load + system added moisture
    4813    27958103 :     Real64 LatentGain = this->ZoneLatentGain + state.dataHeatBalFanSys->SumLatentHTRadSys(zoneNum) + state.dataHeatBalFanSys->SumLatentPool(zoneNum);
    4814             : 
    4815    27958103 :     Real64 SysTimeStepInSeconds = DataGlobalConstants::SecInHour * state.dataHVACGlobal->TimeStepSys;
    4816             : 
    4817             :     // Calculate the coefficients for the 3rd order derivative for final
    4818             :     // zone humidity ratio.  The A, B, C coefficients are analogous to the
    4819             :     // heat balance.  There are 2 cases that should be considered, system
    4820             :     // operating and system shutdown.
    4821             : 
    4822    27958103 :     Real64 const RhoAir = Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, this->ZT, this->ZoneAirHumRat, RoutineName);
    4823    27958103 :     Real64 const H2OHtOfVap = Psychrometrics::PsyHgAirFnWTdb(this->ZoneAirHumRat, this->ZT);
    4824             : 
    4825    27958103 :     Real64 B = (LatentGain / H2OHtOfVap) + ((this->OAMFL + this->VAMFL + this->CTMFL) * state.dataEnvrn->OutHumRat) + this->EAMFLxHumRat +
    4826    27958103 :                (MoistureMassFlowRate) + this->SumHmARaW + this->MixingMassFlowXHumRat + this->MDotOA * state.dataEnvrn->OutHumRat;
    4827    27958103 :     Real64 A = ZoneMassFlowRate + this->OAMFL + this->VAMFL + this->EAMFL + this->CTMFL + this->SumHmARa + this->MixingMassFlowZone + this->MDotOA;
    4828             : 
    4829    55934458 :     if (state.afn->multizone_always_simulated ||
    4830    27479358 :         (state.afn->simulation_control.type == AirflowNetwork::ControlType::MultizoneWithDistributionOnlyDuringFanOperation &&
    4831       23300 :          state.afn->AirflowNetworkFanActivated)) {
    4832      520297 :         auto &exchangeData = state.afn->exchangeData(zoneNum);
    4833             :         // Multizone airflow calculated in AirflowNetwork
    4834      520297 :         B = (LatentGain / H2OHtOfVap) + (exchangeData.SumMHrW + exchangeData.SumMMHrW) + (MoistureMassFlowRate) + this->SumHmARaW;
    4835      520297 :         A = ZoneMassFlowRate + exchangeData.SumMHr + exchangeData.SumMMHr + this->SumHmARa;
    4836             :     }
    4837    27958103 :     Real64 C = RhoAir * zone.Volume * zone.ZoneVolCapMultpMoist / SysTimeStepInSeconds;
    4838             : 
    4839    27958103 :     if (state.afn->distribution_simulated) {
    4840      402445 :         B += state.afn->exchangeData(zoneNum).TotalLat;
    4841             :     }
    4842             : 
    4843             :     // Use a 3rd order derivative to predict final zone humidity ratio and
    4844             :     // smooth the changes using the zone air capacitance.
    4845             :     // auto &zoneAirHumRatTemp = this->ZoneAirHumRatTemp;
    4846             :     // auto &zoneW1 = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).ZoneW1;
    4847    27958103 :     switch (state.dataHeatBal->ZoneAirSolutionAlgo) {
    4848    15577025 :     case DataHeatBalance::SolutionAlgo::ThirdOrder: {
    4849    15577025 :         this->ZoneAirHumRatTemp =
    4850    31154050 :             (B + C * (3.0 * this->WPrevZoneTSTemp[0] - (3.0 / 2.0) * this->WPrevZoneTSTemp[1] + (1.0 / 3.0) * this->WPrevZoneTSTemp[2])) /
    4851    15577025 :             ((11.0 / 6.0) * C + A);
    4852             :         // Exact solution
    4853    15577025 :     } break;
    4854    12342868 :     case DataHeatBalance::SolutionAlgo::AnalyticalSolution: {
    4855    12342868 :         if (A == 0.0) { // B=0
    4856      491667 :             this->ZoneAirHumRatTemp = this->ZoneW1 + B / C;
    4857             :         } else {
    4858    11851201 :             this->ZoneAirHumRatTemp = (this->ZoneW1 - B / A) * std::exp(min(700.0, -A / C)) + B / A;
    4859             :         }
    4860    12342868 :     } break;
    4861       38210 :     case DataHeatBalance::SolutionAlgo::EulerMethod: {
    4862       38210 :         this->ZoneAirHumRatTemp = (C * this->ZoneW1 + B) / (C + A);
    4863       38210 :     } break;
    4864           0 :     default:
    4865           0 :         break;
    4866             :     }
    4867             : 
    4868             :     // Set the humidity ratio to zero if the zone has been dried out
    4869    27958103 :     if (this->ZoneAirHumRatTemp < 0.0) this->ZoneAirHumRatTemp = 0.0;
    4870             : 
    4871             :     // Check to make sure that is saturated there is condensation in the zone
    4872             :     // by resetting to saturation conditions.
    4873    27958103 :     Real64 const WZSat = Psychrometrics::PsyWFnTdbRhPb(state, this->ZT, 1.0, state.dataEnvrn->OutBaroPress, RoutineName);
    4874             : 
    4875    27958103 :     if (this->ZoneAirHumRatTemp > WZSat) this->ZoneAirHumRatTemp = WZSat;
    4876             : 
    4877    27958103 :     if (state.dataRoomAirMod->AirModel(zoneNum).AirModelType == DataRoomAirModel::RoomAirModel::AirflowNetwork) {
    4878       15378 :         this->ZoneAirHumRatTemp = state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum)
    4879        7689 :                                       .Node(state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum).ControlAirNodeID)
    4880        7689 :                                       .HumRat;
    4881             :     }
    4882             : 
    4883             :     // HybridModel with measured humidity ratio begins
    4884             :     // SpaceHB TODO: For now, hybrid model is only for zones
    4885    27958103 :     if (spaceNum == 0 && state.dataHybridModel->FlagHybridModel) {
    4886       88219 :         if ((state.dataHybridModel->HybridModelZone(zoneNum).InfiltrationCalc_H ||
    4887       32382 :              state.dataHybridModel->HybridModelZone(zoneNum).PeopleCountCalc_H) &&
    4888       35747 :             (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing)) {
    4889         600 :             Real64 LatentGainExceptPeople = 0.0;
    4890         600 :             if (state.dataHybridModel->HybridModelZone(zoneNum).PeopleCountCalc_H) {
    4891         596 :                 LatentGainExceptPeople = this->ZoneLatentGainExceptPeople + state.dataHeatBalFanSys->SumLatentHTRadSys(zoneNum) +
    4892         298 :                                          state.dataHeatBalFanSys->SumLatentPool(zoneNum);
    4893             :             }
    4894             : 
    4895         600 :             InverseModelHumidity(state, zoneNum, LatentGain, LatentGainExceptPeople, ZoneMassFlowRate, MoistureMassFlowRate, H2OHtOfVap, RhoAir);
    4896             :         }
    4897             :     }
    4898             : 
    4899             :     // Now put the calculated info into the actual zone nodes; ONLY if there is zone air flow, i.e. controlled zone or plenum zone
    4900    27958103 :     int ZoneNodeNum = zone.SystemZoneNodeNumber;
    4901    27958103 :     if (spaceNum > 0) {
    4902       30012 :         ZoneNodeNum = state.dataHeatBal->space(spaceNum).SystemZoneNodeNumber;
    4903             :     }
    4904    27958103 :     if (ZoneNodeNum > 0) {
    4905    24932253 :         state.dataLoopNodes->Node(ZoneNodeNum).HumRat = this->ZoneAirHumRatTemp;
    4906    24932253 :         state.dataLoopNodes->Node(ZoneNodeNum).Enthalpy = Psychrometrics::PsyHFnTdbW(this->ZT, this->ZoneAirHumRatTemp);
    4907             :     }
    4908    27958103 :     if (state.dataHeatBal->DoLatentSizing) {
    4909       38484 :         Real64 sensibleLoad = 0.0;
    4910       38484 :         Real64 pSat = Psychrometrics::PsyPsatFnTemp(state, this->ZT, RoutineName);
    4911       38484 :         Real64 Tdp = Psychrometrics::PsyTdpFnWPb(state, this->ZoneAirHumRatTemp, state.dataEnvrn->StdBaroPress);
    4912       38484 :         Real64 vaporPressureDiff = pSat - Psychrometrics::PsyPsatFnTemp(state, Tdp, RoutineName);
    4913       38484 :         if (spaceNum > 0) {
    4914           0 :             sensibleLoad = state.dataZoneEnergyDemand->spaceSysEnergyDemand(spaceNum).ZoneSNLoadHeatRate +
    4915           0 :                            state.dataZoneEnergyDemand->spaceSysEnergyDemand(spaceNum).ZoneSNLoadCoolRate;
    4916           0 :             state.dataZoneEnergyDemand->spaceSysMoistureDemand(spaceNum).reportZoneAirSystemMoistureLoads(
    4917             :                 state, LatentGain, sensibleLoad, vaporPressureDiff);
    4918             :         } else {
    4919       76968 :             sensibleLoad = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(zoneNum).ZoneSNLoadHeatRate +
    4920       38484 :                            state.dataZoneEnergyDemand->ZoneSysEnergyDemand(zoneNum).ZoneSNLoadCoolRate;
    4921       38484 :             state.dataZoneEnergyDemand->ZoneSysMoistureDemand(zoneNum).reportZoneAirSystemMoistureLoads(
    4922             :                 state, LatentGain, sensibleLoad, vaporPressureDiff);
    4923             :         }
    4924             :     }
    4925    27958103 : }
    4926             : 
    4927       69602 : void DownInterpolate4HistoryValues(Real64 const OldTimeStep,
    4928             :                                    Real64 const NewTimeStep,
    4929             :                                    Real64 const oldVal0,
    4930             :                                    Real64 const oldVal1,
    4931             :                                    Real64 const oldVal2,
    4932             :                                    Real64 &newVal0,
    4933             :                                    Real64 &newVal1,
    4934             :                                    Real64 &newVal2,
    4935             :                                    Real64 &newVal3,
    4936             :                                    Real64 &newVal4)
    4937             : {
    4938             :     // SUBROUTINE INFORMATION:
    4939             :     //       AUTHOR         Brent Griffith
    4940             :     //       DATE WRITTEN   Feb 2008
    4941             : 
    4942             :     // PURPOSE OF THIS SUBROUTINE:
    4943             :     // provide a reusable routine for the various places that need to
    4944             :     // interpolate a new set of history values on a different time scale
    4945             :     // Once the systemtimestep has shortened, the new history terms need to be interpolated
    4946             : 
    4947             :     // METHODOLOGY EMPLOYED:
    4948             :     // This routine assumes that the direction is to a shorter timestep.
    4949             :     // The down step ratio, DSRatio = OldTimeStep/ NewTimeStep
    4950             :     //  is expected to be roughly integer-valued and near 2.0 or 3.0 or 4.0 or more.
    4951             : 
    4952             :     // first construct data on timestamps for interpolating with later
    4953       69602 :     Real64 const oldTime0 = 0.0;
    4954       69602 :     Real64 const oldTime1 = oldTime0 - OldTimeStep;
    4955             : 
    4956       69602 :     Real64 const newTime0 = 0.0;
    4957       69602 :     Real64 const newTime1 = newTime0 - NewTimeStep;
    4958       69602 :     Real64 const newTime2 = newTime1 - NewTimeStep;
    4959       69602 :     Real64 const newTime3 = newTime2 - NewTimeStep;
    4960       69602 :     Real64 const newTime4 = newTime3 - NewTimeStep;
    4961             : 
    4962       69602 :     Real64 const DSRatio = OldTimeStep / NewTimeStep; // should pretty much be an integer value 2, 3, 4, etc.
    4963             : 
    4964       69602 :     newVal0 = oldVal0;
    4965             : 
    4966       69602 :     if (std::abs(DSRatio - 2.0) < 0.01) { // DSRatio = 2
    4967             :         // first two points lie between oldVal0 and oldVal1
    4968       15689 :         newVal1 = oldVal0 + (oldVal1 - oldVal0) * ((oldTime0 - newTime1) / (OldTimeStep));
    4969       15689 :         newVal2 = oldVal0 + (oldVal1 - oldVal0) * ((oldTime0 - newTime2) / (OldTimeStep));
    4970             :         // last two points lie between oldVal1 and oldVal2
    4971       15689 :         newVal3 = oldVal1 + (oldVal2 - oldVal1) * ((oldTime1 - newTime3) / (OldTimeStep));
    4972       15689 :         newVal4 = oldVal1 + (oldVal2 - oldVal1) * ((oldTime1 - newTime4) / (OldTimeStep));
    4973       53913 :     } else if (std::abs(DSRatio - 3.0) < 0.01) { // DSRatio = 3
    4974             :         // first three points lie between oldVal0 and oldVal1
    4975       10057 :         newVal1 = oldVal0 + (oldVal1 - oldVal0) * ((oldTime0 - newTime1) / (OldTimeStep));
    4976       10057 :         newVal2 = oldVal0 + (oldVal1 - oldVal0) * ((oldTime0 - newTime2) / (OldTimeStep));
    4977       10057 :         newVal3 = oldVal0 + (oldVal1 - oldVal0) * ((oldTime0 - newTime3) / (OldTimeStep));
    4978             :         // last point lie between oldVal1 and oldVal2
    4979       10057 :         newVal4 = oldVal1 + (oldVal2 - oldVal1) * ((oldTime1 - newTime4) / (OldTimeStep));
    4980             : 
    4981             :     } else { // DSRatio = 4 or more
    4982             :         // all new points lie between oldVal0 and oldVal1
    4983       43856 :         newVal1 = oldVal0 + (oldVal1 - oldVal0) * ((oldTime0 - newTime1) / (OldTimeStep));
    4984       43856 :         newVal2 = oldVal0 + (oldVal1 - oldVal0) * ((oldTime0 - newTime2) / (OldTimeStep));
    4985       43856 :         newVal3 = oldVal0 + (oldVal1 - oldVal0) * ((oldTime0 - newTime3) / (OldTimeStep));
    4986       43856 :         newVal4 = oldVal0 + (oldVal1 - oldVal0) * ((oldTime0 - newTime4) / (OldTimeStep));
    4987             :     }
    4988       69602 : }
    4989             : 
    4990     2686582 : Real64 DownInterpolate4HistoryValues(Real64 OldTimeStep, Real64 NewTimeStep, std::array<Real64, 4> const &oldVals, std::array<Real64, 4> &newVals)
    4991             : {
    4992             :     // first construct data on timestamps for interpolating with later
    4993     2686582 :     Real64 const oldTime0 = 0.0;
    4994     2686582 :     Real64 const oldTime1 = oldTime0 - OldTimeStep;
    4995             : 
    4996     2686582 :     Real64 const newTime0 = 0.0;
    4997     2686582 :     Real64 const newTime1 = newTime0 - NewTimeStep;
    4998     2686582 :     Real64 const newTime2 = newTime1 - NewTimeStep;
    4999     2686582 :     Real64 const newTime3 = newTime2 - NewTimeStep;
    5000     2686582 :     Real64 const newTime4 = newTime3 - NewTimeStep;
    5001             : 
    5002     2686582 :     Real64 const DSRatio = OldTimeStep / NewTimeStep; // should pretty much be an integer value 2, 3, 4, etc.
    5003             : 
    5004     2686582 :     if (std::abs(DSRatio - 2.0) < 0.01) { // DSRatio = 2
    5005             :         // first two points lie between oldVals[0] and oldVals[1]
    5006      899860 :         Real64 delta10 = oldVals[1] - oldVals[0];
    5007      899860 :         newVals[0] = oldVals[0] + delta10 * ((oldTime0 - newTime1) / OldTimeStep);
    5008      899860 :         newVals[1] = oldVals[0] + delta10 * ((oldTime0 - newTime2) / OldTimeStep);
    5009             :         // last two points lie between oldVals[1] and oldVals[2]
    5010      899860 :         Real64 delta21 = oldVals[2] - oldVals[1];
    5011      899860 :         newVals[2] = oldVals[1] + delta21 * ((oldTime1 - newTime3) / OldTimeStep);
    5012      899860 :         newVals[3] = oldVals[1] + delta21 * ((oldTime1 - newTime4) / OldTimeStep);
    5013     1786722 :     } else if (std::abs(DSRatio - 3.0) < 0.01) { // DSRatio = 3
    5014             :         // first three points lie between oldVals[0] and oldVals[1]
    5015      450136 :         Real64 delta10 = oldVals[1] - oldVals[0];
    5016      450136 :         newVals[0] = oldVals[0] + delta10 * ((oldTime0 - newTime1) / OldTimeStep);
    5017      450136 :         newVals[1] = oldVals[0] + delta10 * ((oldTime0 - newTime2) / OldTimeStep);
    5018      450136 :         newVals[2] = oldVals[0] + delta10 * ((oldTime0 - newTime3) / OldTimeStep);
    5019             :         // last point lie between oldVals[1] and oldVals[2]
    5020      450136 :         Real64 delta21 = (oldVals[2] - oldVals[1]) / OldTimeStep;
    5021      450136 :         newVals[3] = oldVals[1] + delta21 * ((oldTime1 - newTime4) / OldTimeStep);
    5022             : 
    5023             :     } else { // DSRatio = 4 or more
    5024             :         // all new points lie between oldVals[0] and oldVals[1]
    5025     1336586 :         Real64 delta10 = oldVals[1] - oldVals[0];
    5026     1336586 :         newVals[0] = oldVals[0] + delta10 * ((oldTime0 - newTime1) / OldTimeStep);
    5027     1336586 :         newVals[1] = oldVals[0] + delta10 * ((oldTime0 - newTime2) / OldTimeStep);
    5028     1336586 :         newVals[2] = oldVals[0] + delta10 * ((oldTime0 - newTime3) / OldTimeStep);
    5029     1336586 :         newVals[3] = oldVals[0] + delta10 * ((oldTime0 - newTime4) / OldTimeStep);
    5030             :     }
    5031     2686582 :     return oldVals[0];
    5032             : 
    5033             :     // if (std::abs(DSRatio - 2.0) < 0.01) { // DSRatio = 2
    5034             :     //     // first two points lie between oldVals[0] and oldVals[1]
    5035             :     //     Real64 ratio10 = (oldVals[1] - oldVals[0]) / OldTimeStep;
    5036             :     //     newVals[0] = oldVals[0] + ratio10 * (oldTime0 - newTime1);
    5037             :     //     newVals[1] = oldVals[0] + ratio10 * (oldTime0 - newTime2);
    5038             :     //     // last two points lie between oldVals[1] and oldVals[2]
    5039             :     //     Real64 ratio21 = (oldVals[2] - oldVals[1]) / OldTimeStep;
    5040             :     //     newVals[2] = oldVals[1] + ratio21 * (oldTime1 - newTime3);
    5041             :     //     newVals[3] = oldVals[1] + ratio21 * (oldTime1 - newTime4);
    5042             :     // } else if (std::abs(DSRatio - 3.0) < 0.01) { // DSRatio = 3
    5043             :     //     // first three points lie between oldVals[0] and oldVals[1]
    5044             :     //     Real64 ratio10 = (oldVals[1] - oldVals[0]) / OldTimeStep;
    5045             :     //     newVals[0] = oldVals[0] + ratio10 * (oldTime0 - newTime1);
    5046             :     //     newVals[1] = oldVals[0] + ratio10 * (oldTime0 - newTime2);
    5047             :     //     newVals[2] = oldVals[0] + ratio10 * (oldTime0 - newTime3);
    5048             :     //     // last point lie between oldVals[1] and oldVals[2]
    5049             :     //     Real64 ratio21 = (oldVals[2] - oldVals[1]) / OldTimeStep;
    5050             :     //     newVals[3] = oldVals[1] + ratio21 * (oldTime1 - newTime4);
    5051             : 
    5052             :     //} else { // DSRatio = 4 or more
    5053             :     //    // all new points lie between oldVals[0] and oldVals[1]
    5054             :     //    Real64 ratio10 = (oldVals[1] - oldVals[0]) / OldTimeStep;
    5055             :     //    newVals[0] = oldVals[0] + ratio10 * (oldTime0 - newTime1);
    5056             :     //    newVals[1] = oldVals[0] + ratio10 * (oldTime0 - newTime2);
    5057             :     //    newVals[2] = oldVals[0] + ratio10 * (oldTime0 - newTime3);
    5058             :     //    newVals[3] = oldVals[0] + ratio10 * (oldTime0 - newTime4);
    5059             :     //}
    5060             : }
    5061        1500 : void InverseModelTemperature(EnergyPlusData &state,
    5062             :                              int const ZoneNum,                   // Zone number
    5063             :                              Real64 const SumIntGain,             // Zone sum of convective internal gains
    5064             :                              Real64 const SumIntGainExceptPeople, // Zone sum of convective internal gains except for people
    5065             :                              Real64 const SumHA,                  // Zone sum of Hc*Area
    5066             :                              Real64 const SumHATsurf,             // Zone sum of Hc*Area*Tsurf
    5067             :                              Real64 const SumHATref,              // Zone sum of Hc*Area*Tref, for ceiling diffuser convection correlation
    5068             :                              Real64 const SumMCp,                 // Zone sum of MassFlowRate*Cp
    5069             :                              Real64 const SumMCpT,                // Zone sum of MassFlowRate*Cp*T
    5070             :                              Real64 const SumSysMCp,              // Zone sum of air system MassFlowRate*Cp
    5071             :                              Real64 const SumSysMCpT,             // Zone sum of air system MassFlowRate*Cp*T
    5072             :                              Real64 const AirCap                  // Formerly CoefAirrat, coef in zone temp eqn with dim of "air power capacity"rd
    5073             : )
    5074             : {
    5075             :     // SUBROUTINE INFORMATION:
    5076             :     //       AUTHOR         Han Li
    5077             :     //       DATE WRITTEN   February 2019
    5078             : 
    5079             :     // PURPOSE OF THIS SUBROUTINE:
    5080             :     // This subroutine inversely solve infiltration airflow rate or people count with zone air temperatures measurements.
    5081             : 
    5082             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    5083        1500 :     Real64 AirCapHM(0.0); // Air power capacity for hybrid modeling
    5084        1500 :     Real64 AA(0.0);
    5085        1500 :     Real64 BB(0.0);
    5086        1500 :     Real64 FractionConvection(0.0); // Default convection portion of the sensible heat from people
    5087             : 
    5088        1500 :     auto &zone = state.dataHeatBal->Zone(ZoneNum);
    5089        1500 :     auto &hybridModelZone = state.dataHybridModel->HybridModelZone(ZoneNum);
    5090        1500 :     auto &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum);
    5091             : 
    5092        1500 :     int ZoneMult = zone.Multiplier * zone.ListMultiplier;
    5093        1500 :     zone.ZoneMeasuredTemperature = ScheduleManager::GetCurrentScheduleValue(state, hybridModelZone.ZoneMeasuredTemperatureSchedulePtr);
    5094             : 
    5095             :     // HM calculation only HM calculation period start
    5096        1500 :     if (state.dataEnvrn->DayOfYear >= hybridModelZone.HybridStartDayOfYear && state.dataEnvrn->DayOfYear <= hybridModelZone.HybridEndDayOfYear) {
    5097        1500 :         Real64 HMMultiplierAverage(1.0);
    5098        1500 :         Real64 MultpHM(1.0);
    5099             : 
    5100        1500 :         thisZoneHB.ZT = zone.ZoneMeasuredTemperature; // Array1D<Real64> ZT -- Zone
    5101             :                                                       // Air Temperature Averaged over
    5102             :                                                       // the System Time Increment
    5103        1500 :         if (hybridModelZone.InfiltrationCalc_T && state.dataHVACGlobal->UseZoneTimeStepHistory) {
    5104             :             static constexpr std::string_view RoutineNameInfiltration("CalcAirFlowSimple:Infiltration");
    5105             : 
    5106         576 :             if (hybridModelZone.IncludeSystemSupplyParameters) {
    5107           0 :                 zone.ZoneMeasuredSupplyAirTemperature =
    5108           0 :                     ScheduleManager::GetCurrentScheduleValue(state, hybridModelZone.ZoneSupplyAirTemperatureSchedulePtr);
    5109           0 :                 zone.ZoneMeasuredSupplyAirFlowRate =
    5110           0 :                     ScheduleManager::GetCurrentScheduleValue(state, hybridModelZone.ZoneSupplyAirMassFlowRateSchedulePtr);
    5111           0 :                 zone.ZoneMeasuredSupplyAirHumidityRatio =
    5112           0 :                     ScheduleManager::GetCurrentScheduleValue(state, hybridModelZone.ZoneSupplyAirHumidityRatioSchedulePtr);
    5113             :                 // Calculate the air humidity ratio at supply air inlet.
    5114           0 :                 Real64 CpAirInlet(0.0);
    5115           0 :                 CpAirInlet = Psychrometrics::PsyCpAirFnW(zone.ZoneMeasuredSupplyAirHumidityRatio);
    5116             : 
    5117           0 :                 Real64 SumSysMCp_HM = zone.ZoneMeasuredSupplyAirFlowRate * CpAirInlet;
    5118           0 :                 Real64 SumSysMCpT_HM = zone.ZoneMeasuredSupplyAirFlowRate * CpAirInlet * zone.ZoneMeasuredSupplyAirTemperature;
    5119             : 
    5120           0 :                 AA = SumSysMCp_HM + SumHA + thisZoneHB.MCPV + thisZoneHB.MCPM + thisZoneHB.MCPE + thisZoneHB.MCPC + thisZoneHB.MDotCPOA;
    5121           0 :                 BB = SumSysMCpT_HM + SumIntGain + SumHATsurf - SumHATref + thisZoneHB.MCPTV + thisZoneHB.MCPTM + thisZoneHB.MCPTE + thisZoneHB.MCPTC +
    5122           0 :                      thisZoneHB.MDotCPOA * zone.OutDryBulbTemp + (thisZoneHB.NonAirSystemResponse / ZoneMult + thisZoneHB.SysDepZoneLoadsLagged);
    5123             :             } else {
    5124         576 :                 AA = SumHA + thisZoneHB.MCPV + thisZoneHB.MCPM + thisZoneHB.MCPE + thisZoneHB.MCPC + thisZoneHB.MDotCPOA;
    5125        1152 :                 BB = SumIntGain + SumHATsurf - SumHATref + thisZoneHB.MCPTV + thisZoneHB.MCPTM + thisZoneHB.MCPTE + thisZoneHB.MCPTC +
    5126         576 :                      thisZoneHB.MDotCPOA * zone.OutDryBulbTemp;
    5127             :             }
    5128         576 :             Real64 CC = AirCap;
    5129             :             Real64 DD =
    5130         576 :                 (3.0 * state.dataHeatBalFanSys->PreviousMeasuredZT1(ZoneNum) - (3.0 / 2.0) * state.dataHeatBalFanSys->PreviousMeasuredZT2(ZoneNum) +
    5131         576 :                  (1.0 / 3.0) * state.dataHeatBalFanSys->PreviousMeasuredZT3(ZoneNum));
    5132             : 
    5133         576 :             Real64 delta_T = (zone.ZoneMeasuredTemperature - zone.OutDryBulbTemp);
    5134         576 :             Real64 CpAir = Psychrometrics::PsyCpAirFnW(state.dataEnvrn->OutHumRat);
    5135        1152 :             Real64 AirDensity = Psychrometrics::PsyRhoAirFnPbTdbW(
    5136        1728 :                 state, state.dataEnvrn->OutBaroPress, zone.OutDryBulbTemp, state.dataEnvrn->OutHumRat, RoutineNameInfiltration);
    5137         576 :             zone.delta_T = delta_T;
    5138             : 
    5139             :             // s4 - Set ACH to 0 when delta_T <= 0.5, add max and min limits to ach
    5140         576 :             Real64 M_inf = 0.0;
    5141         576 :             if (std::abs(delta_T) > 0.5) {
    5142         558 :                 M_inf = (BB + CC * DD - ((11.0 / 6.0) * CC + AA) * zone.ZoneMeasuredTemperature) / (CpAir * delta_T);
    5143             :             }
    5144         576 :             Real64 ACH_inf = max(0.0, min(10.0, (M_inf / AirDensity) / zone.Volume * DataGlobalConstants::SecInHour));
    5145         576 :             M_inf = (ACH_inf / DataGlobalConstants::SecInHour) * zone.Volume * AirDensity;
    5146             : 
    5147             :             // Overwrite variable with inverse solution
    5148         576 :             zone.MCPIHM = M_inf;
    5149         576 :             zone.InfilOAAirChangeRateHM = ACH_inf;
    5150             : 
    5151             :         } // Hybrid model infiltration calculation end
    5152             : 
    5153             :         // Hybrid modeling internal thermal mass calculation start
    5154        2076 :         if (hybridModelZone.InternalThermalMassCalc_T && SumSysMCpT == 0 && thisZoneHB.ZT != state.dataHeatBalFanSys->PreviousMeasuredZT1(ZoneNum) &&
    5155         576 :             state.dataHVACGlobal->UseZoneTimeStepHistory) { // HM calculation only when SumSysMCpT =0,
    5156             :                                                             // TimeStepZone (not @ TimeStepSys)
    5157         576 :             Real64 TempDepCoef = SumHA + SumMCp + SumSysMCp;
    5158        1152 :             Real64 TempIndCoef = SumIntGain + SumHATsurf - SumHATref + SumMCpT + SumSysMCpT +
    5159         576 :                                  (thisZoneHB.NonAirSystemResponse / ZoneMult + thisZoneHB.SysDepZoneLoadsLagged);
    5160             :             //    TempHistoryTerm = AirCap * (3.0 * ZTM1(ZoneNum) - (3.0/2.0) * ZTM2(ZoneNum) + (1.0/3.0) * ZTM3(ZoneNum)) !debug only
    5161             : 
    5162         576 :             if (state.afn->distribution_simulated) {
    5163           0 :                 TempIndCoef += state.afn->exchangeData(ZoneNum).TotalSen;
    5164             :             }
    5165             :             // Calculate air capacity using DataHeatBalance::SolutionAlgo::AnalyticalSolution
    5166         576 :             if (TempDepCoef == 0.0) {
    5167             :                 // Is this correct? Shouldn't we use log?? What if thisZT ==
    5168             :                 // PreviousMeasuredZT1(ZoneNum)??
    5169           0 :                 AirCapHM = TempIndCoef / (thisZoneHB.ZT - state.dataHeatBalFanSys->PreviousMeasuredZT1(ZoneNum)); // Inverse equation
    5170             :             } else {
    5171         576 :                 Real64 AirCapHM_temp = 0.0;
    5172         576 :                 if (TempIndCoef == TempDepCoef * thisZoneHB.ZT) {
    5173           0 :                     AirCapHM_temp = 0.0; //  This is the denominator.
    5174             :                 } else {
    5175        1152 :                     AirCapHM_temp = (TempIndCoef - TempDepCoef * state.dataHeatBalFanSys->PreviousMeasuredZT1(ZoneNum)) /
    5176         576 :                                     (TempIndCoef - TempDepCoef * thisZoneHB.ZT);
    5177             :                 }
    5178             : 
    5179         576 :                 if ((AirCapHM_temp > 0) && (AirCapHM_temp != 1)) {    // Avoide IND
    5180         574 :                     AirCapHM = TempDepCoef / std::log(AirCapHM_temp); // Inverse equation
    5181             :                 } else {
    5182           2 :                     AirCapHM = TempIndCoef / (thisZoneHB.ZT - state.dataHeatBalFanSys->PreviousMeasuredZT1(ZoneNum));
    5183             :                 }
    5184             :             }
    5185             : 
    5186             :             // Calculate multiplier
    5187         576 :             if (std::abs(thisZoneHB.ZT - state.dataHeatBalFanSys->PreviousMeasuredZT1(ZoneNum)) > 0.05) { // Filter
    5188         162 :                 MultpHM = AirCapHM /
    5189         162 :                           (zone.Volume *
    5190         243 :                            Psychrometrics::PsyRhoAirFnPbTdbW(state,
    5191          81 :                                                              state.dataEnvrn->OutBaroPress,
    5192             :                                                              thisZoneHB.ZT,
    5193         162 :                                                              thisZoneHB.ZoneAirHumRat) *
    5194          81 :                            Psychrometrics::PsyCpAirFnW(thisZoneHB.ZoneAirHumRat)) *
    5195          81 :                           (state.dataGlobal->TimeStepZone * DataGlobalConstants::SecInHour); // Inverse equation
    5196          81 :                 if ((MultpHM < 1.0) || (MultpHM > 30.0)) {                                   // Temperature capacity multiplier greater than
    5197             :                                                                                              // 1 and less than 30
    5198          16 :                     MultpHM = 1.0;                                                           // Default value 1.0
    5199             :                 }
    5200             :             } else {
    5201         495 :                 MultpHM = 1.0; // Default value 1.0
    5202             :             }
    5203             : 
    5204         576 :             zone.ZoneVolCapMultpSensHM = MultpHM; // For timestep output
    5205             : 
    5206             :             // Calculate the average multiplier of the zone for the whole running period
    5207             :             {
    5208             :                 // count for hybrid model calculations
    5209         576 :                 if (MultpHM > 1.0) {
    5210          65 :                     zone.ZoneVolCapMultpSensHMSum += MultpHM;
    5211          65 :                     zone.ZoneVolCapMultpSensHMCountSum++;
    5212             :                 }
    5213             : 
    5214             :                 // Calculate and store the multiplier average at the end of HM
    5215             :                 // simulations
    5216         576 :                 if (state.dataEnvrn->DayOfYear == hybridModelZone.HybridEndDayOfYear && state.dataGlobal->EndDayFlag) {
    5217           0 :                     HMMultiplierAverage = zone.ZoneVolCapMultpSensHMSum / zone.ZoneVolCapMultpSensHMCountSum;
    5218           0 :                     zone.ZoneVolCapMultpSensHMAverage = HMMultiplierAverage;
    5219             :                 }
    5220             :             }
    5221             :         } // Hybrid model internal thermal mass calcualtion end
    5222             : 
    5223             :         // Hybrid model people count calculation
    5224        1500 :         if (hybridModelZone.PeopleCountCalc_T && state.dataHVACGlobal->UseZoneTimeStepHistory) {
    5225         288 :             zone.ZoneMeasuredTemperature = ScheduleManager::GetCurrentScheduleValue(state, hybridModelZone.ZoneMeasuredTemperatureSchedulePtr);
    5226         288 :             zone.ZonePeopleActivityLevel = ScheduleManager::GetCurrentScheduleValue(state, hybridModelZone.ZonePeopleActivityLevelSchedulePtr);
    5227         288 :             zone.ZonePeopleSensibleHeatFraction =
    5228         288 :                 ScheduleManager::GetCurrentScheduleValue(state, hybridModelZone.ZonePeopleSensibleFractionSchedulePtr);
    5229         288 :             zone.ZonePeopleRadiantHeatFraction =
    5230         288 :                 ScheduleManager::GetCurrentScheduleValue(state, hybridModelZone.ZonePeopleRadiationFractionSchedulePtr);
    5231             : 
    5232         288 :             Real64 FractionSensible = zone.ZonePeopleSensibleHeatFraction;
    5233         288 :             Real64 FractionRadiation = zone.ZonePeopleRadiantHeatFraction;
    5234         288 :             Real64 ActivityLevel = ScheduleManager::GetCurrentScheduleValue(state, hybridModelZone.ZonePeopleActivityLevelSchedulePtr);
    5235             : 
    5236         288 :             if (FractionSensible <= 0.0) {
    5237           0 :                 FractionSensible = 0.6;
    5238             :             }
    5239             : 
    5240         288 :             if (FractionRadiation <= 0.0) {
    5241           0 :                 FractionConvection = 0.7;
    5242             :             } else {
    5243         288 :                 FractionConvection = 1.0 - FractionRadiation;
    5244             :             }
    5245             : 
    5246         288 :             if (ActivityLevel <= 0.0) {
    5247           0 :                 ActivityLevel = 130.0;
    5248             :             }
    5249             : 
    5250         288 :             if (hybridModelZone.IncludeSystemSupplyParameters) {
    5251           0 :                 zone.ZoneMeasuredSupplyAirTemperature =
    5252           0 :                     ScheduleManager::GetCurrentScheduleValue(state, hybridModelZone.ZoneSupplyAirTemperatureSchedulePtr);
    5253           0 :                 zone.ZoneMeasuredSupplyAirFlowRate =
    5254           0 :                     ScheduleManager::GetCurrentScheduleValue(state, hybridModelZone.ZoneSupplyAirMassFlowRateSchedulePtr);
    5255           0 :                 zone.ZoneMeasuredSupplyAirHumidityRatio =
    5256           0 :                     ScheduleManager::GetCurrentScheduleValue(state, hybridModelZone.ZoneSupplyAirHumidityRatioSchedulePtr);
    5257             : 
    5258             :                 // Calculate the air humidity ratio at supply air inlet.
    5259           0 :                 Real64 CpAirInlet = Psychrometrics::PsyCpAirFnW(zone.ZoneMeasuredSupplyAirHumidityRatio);
    5260             : 
    5261           0 :                 Real64 SumSysMCp_HM = zone.ZoneMeasuredSupplyAirFlowRate * CpAirInlet;
    5262           0 :                 Real64 SumSysMCpT_HM = zone.ZoneMeasuredSupplyAirFlowRate * CpAirInlet * zone.ZoneMeasuredSupplyAirTemperature;
    5263             : 
    5264           0 :                 AA = SumSysMCp_HM + SumHA + SumMCp;
    5265           0 :                 BB = SumSysMCpT_HM + SumIntGainExceptPeople + SumHATsurf - SumHATref + SumMCpT +
    5266           0 :                      (thisZoneHB.NonAirSystemResponse / ZoneMult + thisZoneHB.SysDepZoneLoadsLagged);
    5267             :             } else {
    5268         288 :                 AA = SumHA + SumMCp;
    5269         288 :                 BB = SumIntGainExceptPeople + SumHATsurf - SumHATref + SumMCpT;
    5270             :             }
    5271             : 
    5272         288 :             Real64 CC = AirCap;
    5273             :             Real64 DD =
    5274         288 :                 (3.0 * state.dataHeatBalFanSys->PreviousMeasuredZT1(ZoneNum) - (3.0 / 2.0) * state.dataHeatBalFanSys->PreviousMeasuredZT2(ZoneNum) +
    5275         288 :                  (1.0 / 3.0) * state.dataHeatBalFanSys->PreviousMeasuredZT3(ZoneNum));
    5276             : 
    5277         288 :             Real64 SumIntGainPeople = ((11.0 / 6.0) * CC + AA) * zone.ZoneMeasuredTemperature - BB - CC * DD;
    5278         288 :             Real64 UpperBound = max(0.0, SumIntGain / (ActivityLevel * FractionSensible * FractionConvection));
    5279         288 :             Real64 NumPeople = min(UpperBound, max(0.0, SumIntGainPeople / (ActivityLevel * FractionSensible * FractionConvection)));
    5280             : 
    5281         288 :             if (NumPeople < 0.05) {
    5282         286 :                 NumPeople = 0;
    5283             :             }
    5284         288 :             zone.NumOccHM = NumPeople;
    5285             :         }
    5286             :     }
    5287             : 
    5288             :     // Update zone temperatures in the previous steps
    5289        1500 :     state.dataHeatBalFanSys->PreviousMeasuredZT3(ZoneNum) = state.dataHeatBalFanSys->PreviousMeasuredZT2(ZoneNum);
    5290        1500 :     state.dataHeatBalFanSys->PreviousMeasuredZT2(ZoneNum) = state.dataHeatBalFanSys->PreviousMeasuredZT1(ZoneNum);
    5291        1500 :     state.dataHeatBalFanSys->PreviousMeasuredZT1(ZoneNum) = thisZoneHB.ZT;
    5292        1500 : }
    5293             : 
    5294         600 : void InverseModelHumidity(EnergyPlusData &state,
    5295             :                           int const ZoneNum,                   // Zone number
    5296             :                           Real64 const LatentGain,             // Zone sum of latent gain
    5297             :                           Real64 const LatentGainExceptPeople, // Zone sum of latent gain except for people
    5298             :                           Real64 const ZoneMassFlowRate,       // Zone air mass flow rate
    5299             :                           Real64 const MoistureMassFlowRate,   // Zone moisture mass flow rate
    5300             :                           Real64 const H2OHtOfVap,             // Heat of vaporization of air
    5301             :                           Real64 const RhoAir                  // Air density
    5302             : )
    5303             : {
    5304             :     // SUBROUTINE INFORMATION:
    5305             :     //       AUTHOR         Han Li
    5306             :     //       DATE WRITTEN   February 2019
    5307             : 
    5308             :     // PURPOSE OF THIS SUBROUTINE:
    5309             :     // This subroutine inversely solve infiltration airflow rate or people count with zone air humidity measurements.
    5310             : 
    5311             :     // SUBROUTINE PARAMETER DEFINITIONS:
    5312             :     static constexpr std::string_view RoutineName("InverseModelHumidity");
    5313             : 
    5314             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    5315         600 :     Real64 AA(0.0);
    5316         600 :     Real64 BB(0.0);
    5317         600 :     Real64 ActivityLevel(0.0);
    5318         600 :     Real64 SysTimeStepInSeconds = DataGlobalConstants::SecInHour * state.dataHVACGlobal->TimeStepSys;
    5319             : 
    5320         600 :     auto &zone = state.dataHeatBal->Zone(ZoneNum);
    5321         600 :     auto &hybridModelZone = state.dataHybridModel->HybridModelZone(ZoneNum);
    5322         600 :     auto &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum);
    5323             : 
    5324             :     // Get measured zone humidity ratio
    5325         600 :     zone.ZoneMeasuredHumidityRatio = ScheduleManager::GetCurrentScheduleValue(state, hybridModelZone.ZoneMeasuredHumidityRatioSchedulePtr);
    5326             : 
    5327         600 :     if (state.dataEnvrn->DayOfYear >= hybridModelZone.HybridStartDayOfYear && state.dataEnvrn->DayOfYear <= hybridModelZone.HybridEndDayOfYear) {
    5328         600 :         thisZoneHB.ZoneAirHumRat = zone.ZoneMeasuredHumidityRatio;
    5329             : 
    5330             :         // Hybrid Model calculate air infiltration rate
    5331         600 :         if (hybridModelZone.InfiltrationCalc_H && state.dataHVACGlobal->UseZoneTimeStepHistory) {
    5332             :             // Conditionally calculate the time dependent and time independent terms
    5333         288 :             if (hybridModelZone.IncludeSystemSupplyParameters) {
    5334           0 :                 zone.ZoneMeasuredSupplyAirFlowRate =
    5335           0 :                     ScheduleManager::GetCurrentScheduleValue(state, hybridModelZone.ZoneSupplyAirMassFlowRateSchedulePtr);
    5336           0 :                 zone.ZoneMeasuredSupplyAirHumidityRatio =
    5337           0 :                     ScheduleManager::GetCurrentScheduleValue(state, hybridModelZone.ZoneSupplyAirHumidityRatioSchedulePtr);
    5338             : 
    5339           0 :                 Real64 SumSysM_HM = zone.ZoneMeasuredSupplyAirFlowRate;
    5340           0 :                 Real64 SumSysMHumRat_HM = zone.ZoneMeasuredSupplyAirFlowRate * zone.ZoneMeasuredSupplyAirHumidityRatio;
    5341             : 
    5342           0 :                 AA = SumSysM_HM + thisZoneHB.VAMFL + thisZoneHB.EAMFL + thisZoneHB.CTMFL + thisZoneHB.SumHmARa + thisZoneHB.MixingMassFlowZone +
    5343           0 :                      thisZoneHB.MDotOA;
    5344           0 :                 BB = SumSysMHumRat_HM + (LatentGain / H2OHtOfVap) + ((thisZoneHB.VAMFL + thisZoneHB.CTMFL) * state.dataEnvrn->OutHumRat) +
    5345           0 :                      thisZoneHB.EAMFLxHumRat + thisZoneHB.SumHmARaW + thisZoneHB.MixingMassFlowXHumRat +
    5346           0 :                      thisZoneHB.MDotOA * state.dataEnvrn->OutHumRat;
    5347             :             } else {
    5348         288 :                 AA = thisZoneHB.VAMFL + thisZoneHB.EAMFL + thisZoneHB.CTMFL + thisZoneHB.SumHmARa + thisZoneHB.MixingMassFlowZone + thisZoneHB.MDotOA;
    5349         864 :                 BB = (LatentGain / H2OHtOfVap) + ((thisZoneHB.VAMFL + thisZoneHB.CTMFL) * state.dataEnvrn->OutHumRat) + thisZoneHB.EAMFLxHumRat +
    5350         576 :                      thisZoneHB.SumHmARaW + thisZoneHB.MixingMassFlowXHumRat + thisZoneHB.MDotOA * state.dataEnvrn->OutHumRat;
    5351             :             }
    5352             : 
    5353         288 :             Real64 CC = RhoAir * zone.Volume * zone.ZoneVolCapMultpMoist / SysTimeStepInSeconds;
    5354         576 :             Real64 DD = (3.0 * state.dataHeatBalFanSys->PreviousMeasuredHumRat1(ZoneNum) -
    5355         288 :                          (3.0 / 2.0) * state.dataHeatBalFanSys->PreviousMeasuredHumRat2(ZoneNum) +
    5356         288 :                          (1.0 / 3.0) * state.dataHeatBalFanSys->PreviousMeasuredHumRat3(ZoneNum));
    5357             : 
    5358         288 :             Real64 delta_HR = (zone.ZoneMeasuredHumidityRatio - state.dataEnvrn->OutHumRat);
    5359             : 
    5360             :             Real64 AirDensity =
    5361         288 :                 Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, zone.OutDryBulbTemp, state.dataEnvrn->OutHumRat, RoutineName);
    5362             : 
    5363         288 :             Real64 M_inf = 0.0;
    5364         288 :             if (std::abs(zone.ZoneMeasuredHumidityRatio - state.dataEnvrn->OutHumRat) > 0.0000001) {
    5365         288 :                 M_inf = (CC * DD + BB - ((11.0 / 6.0) * CC + AA) * zone.ZoneMeasuredHumidityRatio) / delta_HR;
    5366             :             }
    5367             : 
    5368             :             // Add threshold for air change rate
    5369         288 :             Real64 ACH_inf = max(0.0, min(10.0, (M_inf / AirDensity) / zone.Volume * DataGlobalConstants::SecInHour));
    5370         288 :             M_inf = (ACH_inf / DataGlobalConstants::SecInHour) * zone.Volume * AirDensity;
    5371         288 :             zone.MCPIHM = M_inf;
    5372         288 :             zone.InfilOAAirChangeRateHM = ACH_inf;
    5373             :         }
    5374             : 
    5375             :         // Hybrid Model calculate people count
    5376         600 :         if (hybridModelZone.PeopleCountCalc_H && state.dataHVACGlobal->UseZoneTimeStepHistory) {
    5377         288 :             zone.ZonePeopleActivityLevel = ScheduleManager::GetCurrentScheduleValue(state, hybridModelZone.ZonePeopleActivityLevelSchedulePtr);
    5378         288 :             zone.ZonePeopleSensibleHeatFraction =
    5379         288 :                 ScheduleManager::GetCurrentScheduleValue(state, hybridModelZone.ZonePeopleSensibleFractionSchedulePtr);
    5380         288 :             zone.ZonePeopleRadiantHeatFraction =
    5381         288 :                 ScheduleManager::GetCurrentScheduleValue(state, hybridModelZone.ZonePeopleRadiationFractionSchedulePtr);
    5382             : 
    5383         288 :             Real64 FractionSensible = zone.ZonePeopleSensibleHeatFraction;
    5384             : 
    5385         288 :             if (FractionSensible <= 0.0) {
    5386           0 :                 FractionSensible = 0.6;
    5387             :             }
    5388             : 
    5389         288 :             if (ActivityLevel <= 0.0) {
    5390         288 :                 ActivityLevel = 130.0;
    5391             :             }
    5392             : 
    5393             :             // Conditionally calculate the humidity-dependent and humidity-independent
    5394             :             // terms.
    5395         288 :             if (hybridModelZone.IncludeSystemSupplyParameters) {
    5396         288 :                 zone.ZoneMeasuredSupplyAirFlowRate =
    5397         288 :                     ScheduleManager::GetCurrentScheduleValue(state, hybridModelZone.ZoneSupplyAirMassFlowRateSchedulePtr);
    5398         288 :                 zone.ZoneMeasuredSupplyAirHumidityRatio =
    5399         288 :                     ScheduleManager::GetCurrentScheduleValue(state, hybridModelZone.ZoneSupplyAirHumidityRatioSchedulePtr);
    5400             : 
    5401         288 :                 Real64 SumSysM_HM = zone.ZoneMeasuredSupplyAirFlowRate;
    5402         288 :                 Real64 SumSysMHumRat_HM = zone.ZoneMeasuredSupplyAirFlowRate * zone.ZoneMeasuredSupplyAirHumidityRatio;
    5403             : 
    5404         864 :                 AA = SumSysM_HM + thisZoneHB.OAMFL + thisZoneHB.VAMFL + thisZoneHB.EAMFL + thisZoneHB.CTMFL + thisZoneHB.SumHmARa +
    5405         576 :                      thisZoneHB.MixingMassFlowZone + thisZoneHB.MDotOA;
    5406         864 :                 BB = SumSysMHumRat_HM + (LatentGainExceptPeople / H2OHtOfVap) +
    5407         864 :                      ((thisZoneHB.OAMFL + thisZoneHB.VAMFL + thisZoneHB.CTMFL) * state.dataEnvrn->OutHumRat) + thisZoneHB.EAMFLxHumRat +
    5408         576 :                      thisZoneHB.SumHmARaW + thisZoneHB.MixingMassFlowXHumRat + thisZoneHB.MDotOA * state.dataEnvrn->OutHumRat;
    5409             :             } else {
    5410           0 :                 AA = ZoneMassFlowRate + thisZoneHB.OAMFL + thisZoneHB.VAMFL + thisZoneHB.EAMFL + thisZoneHB.CTMFL + thisZoneHB.SumHmARa +
    5411           0 :                      thisZoneHB.MixingMassFlowZone + thisZoneHB.MDotOA;
    5412           0 :                 BB = (LatentGainExceptPeople / H2OHtOfVap) + ((thisZoneHB.OAMFL + thisZoneHB.VAMFL + thisZoneHB.CTMFL) * state.dataEnvrn->OutHumRat) +
    5413           0 :                      thisZoneHB.EAMFLxHumRat + (MoistureMassFlowRate) + thisZoneHB.SumHmARaW + thisZoneHB.MixingMassFlowXHumRat +
    5414           0 :                      thisZoneHB.MDotOA * state.dataEnvrn->OutHumRat;
    5415             :             }
    5416             : 
    5417         288 :             Real64 CC = RhoAir * zone.Volume * zone.ZoneVolCapMultpMoist / SysTimeStepInSeconds;
    5418         576 :             Real64 DD = (3.0 * state.dataHeatBalFanSys->PreviousMeasuredHumRat1(ZoneNum) -
    5419         288 :                          (3.0 / 2.0) * state.dataHeatBalFanSys->PreviousMeasuredHumRat2(ZoneNum) +
    5420         288 :                          (1.0 / 3.0) * state.dataHeatBalFanSys->PreviousMeasuredHumRat3(ZoneNum));
    5421             : 
    5422         288 :             Real64 LatentGainPeople = (((11.0 / 6.0) * CC + AA) * zone.ZoneMeasuredHumidityRatio - BB - CC * DD) * H2OHtOfVap;
    5423         288 :             Real64 UpperBound = max(0.0, LatentGain / (ActivityLevel * (1.0 - FractionSensible)));
    5424         288 :             Real64 NumPeople = min(UpperBound, max(0.0, LatentGainPeople / (ActivityLevel * (1.0 - FractionSensible))));
    5425         288 :             NumPeople = floor(NumPeople * 100.00 + 0.5) / 100.00;
    5426         288 :             if (NumPeople < 0.05) {
    5427         235 :                 NumPeople = 0;
    5428             :             }
    5429         288 :             zone.NumOccHM = NumPeople;
    5430             :         }
    5431             :     }
    5432             : 
    5433             :     // Update zone humidity ratio in the previous steps
    5434         600 :     state.dataHeatBalFanSys->PreviousMeasuredHumRat3(ZoneNum) = state.dataHeatBalFanSys->PreviousMeasuredHumRat2(ZoneNum);
    5435         600 :     state.dataHeatBalFanSys->PreviousMeasuredHumRat2(ZoneNum) = state.dataHeatBalFanSys->PreviousMeasuredHumRat1(ZoneNum);
    5436         600 :     state.dataHeatBalFanSys->PreviousMeasuredHumRat1(ZoneNum) = zone.ZoneMeasuredHumidityRatio;
    5437         600 : }
    5438             : 
    5439    55917634 : void ZoneSpaceHeatBalanceData::calcZoneOrSpaceSums(EnergyPlusData &state,
    5440             :                                                    bool const CorrectorFlag, // Corrector call flag
    5441             :                                                    int const zoneNum,
    5442             :                                                    int const spaceNum)
    5443             : {
    5444             : 
    5445             :     // SUBROUTINE INFORMATION:
    5446             :     //       AUTHOR         Peter Graham Ellis
    5447             :     //       DATE WRITTEN   July 2003
    5448             :     //       MODIFIED       Aug 2003, FCW: add this->SumHA contributions from window frame and divider
    5449             :     //                      Aug 2003, CC: change how the reference temperatures are used
    5450             : 
    5451             :     // PURPOSE OF THIS SUBROUTINE:
    5452             :     // This subroutine calculates the various sums that go into the zone heat balance
    5453             :     // equation.  This replaces the SUMC, SumHA, and SumHAT calculations that were
    5454             :     // previously done in various places throughout the program.
    5455             :     // The SumHAT portion of the code is reproduced in RadiantSystemHighTemp and
    5456             :     // RadiantSystemLowTemp and should be updated accordingly.
    5457             :     // A reference temperature (Tref) is specified for use with the ceiling diffuser
    5458             :     // convection correlation.  A bogus value of Tref = -999.9 defaults to using
    5459             :     // the zone air (i.e. outlet) temperature for the reference temperature.
    5460             :     // If Tref is applied to all surfaces, SumHA = 0, and SumHATref /= 0.
    5461             :     // If Tref is not used at all, SumHATref = 0, and SumHA /= 0.
    5462             :     // For future implementations, Tref can be easily converted into an array to
    5463             :     // allow a different reference temperature to be specified for each surface.
    5464    55917634 :     assert(zoneNum > 0);
    5465             : 
    5466    55917634 :     this->SumHA = 0.0;
    5467    55917634 :     this->SumHATsurf = 0.0;
    5468    55917634 :     this->SumHATref = 0.0;
    5469    55917634 :     this->SumSysMCp = 0.0;
    5470    55917634 :     this->SumSysMCpT = 0.0;
    5471             :     // Sum all convective internal gains: this->SumIntGain
    5472    55917634 :     if (spaceNum == 0) {
    5473    55857610 :         this->SumIntGain = InternalHeatGains::zoneSumAllInternalConvectionGains(state, zoneNum);
    5474             :     } else {
    5475       60024 :         this->SumIntGain = InternalHeatGains::spaceSumAllInternalConvectionGains(state, spaceNum);
    5476             :     }
    5477    55917634 :     this->SumIntGain += state.dataHeatBalFanSys->SumConvHTRadSys(zoneNum) + state.dataHeatBalFanSys->SumConvPool(zoneNum);
    5478             : 
    5479             :     // Add heat to return air if zonal system (no return air) or cycling system (return air frequently very low or zero)
    5480    55917634 :     assert(zoneNum > 0);
    5481    55917634 :     auto &thisZone = state.dataHeatBal->Zone(zoneNum);
    5482    55917634 :     if (thisZone.NoHeatToReturnAir) {
    5483     6103524 :         if (spaceNum == 0) {
    5484     6103524 :             this->SumIntGain += InternalHeatGains::zoneSumAllReturnAirConvectionGains(state, zoneNum, 0);
    5485             :         } else {
    5486           0 :             this->SumIntGain += InternalHeatGains::spaceSumAllReturnAirConvectionGains(state, spaceNum, 0);
    5487             :         }
    5488             :     }
    5489             : 
    5490             :     // Sum all non-system air flow, i.e. infiltration, simple ventilation, mixing, earth tube: this->SumMCp, this->SumMCpT
    5491    55917634 :     this->SumMCp = this->MCPI + this->MCPV + this->MCPM + this->MCPE + this->MCPC + this->MDotCPOA;
    5492    55917634 :     this->SumMCpT = this->MCPTI + this->MCPTV + this->MCPTM + this->MCPTE + this->MCPTC + this->MDotCPOA * thisZone.OutDryBulbTemp;
    5493             : 
    5494             :     // Sum all multizone air flow calculated from AirflowNetwork by assuming no simple air infiltration model
    5495   111871759 :     if (state.afn->multizone_always_simulated ||
    5496    54960144 :         (state.afn->simulation_control.type == AirflowNetwork::ControlType::MultizoneWithDistributionOnlyDuringFanOperation &&
    5497       46600 :          state.afn->AirflowNetworkFanActivated)) {
    5498     1040581 :         auto &exchangeData = state.afn->exchangeData(zoneNum);
    5499     1040581 :         this->SumMCp = exchangeData.SumMCp + exchangeData.SumMVCp + exchangeData.SumMMCp;
    5500     1040581 :         this->SumMCpT = exchangeData.SumMCpT + exchangeData.SumMVCpT + exchangeData.SumMMCpT;
    5501             :     }
    5502             : 
    5503             :     // Sum all system air flow: this->SumSysMCp, this->SumSysMCpT and check to see if this is a controlled zone
    5504    55917634 :     if (CorrectorFlag) {
    5505             :         // Plenum and controlled zones have a different set of inlet nodes which must be calculated.
    5506    27958103 :         if (thisZone.IsControlled) {
    5507    23861098 :             auto const &zec(state.dataZoneEquip->ZoneEquipConfig(zoneNum));
    5508    48058619 :             for (int NodeNum = 1, NodeNum_end = zec.NumInletNodes; NodeNum <= NodeNum_end; ++NodeNum) {
    5509             :                 // Get node conditions, this next block is of interest to irratic system loads... maybe nodes are not accurate at time of call?
    5510             :                 //  how can we tell?  predict step must be lagged ?  correct step, systems have run.
    5511    24197521 :                 auto const &node(state.dataLoopNodes->Node(zec.InletNode(NodeNum)));
    5512    24197521 :                 Real64 CpAir = Psychrometrics::PsyCpAirFnW(this->ZoneAirHumRat);
    5513    24197521 :                 Real64 const MassFlowRate_CpAir(node.MassFlowRate * CpAir);
    5514    24197521 :                 this->SumSysMCp += MassFlowRate_CpAir;
    5515    24197521 :                 this->SumSysMCpT += MassFlowRate_CpAir * node.Temp;
    5516             :             }
    5517             : 
    5518     4097005 :         } else if (thisZone.IsReturnPlenum) {
    5519     1051397 :             auto const &zrpc(state.dataZonePlenum->ZoneRetPlenCond(thisZone.PlenumCondNum));
    5520     1051397 :             Real64 const air_hum_rat(this->ZoneAirHumRat);
    5521     6087908 :             for (int NodeNum = 1, NodeNum_end = zrpc.NumInletNodes; NodeNum <= NodeNum_end; ++NodeNum) {
    5522     5036511 :                 auto const &node(state.dataLoopNodes->Node(zrpc.InletNode(NodeNum)));
    5523     5036511 :                 Real64 const MassFlowRate_CpAir(node.MassFlowRate * Psychrometrics::PsyCpAirFnW(air_hum_rat));
    5524     5036511 :                 this->SumSysMCp += MassFlowRate_CpAir;
    5525     5036511 :                 this->SumSysMCpT += MassFlowRate_CpAir * node.Temp;
    5526             :             }
    5527             :             // add in the leaks
    5528     6046913 :             for (int ADUListIndex = 1, ADUListIndex_end = zrpc.NumADUs; ADUListIndex <= ADUListIndex_end; ++ADUListIndex) {
    5529     4995516 :                 auto &airDistUnit = state.dataDefineEquipment->AirDistUnit(zrpc.ADUIndex(ADUListIndex));
    5530     4995516 :                 if (airDistUnit.UpStreamLeak) {
    5531      108695 :                     Real64 const MassFlowRate_CpAir(airDistUnit.MassFlowRateUpStrLk * Psychrometrics::PsyCpAirFnW(air_hum_rat));
    5532      108695 :                     this->SumSysMCp += MassFlowRate_CpAir;
    5533      108695 :                     this->SumSysMCpT += MassFlowRate_CpAir * state.dataLoopNodes->Node(airDistUnit.InletNodeNum).Temp;
    5534             :                 }
    5535     4995516 :                 if (airDistUnit.DownStreamLeak) {
    5536      108695 :                     Real64 const MassFlowRate_CpAir(airDistUnit.MassFlowRateDnStrLk * Psychrometrics::PsyCpAirFnW(air_hum_rat));
    5537      108695 :                     this->SumSysMCp += MassFlowRate_CpAir;
    5538      108695 :                     this->SumSysMCpT += MassFlowRate_CpAir * state.dataLoopNodes->Node(airDistUnit.OutletNodeNum).Temp;
    5539             :                 }
    5540             :             }
    5541             : 
    5542     3045608 :         } else if (thisZone.IsSupplyPlenum) {
    5543       19758 :             Real64 MassFlowRate = state.dataLoopNodes->Node(state.dataZonePlenum->ZoneSupPlenCond(thisZone.PlenumCondNum).InletNode).MassFlowRate;
    5544       19758 :             Real64 CpAir = Psychrometrics::PsyCpAirFnW(this->ZoneAirHumRat);
    5545       19758 :             this->SumSysMCp += MassFlowRate * CpAir;
    5546       19758 :             this->SumSysMCpT +=
    5547       19758 :                 MassFlowRate * CpAir * state.dataLoopNodes->Node(state.dataZonePlenum->ZoneSupPlenCond(thisZone.PlenumCondNum).InletNode).Temp;
    5548             :         }
    5549             : 
    5550    27958103 :         int ZoneMult = thisZone.Multiplier * thisZone.ListMultiplier;
    5551             : 
    5552    27958103 :         this->SumSysMCp /= ZoneMult;
    5553    27958103 :         this->SumSysMCpT /= ZoneMult;
    5554             :     }
    5555             : 
    5556    55917634 :     if (spaceNum > 0) {
    5557       60024 :         Real64 spaceFrac = state.dataHeatBal->space(spaceNum).fracZoneVolume;
    5558       60024 :         this->SumSysMCp *= spaceFrac;
    5559       60024 :         this->SumSysMCpT *= spaceFrac;
    5560             :     }
    5561             : 
    5562             :     // Sum all surface convection: this->SumHA, this->SumHATsurf, this->SumHATref (and additional contributions to this->SumIntGain)
    5563    55917634 :     SumHATOutput sumHATResults; // space or zone return values
    5564    55917634 :     sumHATResults = this->calcSumHAT(state, zoneNum, spaceNum);
    5565    55917634 :     this->SumIntGain += sumHATResults.sumIntGain;
    5566    55917634 :     this->SumHA = sumHATResults.sumHA;
    5567    55917634 :     this->SumHATsurf = sumHATResults.sumHATsurf;
    5568    55917634 :     this->SumHATref = sumHATResults.sumHATref;
    5569    55917634 : }
    5570             : 
    5571    55857610 : SumHATOutput ZoneHeatBalanceData::calcSumHAT(EnergyPlusData &state, int const zoneNum, [[maybe_unused]] int const spaceNum)
    5572             : {
    5573    55857610 :     assert(zoneNum > 0);
    5574    55857610 :     assert(spaceNum == 0);
    5575    55857610 :     SumHATOutput zoneResults; // zone-level return values
    5576   111757212 :     for (int zoneSpaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
    5577    55899602 :         SumHATOutput spaceResults; // temporary return value from space-level calcSumHAT
    5578    55899602 :         spaceResults = state.dataZoneTempPredictorCorrector->spaceHeatBalance(zoneSpaceNum).calcSumHAT(state, zoneNum, zoneSpaceNum);
    5579    55899602 :         zoneResults.sumIntGain += spaceResults.sumIntGain;
    5580    55899602 :         zoneResults.sumHA += spaceResults.sumHA;
    5581    55899602 :         zoneResults.sumHATsurf += spaceResults.sumHATsurf;
    5582    55899602 :         zoneResults.sumHATref += spaceResults.sumHATref;
    5583             :     }
    5584    55857610 :     return zoneResults;
    5585             : }
    5586             : 
    5587    55959626 : SumHATOutput SpaceHeatBalanceData::calcSumHAT(EnergyPlusData &state, int const zoneNum, int const spaceNum)
    5588             : {
    5589    55959626 :     assert(zoneNum > 0);
    5590    55959626 :     assert(spaceNum > 0);
    5591    55959626 :     auto &thisZone = state.dataHeatBal->Zone(zoneNum);
    5592    55959626 :     auto &thisSpace = state.dataHeatBal->space(spaceNum);
    5593    55959626 :     SumHATOutput results; // space-level return values
    5594             : 
    5595   545551570 :     for (int SurfNum = thisSpace.HTSurfaceFirst; SurfNum <= thisSpace.HTSurfaceLast; ++SurfNum) {
    5596   489591944 :         Real64 HA = 0.0;
    5597   489591944 :         Real64 Area = state.dataSurface->Surface(SurfNum).Area; // For windows, this is the glazing area
    5598             : 
    5599   489591944 :         if (state.dataSurface->Surface(SurfNum).Class == DataSurfaces::SurfaceClass::Window) {
    5600    68937024 :             DataSurfaces::WinShadingType const shading_flag = state.dataSurface->SurfWinShadingFlag(SurfNum);
    5601             : 
    5602             :             // Add to the convective internal gains
    5603    68937024 :             if (ANY_INTERIOR_SHADE_BLIND(shading_flag)) {
    5604             :                 // The shade area covers the area of the glazing plus the area of the dividers.
    5605      294786 :                 Area += state.dataSurface->SurfWinDividerArea(SurfNum);
    5606             :                 // If interior shade or blind is present it is assumed that both the convective and IR radiative gain
    5607             :                 // from the inside surface of the divider goes directly into the zone air -- i.e., the IR radiative
    5608             :                 // interaction between divider and shade or blind is ignored due to the difficulty of calculating this interaction
    5609             :                 // at the same time that the interaction between glass and shade is calculated.
    5610      294786 :                 results.sumIntGain += state.dataSurface->SurfWinDividerHeatGain(SurfNum);
    5611             :             }
    5612             : 
    5613             :             // Other convection term is applicable to equivalent layer window (ASHWAT) model
    5614    68937024 :             if (state.dataConstruction->Construct(state.dataSurface->Surface(SurfNum).Construction).WindowTypeEQL)
    5615       16350 :                 results.sumIntGain += state.dataSurface->SurfWinOtherConvHeatGain(SurfNum);
    5616             : 
    5617             :             // Convective heat gain from natural convection in gap between glass and interior shade or blind
    5618    68937024 :             if (ANY_INTERIOR_SHADE_BLIND(shading_flag)) results.sumIntGain += state.dataSurface->SurfWinConvHeatFlowNatural(SurfNum);
    5619             : 
    5620             :             // Convective heat gain from airflow window
    5621    68937024 :             if (state.dataSurface->SurfWinAirflowThisTS(SurfNum) > 0.0) {
    5622       40832 :                 results.sumIntGain += state.dataSurface->SurfWinConvHeatGainToZoneAir(SurfNum);
    5623       40832 :                 if (thisZone.NoHeatToReturnAir) {
    5624       40736 :                     results.sumIntGain += state.dataSurface->SurfWinRetHeatGainToZoneAir(SurfNum);
    5625       40736 :                     state.dataSurface->SurfWinHeatGain(SurfNum) += state.dataSurface->SurfWinRetHeatGainToZoneAir(SurfNum);
    5626       40736 :                     if (state.dataSurface->SurfWinHeatGain(SurfNum) >= 0.0) {
    5627       11024 :                         state.dataSurface->SurfWinHeatGainRep(SurfNum) = state.dataSurface->SurfWinHeatGain(SurfNum);
    5628       11024 :                         state.dataSurface->SurfWinHeatGainRepEnergy(SurfNum) =
    5629       11024 :                             state.dataSurface->SurfWinHeatGainRep(SurfNum) * state.dataGlobal->TimeStepZoneSec;
    5630             :                     } else {
    5631       29712 :                         state.dataSurface->SurfWinHeatLossRep(SurfNum) = -state.dataSurface->SurfWinHeatGain(SurfNum);
    5632       29712 :                         state.dataSurface->SurfWinHeatLossRepEnergy(SurfNum) =
    5633       29712 :                             state.dataSurface->SurfWinHeatLossRep(SurfNum) * state.dataGlobal->TimeStepZoneSec;
    5634             :                     }
    5635       40736 :                     state.dataSurface->SurfWinHeatTransferRepEnergy(SurfNum) =
    5636       40736 :                         state.dataSurface->SurfWinHeatGain(SurfNum) * state.dataGlobal->TimeStepZoneSec;
    5637             :                 }
    5638             :             }
    5639             : 
    5640             :             // Add to the surface convection sums
    5641    68937024 :             if (state.dataSurface->SurfWinFrameArea(SurfNum) > 0.0) {
    5642             :                 // Window frame contribution
    5643     2740914 :                 Real64 const HA_surf(state.dataHeatBalSurf->SurfHConvInt(SurfNum) * state.dataSurface->SurfWinFrameArea(SurfNum) *
    5644     2740914 :                                      (1.0 + state.dataSurface->SurfWinProjCorrFrIn(SurfNum)));
    5645     2740914 :                 results.sumHATsurf += HA_surf * state.dataSurface->SurfWinFrameTempIn(SurfNum);
    5646     2740914 :                 HA += HA_surf;
    5647             :             }
    5648             : 
    5649    68937024 :             if (state.dataSurface->SurfWinDividerArea(SurfNum) > 0.0 && !ANY_INTERIOR_SHADE_BLIND(shading_flag)) {
    5650             :                 // Window divider contribution (only from shade or blind for window with divider and interior shade or blind)
    5651      859216 :                 Real64 const HA_surf(state.dataHeatBalSurf->SurfHConvInt(SurfNum) * state.dataSurface->SurfWinDividerArea(SurfNum) *
    5652      859216 :                                      (1.0 + 2.0 * state.dataSurface->SurfWinProjCorrDivIn(SurfNum)));
    5653      859216 :                 results.sumHATsurf += HA_surf * state.dataSurface->SurfWinDividerTempIn(SurfNum);
    5654      859216 :                 HA += HA_surf;
    5655             :             }
    5656             : 
    5657             :         } // End of check if window
    5658             : 
    5659   489591944 :         HA += state.dataHeatBalSurf->SurfHConvInt(SurfNum) * Area;
    5660   489591944 :         results.sumHATsurf += state.dataHeatBalSurf->SurfHConvInt(SurfNum) * Area * state.dataHeatBalSurf->SurfTempInTmp(SurfNum);
    5661             : 
    5662             :         // determine reference air temperature for this surface
    5663   489591944 :         switch (state.dataSurface->SurfTAirRef(SurfNum)) {
    5664     3100962 :         case DataSurfaces::RefAirTemp::ZoneMeanAirTemp:
    5665             :             // The zone air is the reference temperature (which is to be solved for in CorrectZoneAirTemp).
    5666     3100962 :             results.sumHA += HA;
    5667     3100962 :             break;
    5668     4463135 :         case DataSurfaces::RefAirTemp::AdjacentAirTemp:
    5669     4463135 :             results.sumHATref += HA * state.dataHeatBal->SurfTempEffBulkAir(SurfNum);
    5670     4463135 :             break;
    5671           0 :         case DataSurfaces::RefAirTemp::ZoneSupplyAirTemp:
    5672             :             // check whether this zone is a controlled zone or not
    5673           0 :             if (!thisZone.IsControlled) {
    5674           0 :                 ShowFatalError(state, "Zones must be controlled for Ceiling-Diffuser Convection model. No system serves zone " + thisZone.Name);
    5675           0 :                 return results;
    5676             :             }
    5677             :             // determine supply air temperature as a weighted average of the inlet temperatures.
    5678             :             // TODO: For now, use zone-level values for system flow
    5679           0 :             if (state.dataZoneTempPredictorCorrector->zoneHeatBalance(zoneNum).SumSysMCp > 0.0) {
    5680           0 :                 results.sumHATref += HA * state.dataZoneTempPredictorCorrector->zoneHeatBalance(zoneNum).SumSysMCpT /
    5681           0 :                                      state.dataZoneTempPredictorCorrector->zoneHeatBalance(zoneNum).SumSysMCp;
    5682             :             } else {
    5683             :                 // no system flow (yet) so just use zone air temperature #5906
    5684           0 :                 results.sumHA += HA;
    5685             :             }
    5686           0 :             break;
    5687   482027847 :         default:
    5688             :             // currently set to mean air temp but should add error warning here
    5689   482027847 :             results.sumHA += HA;
    5690   482027847 :             break;
    5691             :         }
    5692             : 
    5693             :     } // SurfNum
    5694    55959626 :     return results;
    5695             : }
    5696    27958103 : void CalcZoneComponentLoadSums(EnergyPlusData &state,
    5697             :                                int const ZoneNum,        // Zone number
    5698             :                                Real64 const TempDepCoef, // Dependent coefficient
    5699             :                                Real64 const TempIndCoef, // Independent coefficient
    5700             :                                Real64 &SumIntGains,      // Zone sum of convective internal gains
    5701             :                                Real64 &SumHADTsurfs,     // Zone sum of Hc*Area*(Tsurf - Tz)
    5702             :                                Real64 &SumMCpDTzones,    // zone sum of MassFlowRate*cp*(TremotZone - Tz) transfer air from other zone, Mixing
    5703             :                                Real64 &SumMCpDtInfil,    // Zone sum of MassFlowRate*Cp*(Tout - Tz) transfer from outside, ventil, earth tube
    5704             :                                Real64 &SumMCpDTsystem,   // Zone sum of air system MassFlowRate*Cp*(Tsup - Tz)
    5705             :                                Real64 &SumNonAirSystem,  // Zone sum of non air system convective heat gains
    5706             :                                Real64 &CzdTdt,           // Zone air energy storage term.
    5707             :                                Real64 &imBalance,        // put all terms in eq. 5 on RHS , should be zero
    5708             :                                Real64 &SumEnthalpyM,     // Zone sum of phase change material melting enthlpy
    5709             :                                Real64 &SumEnthalpyH      // Zone sum of phase change material freezing enthalpy
    5710             : )
    5711             : {
    5712             : 
    5713             :     // SUBROUTINE INFORMATION:
    5714             :     //       AUTHOR         Brent Griffith
    5715             :     //       DATE WRITTEN   Feb 2008
    5716             : 
    5717             :     // PURPOSE OF THIS SUBROUTINE:
    5718             :     // This subroutine calculates the various sums that go into the zone heat balance
    5719             :     // equation for reporting (and diagnostic) purposes only.
    5720             :     // It was derived from CalcZoneSums but differs in that that routine
    5721             :     // breaks up the component's dependence on zone air temp in order to *solve* for zone air temp,
    5722             :     // but here we *use* the result for zone air temp and calculate the terms of the heat balance
    5723             :     // Go back and calculate each of the 6 terms in Equation 5 and fill report variables.
    5724             :     // notes on these raw terms for zone air heat balance model :
    5725             :     //  these are state variables at the end of the last system timestep.
    5726             :     //  they are not necessarily proper averages for what happened over entire zone time step
    5727             :     //  these are not multiplied by zone multipliers.
    5728             :     //  The values are all Watts.
    5729             : 
    5730             :     // REFERENCES:
    5731             :     // Equation 5 in Engineering Reference.
    5732             : 
    5733    27958103 :     SumIntGains = 0.0;    // Zone sum of convective internal gains
    5734    27958103 :     SumHADTsurfs = 0.0;   // Zone sum of Hc*Area*(Tsurf - Tz)
    5735    27958103 :     SumMCpDTzones = 0.0;  // zone sum of MassFlowRate*cp*(TremotZone - Tz) transfer air from other zone, Mixing
    5736    27958103 :     SumMCpDtInfil = 0.0;  // Zone sum of MassFlowRate*Cp*(Tout - Tz)
    5737    27958103 :     SumMCpDTsystem = 0.0; // Zone sum of air system MassFlowRate*Cp*(Tsup - Tz)
    5738    27958103 :     SumNonAirSystem = 0.0;
    5739    27958103 :     CzdTdt = 0.0;
    5740    27958103 :     imBalance = 0.0;
    5741    27958103 :     SumEnthalpyM = 0.0;
    5742    27958103 :     SumEnthalpyH = 0.0;
    5743             : 
    5744    27958103 :     auto &thisZone = state.dataHeatBal->Zone(ZoneNum);
    5745    27958103 :     auto const &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum);
    5746             : 
    5747             :     // Sum all convective internal gains: SumIntGain
    5748    27958103 :     SumIntGains = InternalHeatGains::zoneSumAllInternalConvectionGains(state, ZoneNum);
    5749             : 
    5750             :     // Add heat to return air if zonal system (no return air) or cycling system (return air frequently very
    5751             :     // low or zero)
    5752    27958103 :     if (thisZone.NoHeatToReturnAir) {
    5753     3051762 :         SumIntGains += InternalHeatGains::zoneSumAllReturnAirConvectionGains(state, ZoneNum, 0);
    5754             :     }
    5755             : 
    5756             :     // sum non-system air flow transfers between zones
    5757    27958103 :     SumMCpDTzones = thisZoneHB.MCPTM - thisZoneHB.MCPM * thisZoneHB.MAT; // but maybe it should be ZTAV(ZoneNum)
    5758             : 
    5759             :     // Sum non-system air flow, i.e. infiltration, simple ventilation, earth tube
    5760             :     //  reuse SumMCp, SumMCpT from CalcZoneSum but use MAT (or maybe ZTAV?) to complete
    5761    83874309 :     SumMCpDtInfil = (thisZoneHB.MCPTI - thisZoneHB.MCPI * thisZoneHB.MAT) + (thisZoneHB.MCPTV - thisZoneHB.MCPV * thisZoneHB.MAT) +
    5762    83874309 :                     (thisZoneHB.MCPTE - thisZoneHB.MCPE * thisZoneHB.MAT) + (thisZoneHB.MCPTC - thisZoneHB.MCPC * thisZoneHB.MAT) +
    5763    55916206 :                     (thisZoneHB.MDotCPOA * thisZone.OutDryBulbTemp -
    5764    27958103 :                      thisZoneHB.MDotCPOA * thisZoneHB.MAT); // infiltration | Ventilation (simple) | Earth tube. | Cooltower | combined OA flow
    5765             : 
    5766             :     // Sum all multizone air flow calculated from AirflowNetwork by assuming no simple air infiltration model (if used)
    5767    55934458 :     if (state.afn->multizone_always_simulated ||
    5768    27479358 :         (state.afn->simulation_control.type == AirflowNetwork::ControlType::MultizoneWithDistributionOnlyDuringFanOperation &&
    5769       23300 :          state.afn->AirflowNetworkFanActivated)) {
    5770             :         // Multizone airflow calculated in AirflowNetwork
    5771     1040594 :         SumMCpDtInfil = state.afn->exchangeData(ZoneNum).SumMCpT + state.afn->exchangeData(ZoneNum).SumMVCpT -
    5772      520297 :                         (state.afn->exchangeData(ZoneNum).SumMCp + state.afn->exchangeData(ZoneNum).SumMVCp) * thisZoneHB.MAT;
    5773      520297 :         SumMCpDTzones = state.afn->exchangeData(ZoneNum).SumMMCpT - state.afn->exchangeData(ZoneNum).SumMMCp * thisZoneHB.MAT;
    5774             :     }
    5775             : 
    5776             :     // Sum all system air flow: reusing how SumSysMCp, SumSysMCpT are calculated in CalcZoneSums
    5777             :     // Plenum and controlled zones have a different set of inlet nodes which must be calculated.
    5778    27958103 :     Real64 QSensRate = 0.0;
    5779    27958103 :     if (thisZone.IsControlled) {
    5780    23861098 :         auto &zoneEquipConfig = state.dataZoneEquip->ZoneEquipConfig(ZoneNum);
    5781    48058619 :         for (int NodeNum = 1; NodeNum <= zoneEquipConfig.NumInletNodes; ++NodeNum) {
    5782             :             // Get node conditions
    5783    24197521 :             Real64 const NodeTemp = state.dataLoopNodes->Node(zoneEquipConfig.InletNode(NodeNum)).Temp;
    5784    24197521 :             Real64 const MassFlowRate = state.dataLoopNodes->Node(zoneEquipConfig.InletNode(NodeNum)).MassFlowRate;
    5785    24197521 :             QSensRate = calcZoneSensibleOutput(MassFlowRate, NodeTemp, thisZoneHB.MAT, thisZoneHB.ZoneAirHumRat);
    5786    24197521 :             SumMCpDTsystem += QSensRate;
    5787             : 
    5788    24197521 :             if (zoneEquipConfig.InletNodeADUNum(NodeNum) > 0) {
    5789    12936980 :                 auto &airDistUnit = state.dataDefineEquipment->AirDistUnit(zoneEquipConfig.InletNodeADUNum(NodeNum));
    5790    12936980 :                 Real64 ADUHeatAddRate = calcZoneSensibleOutput(state.dataLoopNodes->Node(airDistUnit.OutletNodeNum).MassFlowRate,
    5791    12936980 :                                                                state.dataLoopNodes->Node(airDistUnit.OutletNodeNum).Temp,
    5792    12936980 :                                                                thisZoneHB.MAT,
    5793    25873960 :                                                                thisZoneHB.ZoneAirHumRat);
    5794    12936980 :                 airDistUnit.HeatRate = max(0.0, ADUHeatAddRate);
    5795    12936980 :                 airDistUnit.CoolRate = std::abs(min(0.0, ADUHeatAddRate));
    5796    12936980 :                 airDistUnit.HeatGain = airDistUnit.HeatRate * state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour;
    5797    12936980 :                 airDistUnit.CoolGain = airDistUnit.CoolRate * state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour;
    5798             :             }
    5799             :         }
    5800             : 
    5801     4097005 :     } else if (thisZone.IsReturnPlenum) {
    5802     1051397 :         auto &zoneRetPlenCond = state.dataZonePlenum->ZoneRetPlenCond(thisZone.PlenumCondNum);
    5803     6087908 :         for (int NodeNum = 1; NodeNum <= zoneRetPlenCond.NumInletNodes; ++NodeNum) {
    5804     5036511 :             QSensRate = calcZoneSensibleOutput(state.dataLoopNodes->Node(zoneRetPlenCond.InletNode(NodeNum)).MassFlowRate,
    5805     5036511 :                                                state.dataLoopNodes->Node(zoneRetPlenCond.InletNode(NodeNum)).Temp,
    5806     5036511 :                                                thisZoneHB.MAT,
    5807     5036511 :                                                thisZoneHB.ZoneAirHumRat);
    5808     5036511 :             SumMCpDTsystem += QSensRate;
    5809             :         }
    5810             :         // add in the leaks
    5811     6046913 :         for (int ADUListIndex = 1; ADUListIndex <= zoneRetPlenCond.NumADUs; ++ADUListIndex) {
    5812     4995516 :             auto &airDistUnit = state.dataDefineEquipment->AirDistUnit(zoneRetPlenCond.ADUIndex(ADUListIndex));
    5813     4995516 :             if (airDistUnit.UpStreamLeak) {
    5814      108695 :                 QSensRate = calcZoneSensibleOutput(airDistUnit.MassFlowRateUpStrLk,
    5815      108695 :                                                    state.dataLoopNodes->Node(airDistUnit.InletNodeNum).Temp,
    5816      108695 :                                                    thisZoneHB.MAT,
    5817      108695 :                                                    thisZoneHB.ZoneAirHumRat);
    5818      108695 :                 SumMCpDTsystem += QSensRate;
    5819             :             }
    5820     4995516 :             if (airDistUnit.DownStreamLeak) {
    5821      108695 :                 QSensRate = calcZoneSensibleOutput(airDistUnit.MassFlowRateDnStrLk,
    5822      108695 :                                                    state.dataLoopNodes->Node(airDistUnit.OutletNodeNum).Temp,
    5823      108695 :                                                    thisZoneHB.MAT,
    5824      108695 :                                                    thisZoneHB.ZoneAirHumRat);
    5825      108695 :                 SumMCpDTsystem += QSensRate;
    5826             :             }
    5827             :         }
    5828             : 
    5829     3045608 :     } else if (thisZone.IsSupplyPlenum) {
    5830       19758 :         auto &zoneSupPlenCond = state.dataZonePlenum->ZoneSupPlenCond(thisZone.PlenumCondNum);
    5831       19758 :         QSensRate = calcZoneSensibleOutput(state.dataLoopNodes->Node(zoneSupPlenCond.InletNode).MassFlowRate,
    5832       19758 :                                            state.dataLoopNodes->Node(zoneSupPlenCond.InletNode).Temp,
    5833       19758 :                                            thisZoneHB.MAT,
    5834       19758 :                                            thisZoneHB.ZoneAirHumRat);
    5835       19758 :         SumMCpDTsystem += QSensRate;
    5836             :     }
    5837             : 
    5838             :     // non air system response.
    5839    27958103 :     SumNonAirSystem =
    5840    27958103 :         thisZoneHB.NonAirSystemResponse + state.dataHeatBalFanSys->SumConvHTRadSys(ZoneNum) + state.dataHeatBalFanSys->SumConvPool(ZoneNum);
    5841             : 
    5842             :     // Sum all surface convection: SumHA, SumHATsurf, SumHATref (and additional contributions to SumIntGain)
    5843    55937202 :     for (int spaceNum : state.dataHeatBal->Zone(ZoneNum).spaceIndexes) {
    5844    27979099 :         auto &thisSpace = state.dataHeatBal->space(spaceNum);
    5845   272769597 :         for (int SurfNum = thisSpace.HTSurfaceFirst; SurfNum <= thisSpace.HTSurfaceLast; ++SurfNum) {
    5846             : 
    5847   244790498 :             Real64 Area = state.dataSurface->Surface(SurfNum).Area; // For windows, this is the glazing area
    5848   244790498 :             Real64 RefAirTemp = state.dataSurface->Surface(SurfNum).getInsideAirTemperature(state, SurfNum);
    5849             : 
    5850   244790498 :             if (state.dataSurface->Surface(SurfNum).Class == DataSurfaces::SurfaceClass::Window) {
    5851             : 
    5852             :                 // Add to the convective internal gains
    5853    34467798 :                 if (ANY_INTERIOR_SHADE_BLIND(state.dataSurface->SurfWinShadingFlag(SurfNum))) {
    5854             :                     // The shade area covers the area of the glazing plus the area of the dividers.
    5855      147393 :                     Area += state.dataSurface->SurfWinDividerArea(SurfNum);
    5856             :                     // If interior shade or blind is present it is assumed that both the convective and IR radiative gain
    5857             :                     // from the inside surface of the divider goes directly into the zone air -- i.e., the IR radiative
    5858             :                     // interaction between divider and shade or blind is ignored due to the difficulty of calculating this interaction
    5859             :                     // at the same time that the interaction between glass and shade is calculated.
    5860      147393 :                     SumIntGains += state.dataSurface->SurfWinDividerHeatGain(SurfNum);
    5861             :                 }
    5862             : 
    5863             :                 // Other convection term is applicable to equivalent layer window (ASHWAT) model
    5864    34467798 :                 if (state.dataConstruction->Construct(state.dataSurface->Surface(SurfNum).Construction).WindowTypeEQL)
    5865        8175 :                     SumIntGains += state.dataSurface->SurfWinOtherConvHeatGain(SurfNum);
    5866             : 
    5867             :                 // Convective heat gain from natural convection in gap between glass and interior shade or blind
    5868    34467798 :                 if (ANY_INTERIOR_SHADE_BLIND(state.dataSurface->SurfWinShadingFlag(SurfNum)))
    5869      147393 :                     SumIntGains += state.dataSurface->SurfWinConvHeatFlowNatural(SurfNum);
    5870             : 
    5871             :                 // Convective heat gain from airflow window
    5872    34467798 :                 if (state.dataSurface->SurfWinAirflowThisTS(SurfNum) > 0.0) {
    5873       20416 :                     SumIntGains += state.dataSurface->SurfWinConvHeatGainToZoneAir(SurfNum);
    5874       20416 :                     if (thisZone.NoHeatToReturnAir) {
    5875       20368 :                         SumIntGains += state.dataSurface->SurfWinRetHeatGainToZoneAir(SurfNum);
    5876             :                     }
    5877             :                 }
    5878             : 
    5879             :                 // Add to the surface convection sums
    5880    34467798 :                 if (state.dataSurface->SurfWinFrameArea(SurfNum) > 0.0) {
    5881             :                     // Window frame contribution
    5882     4111371 :                     SumHADTsurfs += state.dataHeatBalSurf->SurfHConvInt(SurfNum) * state.dataSurface->SurfWinFrameArea(SurfNum) *
    5883     2740914 :                                     (1.0 + state.dataSurface->SurfWinProjCorrFrIn(SurfNum)) *
    5884     1370457 :                                     (state.dataSurface->SurfWinFrameTempIn(SurfNum) - RefAirTemp);
    5885             :                 }
    5886             : 
    5887    34900395 :                 if (state.dataSurface->SurfWinDividerArea(SurfNum) > 0.0 &&
    5888      432597 :                     !ANY_INTERIOR_SHADE_BLIND(state.dataSurface->SurfWinShadingFlag(SurfNum))) {
    5889             :                     // Window divider contribution (only from shade or blind for window with divider and interior shade or blind)
    5890     1288824 :                     SumHADTsurfs += state.dataHeatBalSurf->SurfHConvInt(SurfNum) * state.dataSurface->SurfWinDividerArea(SurfNum) *
    5891      859216 :                                     (1.0 + 2.0 * state.dataSurface->SurfWinProjCorrDivIn(SurfNum)) *
    5892      429608 :                                     (state.dataSurface->SurfWinDividerTempIn(SurfNum) - RefAirTemp);
    5893             :                 }
    5894             : 
    5895             :             } // End of check if window
    5896             : 
    5897   244790498 :             SumHADTsurfs += state.dataHeatBalSurf->SurfHConvInt(SurfNum) * Area * (state.dataHeatBalSurf->SurfTempInTmp(SurfNum) - RefAirTemp);
    5898             : 
    5899             :             // Accumulate Zone Phase Change Material Melting/Freezing Enthalpy output variables
    5900   244790498 :             if (state.dataSurface->Surface(SurfNum).HeatTransferAlgorithm == DataSurfaces::HeatTransferModel::CondFD) {
    5901     1568382 :                 state.dataHeatBal->ZnAirRpt(ZoneNum).SumEnthalpyM += state.dataHeatBalFiniteDiffMgr->SurfaceFD(SurfNum).EnthalpyM;
    5902     1568382 :                 state.dataHeatBal->ZnAirRpt(ZoneNum).SumEnthalpyH += state.dataHeatBalFiniteDiffMgr->SurfaceFD(SurfNum).EnthalpyF;
    5903             :             }
    5904             :         }
    5905             :     }
    5906             :     // now calculate air energy storage source term.
    5907             :     // capacitance is volume * density * heat capacity
    5908    27958103 :     Real64 CpAir = Psychrometrics::PsyCpAirFnW(thisZoneHB.ZoneAirHumRat);
    5909    27958103 :     Real64 RhoAir = Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, thisZoneHB.MAT, thisZoneHB.ZoneAirHumRat);
    5910             : 
    5911    27958103 :     switch (state.dataHeatBal->ZoneAirSolutionAlgo) {
    5912    15577025 :     case DataHeatBalance::SolutionAlgo::ThirdOrder: {
    5913    31154050 :         CzdTdt = RhoAir * CpAir * thisZone.Volume * thisZone.ZoneVolCapMultpSens * (thisZoneHB.MAT - thisZoneHB.ZTM[0]) /
    5914    15577025 :                  (state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour);
    5915             :         // Exact solution
    5916    15577025 :     } break;
    5917    12342868 :     case DataHeatBalance::SolutionAlgo::AnalyticalSolution: {
    5918    12342868 :         CzdTdt = TempIndCoef - TempDepCoef * thisZoneHB.MAT;
    5919    12342868 :     } break;
    5920       38210 :     case DataHeatBalance::SolutionAlgo::EulerMethod: {
    5921       38210 :         CzdTdt = thisZoneHB.AirPowerCap * (thisZoneHB.MAT - thisZoneHB.ZoneT1);
    5922       38210 :     } break;
    5923           0 :     default:
    5924           0 :         break;
    5925             :     }
    5926             : 
    5927    27958103 :     if (state.dataGlobal->DisplayZoneAirHeatBalanceOffBalance) {
    5928      247170 :         imBalance = SumIntGains + SumHADTsurfs + SumMCpDTzones + SumMCpDtInfil + SumMCpDTsystem + SumNonAirSystem - CzdTdt;
    5929             : 
    5930             :         // throw warning if seriously out of balance (this may need to be removed if too noisy... )
    5931             :         // formulate dynamic threshold value based on 20% of quadrature sum of components
    5932      741510 :         Real64 Threshold = 0.2 * std::sqrt(pow_2(SumIntGains) + pow_2(SumHADTsurfs) + pow_2(SumMCpDTzones) + pow_2(SumMCpDtInfil) +
    5933      741510 :                                            pow_2(SumMCpDTsystem) + pow_2(SumNonAirSystem) + pow_2(CzdTdt));
    5934      248020 :         if ((std::abs(imBalance) > Threshold) && (!state.dataGlobal->WarmupFlag) &&
    5935         850 :             (!state.dataGlobal->DoingSizing)) { // air balance is out by more than threshold
    5936         850 :             if (thisZone.AirHBimBalanceErrIndex == 0) {
    5937          14 :                 ShowWarningMessage(state, format("Zone Air Heat Balance is out of balance for zone named {}", thisZone.Name));
    5938          14 :                 ShowContinueError(state, format("Zone Air Heat Balance Deviation Rate is more than {:.1R} {{W}}", Threshold));
    5939          14 :                 if (state.dataHVACGlobal->TurnFansOn) {
    5940           0 :                     ShowContinueError(state, "Night cycle fan operation may be causing above error");
    5941             :                 }
    5942             : 
    5943          14 :                 ShowContinueErrorTimeStamp(state, " Occurrence info:");
    5944             :             }
    5945        5950 :             ShowRecurringWarningErrorAtEnd(state,
    5946        1700 :                                            format("Zone Air Heat Balance is out of balance ... zone named {}", thisZone.Name),
    5947             :                                            thisZone.AirHBimBalanceErrIndex,
    5948        1700 :                                            std::abs(imBalance) - Threshold,
    5949        1700 :                                            std::abs(imBalance) - Threshold,
    5950             :                                            _,
    5951             :                                            "{W}",
    5952             :                                            "{W}");
    5953             :         }
    5954             :     }
    5955    27958103 : }
    5956             : 
    5957        3292 : bool VerifyThermostatInZone(EnergyPlusData &state, std::string const &ZoneName) // Zone to verify
    5958             : {
    5959             : 
    5960             :     // FUNCTION INFORMATION:
    5961             :     //       AUTHOR         Linda Lawrie
    5962             :     //       DATE WRITTEN   Feb 2005
    5963             : 
    5964             :     // PURPOSE OF THIS FUNCTION:
    5965             :     // This function verifies that a zone (by name) has a Zone Control:Thermostatic object entered.
    5966             : 
    5967        3292 :     if (state.dataZoneCtrls->GetZoneAirStatsInputFlag) {
    5968           0 :         GetZoneAirSetPoints(state);
    5969           0 :         state.dataZoneCtrls->GetZoneAirStatsInputFlag = false;
    5970             :     }
    5971        3292 :     if (state.dataZoneCtrls->NumTempControlledZones > 0) {
    5972        3289 :         if (UtilityRoutines::FindItemInList(ZoneName, state.dataZoneCtrls->TempControlledZone, &DataZoneControls::ZoneTempControls::ZoneName) > 0) {
    5973        3288 :             return true;
    5974             :         } else {
    5975           1 :             return false;
    5976             :         }
    5977             :     }
    5978           3 :     return false;
    5979             : }
    5980             : 
    5981        3983 : bool VerifyControlledZoneForThermostat(EnergyPlusData &state, std::string const &ZoneName) // Zone to verify
    5982             : {
    5983             : 
    5984             :     // FUNCTION INFORMATION:
    5985             :     //       AUTHOR         Linda Lawrie
    5986             :     //       DATE WRITTEN   Mar 2007
    5987             : 
    5988             :     // PURPOSE OF THIS FUNCTION:
    5989             :     // This function verifies that a zone (by name) has a ZoneHVAC:EquipmentConnections object entered.
    5990             : 
    5991        3983 :     return (UtilityRoutines::FindItemInList(ZoneName, state.dataZoneEquip->ZoneEquipConfig, &DataZoneEquipment::EquipConfiguration::ZoneName) > 0);
    5992             : }
    5993             : 
    5994     3318787 : void DetectOscillatingZoneTemp(EnergyPlusData &state)
    5995             : {
    5996             :     // SUBROUTINE INFORMATION:
    5997             :     //       AUTHOR         Jason Glazer
    5998             :     //       DATE WRITTEN   August 2005
    5999             : 
    6000             :     // PURPOSE OF THIS SUBROUTINE:
    6001             :     // Oscillating temperatures between HVAC timesteps indicate that the
    6002             :     // simulation may be poor. Code is trying to be fast since the purpose
    6003             :     // is to see the impact on oscillating by trying longer time steps in
    6004             :     // an attempt to speed up the simulation.
    6005             :     // Note that the OscillateMagnitude threshold must be less than
    6006             :     // MaxZoneTempDiff since ManageHVAC keeps shortening the timestep
    6007             :     // until that is reached unless it goes to less than the
    6008             :     // MinTimeStepSys.
    6009             : 
    6010             :     // first time run allocate arrays and setup output variable
    6011     3318787 :     if (state.dataZoneTempPredictorCorrector->SetupOscillationOutputFlag) {
    6012         771 :         state.dataZoneTempPredictorCorrector->ZoneTempHist.allocate(4, state.dataGlobal->NumOfZones);
    6013         771 :         state.dataZoneTempPredictorCorrector->ZoneTempHist = 0.0;
    6014         771 :         state.dataZoneTempPredictorCorrector->ZoneTempOscillate.dimension(state.dataGlobal->NumOfZones, 0.0);
    6015         771 :         state.dataZoneTempPredictorCorrector->ZoneTempOscillateDuringOccupancy.dimension(state.dataGlobal->NumOfZones, 0.0);
    6016         771 :         state.dataZoneTempPredictorCorrector->ZoneTempOscillateInDeadband.dimension(state.dataGlobal->NumOfZones, 0.0);
    6017             :         // set up zone by zone variables, CurrentModuleObject='Zone'
    6018        5585 :         for (int iZone = 1; iZone <= state.dataGlobal->NumOfZones; ++iZone) {
    6019        4814 :             auto &zone = state.dataHeatBal->Zone(iZone);
    6020        9628 :             SetupOutputVariable(state,
    6021             :                                 "Zone Oscillating Temperatures Time",
    6022             :                                 OutputProcessor::Unit::hr,
    6023        4814 :                                 state.dataZoneTempPredictorCorrector->ZoneTempOscillate(iZone),
    6024             :                                 OutputProcessor::SOVTimeStepType::System,
    6025             :                                 OutputProcessor::SOVStoreType::Summed,
    6026        4814 :                                 zone.Name);
    6027        9628 :             SetupOutputVariable(state,
    6028             :                                 "Zone Oscillating Temperatures During Occupancy Time",
    6029             :                                 OutputProcessor::Unit::hr,
    6030        4814 :                                 state.dataZoneTempPredictorCorrector->ZoneTempOscillateDuringOccupancy(iZone),
    6031             :                                 OutputProcessor::SOVTimeStepType::System,
    6032             :                                 OutputProcessor::SOVStoreType::Summed,
    6033        4814 :                                 zone.Name);
    6034        9628 :             SetupOutputVariable(state,
    6035             :                                 "Zone Oscillating Temperatures in Deadband Time",
    6036             :                                 OutputProcessor::Unit::hr,
    6037        4814 :                                 state.dataZoneTempPredictorCorrector->ZoneTempOscillateInDeadband(iZone),
    6038             :                                 OutputProcessor::SOVTimeStepType::System,
    6039             :                                 OutputProcessor::SOVStoreType::Summed,
    6040        4814 :                                 zone.Name);
    6041             :         }
    6042             :         // set up a variable covering all zones
    6043        2313 :         SetupOutputVariable(state,
    6044             :                             "Facility Any Zone Oscillating Temperatures Time",
    6045             :                             OutputProcessor::Unit::hr,
    6046         771 :                             state.dataZoneTempPredictorCorrector->AnyZoneTempOscillate,
    6047             :                             OutputProcessor::SOVTimeStepType::System,
    6048             :                             OutputProcessor::SOVStoreType::Summed,
    6049        1542 :                             "Facility");
    6050        2313 :         SetupOutputVariable(state,
    6051             :                             "Facility Any Zone Oscillating Temperatures During Occupancy Time",
    6052             :                             OutputProcessor::Unit::hr,
    6053         771 :                             state.dataZoneTempPredictorCorrector->AnyZoneTempOscillateDuringOccupancy,
    6054             :                             OutputProcessor::SOVTimeStepType::System,
    6055             :                             OutputProcessor::SOVStoreType::Summed,
    6056        1542 :                             "Facility");
    6057        2313 :         SetupOutputVariable(state,
    6058             :                             "Facility Any Zone Oscillating Temperatures in Deadband Time",
    6059             :                             OutputProcessor::Unit::hr,
    6060         771 :                             state.dataZoneTempPredictorCorrector->AnyZoneTempOscillateInDeadband,
    6061             :                             OutputProcessor::SOVTimeStepType::System,
    6062             :                             OutputProcessor::SOVStoreType::Summed,
    6063        1542 :                             "Facility");
    6064             :         // test if the oscillation variables are even used
    6065        3855 :         if (ReportingThisVariable(state, "Zone Oscillating Temperatures Time") ||
    6066        3855 :             ReportingThisVariable(state, "Zone Oscillating Temperatures During Occupancy Time") ||
    6067        3855 :             ReportingThisVariable(state, "Zone Oscillating Temperatures in Deadband Time") ||
    6068        3855 :             ReportingThisVariable(state, "Facility Any Zone Oscillating Temperatures Time") ||
    6069        6168 :             ReportingThisVariable(state, "Facility Any Zone Oscillating Temperatures During Occupancy Time") ||
    6070        2313 :             ReportingThisVariable(state, "Facility Any Zone Oscillating Temperatures in Deadband Time")) {
    6071           0 :             state.dataZoneTempPredictorCorrector->OscillationVariablesNeeded = true;
    6072             :         }
    6073         771 :         state.dataZoneTempPredictorCorrector->SetupOscillationOutputFlag = false;
    6074             :     }
    6075             : 
    6076     3318787 :     auto &TimeStepSys = state.dataHVACGlobal->TimeStepSys;
    6077     3318787 :     if (state.dataZoneTempPredictorCorrector->OscillationVariablesNeeded) {
    6078             :         // precalc the negative value for performance
    6079       18371 :         Real64 NegOscillateMagnitude = -DataHVACGlobals::OscillateMagnitude;
    6080             :         // assume no zone is oscillating
    6081       18371 :         bool isAnyZoneOscillating = false;
    6082       18371 :         bool isAnyZoneOscillatingDuringOccupancy = false;
    6083       18371 :         bool isAnyZoneOscillatingInDeadband = false;
    6084             : 
    6085      342945 :         for (int iZone = 1; iZone <= state.dataGlobal->NumOfZones; ++iZone) {
    6086      324574 :             bool isOscillate = false;
    6087      324574 :             state.dataZoneTempPredictorCorrector->ZoneTempHist(4, iZone) = state.dataZoneTempPredictorCorrector->ZoneTempHist(3, iZone);
    6088      324574 :             state.dataZoneTempPredictorCorrector->ZoneTempHist(3, iZone) = state.dataZoneTempPredictorCorrector->ZoneTempHist(2, iZone);
    6089      324574 :             state.dataZoneTempPredictorCorrector->ZoneTempHist(2, iZone) = state.dataZoneTempPredictorCorrector->ZoneTempHist(1, iZone);
    6090      324574 :             state.dataZoneTempPredictorCorrector->ZoneTempHist(1, iZone) = state.dataZoneTempPredictorCorrector->zoneHeatBalance(iZone).ZT;
    6091             :             Real64 Diff34 =
    6092      324574 :                 state.dataZoneTempPredictorCorrector->ZoneTempHist(3, iZone) - state.dataZoneTempPredictorCorrector->ZoneTempHist(4, iZone);
    6093             :             Real64 Diff23 =
    6094      324574 :                 state.dataZoneTempPredictorCorrector->ZoneTempHist(2, iZone) - state.dataZoneTempPredictorCorrector->ZoneTempHist(3, iZone);
    6095             :             Real64 Diff12 =
    6096      324574 :                 state.dataZoneTempPredictorCorrector->ZoneTempHist(1, iZone) - state.dataZoneTempPredictorCorrector->ZoneTempHist(2, iZone);
    6097             :             // roll out the conditionals for increased performance
    6098      324574 :             if (Diff12 > DataHVACGlobals::OscillateMagnitude) {
    6099       58186 :                 if (Diff23 < NegOscillateMagnitude) {
    6100       10895 :                     if (Diff34 > DataHVACGlobals::OscillateMagnitude) {
    6101        2746 :                         isOscillate = true;
    6102             :                     }
    6103             :                 }
    6104             :             }
    6105             :             // now try the opposite sequence of swings
    6106      324574 :             if (Diff12 < NegOscillateMagnitude) {
    6107       52776 :                 if (Diff23 > DataHVACGlobals::OscillateMagnitude) {
    6108        7385 :                     if (Diff34 < NegOscillateMagnitude) {
    6109        2385 :                         isOscillate = true;
    6110             :                     }
    6111             :                 }
    6112             :             }
    6113      324574 :             state.dataZoneTempPredictorCorrector->ZoneTempOscillateDuringOccupancy(iZone) = 0.0;
    6114      324574 :             state.dataZoneTempPredictorCorrector->ZoneTempOscillateInDeadband(iZone) = 0.0;
    6115      324574 :             if (isOscillate) {
    6116        5131 :                 state.dataZoneTempPredictorCorrector->ZoneTempOscillate(iZone) = TimeStepSys;
    6117        5131 :                 isAnyZoneOscillating = true;
    6118        5131 :                 if (allocated(state.dataThermalComforts->ThermalComfortInASH55)) {
    6119        5131 :                     if (state.dataThermalComforts->ThermalComfortInASH55(iZone).ZoneIsOccupied) {
    6120         374 :                         state.dataZoneTempPredictorCorrector->ZoneTempOscillateDuringOccupancy(iZone) = TimeStepSys;
    6121         374 :                         isAnyZoneOscillatingDuringOccupancy = true;
    6122             :                     }
    6123             :                 }
    6124        5131 :                 if (state.dataZoneEnergyDemand->CurDeadBandOrSetback(iZone)) {
    6125         883 :                     state.dataZoneTempPredictorCorrector->ZoneTempOscillateInDeadband(iZone) = TimeStepSys;
    6126         883 :                     isAnyZoneOscillatingInDeadband = true;
    6127             :                 }
    6128             :             } else {
    6129      319443 :                 state.dataZoneTempPredictorCorrector->ZoneTempOscillate(iZone) = 0.0;
    6130             :             }
    6131             :         }
    6132             :         // any zone variable
    6133       18371 :         state.dataZoneTempPredictorCorrector->AnyZoneTempOscillate = (isAnyZoneOscillating) ? TimeStepSys : 0.0;
    6134       18371 :         state.dataZoneTempPredictorCorrector->AnyZoneTempOscillateDuringOccupancy = (isAnyZoneOscillatingDuringOccupancy) ? TimeStepSys : 0.0;
    6135       18371 :         state.dataZoneTempPredictorCorrector->AnyZoneTempOscillateInDeadband = (isAnyZoneOscillatingInDeadband) ? TimeStepSys : 0.0;
    6136             : 
    6137             :         // annual/runperiod sum for _perflog.csv file
    6138       18371 :         state.dataZoneTempPredictorCorrector->AnnualAnyZoneTempOscillate += state.dataZoneTempPredictorCorrector->AnyZoneTempOscillate;
    6139       18371 :         state.dataZoneTempPredictorCorrector->AnnualAnyZoneTempOscillateDuringOccupancy +=
    6140       18371 :             state.dataZoneTempPredictorCorrector->AnyZoneTempOscillateDuringOccupancy;
    6141       18371 :         state.dataZoneTempPredictorCorrector->AnnualAnyZoneTempOscillateInDeadband +=
    6142       18371 :             state.dataZoneTempPredictorCorrector->AnyZoneTempOscillateInDeadband;
    6143             :     }
    6144     3318787 : }
    6145             : 
    6146    27780591 : void AdjustAirSetPointsforOpTempCntrl(EnergyPlusData &state, int const TempControlledZoneID, int const ActualZoneNum, Real64 &ZoneAirSetPoint)
    6147             : {
    6148             : 
    6149             :     // SUBROUTINE INFORMATION:
    6150             :     //       AUTHOR         B. Griffith
    6151             :     //       DATE WRITTEN   June 2006
    6152             : 
    6153             :     // PURPOSE OF THIS SUBROUTINE:
    6154             :     // This subroutine modifies the air temperature setpoint to effect operative temperature control
    6155             : 
    6156             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    6157             :     Real64 thisMRTFraction; // local variable for fraction that MRT is in Op Temp definition
    6158             : 
    6159    27780591 :     if (!(state.dataZoneCtrls->AnyOpTempControl)) return; // do nothing to setpoint
    6160             : 
    6161       33144 :     auto &tempControlledZone = state.dataZoneCtrls->TempControlledZone(TempControlledZoneID);
    6162       33144 :     if (!(tempControlledZone.OperativeTempControl)) return; // do nothing to setpoint
    6163             : 
    6164             :     // is operative temp radiative fraction scheduled or fixed?
    6165       36528 :     thisMRTFraction = (tempControlledZone.OpTempCntrlModeScheduled)
    6166       18264 :                           ? ScheduleManager::GetCurrentScheduleValue(state, tempControlledZone.OpTempRadiativeFractionSched)
    6167             :                           : tempControlledZone.FixedRadiativeFraction;
    6168             : 
    6169             :     // get mean radiant temperature for zone
    6170       18264 :     Real64 thisMRT = state.dataHeatBal->ZoneMRT(ActualZoneNum);
    6171             : 
    6172             :     // modify setpoint for operative temperature control
    6173             :     //  traping for MRT fractions between 0.0 and 0.9 during get input, so shouldn't be able to divide by zero here.
    6174       18264 :     ZoneAirSetPoint = (ZoneAirSetPoint - thisMRTFraction * thisMRT) / (1.0 - thisMRTFraction);
    6175             : }
    6176             : 
    6177        6765 : void AdjustOperativeSetPointsforAdapComfort(EnergyPlusData &state, int const TempControlledZoneID, Real64 &ZoneAirSetPoint)
    6178             : {
    6179             :     // SUBROUTINE INFORMATION:
    6180             :     //       AUTHOR         Xuan Luo
    6181             :     //       DATE WRITTEN   Jan 2017
    6182             : 
    6183             :     // PURPOSE OF THIS SUBROUTINE:
    6184             :     // This routine adjust the operative setpoints for each controlled adaptive thermal comfort models.
    6185             : 
    6186        6765 :     auto &tempControlledZone = state.dataZoneCtrls->TempControlledZone(TempControlledZoneID);
    6187        6765 :     auto &AdapComfortDailySetPointSchedule = state.dataZoneTempPredictorCorrector->AdapComfortDailySetPointSchedule;
    6188             : 
    6189             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    6190        6765 :     int originZoneAirSetPoint = ZoneAirSetPoint;
    6191        6765 :     int AdaptiveComfortModelTypeIndex = tempControlledZone.AdaptiveComfortModelTypeIndex;
    6192             : 
    6193             :     // adjust zone operative setpoint
    6194        6765 :     if (!(tempControlledZone.AdaptiveComfortTempControl)) return; // do nothing to setpoint
    6195        6780 :     if ((state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).KindOfEnvrn != DataGlobalConstants::KindOfSim::DesignDay) &&
    6196          15 :         (state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).KindOfEnvrn != DataGlobalConstants::KindOfSim::HVACSizeDesignDay)) {
    6197             :         // Adjust run period cooling set point
    6198          15 :         switch (AdaptiveComfortModelTypeIndex) {
    6199          15 :         case static_cast<int>(AdaptiveComfortModel::ASH55_CENTRAL):
    6200          15 :             ZoneAirSetPoint = AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveASH55_Central(state.dataEnvrn->DayOfYear);
    6201          15 :             break;
    6202           0 :         case static_cast<int>(AdaptiveComfortModel::ASH55_UPPER_90):
    6203           0 :             ZoneAirSetPoint = AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveASH55_Upper_90(state.dataEnvrn->DayOfYear);
    6204           0 :             break;
    6205           0 :         case static_cast<int>(AdaptiveComfortModel::ASH55_UPPER_80):
    6206           0 :             ZoneAirSetPoint = AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveASH55_Upper_80(state.dataEnvrn->DayOfYear);
    6207           0 :             break;
    6208           0 :         case static_cast<int>(AdaptiveComfortModel::CEN15251_CENTRAL):
    6209           0 :             ZoneAirSetPoint = AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveCEN15251_Central(state.dataEnvrn->DayOfYear);
    6210           0 :             break;
    6211           0 :         case static_cast<int>(AdaptiveComfortModel::CEN15251_UPPER_I):
    6212           0 :             ZoneAirSetPoint = AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveCEN15251_Upper_I(state.dataEnvrn->DayOfYear);
    6213           0 :             break;
    6214           0 :         case static_cast<int>(AdaptiveComfortModel::CEN15251_UPPER_II):
    6215           0 :             ZoneAirSetPoint = AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveCEN15251_Upper_II(state.dataEnvrn->DayOfYear);
    6216           0 :             break;
    6217           0 :         case static_cast<int>(AdaptiveComfortModel::CEN15251_UPPER_III):
    6218           0 :             ZoneAirSetPoint = AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveCEN15251_Upper_III(state.dataEnvrn->DayOfYear);
    6219           0 :             break;
    6220           0 :         default:
    6221           0 :             break;
    6222             :         }
    6223             :     } else {
    6224        6750 :         int const envrnDayNum(state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).DesignDayNum);
    6225        6750 :         int constexpr summerDesignDayTypeIndex(9);
    6226             :         // Adjust summer design day set point
    6227        6750 :         if (state.dataWeatherManager->DesDayInput(envrnDayNum).DayType == summerDesignDayTypeIndex) {
    6228        6750 :             ZoneAirSetPoint = state.dataZoneTempPredictorCorrector->AdapComfortSetPointSummerDesDay[AdaptiveComfortModelTypeIndex - 2];
    6229             :         }
    6230             :     }
    6231             :     // If adaptive operative temperature not applicable, set back
    6232        6765 :     if (ZoneAirSetPoint < originZoneAirSetPoint) {
    6233          15 :         ZoneAirSetPoint = originZoneAirSetPoint;
    6234             :     }
    6235             :     // If meet fault flag, set back
    6236        6765 :     if (ZoneAirSetPoint == -1) {
    6237           0 :         ZoneAirSetPoint = originZoneAirSetPoint;
    6238             :     }
    6239             : }
    6240             : 
    6241        2025 : void CalcZoneAirComfortSetPoints(EnergyPlusData &state)
    6242             : {
    6243             : 
    6244             :     // SUBROUTINE INFORMATION:
    6245             :     //       AUTHOR         Lixing Gu
    6246             :     //       DATE WRITTEN   May 2006
    6247             : 
    6248             :     // PURPOSE OF THIS SUBROUTINE:
    6249             :     // This routine sets the thermal comfort setpoints for each controlled zone based on air tempeature obtained from thermal comfort models.
    6250             : 
    6251             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    6252        2025 :     Real64 SetPointLo = 0.0;
    6253        2025 :     Real64 SetPointHi = 0.0;
    6254        2025 :     Real64 Tset = 0.0;
    6255        2025 :     int PeopleNum = 0;
    6256        2025 :     int ObjectCount = 0;
    6257        2025 :     Real64 PeopleCount = 0.0;
    6258        2025 :     int SetPointComfortSchedIndex = 0;
    6259        2025 :     int SchedTypeIndex = 0;
    6260             : 
    6261             :     // Call thermal comfort module to read zone control comfort object
    6262        2025 :     if (state.dataZoneTempPredictorCorrector->CalcZoneAirComfortSetPointsFirstTimeFlag) {
    6263           1 :         ThermalComfort::ManageThermalComfort(state, true);
    6264           1 :         state.dataZoneTempPredictorCorrector->CalcZoneAirComfortSetPointsFirstTimeFlag = false;
    6265             :     }
    6266             : 
    6267        2025 :     state.dataHeatBalFanSys->ComfortControlType = DataHVACGlobals::ThermostatType::Uncontrolled; // Default
    6268             : 
    6269        4050 :     for (int RelativeZoneNum = 1; RelativeZoneNum <= state.dataZoneCtrls->NumComfortControlledZones; ++RelativeZoneNum) {
    6270             : 
    6271        2025 :         auto &comfortControlledZone = state.dataZoneCtrls->ComfortControlledZone(RelativeZoneNum);
    6272        2025 :         int ActualZoneNum = comfortControlledZone.ActualZoneNum;
    6273        2025 :         auto &zone = state.dataHeatBal->Zone(ActualZoneNum);
    6274        2025 :         auto &comfortControlType = state.dataHeatBalFanSys->ComfortControlType(ActualZoneNum);
    6275        2025 :         auto &comfortControlTypeRpt = state.dataHeatBalFanSys->ComfortControlTypeRpt(ActualZoneNum);
    6276        2025 :         auto &tempZoneThermostatSetPoint = state.dataHeatBalFanSys->TempZoneThermostatSetPoint(ActualZoneNum);
    6277        2025 :         auto &zoneComfortControlsFanger = state.dataHeatBalFanSys->ZoneComfortControlsFanger(ActualZoneNum);
    6278        2025 :         comfortControlType =
    6279        2025 :             static_cast<DataHVACGlobals::ThermostatType>(ScheduleManager::GetCurrentScheduleValue(state, comfortControlledZone.ComfortSchedIndex));
    6280        2025 :         comfortControlTypeRpt = static_cast<int>(comfortControlType);
    6281             : 
    6282             :         // Get PMV values
    6283        2025 :         switch (comfortControlType) {
    6284        1185 :         case DataHVACGlobals::ThermostatType::Uncontrolled:
    6285        1185 :             zoneComfortControlsFanger.LowPMV = -999.0;
    6286        1185 :             zoneComfortControlsFanger.HighPMV = -999.0;
    6287        1185 :             break;
    6288         210 :         case DataHVACGlobals::ThermostatType::SingleHeating:
    6289         210 :             zoneComfortControlsFanger.FangerType = static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeating);
    6290         210 :             zoneComfortControlsFanger.LowPMV = ScheduleManager::GetCurrentScheduleValue(
    6291             :                 state,
    6292             :                 state.dataZoneTempPredictorCorrector
    6293         210 :                     ->SetPointSingleHeatingFanger(comfortControlledZone.ControlTypeSchIndx(comfortControlledZone.SchIndx_SingleHeating))
    6294             :                     .PMVSchedIndex);
    6295         210 :             zoneComfortControlsFanger.HighPMV = -999.0;
    6296         210 :             break;
    6297         210 :         case DataHVACGlobals::ThermostatType::SingleCooling:
    6298         210 :             zoneComfortControlsFanger.FangerType = static_cast<int>(DataHVACGlobals::ThermostatType::SingleCooling);
    6299         210 :             zoneComfortControlsFanger.LowPMV = -999.0;
    6300         210 :             zoneComfortControlsFanger.HighPMV = ScheduleManager::GetCurrentScheduleValue(
    6301             :                 state,
    6302             :                 state.dataZoneTempPredictorCorrector
    6303         210 :                     ->SetPointSingleCoolingFanger(comfortControlledZone.ControlTypeSchIndx(comfortControlledZone.SchIndx_SingleCooling))
    6304             :                     .PMVSchedIndex);
    6305         210 :             break;
    6306         210 :         case DataHVACGlobals::ThermostatType::SingleHeatCool:
    6307         210 :             SetPointComfortSchedIndex =
    6308             :                 state.dataZoneTempPredictorCorrector
    6309         210 :                     ->SetPointSingleHeatCoolFanger(comfortControlledZone.ControlTypeSchIndx(comfortControlledZone.SchIndx_SingleHeatCool))
    6310             :                     .PMVSchedIndex;
    6311         210 :             zoneComfortControlsFanger.FangerType = static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeatCool);
    6312         210 :             zoneComfortControlsFanger.LowPMV = ScheduleManager::GetCurrentScheduleValue(state, SetPointComfortSchedIndex);
    6313         210 :             zoneComfortControlsFanger.HighPMV = ScheduleManager::GetCurrentScheduleValue(state, SetPointComfortSchedIndex);
    6314         210 :             break;
    6315         210 :         case DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand:
    6316         210 :             SchedTypeIndex = comfortControlledZone.ControlTypeSchIndx(comfortControlledZone.SchIndx_DualSetPointWithDeadBand);
    6317         210 :             zoneComfortControlsFanger.FangerType = static_cast<int>(DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand);
    6318         210 :             zoneComfortControlsFanger.LowPMV = ScheduleManager::GetCurrentScheduleValue(
    6319         210 :                 state, state.dataZoneTempPredictorCorrector->SetPointDualHeatCoolFanger(SchedTypeIndex).HeatPMVSchedIndex);
    6320         210 :             zoneComfortControlsFanger.HighPMV = ScheduleManager::GetCurrentScheduleValue(
    6321         210 :                 state, state.dataZoneTempPredictorCorrector->SetPointDualHeatCoolFanger(SchedTypeIndex).CoolPMVSchedIndex);
    6322         210 :             if (zoneComfortControlsFanger.LowPMV > zoneComfortControlsFanger.HighPMV) {
    6323           0 :                 ++zoneComfortControlsFanger.DualPMVErrCount;
    6324           0 :                 if (zoneComfortControlsFanger.DualPMVErrCount < 2) {
    6325           0 :                     ShowWarningError(state,
    6326             :                                      "ThermostatSetpoint:ThermalComfort:Fanger:DualSetpoint: The heating PMV setpoint is above the cooling "
    6327           0 :                                      "PMV setpoint in " +
    6328           0 :                                          state.dataZoneTempPredictorCorrector->SetPointDualHeatCoolFanger(SchedTypeIndex).Name);
    6329           0 :                     ShowContinueError(state, "The zone dual heating PMV setpoint is set to the dual cooling PMV setpoint.");
    6330           0 :                     ShowContinueErrorTimeStamp(state, "Occurrence info:");
    6331             :                 } else {
    6332           0 :                     ShowRecurringWarningErrorAtEnd(state,
    6333             :                                                    "The heating PMV setpoint is still above the cooling PMV setpoint",
    6334             :                                                    zoneComfortControlsFanger.DualPMVErrIndex,
    6335             :                                                    zoneComfortControlsFanger.LowPMV,
    6336             :                                                    zoneComfortControlsFanger.LowPMV);
    6337             :                 }
    6338           0 :                 zoneComfortControlsFanger.LowPMV = zoneComfortControlsFanger.HighPMV;
    6339             :             }
    6340         210 :             break;
    6341           0 :         default:
    6342           0 :             ShowSevereError(state,
    6343           0 :                             format("CalcZoneAirTempSetpoints: Illegal thermal control control type for Zone={}, Found value={}, in Schedule={}",
    6344             :                                    zone.Name,
    6345             :                                    comfortControlTypeRpt,
    6346           0 :                                    comfortControlledZone.ControlTypeSchedName));
    6347           0 :             break;
    6348             :         }
    6349             : 
    6350             :         // Check Average method
    6351        2025 :         switch (comfortControlledZone.AverageMethod) {
    6352        2025 :         case DataZoneControls::AverageMethod::NO:
    6353        2025 :             PeopleNum = comfortControlledZone.SpecificObjectNum;
    6354        2025 :             if (comfortControlType == DataHVACGlobals::ThermostatType::SingleCooling) {
    6355         210 :                 GetComfortSetPoints(state, PeopleNum, RelativeZoneNum, zoneComfortControlsFanger.HighPMV, SetPointLo);
    6356             :             } else {
    6357        1815 :                 GetComfortSetPoints(state, PeopleNum, RelativeZoneNum, zoneComfortControlsFanger.LowPMV, SetPointLo);
    6358             :             }
    6359        2025 :             if (comfortControlType == DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand)
    6360         210 :                 GetComfortSetPoints(state, PeopleNum, RelativeZoneNum, zoneComfortControlsFanger.HighPMV, SetPointHi);
    6361        2025 :             break;
    6362           0 :         case DataZoneControls::AverageMethod::SPE:
    6363           0 :             PeopleNum = comfortControlledZone.SpecificObjectNum;
    6364           0 :             if (comfortControlType == DataHVACGlobals::ThermostatType::SingleCooling) {
    6365           0 :                 GetComfortSetPoints(state, PeopleNum, RelativeZoneNum, zoneComfortControlsFanger.HighPMV, SetPointLo);
    6366             :             } else {
    6367           0 :                 GetComfortSetPoints(state, PeopleNum, RelativeZoneNum, zoneComfortControlsFanger.LowPMV, SetPointLo);
    6368             :             }
    6369           0 :             if (comfortControlType == DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand)
    6370           0 :                 GetComfortSetPoints(state, PeopleNum, RelativeZoneNum, zoneComfortControlsFanger.HighPMV, SetPointHi);
    6371           0 :             break;
    6372           0 :         case DataZoneControls::AverageMethod::OBJ:
    6373           0 :             SetPointLo = 0.0;
    6374           0 :             SetPointHi = 0.0;
    6375           0 :             for (int PeopleNum = 1; PeopleNum <= state.dataHeatBal->TotPeople; ++PeopleNum) {
    6376           0 :                 if (ActualZoneNum == state.dataHeatBal->People(PeopleNum).ZonePtr) {
    6377           0 :                     ++ObjectCount;
    6378           0 :                     GetComfortSetPoints(state, PeopleNum, RelativeZoneNum, zoneComfortControlsFanger.LowPMV, Tset);
    6379           0 :                     SetPointLo += Tset;
    6380           0 :                     if (comfortControlType == DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand) {
    6381           0 :                         GetComfortSetPoints(state, PeopleNum, RelativeZoneNum, zoneComfortControlsFanger.HighPMV, Tset);
    6382           0 :                         SetPointHi += Tset;
    6383             :                     }
    6384             :                 }
    6385           0 :             }
    6386           0 :             SetPointLo /= ObjectCount;
    6387           0 :             if (comfortControlType == DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand) SetPointHi /= ObjectCount;
    6388           0 :             break;
    6389           0 :         case DataZoneControls::AverageMethod::PEO:
    6390           0 :             SetPointLo = 0.0;
    6391           0 :             SetPointHi = 0.0;
    6392           0 :             for (int PeopleNum = 1; PeopleNum <= state.dataHeatBal->TotPeople; ++PeopleNum) {
    6393           0 :                 if (ActualZoneNum == state.dataHeatBal->People(PeopleNum).ZonePtr) {
    6394           0 :                     int NumberOccupants = state.dataHeatBal->People(PeopleNum).NumberOfPeople *
    6395           0 :                                           ScheduleManager::GetCurrentScheduleValue(state, state.dataHeatBal->People(PeopleNum).NumberOfPeoplePtr);
    6396           0 :                     PeopleCount += NumberOccupants;
    6397           0 :                     GetComfortSetPoints(state, PeopleNum, RelativeZoneNum, zoneComfortControlsFanger.LowPMV, Tset);
    6398           0 :                     SetPointLo += Tset * NumberOccupants;
    6399           0 :                     if (comfortControlType == DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand) {
    6400           0 :                         GetComfortSetPoints(state, PeopleNum, RelativeZoneNum, zoneComfortControlsFanger.HighPMV, Tset);
    6401           0 :                         SetPointHi += Tset * NumberOccupants;
    6402             :                     }
    6403             :                 }
    6404           0 :             }
    6405           0 :             if (PeopleCount > 0) {
    6406           0 :                 SetPointLo /= PeopleCount;
    6407           0 :                 if (comfortControlType == DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand) SetPointHi /= PeopleCount;
    6408             :             } else {
    6409           0 :                 if (comfortControlledZone.PeopleAverageErrIndex == 0) {
    6410           0 :                     ShowWarningMessage(state,
    6411           0 :                                        "ZoneControl:Thermostat:ThermalComfort: The total number of people in Zone = " + zone.Name +
    6412             :                                            " is zero. The People Average option is not used.");
    6413           0 :                     ShowContinueError(state, "The Object Average option is used instead. Simulation continues .....");
    6414           0 :                     ShowContinueErrorTimeStamp(state, "Occurrence info:");
    6415             :                 }
    6416           0 :                 ShowRecurringWarningErrorAtEnd(state,
    6417           0 :                                                "ZoneControl:Thermostat:ThermalComfort: The total number of people in Zone = " + zone.Name +
    6418             :                                                    " is still zero. The People Average option is not used",
    6419             :                                                comfortControlledZone.PeopleAverageErrIndex,
    6420             :                                                PeopleCount,
    6421             :                                                PeopleCount);
    6422           0 :                 SetPointLo = 0.0;
    6423           0 :                 SetPointHi = 0.0;
    6424           0 :                 for (int PeopleNum = 1; PeopleNum <= state.dataHeatBal->TotPeople; ++PeopleNum) {
    6425           0 :                     if (ActualZoneNum == state.dataHeatBal->People(PeopleNum).ZonePtr) {
    6426           0 :                         ++ObjectCount;
    6427           0 :                         GetComfortSetPoints(state, PeopleNum, RelativeZoneNum, zoneComfortControlsFanger.LowPMV, Tset);
    6428           0 :                         SetPointLo += Tset;
    6429           0 :                         if (comfortControlType == DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand) {
    6430           0 :                             GetComfortSetPoints(state, PeopleNum, RelativeZoneNum, zoneComfortControlsFanger.HighPMV, Tset);
    6431           0 :                             SetPointHi += Tset;
    6432             :                         }
    6433             :                     }
    6434             :                 }
    6435           0 :                 SetPointLo /= ObjectCount;
    6436           0 :                 if (comfortControlType == DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand) SetPointHi /= ObjectCount;
    6437             :             }
    6438           0 :             break;
    6439           0 :         default:
    6440           0 :             break;
    6441             :         }
    6442             : 
    6443             :         // Assign setpoint
    6444        2025 :         switch (comfortControlType) {
    6445        1185 :         case DataHVACGlobals::ThermostatType::Uncontrolled:
    6446        1185 :             switch (state.dataHeatBalFanSys->TempControlType(ActualZoneNum)) {
    6447         594 :             case DataHVACGlobals::ThermostatType::SingleHeating:
    6448         594 :                 state.dataHeatBalFanSys->ZoneThermostatSetPointHi(ActualZoneNum) = 0.0;
    6449         594 :                 break;
    6450         591 :             case DataHVACGlobals::ThermostatType::SingleCooling:
    6451         591 :                 state.dataHeatBalFanSys->ZoneThermostatSetPointLo(ActualZoneNum) = 0.0;
    6452         591 :                 break;
    6453           0 :             default:
    6454           0 :                 break;
    6455             :             }
    6456        1185 :             break;
    6457         210 :         case DataHVACGlobals::ThermostatType::SingleHeating:
    6458         210 :             if (SetPointLo < comfortControlledZone.TdbMinSetPoint) {
    6459           0 :                 SetPointLo = comfortControlledZone.TdbMinSetPoint;
    6460           0 :                 if (comfortControlledZone.TdbMinErrIndex < 2) {
    6461           0 :                     ShowWarningMessage(state,
    6462             :                                        "ThermostatSetpoint:ThermalComfort:Fanger:SingleHeating temperature is below the Minimum dry-bulb "
    6463           0 :                                        "temperature setpoint " +
    6464             :                                            comfortControlledZone.Name);
    6465           0 :                     ShowContinueError(state, "The zone heating setpoint is set to the Minimum dry-bulb temperature setpoint");
    6466           0 :                     ShowContinueErrorTimeStamp(state, "Occurrence info:");
    6467             :                 }
    6468           0 :                 ShowRecurringWarningErrorAtEnd(state,
    6469             :                                                "ThermostatSetpoint:ThermalComfort:Fanger:SingleHeating temperature is still below the "
    6470             :                                                "Minimum dry-bulb temperature setpoint ...",
    6471             :                                                comfortControlledZone.TdbMinErrIndex,
    6472             :                                                SetPointLo,
    6473             :                                                SetPointLo);
    6474             :             }
    6475         210 :             tempZoneThermostatSetPoint = SetPointLo;
    6476         210 :             state.dataHeatBalFanSys->ZoneThermostatSetPointLo(ActualZoneNum) = tempZoneThermostatSetPoint;
    6477         210 :             state.dataHeatBalFanSys->TempControlType(ActualZoneNum) = DataHVACGlobals::ThermostatType::SingleHeating;
    6478         210 :             state.dataHeatBalFanSys->TempControlTypeRpt(ActualZoneNum) = static_cast<int>(state.dataHeatBalFanSys->TempControlType(ActualZoneNum));
    6479         210 :             break;
    6480         210 :         case DataHVACGlobals::ThermostatType::SingleCooling:
    6481         210 :             if (SetPointLo > comfortControlledZone.TdbMaxSetPoint) {
    6482           0 :                 SetPointLo = comfortControlledZone.TdbMaxSetPoint;
    6483           0 :                 if (comfortControlledZone.TdbMaxErrIndex == 0) {
    6484           0 :                     ShowWarningMessage(state,
    6485             :                                        "ThermostatSetpoint:ThermalComfort:Fanger:SingleCooling temperature is above the Maximum dry-bulb "
    6486           0 :                                        "temperature setpoint " +
    6487             :                                            comfortControlledZone.Name);
    6488           0 :                     ShowContinueError(state, "The zone cooling setpoint is set to the Maximum dry-bulb temperature setpoint");
    6489           0 :                     ShowContinueErrorTimeStamp(state, "Occurrence info:");
    6490             :                 }
    6491           0 :                 ShowRecurringWarningErrorAtEnd(state,
    6492             :                                                "ThermostatSetpoint:ThermalComfort:Fanger:SingleCooling temperature is still above the "
    6493             :                                                "Maximum dry-bulb temperature setpoint ...",
    6494             :                                                comfortControlledZone.TdbMaxErrIndex,
    6495             :                                                SetPointLo,
    6496             :                                                SetPointLo);
    6497             :             }
    6498         210 :             tempZoneThermostatSetPoint = SetPointLo;
    6499         210 :             state.dataHeatBalFanSys->ZoneThermostatSetPointHi(ActualZoneNum) = tempZoneThermostatSetPoint;
    6500         210 :             state.dataHeatBalFanSys->TempControlType(ActualZoneNum) = DataHVACGlobals::ThermostatType::SingleCooling;
    6501         210 :             state.dataHeatBalFanSys->TempControlTypeRpt(ActualZoneNum) = static_cast<int>(state.dataHeatBalFanSys->TempControlType(ActualZoneNum));
    6502         210 :             break;
    6503         210 :         case DataHVACGlobals::ThermostatType::SingleHeatCool:
    6504         210 :             if (comfortControlledZone.TdbMaxSetPoint == comfortControlledZone.TdbMinSetPoint) {
    6505           0 :                 SetPointLo = comfortControlledZone.TdbMaxSetPoint;
    6506             :             }
    6507         210 :             if (SetPointLo > comfortControlledZone.TdbMaxSetPoint) SetPointLo = comfortControlledZone.TdbMaxSetPoint;
    6508         210 :             if (SetPointLo < comfortControlledZone.TdbMinSetPoint) SetPointLo = comfortControlledZone.TdbMinSetPoint;
    6509         210 :             if (SetPointLo < comfortControlledZone.TdbMinSetPoint || SetPointLo > comfortControlledZone.TdbMaxSetPoint) {
    6510           0 :                 if (comfortControlledZone.TdbHCErrIndex == 0) {
    6511           0 :                     ShowWarningMessage(state,
    6512             :                                        "ThermostatSetpoint:ThermalComfort:Fanger:SingleHeatingOrCooling temperature is above the Maximum or "
    6513           0 :                                        "below the Minimum dry-bulb temperature setpoint " +
    6514             :                                            comfortControlledZone.Name);
    6515           0 :                     ShowContinueError(state,
    6516             :                                       "The zone setpoint is set to the Maximum dry-bulb temperature setpoint if above or the Minimum "
    6517             :                                       "dry-bulb temperature setpoint if below");
    6518           0 :                     ShowContinueErrorTimeStamp(state, "Occurrence info:");
    6519             :                 }
    6520           0 :                 ShowRecurringWarningErrorAtEnd(state,
    6521             :                                                "ThermostatSetpoint:ThermalComfort:Fanger:SingleHeatingOrCooling temperature is still beyond "
    6522             :                                                "the range between Maximum and Minimum dry-bulb temperature setpoint ...",
    6523             :                                                comfortControlledZone.TdbHCErrIndex,
    6524             :                                                SetPointLo,
    6525             :                                                SetPointLo);
    6526             :             }
    6527         210 :             tempZoneThermostatSetPoint = SetPointLo;
    6528         210 :             state.dataHeatBalFanSys->ZoneThermostatSetPointHi(ActualZoneNum) = tempZoneThermostatSetPoint;
    6529         210 :             state.dataHeatBalFanSys->ZoneThermostatSetPointLo(ActualZoneNum) = tempZoneThermostatSetPoint;
    6530         210 :             state.dataHeatBalFanSys->TempControlType(ActualZoneNum) = DataHVACGlobals::ThermostatType::SingleHeatCool;
    6531         210 :             state.dataHeatBalFanSys->TempControlTypeRpt(ActualZoneNum) = static_cast<int>(state.dataHeatBalFanSys->TempControlType(ActualZoneNum));
    6532         210 :             break;
    6533         210 :         case DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand:
    6534         210 :             if (SetPointLo < comfortControlledZone.TdbMinSetPoint) {
    6535           0 :                 SetPointLo = comfortControlledZone.TdbMinSetPoint;
    6536             : 
    6537           0 :                 if (comfortControlledZone.TdbDualMinErrIndex == 0) {
    6538           0 :                     ShowWarningMessage(state,
    6539             :                                        "ThermostatSetpoint:ThermalComfort:Fanger:DualSetpoint temperature is below the Minimum dry-bulb "
    6540           0 :                                        "temperature setpoint " +
    6541             :                                            comfortControlledZone.Name);
    6542           0 :                     ShowContinueError(state, "The zone dual heating setpoint is set to the Minimum dry-bulb temperature setpoint");
    6543           0 :                     ShowContinueErrorTimeStamp(state, "Occurrence info:");
    6544             :                 }
    6545           0 :                 ShowRecurringWarningErrorAtEnd(state,
    6546             :                                                "ThermostatSetpoint:ThermalComfort:Fanger:DualSetpoint temperature is still below the Minimum "
    6547             :                                                "dry-bulb temperature setpoint ...",
    6548             :                                                comfortControlledZone.TdbDualMinErrIndex,
    6549             :                                                SetPointLo,
    6550             :                                                SetPointLo);
    6551             :             }
    6552         210 :             if (SetPointHi > comfortControlledZone.TdbMaxSetPoint) {
    6553           0 :                 SetPointHi = comfortControlledZone.TdbMaxSetPoint;
    6554           0 :                 if (comfortControlledZone.TdbDualMaxErrIndex == 0) {
    6555           0 :                     ShowWarningMessage(state,
    6556           0 :                                        format("ThermostatSetpoint:ThermalComfort:Fanger:DualSetpoint temperature is above the Maximum dry-bulb "
    6557             :                                               "temperature setpoint in zone = {}",
    6558           0 :                                               comfortControlledZone.Name));
    6559           0 :                     ShowContinueError(state, "The zone dual cooling setpoint is set to the Maximum dry-bulb temperature setpoint");
    6560           0 :                     ShowContinueErrorTimeStamp(state, "Occurrence info:");
    6561             :                 }
    6562           0 :                 ShowRecurringWarningErrorAtEnd(state,
    6563             :                                                "ThermostatSetpoint:ThermalComfort:Fanger:DualSetpoint temperature is still above the Maximum "
    6564             :                                                "dry-bulb temperature setpoint ...",
    6565             :                                                comfortControlledZone.TdbDualMaxErrIndex,
    6566             :                                                SetPointLo,
    6567             :                                                SetPointLo);
    6568             :             }
    6569             : 
    6570         210 :             state.dataHeatBalFanSys->ZoneThermostatSetPointLo(ActualZoneNum) = SetPointLo;
    6571         210 :             state.dataHeatBalFanSys->ZoneThermostatSetPointHi(ActualZoneNum) = SetPointHi;
    6572         210 :             state.dataHeatBalFanSys->TempControlType(ActualZoneNum) = DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand;
    6573         210 :             state.dataHeatBalFanSys->TempControlTypeRpt(ActualZoneNum) = static_cast<int>(state.dataHeatBalFanSys->TempControlType(ActualZoneNum));
    6574         210 :             break;
    6575           0 :         default:
    6576           0 :             ShowSevereError(state,
    6577           0 :                             format("CalcZoneAirComfortSetpoints: Illegal thermal control control type for Zone={}, Found value={}, in Schedule={}",
    6578             :                                    zone.Name,
    6579             :                                    comfortControlTypeRpt,
    6580           0 :                                    comfortControlledZone.ControlTypeSchedName));
    6581             :         }
    6582             :     }
    6583        2025 : }
    6584             : 
    6585        2235 : void GetComfortSetPoints(EnergyPlusData &state,
    6586             :                          int const PeopleNum,
    6587             :                          int const ComfortControlNum,
    6588             :                          Real64 const PMVSet,
    6589             :                          Real64 &Tset // drybulb setpoint temperature for a given PMV value
    6590             : )
    6591             : {
    6592             : 
    6593             :     // SUBROUTINE INFORMATION:
    6594             :     //       AUTHOR         Lixing Gu
    6595             :     //       DATE WRITTEN   May, 2006
    6596             :     // PURPOSE OF THIS SUBROUTINE:
    6597             :     // This routine sets what the thermal comfort setpoints for each controlled zone should be based on air temperature
    6598             :     // obtained from thermal comfort models. This is called each time step.
    6599             : 
    6600             :     // SUBROUTINE ARGUMENT DEFINITIONS:
    6601             :     // 0 = Solution; 1 = Set to Min; 2 Set to Max
    6602             : 
    6603             :     // SUBROUTINE PARAMETER DEFINITIONS:
    6604        2235 :     Real64 constexpr Acc(0.001); // accuracy control for SolveRoot
    6605        2235 :     int constexpr MaxIter(500);  // iteration control for SolveRoot
    6606             : 
    6607             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    6608        2235 :     Real64 PMVResult = 0.0; // Calculated PMV value
    6609        2235 :     int SolFla = 0;         // feed back flag from SolveRoot
    6610             : 
    6611        2235 :     auto &comfortControlledZone = state.dataZoneCtrls->ComfortControlledZone(ComfortControlNum);
    6612        2235 :     Real64 Tmin = comfortControlledZone.TdbMinSetPoint;
    6613        2235 :     Real64 Tmax = comfortControlledZone.TdbMaxSetPoint;
    6614             : 
    6615        2235 :     ThermalComfort::CalcThermalComfortFanger(state, PeopleNum, Tmin, PMVResult);
    6616        2235 :     Real64 PMVMin = PMVResult;
    6617        2235 :     ThermalComfort::CalcThermalComfortFanger(state, PeopleNum, Tmax, PMVResult);
    6618        2235 :     Real64 PMVMax = PMVResult;
    6619        2235 :     if (PMVSet > PMVMin && PMVSet < PMVMax) {
    6620             : 
    6621       15846 :         auto f = [&state, PMVSet, PeopleNum](Real64 Tset) {
    6622        5282 :             Real64 PMVresult = 0.0; // resulting PMV values
    6623       10564 :             ThermalComfort::CalcThermalComfortFanger(state, PeopleNum, Tset, PMVresult);
    6624        5282 :             return (PMVSet - PMVresult);
    6625        1050 :         };
    6626             : 
    6627        1050 :         General::SolveRoot(state, Acc, MaxIter, SolFla, Tset, f, Tmin, Tmax);
    6628        1050 :         if (SolFla == -1) {
    6629           0 :             if (!state.dataGlobal->WarmupFlag) {
    6630           0 :                 ++state.dataZoneTempPredictorCorrector->IterLimitExceededNum1;
    6631           0 :                 if (state.dataZoneTempPredictorCorrector->IterLimitExceededNum1 == 1) {
    6632           0 :                     ShowWarningError(state,
    6633           0 :                                      comfortControlledZone.Name +
    6634             :                                          ": Iteration limit exceeded calculating thermal comfort Fanger setpoint and non-converged setpoint is used");
    6635             :                 } else {
    6636           0 :                     ShowRecurringWarningErrorAtEnd(state,
    6637           0 :                                                    comfortControlledZone.Name + ":  Iteration limit exceeded calculating thermal comfort setpoint.",
    6638           0 :                                                    state.dataZoneTempPredictorCorrector->IterLimitErrIndex1,
    6639             :                                                    Tset,
    6640             :                                                    Tset);
    6641             :                 }
    6642             :             }
    6643        1050 :         } else if (SolFla == -2) {
    6644           0 :             if (!state.dataGlobal->WarmupFlag) {
    6645           0 :                 ++state.dataZoneTempPredictorCorrector->IterLimitExceededNum2;
    6646           0 :                 if (state.dataZoneTempPredictorCorrector->IterLimitExceededNum2 == 1) {
    6647           0 :                     ShowWarningError(
    6648             :                         state,
    6649           0 :                         format("{}: Solution is not found in calculating thermal comfort Fanger setpoint and the minimum setpoint is used",
    6650           0 :                                comfortControlledZone.Name));
    6651             :                 } else {
    6652           0 :                     ShowRecurringWarningErrorAtEnd(
    6653             :                         state,
    6654           0 :                         format("{}:  Solution is not found in  calculating thermal comfort Fanger setpoint.", comfortControlledZone.Name),
    6655           0 :                         state.dataZoneTempPredictorCorrector->IterLimitErrIndex2,
    6656             :                         Tset,
    6657             :                         Tset);
    6658             :                 }
    6659             :             }
    6660        1050 :         }
    6661        1185 :     } else if (PMVSet < PMVMin) {
    6662        1185 :         Tset = Tmin;
    6663           0 :     } else if (PMVSet > PMVMax) {
    6664           0 :         Tset = Tmax;
    6665             :     }
    6666        2235 : }
    6667             : 
    6668    13852321 : void AdjustCoolingSetPointforTempAndHumidityControl(EnergyPlusData &state,
    6669             :                                                     int const TempControlledZoneID,
    6670             :                                                     int const ActualZoneNum // controlled zone actual zone number
    6671             : )
    6672             : {
    6673             :     // SUBROUTINE INFORMATION:
    6674             :     //       AUTHOR         Bereket A Nigusse, FSEC/UCF
    6675             :     //       DATE WRITTEN   Nov 2010
    6676             : 
    6677             :     // PURPOSE OF THIS SUBROUTINE:
    6678             :     //  This subroutine modifies the air cooling setpoint temperature to effect zone air Temperature and humidity control
    6679             :     //  Alter the zone air cooling setpoint if the zone air relative humidity value exceeds the the zone dehumidifying relative humidity setpoint.
    6680             : 
    6681    13852321 :     Real64 ZoneOvercoolRange = 0.0;
    6682    13852321 :     auto &tempControlledZone = state.dataZoneCtrls->TempControlledZone(TempControlledZoneID);
    6683             : 
    6684    13852321 :     if (!(state.dataZoneCtrls->AnyZoneTempAndHumidityControl)) return; // do nothing to setpoint
    6685        6495 :     if (!(tempControlledZone.ZoneOvercoolControl)) return;             // do nothing to setpoint
    6686             : 
    6687        6495 :     if (tempControlledZone.OvercoolCntrlModeScheduled) {
    6688           0 :         ZoneOvercoolRange = ScheduleManager::GetCurrentScheduleValue(state, tempControlledZone.ZoneOvercoolRangeSchedIndex);
    6689             :     } else {
    6690        6495 :         ZoneOvercoolRange = tempControlledZone.ZoneOvercoolConstRange;
    6691             :     }
    6692        6495 :     Real64 ZoneOvercoolControlRatio = tempControlledZone.ZoneOvercoolControlRatio;
    6693             : 
    6694             :     // For Dual Setpoint thermostat the overcool range is limited by the temperature difference between cooling and heating setpoints
    6695             :     Real64 MaxAllowedOvercoolRange =
    6696        6495 :         state.dataHeatBalFanSys->ZoneThermostatSetPointHi(ActualZoneNum) - state.dataHeatBalFanSys->ZoneThermostatSetPointLo(ActualZoneNum);
    6697        6495 :     if (MaxAllowedOvercoolRange > 0.0) {
    6698        6495 :         ZoneOvercoolRange = min(ZoneOvercoolRange, MaxAllowedOvercoolRange);
    6699             :     }
    6700             :     // Calculate difference between zone air relative humidity and the dehumidifying setpoint
    6701        6495 :     Real64 RelativeHumidityDiff = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ActualZoneNum).ZoneAirRelHum -
    6702        6495 :                                   ScheduleManager::GetCurrentScheduleValue(state, tempControlledZone.DehumidifyingSchedIndex);
    6703        6495 :     if (RelativeHumidityDiff > 0.0 && ZoneOvercoolControlRatio > 0.0) {
    6704             :         // proportionally reset the cooling setpoint temperature downward (zone Overcool)
    6705        4763 :         ZoneOvercoolRange = min(ZoneOvercoolRange, RelativeHumidityDiff / ZoneOvercoolControlRatio);
    6706        4763 :         state.dataHeatBalFanSys->ZoneThermostatSetPointHi(ActualZoneNum) -= ZoneOvercoolRange;
    6707             :     }
    6708             : }
    6709             : 
    6710     2568551 : void OverrideAirSetPointsforEMSCntrl(EnergyPlusData &state)
    6711             : {
    6712             : 
    6713             :     // SUBROUTINE INFORMATION:
    6714             :     //       AUTHOR         L. Gu
    6715             :     //       DATE WRITTEN   June 2017
    6716             : 
    6717             :     // PURPOSE OF THIS SUBROUTINE:
    6718             :     // This subroutine overrides the air temperature setpoint based on EMS
    6719             : 
    6720     2568551 :     auto &ZoneThermostatSetPointLo = state.dataHeatBalFanSys->ZoneThermostatSetPointLo;
    6721     2568551 :     auto &ZoneThermostatSetPointHi = state.dataHeatBalFanSys->ZoneThermostatSetPointHi;
    6722             : 
    6723    18204603 :     for (int Loop = 1; Loop <= state.dataZoneCtrls->NumTempControlledZones; ++Loop) {
    6724    15636052 :         auto &tempControlledZone = state.dataZoneCtrls->TempControlledZone(Loop);
    6725    15636052 :         if (tempControlledZone.EMSOverrideHeatingSetPointOn) {
    6726           0 :             int ZoneNum = tempControlledZone.ActualZoneNum;
    6727             : 
    6728           0 :             switch (state.dataHeatBalFanSys->TempControlType(ZoneNum)) {
    6729           0 :             case DataHVACGlobals::ThermostatType::SingleHeating:
    6730           0 :                 state.dataHeatBalFanSys->TempZoneThermostatSetPoint(ZoneNum) = tempControlledZone.EMSOverrideHeatingSetPointValue;
    6731           0 :                 ZoneThermostatSetPointLo(ZoneNum) = tempControlledZone.EMSOverrideHeatingSetPointValue;
    6732           0 :                 break;
    6733           0 :             case DataHVACGlobals::ThermostatType::SingleHeatCool:
    6734           0 :                 state.dataHeatBalFanSys->TempZoneThermostatSetPoint(ZoneNum) = tempControlledZone.EMSOverrideHeatingSetPointValue;
    6735           0 :                 ZoneThermostatSetPointLo(ZoneNum) = tempControlledZone.EMSOverrideHeatingSetPointValue;
    6736           0 :                 break;
    6737           0 :             case DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand:
    6738           0 :                 ZoneThermostatSetPointLo(ZoneNum) = tempControlledZone.EMSOverrideHeatingSetPointValue;
    6739           0 :                 break;
    6740           0 :             default:
    6741           0 :                 break;
    6742             :             }
    6743             :         }
    6744    15636052 :         if (tempControlledZone.EMSOverrideCoolingSetPointOn) {
    6745           0 :             int ZoneNum = tempControlledZone.ActualZoneNum;
    6746             : 
    6747           0 :             switch (state.dataHeatBalFanSys->TempControlType(ZoneNum)) {
    6748           0 :             case DataHVACGlobals::ThermostatType::SingleCooling:
    6749           0 :                 state.dataHeatBalFanSys->TempZoneThermostatSetPoint(ZoneNum) = tempControlledZone.EMSOverrideCoolingSetPointValue;
    6750           0 :                 ZoneThermostatSetPointHi(ZoneNum) = tempControlledZone.EMSOverrideCoolingSetPointValue;
    6751           0 :                 break;
    6752           0 :             case DataHVACGlobals::ThermostatType::SingleHeatCool:
    6753           0 :                 state.dataHeatBalFanSys->TempZoneThermostatSetPoint(ZoneNum) = tempControlledZone.EMSOverrideCoolingSetPointValue;
    6754           0 :                 ZoneThermostatSetPointHi(ZoneNum) = tempControlledZone.EMSOverrideCoolingSetPointValue;
    6755           0 :                 break;
    6756           0 :             case DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand:
    6757           0 :                 ZoneThermostatSetPointHi(ZoneNum) = tempControlledZone.EMSOverrideCoolingSetPointValue;
    6758           0 :                 break;
    6759           0 :             default:
    6760           0 :                 break;
    6761             :             }
    6762             :         }
    6763             :     }
    6764             : 
    6765     2570576 :     for (int Loop = 1; Loop <= state.dataZoneCtrls->NumComfortControlledZones; ++Loop) {
    6766        2025 :         auto &comfortControlledZone = state.dataZoneCtrls->ComfortControlledZone(Loop);
    6767        2025 :         if (comfortControlledZone.EMSOverrideHeatingSetPointOn) {
    6768           0 :             int ZoneNum = comfortControlledZone.ActualZoneNum;
    6769           0 :             switch (state.dataHeatBalFanSys->ComfortControlType(ZoneNum)) {
    6770           0 :             case DataHVACGlobals::ThermostatType::SingleHeating:
    6771           0 :                 state.dataHeatBalFanSys->TempZoneThermostatSetPoint(ZoneNum) = comfortControlledZone.EMSOverrideHeatingSetPointValue;
    6772           0 :                 ZoneThermostatSetPointLo(ZoneNum) = comfortControlledZone.EMSOverrideHeatingSetPointValue;
    6773           0 :                 break;
    6774           0 :             case DataHVACGlobals::ThermostatType::SingleHeatCool:
    6775           0 :                 state.dataHeatBalFanSys->TempZoneThermostatSetPoint(ZoneNum) = comfortControlledZone.EMSOverrideHeatingSetPointValue;
    6776           0 :                 ZoneThermostatSetPointLo(ZoneNum) = comfortControlledZone.EMSOverrideHeatingSetPointValue;
    6777           0 :                 break;
    6778           0 :             case DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand:
    6779           0 :                 ZoneThermostatSetPointLo(ZoneNum) = comfortControlledZone.EMSOverrideHeatingSetPointValue;
    6780           0 :                 break;
    6781           0 :             default:
    6782           0 :                 break;
    6783             :             }
    6784             :         }
    6785             : 
    6786        2025 :         if (comfortControlledZone.EMSOverrideCoolingSetPointOn) {
    6787           0 :             int ZoneNum = comfortControlledZone.ActualZoneNum;
    6788           0 :             switch (static_cast<DataHVACGlobals::ThermostatType>(state.dataHeatBalFanSys->ComfortControlType(ZoneNum))) {
    6789           0 :             case DataHVACGlobals::ThermostatType::SingleCooling:
    6790           0 :                 state.dataHeatBalFanSys->TempZoneThermostatSetPoint(ZoneNum) = comfortControlledZone.EMSOverrideCoolingSetPointValue;
    6791           0 :                 ZoneThermostatSetPointHi(ZoneNum) = comfortControlledZone.EMSOverrideCoolingSetPointValue;
    6792           0 :                 break;
    6793           0 :             case DataHVACGlobals::ThermostatType::SingleHeatCool:
    6794           0 :                 state.dataHeatBalFanSys->TempZoneThermostatSetPoint(ZoneNum) = comfortControlledZone.EMSOverrideCoolingSetPointValue;
    6795           0 :                 ZoneThermostatSetPointHi(ZoneNum) = comfortControlledZone.EMSOverrideCoolingSetPointValue;
    6796           0 :                 break;
    6797           0 :             case DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand:
    6798           0 :                 ZoneThermostatSetPointHi(ZoneNum) = comfortControlledZone.EMSOverrideCoolingSetPointValue;
    6799           0 :                 break;
    6800           0 :             default:
    6801           0 :                 break;
    6802             :             }
    6803             :         }
    6804             :     }
    6805     2568551 : }
    6806             : 
    6807             : // add values to the LEED tabular report related to schedules used by the thermostat objects
    6808         769 : void FillPredefinedTableOnThermostatSetpoints(EnergyPlusData &state)
    6809             : {
    6810             :     // J.Glazer - Aug 2017
    6811             :     using namespace OutputReportPredefined;
    6812        1538 :     std::vector<int> uniqSch;
    6813         769 :     uniqSch.reserve(
    6814        1538 :         state.dataZoneTempPredictorCorrector->NumSingleTempHeatingControls + state.dataZoneTempPredictorCorrector->NumSingleTempCoolingControls +
    6815        1538 :         state.dataZoneTempPredictorCorrector->NumSingleTempHeatCoolControls + state.dataZoneTempPredictorCorrector->NumDualTempHeatCoolControls * 2);
    6816             :     Real64 setPointAt11;
    6817             :     Real64 setPointAt23;
    6818             :     int numDays;
    6819        1538 :     std::string monthAssumed;
    6820        1538 :     std::string monthAssumed2;
    6821         769 :     constexpr int wednesday = 4;
    6822             : 
    6823        1204 :     for (int idx = 1; idx <= state.dataZoneTempPredictorCorrector->NumSingleTempHeatingControls; ++idx) {
    6824         435 :         auto &singleHtgSetpoint = state.dataZoneTempPredictorCorrector->SetPointSingleHeating(idx);
    6825         435 :         if (std::find(uniqSch.begin(), uniqSch.end(), singleHtgSetpoint.TempSchedIndex) == uniqSch.end()) {
    6826         430 :             uniqSch.emplace_back(singleHtgSetpoint.TempSchedIndex);
    6827         430 :             PreDefTableEntry(state, state.dataOutRptPredefined->pdChLeedSchStPtFirstObjUsed, singleHtgSetpoint.TempSchedName, singleHtgSetpoint.Name);
    6828             : 
    6829         430 :             std::tie(setPointAt11, numDays, monthAssumed) = temperatureAndCountInSch(state, singleHtgSetpoint.TempSchedIndex, false, wednesday, 11);
    6830         430 :             PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedSchStPt11amWednesday, singleHtgSetpoint.TempSchedName, setPointAt11);
    6831         430 :             PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedSchStPt11amWedCnt, singleHtgSetpoint.TempSchedName, numDays);
    6832             : 
    6833         430 :             std::tie(setPointAt23, numDays, monthAssumed) = temperatureAndCountInSch(state, singleHtgSetpoint.TempSchedIndex, false, wednesday, 23);
    6834         430 :             PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedSchStPt11pmWednesday, singleHtgSetpoint.TempSchedName, setPointAt23);
    6835         430 :             PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedSchStPt11pmWedCnt, singleHtgSetpoint.TempSchedName, numDays);
    6836             : 
    6837         430 :             PreDefTableEntry(state, state.dataOutRptPredefined->pdChLeedSchStPtMonthUsed, singleHtgSetpoint.TempSchedName, monthAssumed);
    6838             :         }
    6839             :     }
    6840        1198 :     for (int idx = 1; idx <= state.dataZoneTempPredictorCorrector->NumSingleTempCoolingControls; ++idx) {
    6841         429 :         auto &singleClgSetpoint = state.dataZoneTempPredictorCorrector->SetPointSingleCooling(idx);
    6842         429 :         if (std::find(uniqSch.begin(), uniqSch.end(), singleClgSetpoint.TempSchedIndex) == uniqSch.end()) {
    6843         419 :             uniqSch.emplace_back(singleClgSetpoint.TempSchedIndex);
    6844         419 :             PreDefTableEntry(state, state.dataOutRptPredefined->pdChLeedSchStPtFirstObjUsed, singleClgSetpoint.TempSchedName, singleClgSetpoint.Name);
    6845             : 
    6846         419 :             std::tie(setPointAt11, numDays, monthAssumed) = temperatureAndCountInSch(state, singleClgSetpoint.TempSchedIndex, true, wednesday, 11);
    6847         419 :             PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedSchStPt11amWednesday, singleClgSetpoint.TempSchedName, setPointAt11);
    6848         419 :             PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedSchStPt11amWedCnt, singleClgSetpoint.TempSchedName, numDays);
    6849             : 
    6850         419 :             std::tie(setPointAt23, numDays, monthAssumed) = temperatureAndCountInSch(state, singleClgSetpoint.TempSchedIndex, true, wednesday, 23);
    6851         419 :             PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedSchStPt11pmWednesday, singleClgSetpoint.TempSchedName, setPointAt23);
    6852         419 :             PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedSchStPt11pmWedCnt, singleClgSetpoint.TempSchedName, numDays);
    6853             : 
    6854         419 :             PreDefTableEntry(state, state.dataOutRptPredefined->pdChLeedSchStPtMonthUsed, singleClgSetpoint.TempSchedName, monthAssumed);
    6855             :         }
    6856             :     }
    6857         780 :     for (int idx = 1; idx <= state.dataZoneTempPredictorCorrector->NumSingleTempHeatCoolControls; ++idx) {
    6858          11 :         auto &singleHeatCoolSetpoint = state.dataZoneTempPredictorCorrector->SetPointSingleHeatCool(idx);
    6859          11 :         if (std::find(uniqSch.begin(), uniqSch.end(), singleHeatCoolSetpoint.TempSchedIndex) == uniqSch.end()) {
    6860          11 :             uniqSch.emplace_back(singleHeatCoolSetpoint.TempSchedIndex);
    6861          22 :             PreDefTableEntry(
    6862          11 :                 state, state.dataOutRptPredefined->pdChLeedSchStPtFirstObjUsed, singleHeatCoolSetpoint.TempSchedName, singleHeatCoolSetpoint.Name);
    6863             : 
    6864          22 :             std::string schNm = singleHeatCoolSetpoint.TempSchedName + " (summer)";
    6865          11 :             std::tie(setPointAt11, numDays, monthAssumed) =
    6866          22 :                 temperatureAndCountInSch(state, singleHeatCoolSetpoint.TempSchedIndex, true, wednesday, 11);
    6867          11 :             PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedSchStPt11amWednesday, schNm, setPointAt11);
    6868          11 :             PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedSchStPt11amWedCnt, schNm, numDays);
    6869             : 
    6870          11 :             std::tie(setPointAt23, numDays, monthAssumed) =
    6871          22 :                 temperatureAndCountInSch(state, singleHeatCoolSetpoint.TempSchedIndex, true, wednesday, 23);
    6872          11 :             PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedSchStPt11pmWednesday, schNm, setPointAt23);
    6873          11 :             PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedSchStPt11pmWedCnt, schNm, numDays);
    6874             : 
    6875          11 :             schNm = singleHeatCoolSetpoint.TempSchedName + " (winter)";
    6876          11 :             std::tie(setPointAt11, numDays, monthAssumed2) =
    6877          22 :                 temperatureAndCountInSch(state, singleHeatCoolSetpoint.TempSchedIndex, false, wednesday, 11);
    6878          11 :             PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedSchStPt11amWednesday, schNm, setPointAt11);
    6879          11 :             PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedSchStPt11amWedCnt, schNm, numDays);
    6880             : 
    6881          11 :             std::tie(setPointAt23, numDays, monthAssumed2) =
    6882          22 :                 temperatureAndCountInSch(state, singleHeatCoolSetpoint.TempSchedIndex, false, wednesday, 23);
    6883          11 :             PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedSchStPt11pmWednesday, schNm, setPointAt23);
    6884          11 :             PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedSchStPt11pmWedCnt, schNm, numDays);
    6885             : 
    6886          22 :             PreDefTableEntry(state,
    6887          11 :                              state.dataOutRptPredefined->pdChLeedSchStPtMonthUsed,
    6888             :                              singleHeatCoolSetpoint.TempSchedName,
    6889          22 :                              monthAssumed + " and " + monthAssumed2);
    6890             :         }
    6891             :     }
    6892        3055 :     for (int idx = 1; idx <= state.dataZoneTempPredictorCorrector->NumDualTempHeatCoolControls; ++idx) {
    6893        2286 :         auto &dualHeatCoolSetpoint = state.dataZoneTempPredictorCorrector->SetPointDualHeatCool(idx);
    6894        2286 :         if (std::find(uniqSch.begin(), uniqSch.end(), dualHeatCoolSetpoint.HeatTempSchedIndex) == uniqSch.end()) {
    6895         468 :             uniqSch.emplace_back(dualHeatCoolSetpoint.HeatTempSchedIndex);
    6896         936 :             PreDefTableEntry(state,
    6897         468 :                              state.dataOutRptPredefined->pdChLeedSchStPtFirstObjUsed,
    6898             :                              dualHeatCoolSetpoint.HeatTempSetptSchedName,
    6899             :                              dualHeatCoolSetpoint.Name);
    6900             : 
    6901         468 :             std::tie(setPointAt11, numDays, monthAssumed) =
    6902         936 :                 temperatureAndCountInSch(state, dualHeatCoolSetpoint.HeatTempSchedIndex, false, wednesday, 11);
    6903         936 :             PreDefTableEntry(
    6904         468 :                 state, state.dataOutRptPredefined->pdchLeedSchStPt11amWednesday, dualHeatCoolSetpoint.HeatTempSetptSchedName, setPointAt11);
    6905         468 :             PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedSchStPt11amWedCnt, dualHeatCoolSetpoint.HeatTempSetptSchedName, numDays);
    6906             : 
    6907         468 :             std::tie(setPointAt23, numDays, monthAssumed) =
    6908         936 :                 temperatureAndCountInSch(state, dualHeatCoolSetpoint.HeatTempSchedIndex, false, wednesday, 23);
    6909         936 :             PreDefTableEntry(
    6910         468 :                 state, state.dataOutRptPredefined->pdchLeedSchStPt11pmWednesday, dualHeatCoolSetpoint.HeatTempSetptSchedName, setPointAt23);
    6911         468 :             PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedSchStPt11pmWedCnt, dualHeatCoolSetpoint.HeatTempSetptSchedName, numDays);
    6912             : 
    6913         468 :             PreDefTableEntry(state, state.dataOutRptPredefined->pdChLeedSchStPtMonthUsed, dualHeatCoolSetpoint.HeatTempSetptSchedName, monthAssumed);
    6914             :         }
    6915        2286 :         if (std::find(uniqSch.begin(), uniqSch.end(), dualHeatCoolSetpoint.CoolTempSchedIndex) == uniqSch.end()) {
    6916         463 :             uniqSch.emplace_back(dualHeatCoolSetpoint.CoolTempSchedIndex);
    6917         926 :             PreDefTableEntry(state,
    6918         463 :                              state.dataOutRptPredefined->pdChLeedSchStPtFirstObjUsed,
    6919             :                              dualHeatCoolSetpoint.CoolTempSetptSchedName,
    6920             :                              dualHeatCoolSetpoint.Name);
    6921             : 
    6922         463 :             std::tie(setPointAt11, numDays, monthAssumed) =
    6923         926 :                 temperatureAndCountInSch(state, dualHeatCoolSetpoint.CoolTempSchedIndex, true, wednesday, 11);
    6924         926 :             PreDefTableEntry(
    6925         463 :                 state, state.dataOutRptPredefined->pdchLeedSchStPt11amWednesday, dualHeatCoolSetpoint.CoolTempSetptSchedName, setPointAt11);
    6926         463 :             PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedSchStPt11amWedCnt, dualHeatCoolSetpoint.CoolTempSetptSchedName, numDays);
    6927             : 
    6928         463 :             std::tie(setPointAt23, numDays, monthAssumed) =
    6929         926 :                 temperatureAndCountInSch(state, dualHeatCoolSetpoint.CoolTempSchedIndex, true, wednesday, 23);
    6930         926 :             PreDefTableEntry(
    6931         463 :                 state, state.dataOutRptPredefined->pdchLeedSchStPt11pmWednesday, dualHeatCoolSetpoint.CoolTempSetptSchedName, setPointAt23);
    6932         463 :             PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedSchStPt11pmWedCnt, dualHeatCoolSetpoint.CoolTempSetptSchedName, numDays);
    6933             : 
    6934         463 :             PreDefTableEntry(state, state.dataOutRptPredefined->pdChLeedSchStPtMonthUsed, dualHeatCoolSetpoint.CoolTempSetptSchedName, monthAssumed);
    6935             :         }
    6936             :     }
    6937         769 : }
    6938             : 
    6939             : // returns the temperature value from a schedule at a certain time for the first day of the week in either January or July
    6940             : std::tuple<Real64, int, std::string>
    6941        3604 : temperatureAndCountInSch(EnergyPlusData &state, int const scheduleIndex, bool const isSummer, int const dayOfWeek, int const hourOfDay)
    6942             : {
    6943             :     // J.Glazer - Aug 2017
    6944             : 
    6945             :     // determine month to use based on hemiphere and season
    6946             :     int monthToUse;
    6947        3604 :     if (isSummer) {
    6948        1786 :         if (state.dataEnvrn->Latitude > 0.) {
    6949        1786 :             monthToUse = 7; // July - summer in northern hemisphere
    6950             :         } else {
    6951           0 :             monthToUse = 1; // January - summer in southern hemisphere
    6952             :         }
    6953             :     } else {
    6954        1818 :         if (state.dataEnvrn->Latitude > 0.) {
    6955        1818 :             monthToUse = 1; // January - winter in northern hemisphere
    6956             :         } else {
    6957           0 :             monthToUse = 7; // July - winter in southern hemisphere
    6958             :         }
    6959             :     }
    6960        7208 :     std::string monthName;
    6961        3604 :     if (monthToUse == 1) {
    6962        1818 :         monthName = "January";
    6963             :     } else {
    6964        1786 :         monthName = "July";
    6965             :     }
    6966             : 
    6967        3604 :     int jdateSelect = General::nthDayOfWeekOfMonth(state, dayOfWeek, 1, monthToUse);
    6968             : 
    6969             :     // determine number of days in year
    6970             :     int DaysInYear;
    6971        3604 :     if (state.dataEnvrn->CurrentYearIsLeapYear) {
    6972           8 :         DaysInYear = 366;
    6973             :     } else {
    6974        3596 :         DaysInYear = 365;
    6975             :     }
    6976             : 
    6977             :     // should adjust date if lands on a holiday but for now assume that it does not
    6978             : 
    6979             :     // adjust time of day for daylight savings time
    6980        3604 :     int hourSelect = hourOfDay + state.dataWeatherManager->DSTIndex(jdateSelect);
    6981             : 
    6982             :     // get the value at the selected time
    6983        3604 :     int constexpr firstTimeStep = 1;
    6984        3604 :     int weekSchIndexSelect = state.dataScheduleMgr->Schedule(scheduleIndex).WeekSchedulePointer(jdateSelect);
    6985        3604 :     int daySchIndexSelect = state.dataScheduleMgr->WeekSchedule(weekSchIndexSelect).DaySchedulePointer(dayOfWeek);
    6986        3604 :     Real64 valueAtSelectTime = state.dataScheduleMgr->DaySchedule(daySchIndexSelect).TSValue(firstTimeStep, hourSelect);
    6987        3604 :     int countOfSame = 0;
    6988             : 
    6989             :     // count the number of times with that same value
    6990     1319072 :     for (int jdateOfYear = 1; jdateOfYear <= DaysInYear; ++jdateOfYear) {
    6991     1315468 :         int wkSch = state.dataScheduleMgr->Schedule(scheduleIndex).WeekSchedulePointer(jdateOfYear);
    6992     1315468 :         if (wkSch == weekSchIndexSelect) { // if same week schedule can short circuit rest of testing and increment counter
    6993     1302652 :             ++countOfSame;
    6994             :         } else {
    6995       12816 :             int daySch = state.dataScheduleMgr->WeekSchedule(wkSch).DaySchedulePointer(dayOfWeek);
    6996       12816 :             if (daySch == daySchIndexSelect) { // if same day schedule can short circuit rest of testing and increment counter
    6997           0 :                 ++countOfSame;
    6998             :             } else {
    6999       12816 :                 Real64 valueAt = state.dataScheduleMgr->DaySchedule(daySch).TSValue(firstTimeStep, hourSelect);
    7000       12816 :                 if (valueAt == valueAtSelectTime) {
    7001        6250 :                     ++countOfSame;
    7002             :                 }
    7003             :             }
    7004             :         }
    7005             :     }
    7006             : 
    7007        7208 :     return std::make_tuple(valueAtSelectTime, countOfSame, monthName);
    7008             : }
    7009             : 
    7010    27959531 : void ZoneSpaceHeatBalanceData::updateTemperatures(EnergyPlusData &state,
    7011             :                                                   bool const ShortenTimeStepSys,
    7012             :                                                   bool const UseZoneTimeStepHistory,
    7013             :                                                   Real64 const PriorTimeStep,
    7014             :                                                   int const zoneNum,
    7015             :                                                   int const spaceNum)
    7016             : {
    7017    27959531 :     assert(zoneNum > 0);
    7018    27959531 :     if (ShortenTimeStepSys) {
    7019             :         // timestep has just shifted from full zone timestep to a new shorter system timestep
    7020             :         // throw away last updates in corrector and rewind for resimulating smaller timestep
    7021     2749903 :         if (spaceNum == 0) {
    7022     2747425 :             if (state.dataHeatBal->Zone(zoneNum).SystemZoneNodeNumber > 0) { // roll back result for zone air node,
    7023     2379472 :                 auto &zoneNode = state.dataLoopNodes->Node(state.dataHeatBal->Zone(zoneNum).SystemZoneNodeNumber);
    7024     2379472 :                 zoneNode.Temp = this->XMAT[0];
    7025     2379472 :                 state.dataHeatBalFanSys->TempTstatAir(zoneNum) = this->XMAT[0];
    7026     2379472 :                 zoneNode.HumRat = this->WPrevZoneTS[0];
    7027     2379472 :                 zoneNode.Enthalpy = Psychrometrics::PsyHFnTdbW(this->XMAT[0], this->WPrevZoneTS[0]);
    7028             :             }
    7029             :         } else {
    7030        2478 :             if (state.dataHeatBal->space(spaceNum).SystemZoneNodeNumber > 0) { // roll back result for space air node,
    7031        2257 :                 auto &spaceNode = state.dataLoopNodes->Node(state.dataHeatBal->space(spaceNum).SystemZoneNodeNumber);
    7032        2257 :                 spaceNode.Temp = this->XMAT[0];
    7033        2257 :                 state.dataHeatBalFanSys->TempTstatAir(zoneNum) = this->XMAT[0];
    7034        2257 :                 spaceNode.HumRat = this->WPrevZoneTS[0];
    7035        2257 :                 spaceNode.Enthalpy = Psychrometrics::PsyHFnTdbW(this->XMAT[0], this->WPrevZoneTS[0]);
    7036             :             }
    7037             :         }
    7038             : 
    7039     5499806 :         if (state.dataHVACGlobal->NumOfSysTimeSteps !=
    7040     2749903 :             state.dataHVACGlobal->NumOfSysTimeStepsLastZoneTimeStep) { // cannot reuse existing DS data, interpolate from zone time
    7041             : 
    7042     1343291 :             this->MAT = DownInterpolate4HistoryValues(PriorTimeStep, state.dataHVACGlobal->TimeStepSys, this->XMAT, this->DSXMAT);
    7043     1343291 :             this->ZoneAirHumRat =
    7044     1343291 :                 DownInterpolate4HistoryValues(PriorTimeStep, state.dataHVACGlobal->TimeStepSys, this->WPrevZoneTS, this->DSWPrevZoneTS);
    7045             : 
    7046     1343291 :             if (spaceNum == 0 && state.dataRoomAirMod->anyNonMixingRoomAirModel) {
    7047        8737 :                 if (state.dataRoomAirMod->IsZoneDV(zoneNum) || state.dataRoomAirMod->IsZoneUI(zoneNum)) {
    7048             : 
    7049        5604 :                     DownInterpolate4HistoryValues(PriorTimeStep,
    7050        1401 :                                                   state.dataHVACGlobal->TimeStepSys,
    7051        1401 :                                                   state.dataRoomAirMod->XMATFloor(zoneNum),
    7052        1401 :                                                   state.dataRoomAirMod->XM2TFloor(zoneNum),
    7053        1401 :                                                   state.dataRoomAirMod->XM3TFloor(zoneNum),
    7054        1401 :                                                   state.dataRoomAirMod->MATFloor(zoneNum),
    7055        1401 :                                                   state.dataRoomAirMod->DSXMATFloor(zoneNum),
    7056        1401 :                                                   state.dataRoomAirMod->DSXM2TFloor(zoneNum),
    7057        1401 :                                                   state.dataRoomAirMod->DSXM3TFloor(zoneNum),
    7058        1401 :                                                   state.dataRoomAirMod->DSXM4TFloor(zoneNum));
    7059        5604 :                     DownInterpolate4HistoryValues(PriorTimeStep,
    7060        1401 :                                                   state.dataHVACGlobal->TimeStepSys,
    7061        1401 :                                                   state.dataRoomAirMod->XMATOC(zoneNum),
    7062        1401 :                                                   state.dataRoomAirMod->XM2TOC(zoneNum),
    7063        1401 :                                                   state.dataRoomAirMod->XM3TOC(zoneNum),
    7064        1401 :                                                   state.dataRoomAirMod->MATOC(zoneNum),
    7065        1401 :                                                   state.dataRoomAirMod->DSXMATOC(zoneNum),
    7066        1401 :                                                   state.dataRoomAirMod->DSXM2TOC(zoneNum),
    7067        1401 :                                                   state.dataRoomAirMod->DSXM3TOC(zoneNum),
    7068        1401 :                                                   state.dataRoomAirMod->DSXM4TOC(zoneNum));
    7069        5604 :                     DownInterpolate4HistoryValues(PriorTimeStep,
    7070        1401 :                                                   state.dataHVACGlobal->TimeStepSys,
    7071        1401 :                                                   state.dataRoomAirMod->XMATMX(zoneNum),
    7072        1401 :                                                   state.dataRoomAirMod->XM2TMX(zoneNum),
    7073        1401 :                                                   state.dataRoomAirMod->XM3TMX(zoneNum),
    7074        1401 :                                                   state.dataRoomAirMod->MATMX(zoneNum),
    7075        1401 :                                                   state.dataRoomAirMod->DSXMATMX(zoneNum),
    7076        1401 :                                                   state.dataRoomAirMod->DSXM2TMX(zoneNum),
    7077        1401 :                                                   state.dataRoomAirMod->DSXM3TMX(zoneNum),
    7078        1401 :                                                   state.dataRoomAirMod->DSXM4TMX(zoneNum));
    7079             :                 }
    7080        8737 :                 if (state.dataRoomAirMod->AirModel(zoneNum).AirModelType == DataRoomAirModel::RoomAirModel::AirflowNetwork) {
    7081        2345 :                     for (int LoopNode = 1; LoopNode <= state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum).NumOfAirNodes; ++LoopNode) {
    7082        2010 :                         auto &ThisRAFNNode(state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum).Node(LoopNode));
    7083        4020 :                         DownInterpolate4HistoryValues(PriorTimeStep,
    7084        2010 :                                                       state.dataHVACGlobal->TimeStepSys,
    7085             :                                                       ThisRAFNNode.AirTempX1,
    7086             :                                                       ThisRAFNNode.AirTempX2,
    7087             :                                                       ThisRAFNNode.AirTempX3,
    7088             :                                                       ThisRAFNNode.AirTemp,
    7089             :                                                       ThisRAFNNode.AirTempDSX1,
    7090             :                                                       ThisRAFNNode.AirTempDSX2,
    7091             :                                                       ThisRAFNNode.AirTempDSX3,
    7092             :                                                       ThisRAFNNode.AirTempDSX4);
    7093        4020 :                         DownInterpolate4HistoryValues(PriorTimeStep,
    7094        2010 :                                                       state.dataHVACGlobal->TimeStepSys,
    7095             :                                                       ThisRAFNNode.HumRatX1,
    7096             :                                                       ThisRAFNNode.HumRatX2,
    7097             :                                                       ThisRAFNNode.HumRatX3,
    7098             :                                                       ThisRAFNNode.HumRat,
    7099             :                                                       ThisRAFNNode.HumRatDSX1,
    7100             :                                                       ThisRAFNNode.HumRatDSX2,
    7101             :                                                       ThisRAFNNode.HumRatDSX3,
    7102             :                                                       ThisRAFNNode.HumRatDSX4);
    7103             :                     }
    7104             :                 }
    7105             :             }
    7106             :         } else { // reuse history data in DS terms from last zone time step to preserve information that would be lost
    7107             :                  // do nothing because DS history would have been pushed prior and should be ready
    7108             :         }
    7109             :     }
    7110             :     // now update the variables actually used in the balance equations.
    7111    27959531 :     if (UseZoneTimeStepHistory) {
    7112    18471081 :         this->ZTM = this->XMAT;
    7113    18471081 :         this->WPrevZoneTSTemp = this->WPrevZoneTS;
    7114             :     } else { // use down-stepped history
    7115     9488450 :         this->ZTM = this->DSXMAT;
    7116     9488450 :         this->WPrevZoneTSTemp = this->DSWPrevZoneTS;
    7117             :     }
    7118    27959531 : }
    7119             : 
    7120    27959531 : void ZoneSpaceHeatBalanceData::calcPredictedSystemLoad(EnergyPlusData &state, Real64 const RAFNFrac, int const zoneNum, int const spaceNum)
    7121             : {
    7122             :     // Calculate the predicted system load for a time step.
    7123             : 
    7124    27959531 :     assert(zoneNum > 0);
    7125    27959531 :     auto const &thisZone = state.dataHeatBal->Zone(zoneNum);
    7126    27959531 :     Real64 const thisTempZoneThermostatSetPoint = state.dataHeatBalFanSys->TempZoneThermostatSetPoint(zoneNum);
    7127    27959531 :     Real64 const thisZoneThermostatSetPointLo = state.dataHeatBalFanSys->ZoneThermostatSetPointLo(zoneNum);
    7128    27959531 :     Real64 const thisZoneThermostatSetPointHi = state.dataHeatBalFanSys->ZoneThermostatSetPointHi(zoneNum);
    7129             : 
    7130    27959531 :     bool thisDeadBandOrSetBack = false;
    7131    27959531 :     Real64 ZoneSetPoint = 0.0;
    7132    27959531 :     Real64 totalLoad = 0.0;
    7133    27959531 :     Real64 LoadToHeatingSetPoint = 0.0;
    7134    27959531 :     Real64 LoadToCoolingSetPoint = 0.0;
    7135             : 
    7136    27959531 :     switch (state.dataHeatBalFanSys->TempControlType(zoneNum)) {
    7137     4581159 :     case DataHVACGlobals::ThermostatType::Uncontrolled:
    7138             :         // Uncontrolled Zone
    7139     4581159 :         LoadToHeatingSetPoint = 0.0;
    7140     4581159 :         LoadToCoolingSetPoint = 0.0;
    7141     4581159 :         totalLoad = 0.0;
    7142     4581159 :         break;
    7143     2017978 :     case DataHVACGlobals::ThermostatType::SingleHeating:
    7144     2017978 :         switch (state.dataHeatBal->ZoneAirSolutionAlgo) {
    7145     2017978 :         case DataHeatBalance::SolutionAlgo::ThirdOrder: {
    7146     2017978 :             LoadToHeatingSetPoint = (this->TempDepZnLd * thisTempZoneThermostatSetPoint - this->TempIndZnLd);
    7147     2017978 :             break;
    7148             :         }
    7149           0 :         case DataHeatBalance::SolutionAlgo::AnalyticalSolution: {
    7150           0 :             if (this->TempDepZnLd == 0.0) { // B=0
    7151           0 :                 LoadToHeatingSetPoint = this->AirPowerCap * (thisTempZoneThermostatSetPoint - this->ZoneT1) - this->TempIndZnLd;
    7152             :             } else {
    7153           0 :                 Real64 const exp_700_TA(std::exp(min(700.0, -this->TempDepZnLd / this->AirPowerCap)));
    7154           0 :                 LoadToHeatingSetPoint =
    7155           0 :                     this->TempDepZnLd * (thisTempZoneThermostatSetPoint - this->ZoneT1 * exp_700_TA) / (1.0 - exp_700_TA) - this->TempIndZnLd;
    7156             :             }
    7157           0 :             break;
    7158             :         }
    7159           0 :         case DataHeatBalance::SolutionAlgo::EulerMethod: {
    7160           0 :             LoadToHeatingSetPoint = this->AirPowerCap * (thisTempZoneThermostatSetPoint - this->ZoneT1) +
    7161           0 :                                     this->TempDepZnLd * (thisTempZoneThermostatSetPoint) - this->TempIndZnLd;
    7162           0 :             break;
    7163             :         }
    7164           0 :         default: {
    7165           0 :             assert(false);
    7166             :         }
    7167             :         }
    7168     2017978 :         if (RAFNFrac > 0.0) LoadToHeatingSetPoint = LoadToHeatingSetPoint / RAFNFrac;
    7169     2017978 :         totalLoad = LoadToHeatingSetPoint;
    7170     2017978 :         ZoneSetPoint = thisTempZoneThermostatSetPoint;
    7171     2017978 :         LoadToCoolingSetPoint = LoadToHeatingSetPoint;
    7172             :         // for consistency with the other cases, use LE instead of LT and don't subtract 1.0 Watt as a way of pushing the zero load
    7173             :         // case over the threshold
    7174     2017978 :         if ((totalLoad) <= 0.0) thisDeadBandOrSetBack = true;
    7175             : 
    7176     2017978 :         break;
    7177     2453117 :     case DataHVACGlobals::ThermostatType::SingleCooling:
    7178     2453117 :         switch (state.dataHeatBal->ZoneAirSolutionAlgo) {
    7179     2453117 :         case DataHeatBalance::SolutionAlgo::ThirdOrder: {
    7180     2453117 :             LoadToCoolingSetPoint = this->TempDepZnLd * thisTempZoneThermostatSetPoint - this->TempIndZnLd;
    7181     2453117 :             break;
    7182             :         }
    7183           0 :         case DataHeatBalance::SolutionAlgo::AnalyticalSolution: {
    7184           0 :             if (this->TempDepZnLd == 0.0) { // B=0
    7185           0 :                 LoadToCoolingSetPoint = this->AirPowerCap * (thisTempZoneThermostatSetPoint - this->ZoneT1) - this->TempIndZnLd;
    7186             :             } else {
    7187           0 :                 Real64 const exp_700_TA(std::exp(min(700.0, -this->TempDepZnLd / this->AirPowerCap)));
    7188           0 :                 LoadToCoolingSetPoint =
    7189           0 :                     this->TempDepZnLd * (thisTempZoneThermostatSetPoint - this->ZoneT1 * exp_700_TA) / (1.0 - exp_700_TA) - this->TempIndZnLd;
    7190             :             }
    7191           0 :             break;
    7192             :         }
    7193           0 :         case DataHeatBalance::SolutionAlgo::EulerMethod: {
    7194           0 :             LoadToCoolingSetPoint = this->AirPowerCap * (thisTempZoneThermostatSetPoint - this->ZoneT1) +
    7195           0 :                                     this->TempDepZnLd * thisTempZoneThermostatSetPoint - this->TempIndZnLd;
    7196           0 :             break;
    7197             :         }
    7198           0 :         default: {
    7199           0 :             assert(false);
    7200             :         }
    7201             :         }
    7202     2453117 :         if (RAFNFrac > 0.0) LoadToHeatingSetPoint = LoadToHeatingSetPoint / RAFNFrac;
    7203     2453117 :         if (thisZone.HasAdjustedReturnTempByITE && !(state.dataGlobal->BeginSimFlag)) {
    7204           0 :             LoadToCoolingSetPoint = this->TempDepZnLd * thisZone.AdjustedReturnTempByITE - this->TempIndZnLd;
    7205             :         }
    7206     2453117 :         totalLoad = LoadToCoolingSetPoint;
    7207     2453117 :         ZoneSetPoint = thisTempZoneThermostatSetPoint;
    7208     2453117 :         LoadToHeatingSetPoint = LoadToCoolingSetPoint;
    7209             :         // for consistency with the other cases, use GE instead of GT and don't add 1.0 Watt as a way of pushing the zero load
    7210             :         // case over the threshold
    7211     2453117 :         if ((totalLoad) >= 0.0) thisDeadBandOrSetBack = true;
    7212     2453117 :         break;
    7213       94874 :     case DataHVACGlobals::ThermostatType::SingleHeatCool:
    7214       94874 :         switch (state.dataHeatBal->ZoneAirSolutionAlgo) {
    7215       94874 :         case DataHeatBalance::SolutionAlgo::ThirdOrder: {
    7216       94874 :             LoadToHeatingSetPoint = (this->TempDepZnLd * (thisTempZoneThermostatSetPoint) - this->TempIndZnLd);
    7217       94874 :             LoadToCoolingSetPoint = (this->TempDepZnLd * (thisTempZoneThermostatSetPoint) - this->TempIndZnLd);
    7218       94874 :             break;
    7219             :         }
    7220           0 :         case DataHeatBalance::SolutionAlgo::AnalyticalSolution: {
    7221           0 :             if (this->TempDepZnLd == 0.0) { // B=0
    7222           0 :                 LoadToHeatingSetPoint = this->AirPowerCap * (thisTempZoneThermostatSetPoint - this->ZoneT1) - this->TempIndZnLd;
    7223           0 :                 LoadToCoolingSetPoint = this->AirPowerCap * (thisTempZoneThermostatSetPoint - this->ZoneT1) - this->TempIndZnLd;
    7224             :             } else {
    7225           0 :                 Real64 const exp_700_TA(std::exp(min(700.0, -this->TempDepZnLd / this->AirPowerCap)));
    7226           0 :                 LoadToHeatingSetPoint =
    7227           0 :                     this->TempDepZnLd * (thisTempZoneThermostatSetPoint - this->ZoneT1 * exp_700_TA) / (1.0 - exp_700_TA) - this->TempIndZnLd;
    7228           0 :                 LoadToCoolingSetPoint =
    7229           0 :                     this->TempDepZnLd * (thisTempZoneThermostatSetPoint - this->ZoneT1 * exp_700_TA) / (1.0 - exp_700_TA) - this->TempIndZnLd;
    7230             :             }
    7231           0 :             break;
    7232             :         }
    7233           0 :         case DataHeatBalance::SolutionAlgo::EulerMethod: {
    7234           0 :             LoadToHeatingSetPoint = this->AirPowerCap * (thisTempZoneThermostatSetPoint - this->ZoneT1) +
    7235           0 :                                     this->TempDepZnLd * thisTempZoneThermostatSetPoint - this->TempIndZnLd;
    7236           0 :             LoadToCoolingSetPoint = this->AirPowerCap * (thisTempZoneThermostatSetPoint - this->ZoneT1) +
    7237           0 :                                     this->TempDepZnLd * thisTempZoneThermostatSetPoint - this->TempIndZnLd;
    7238           0 :             break;
    7239             :         }
    7240           0 :         default: {
    7241           0 :             assert(false);
    7242             :         }
    7243             :         }
    7244       94874 :         ZoneSetPoint = thisTempZoneThermostatSetPoint;
    7245       94874 :         if (RAFNFrac > 0.0) LoadToHeatingSetPoint = LoadToHeatingSetPoint / RAFNFrac;
    7246       94874 :         if (RAFNFrac > 0.0) LoadToCoolingSetPoint = LoadToCoolingSetPoint / RAFNFrac;
    7247             : 
    7248       94874 :         if (thisZone.HasAdjustedReturnTempByITE && !(state.dataGlobal->BeginSimFlag)) {
    7249           0 :             LoadToCoolingSetPoint = this->TempDepZnLd * thisZone.AdjustedReturnTempByITE - this->TempIndZnLd;
    7250             :         }
    7251             : 
    7252             :         // Note that LoadToHeatingSetPoint is generally not equal to LoadToCoolingSetPoint
    7253             :         // when the heating and cooling set-points are equal if the zone is unmixed,
    7254             :         // e.g. displacement ventilation or UFAD, since the stratification is generally not the same in heating and cooling modes
    7255             : 
    7256             :         // Possible combinations:
    7257             :         // 1/  LoadToHeatingSetPoint > 0 & LoadToCoolingSetPoint > 0 -->  Heating required
    7258             :         // 2/  LoadToHeatingSetPoint  >  LoadToCoolingSetPoint       -->  Possible in the unmixed case but should be trapped
    7259             :         //                                                                 as a poor choice of set-points
    7260             :         // 3/  LoadToHeatingSetPoint < 0 & LoadToCoolingSetPoint < 0 -->  Cooling Required
    7261             :         // 4/  LoadToHeatingSetPoint <=0 & LoadToCoolingSetPoint >=0 -->  Dead Band Operation ! includes zero load cases
    7262             :         // First trap bad set-points
    7263       94874 :         if (LoadToHeatingSetPoint > LoadToCoolingSetPoint) {
    7264           0 :             ShowSevereError(
    7265             :                 state,
    7266             :                 "DataHVACGlobals::ThermostatType::SingleHeatCool: Effective heating set-point higher than effective cooling set-point - use "
    7267             :                 "DualSetPointWithDeadBand if using unmixed air model");
    7268           0 :             ShowContinueErrorTimeStamp(state, "occurs in Zone=" + thisZone.Name);
    7269           0 :             ShowContinueError(state,
    7270           0 :                               format("LoadToHeatingSetPoint={:.3R}, LoadToCoolingSetPoint={:.3R}", LoadToHeatingSetPoint, LoadToCoolingSetPoint));
    7271           0 :             ShowContinueError(state, format("Zone TempDepZnLd={:.2R}", this->TempDepZnLd));
    7272           0 :             ShowContinueError(state, format("Zone TempIndZnLd={:.2R}", this->TempIndZnLd));
    7273           0 :             ShowContinueError(state, format("Zone ThermostatSetPoint={:.2R}", thisTempZoneThermostatSetPoint));
    7274           0 :             ShowFatalError(state, "Program terminates due to above conditions.");
    7275             :         }
    7276             : 
    7277       94874 :         if (LoadToHeatingSetPoint > 0.0 && LoadToCoolingSetPoint > 0.0) {
    7278       47492 :             totalLoad = LoadToHeatingSetPoint;
    7279       47382 :         } else if (LoadToHeatingSetPoint < 0.0 && LoadToCoolingSetPoint < 0.0) {
    7280       47382 :             totalLoad = LoadToCoolingSetPoint;
    7281           0 :         } else if (LoadToHeatingSetPoint <= 0.0 && LoadToCoolingSetPoint >= 0.0) { // deadband includes zero loads
    7282           0 :             totalLoad = 0.0;
    7283           0 :             if (thisZone.SystemZoneNodeNumber > 0) {
    7284           0 :                 ZoneSetPoint = state.dataLoopNodes->Node(thisZone.SystemZoneNodeNumber).Temp;
    7285           0 :                 ZoneSetPoint = max(ZoneSetPoint, thisZoneThermostatSetPointLo); // trap out of deadband
    7286           0 :                 ZoneSetPoint = min(ZoneSetPoint, thisZoneThermostatSetPointHi); // trap out of deadband
    7287             :             }
    7288           0 :             thisDeadBandOrSetBack = true;
    7289             :         } else { // this should never occur!
    7290           0 :             ShowSevereError(state,
    7291             :                             "SingleHeatCoolSetPoint: Unanticipated combination of heating and cooling loads - report to EnergyPlus Development Team");
    7292           0 :             ShowContinueErrorTimeStamp(state, "occurs in Zone=" + thisZone.Name);
    7293           0 :             ShowContinueError(state,
    7294           0 :                               format("LoadToHeatingSetPoint={:.3R}, LoadToCoolingSetPoint={:.3R}", LoadToHeatingSetPoint, LoadToCoolingSetPoint));
    7295           0 :             ShowContinueError(state, format("Zone TempDepZnLd={:.2R}", this->TempDepZnLd));
    7296           0 :             ShowContinueError(state, format("Zone TempIndZnLd={:.2R}", this->TempIndZnLd));
    7297           0 :             ShowContinueError(state, format("Zone ThermostatSetPoint={:.2R}", thisTempZoneThermostatSetPoint));
    7298           0 :             ShowFatalError(state, "Program terminates due to above conditions.");
    7299             :         }
    7300       94874 :         break;
    7301    18812403 :     case DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand:
    7302    18812403 :         switch (state.dataHeatBal->ZoneAirSolutionAlgo) {
    7303     7883629 :         case DataHeatBalance::SolutionAlgo::ThirdOrder: {
    7304     7883629 :             LoadToHeatingSetPoint = (this->TempDepZnLd * (thisZoneThermostatSetPointLo) - this->TempIndZnLd);
    7305     7883629 :             LoadToCoolingSetPoint = (this->TempDepZnLd * (thisZoneThermostatSetPointHi) - this->TempIndZnLd);
    7306     7883629 :             break;
    7307             :         }
    7308    10897172 :         case DataHeatBalance::SolutionAlgo::AnalyticalSolution: {
    7309    10897172 :             if (this->TempDepZnLd == 0.0) { // B=0
    7310           0 :                 LoadToHeatingSetPoint = this->AirPowerCap * (thisZoneThermostatSetPointLo - this->ZoneT1) - this->TempIndZnLd;
    7311           0 :                 LoadToCoolingSetPoint = this->AirPowerCap * (thisZoneThermostatSetPointHi - this->ZoneT1) - this->TempIndZnLd;
    7312             :             } else {
    7313    10897172 :                 Real64 const exp_700_TA(std::exp(min(700.0, -this->TempDepZnLd / this->AirPowerCap)));
    7314    10897172 :                 LoadToHeatingSetPoint =
    7315    10897172 :                     this->TempDepZnLd * (thisZoneThermostatSetPointLo - this->ZoneT1 * exp_700_TA) / (1.0 - exp_700_TA) - this->TempIndZnLd;
    7316    10897172 :                 LoadToCoolingSetPoint =
    7317    10897172 :                     this->TempDepZnLd * (thisZoneThermostatSetPointHi - this->ZoneT1 * exp_700_TA) / (1.0 - exp_700_TA) - this->TempIndZnLd;
    7318             :             }
    7319    10897172 :             break;
    7320             :         }
    7321       31602 :         case DataHeatBalance::SolutionAlgo::EulerMethod: {
    7322       94806 :             LoadToHeatingSetPoint = this->AirPowerCap * (thisZoneThermostatSetPointLo - this->ZoneT1) +
    7323       63204 :                                     this->TempDepZnLd * thisZoneThermostatSetPointLo - this->TempIndZnLd;
    7324       94806 :             LoadToCoolingSetPoint = this->AirPowerCap * (thisZoneThermostatSetPointHi - this->ZoneT1) +
    7325       63204 :                                     this->TempDepZnLd * thisZoneThermostatSetPointHi - this->TempIndZnLd;
    7326       31602 :             break;
    7327             :         }
    7328           0 :         default: {
    7329           0 :             assert(false);
    7330             :         }
    7331             :         }
    7332    18812403 :         if (RAFNFrac > 0.0) LoadToHeatingSetPoint = LoadToHeatingSetPoint / RAFNFrac;
    7333    18812403 :         if (RAFNFrac > 0.0) LoadToCoolingSetPoint = LoadToCoolingSetPoint / RAFNFrac;
    7334             : 
    7335    18812403 :         if (thisZone.HasAdjustedReturnTempByITE && !(state.dataGlobal->BeginSimFlag)) {
    7336       11156 :             LoadToCoolingSetPoint = this->TempDepZnLd * thisZone.AdjustedReturnTempByITE - this->TempIndZnLd;
    7337             :         }
    7338             : 
    7339             :         // Possible combinations:
    7340             :         // 1/  LoadToHeatingSetPoint > 0 & LoadToCoolingSetPoint > 0 -->  Heating required
    7341             :         // 2/  LoadToHeatingSetPoint  >  LoadToCoolingSetPoint       -->  Possible in the unmixed case but should be trapped
    7342             :         //                                                                  as a poor choice of set-points
    7343             :         // 3/  LoadToHeatingSetPoint < 0 & LoadToCoolingSetPoint < 0 -->  Cooling Required
    7344             :         // 4/  LoadToHeatingSetPoint <=0 & LoadToCoolingSetPoint >=0 -->  Dead Band Operation - includes zero load cases
    7345             :         // First trap bad set-points
    7346    18812403 :         if (LoadToHeatingSetPoint > LoadToCoolingSetPoint) {
    7347           0 :             ShowSevereError(state,
    7348             :                             "DualSetPointWithDeadBand: Effective heating set-point higher than effective cooling set-point - increase "
    7349             :                             "deadband if using unmixed air model");
    7350           0 :             ShowContinueErrorTimeStamp(state, "occurs in Zone=" + thisZone.Name);
    7351           0 :             ShowContinueError(state,
    7352           0 :                               format("LoadToHeatingSetPoint={:.3R}, LoadToCoolingSetPoint={:.3R}", LoadToHeatingSetPoint, LoadToCoolingSetPoint));
    7353           0 :             ShowContinueError(state, format("Zone TempDepZnLd={:.2R}", this->TempDepZnLd));
    7354           0 :             ShowContinueError(state, format("Zone TempIndZnLd={:.2R}", this->TempIndZnLd));
    7355           0 :             ShowContinueError(state, format("Zone Heating ThermostatSetPoint={:.2R}", thisZoneThermostatSetPointLo));
    7356           0 :             ShowContinueError(state, format("Zone Cooling ThermostatSetPoint={:.2R}", thisZoneThermostatSetPointHi));
    7357           0 :             ShowFatalError(state, "Program terminates due to above conditions.");
    7358             :         }
    7359             : 
    7360    18812403 :         if (LoadToHeatingSetPoint > 0.0 && LoadToCoolingSetPoint > 0.0) {
    7361     7762096 :             totalLoad = LoadToHeatingSetPoint;
    7362     7762096 :             ZoneSetPoint = thisZoneThermostatSetPointLo;
    7363    11050307 :         } else if (LoadToHeatingSetPoint < 0.0 && LoadToCoolingSetPoint < 0.0) {
    7364     6715981 :             totalLoad = LoadToCoolingSetPoint;
    7365     6715981 :             ZoneSetPoint = thisZoneThermostatSetPointHi;
    7366     4334326 :         } else if (LoadToHeatingSetPoint <= 0.0 && LoadToCoolingSetPoint >= 0.0) { // deadband includes zero loads
    7367             :             // this turns out to cause instabilities sometimes? that lead to setpoint errors if predictor is off.
    7368     4334326 :             totalLoad = 0.0;
    7369     4334326 :             if (thisZone.SystemZoneNodeNumber > 0) {
    7370     4334297 :                 ZoneSetPoint = state.dataLoopNodes->Node(thisZone.SystemZoneNodeNumber).Temp;
    7371     4334297 :                 ZoneSetPoint = max(ZoneSetPoint, thisZoneThermostatSetPointLo); // trap out of deadband
    7372     4334297 :                 ZoneSetPoint = min(ZoneSetPoint, thisZoneThermostatSetPointHi); // trap out of deadband
    7373             :             }
    7374     4334326 :             thisDeadBandOrSetBack = true;
    7375             :         } else { // this should never occur!
    7376           0 :             ShowSevereError(
    7377             :                 state, "DualSetPointWithDeadBand: Unanticipated combination of heating and cooling loads - report to EnergyPlus Development Team");
    7378           0 :             ShowContinueErrorTimeStamp(state, "occurs in Zone=" + thisZone.Name);
    7379           0 :             ShowContinueError(state,
    7380           0 :                               format("LoadToHeatingSetPoint={:.3R}, LoadToCoolingSetPoint={:.3R}", LoadToHeatingSetPoint, LoadToCoolingSetPoint));
    7381           0 :             ShowContinueError(state, format("Zone Heating Set-point={:.2R}", thisZoneThermostatSetPointLo));
    7382           0 :             ShowContinueError(state, format("Zone Cooling Set-point={:.2R}", thisZoneThermostatSetPointHi));
    7383           0 :             ShowContinueError(state, format("Zone TempDepZnLd={:.2R}", this->TempDepZnLd));
    7384           0 :             ShowContinueError(state, format("Zone TempIndZnLd={:.2R}", this->TempIndZnLd));
    7385           0 :             ShowContinueError(state, format("Zone ThermostatSetPoint={:.2R}", thisTempZoneThermostatSetPoint));
    7386             : 
    7387           0 :             ShowFatalError(state, "Program terminates due to above conditions.");
    7388             :         }
    7389    18812403 :         break;
    7390           0 :     default:
    7391           0 :         break;
    7392             :     }
    7393             : 
    7394    27959531 :     int systemNodeNumber = 0;
    7395    27959531 :     int stageNum = 0;
    7396    27959531 :     if (spaceNum > 0) {
    7397       30012 :         systemNodeNumber = state.dataHeatBal->space(spaceNum).SystemZoneNodeNumber;
    7398       30012 :         stageNum = state.dataZoneEnergyDemand->spaceSysEnergyDemand(spaceNum).StageNum;
    7399       30012 :         assert(stageNum == state.dataZoneEnergyDemand->ZoneSysEnergyDemand(zoneNum).StageNum);
    7400             :     } else {
    7401    27929519 :         systemNodeNumber = thisZone.SystemZoneNodeNumber;
    7402    27929519 :         stageNum = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(zoneNum).StageNum;
    7403             :     }
    7404             :     // Staged control zone
    7405    27959531 :     if (state.dataZoneTempPredictorCorrector->NumStageCtrZone > 0) {
    7406      123027 :         if (state.dataZoneCtrls->StageZoneLogic(zoneNum)) {
    7407      101418 :             if (stageNum == 0) { // No load
    7408       44397 :                 LoadToHeatingSetPoint = 0.0;
    7409       44397 :                 LoadToCoolingSetPoint = 0.0;
    7410       44397 :                 totalLoad = 0.0;
    7411       44397 :                 if (systemNodeNumber > 0) {
    7412       44397 :                     ZoneSetPoint = state.dataLoopNodes->Node(systemNodeNumber).Temp;
    7413       44397 :                     ZoneSetPoint = max(ZoneSetPoint, thisZoneThermostatSetPointLo); // trap out of deadband
    7414       44397 :                     ZoneSetPoint = min(ZoneSetPoint, thisZoneThermostatSetPointHi); // trap out of deadband
    7415             :                 }
    7416       44397 :                 thisDeadBandOrSetBack = true;
    7417       57021 :             } else if (stageNum < 0) { // Cooling load
    7418       19883 :                 switch (state.dataHeatBal->ZoneAirSolutionAlgo) {
    7419       19883 :                 case DataHeatBalance::SolutionAlgo::ThirdOrder: {
    7420       19883 :                     LoadToCoolingSetPoint = (this->TempDepZnLd * (thisZoneThermostatSetPointHi) - this->TempIndZnLd);
    7421       19883 :                     break;
    7422             :                 }
    7423           0 :                 case DataHeatBalance::SolutionAlgo::AnalyticalSolution: {
    7424           0 :                     if (this->TempDepZnLd == 0.0) { // B=0
    7425           0 :                         LoadToCoolingSetPoint = this->AirPowerCap * (thisZoneThermostatSetPointHi - this->ZoneT1) - this->TempIndZnLd;
    7426             :                     } else {
    7427           0 :                         Real64 const exp_700_TA(std::exp(min(700.0, -this->TempDepZnLd / this->AirPowerCap)));
    7428           0 :                         LoadToCoolingSetPoint =
    7429           0 :                             this->TempDepZnLd * (thisZoneThermostatSetPointHi - this->ZoneT1 * exp_700_TA) / (1.0 - exp_700_TA) - this->TempIndZnLd;
    7430             :                     }
    7431           0 :                     break;
    7432             :                 }
    7433           0 :                 case DataHeatBalance::SolutionAlgo::EulerMethod: {
    7434           0 :                     LoadToCoolingSetPoint = this->AirPowerCap * (thisZoneThermostatSetPointHi - this->ZoneT1) +
    7435           0 :                                             this->TempDepZnLd * thisZoneThermostatSetPointHi - this->TempIndZnLd;
    7436           0 :                     break;
    7437             :                 }
    7438           0 :                 default: {
    7439           0 :                     assert(false);
    7440             :                 }
    7441             :                 }
    7442       19883 :                 totalLoad = LoadToCoolingSetPoint;
    7443       19883 :                 ZoneSetPoint = thisZoneThermostatSetPointHi;
    7444       19883 :                 LoadToHeatingSetPoint = LoadToCoolingSetPoint;
    7445       19883 :                 if ((totalLoad) >= 0.0) thisDeadBandOrSetBack = true;
    7446             :             } else { // Heating load
    7447       37138 :                 switch (state.dataHeatBal->ZoneAirSolutionAlgo) {
    7448       37138 :                 case DataHeatBalance::SolutionAlgo::ThirdOrder: {
    7449       37138 :                     LoadToHeatingSetPoint = (this->TempDepZnLd * thisZoneThermostatSetPointLo - this->TempIndZnLd);
    7450       37138 :                     break;
    7451             :                 }
    7452           0 :                 case DataHeatBalance::SolutionAlgo::AnalyticalSolution: {
    7453           0 :                     if (this->TempDepZnLd == 0.0) { // B=0
    7454           0 :                         LoadToHeatingSetPoint = this->AirPowerCap * (thisZoneThermostatSetPointLo - this->ZoneT1) - this->TempIndZnLd;
    7455             :                     } else {
    7456           0 :                         Real64 const exp_700_TA(std::exp(min(700.0, -this->TempDepZnLd / this->AirPowerCap)));
    7457           0 :                         LoadToHeatingSetPoint =
    7458           0 :                             this->TempDepZnLd * (thisZoneThermostatSetPointLo - this->ZoneT1 * exp_700_TA) / (1.0 - exp_700_TA) - this->TempIndZnLd;
    7459             :                     }
    7460           0 :                     break;
    7461             :                 }
    7462           0 :                 case DataHeatBalance::SolutionAlgo::EulerMethod: {
    7463           0 :                     LoadToHeatingSetPoint = this->AirPowerCap * (thisZoneThermostatSetPointLo - this->ZoneT1) +
    7464           0 :                                             this->TempDepZnLd * (thisZoneThermostatSetPointLo) - this->TempIndZnLd;
    7465           0 :                     break;
    7466             :                 }
    7467           0 :                 default: {
    7468           0 :                     assert(false);
    7469             :                 }
    7470             :                 }
    7471       37138 :                 totalLoad = LoadToHeatingSetPoint;
    7472       37138 :                 ZoneSetPoint = thisZoneThermostatSetPointLo;
    7473       37138 :                 LoadToCoolingSetPoint = LoadToHeatingSetPoint;
    7474       37138 :                 if ((totalLoad) <= 0.0) thisDeadBandOrSetBack = true;
    7475             :             }
    7476             :         }
    7477             :     }
    7478             : 
    7479             :     // If the ZoneNodeNum has been set for a Controlled Zone, then the zone setpoint is placed on the node.
    7480    27959531 :     if (thisZone.SystemZoneNodeNumber > 0) {
    7481    24933534 :         state.dataLoopNodes->Node(thisZone.SystemZoneNodeNumber).TempSetPoint = ZoneSetPoint;
    7482             :     }
    7483             : 
    7484    27959531 :     state.dataZoneEnergyDemand->Setback(zoneNum) = (ZoneSetPoint > this->ZoneSetPointLast);
    7485             : 
    7486    27959531 :     this->ZoneSetPointLast = ZoneSetPoint;
    7487    27959531 :     state.dataHeatBalFanSys->TempZoneThermostatSetPoint(zoneNum) = ZoneSetPoint; // needed to fix Issue # 5048
    7488    27959531 :     state.dataZoneEnergyDemand->DeadBandOrSetback(zoneNum) = thisDeadBandOrSetBack;
    7489    27959531 :     state.dataZoneEnergyDemand->CurDeadBandOrSetback(zoneNum) = thisDeadBandOrSetBack;
    7490             : 
    7491             :     // Apply the Zone Multiplier and Load Correction factor as needed
    7492    27959531 :     if (spaceNum > 0) {
    7493       30012 :         state.dataZoneEnergyDemand->spaceSysEnergyDemand(spaceNum).reportSensibleLoadsZoneMultiplier(
    7494             :             state, zoneNum, totalLoad, LoadToHeatingSetPoint, LoadToCoolingSetPoint);
    7495             :     } else {
    7496    27929519 :         state.dataZoneEnergyDemand->ZoneSysEnergyDemand(zoneNum).reportSensibleLoadsZoneMultiplier(
    7497             :             state, zoneNum, totalLoad, LoadToHeatingSetPoint, LoadToCoolingSetPoint);
    7498             :     }
    7499    27959531 : }
    7500        2313 : } // namespace EnergyPlus::ZoneTempPredictorCorrector

Generated by: LCOV version 1.13