LCOV - code coverage report
Current view: top level - EnergyPlus - ScheduleManager.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 72.5 % 1940 1406
Test Date: 2025-06-02 07:23:51 Functions: 76.9 % 65 50

            Line data    Source code
       1              : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
       2              : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
       3              : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
       4              : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
       5              : // contributors. All rights reserved.
       6              : //
       7              : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
       8              : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
       9              : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
      10              : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
      11              : // derivative works, and perform publicly and display publicly, and to permit others to do so.
      12              : //
      13              : // Redistribution and use in source and binary forms, with or without modification, are permitted
      14              : // provided that the following conditions are met:
      15              : //
      16              : // (1) Redistributions of source code must retain the above copyright notice, this list of
      17              : //     conditions and the following disclaimer.
      18              : //
      19              : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
      20              : //     conditions and the following disclaimer in the documentation and/or other materials
      21              : //     provided with the distribution.
      22              : //
      23              : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
      24              : //     the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
      25              : //     used to endorse or promote products derived from this software without specific prior
      26              : //     written permission.
      27              : //
      28              : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
      29              : //     without changes from the version obtained under this License, or (ii) Licensee makes a
      30              : //     reference solely to the software portion of its product, Licensee must refer to the
      31              : //     software as "EnergyPlus version X" software, where "X" is the version number Licensee
      32              : //     obtained under this License and may not use a different name for the software. Except as
      33              : //     specifically required in this Section (4), Licensee shall not use in a company name, a
      34              : //     product name, in advertising, publicity, or other promotional activities any name, trade
      35              : //     name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
      36              : //     similar designation, without the U.S. Department of Energy's prior written consent.
      37              : //
      38              : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
      39              : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
      40              : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
      41              : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      42              : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      43              : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      44              : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      45              : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      46              : // POSSIBILITY OF SUCH DAMAGE.
      47              : 
      48              : // C++ Headers
      49              : #include <map>
      50              : 
      51              : // ObjexxFCL Headers
      52              : #include <ObjexxFCL/string.functions.hh>
      53              : 
      54              : // EnergyPlus Headers
      55              : #include <EnergyPlus/CommandLineInterface.hh>
      56              : #include <EnergyPlus/Data/EnergyPlusData.hh>
      57              : #include <EnergyPlus/DataEnvironment.hh>
      58              : #include <EnergyPlus/DataStringGlobals.hh>
      59              : #include <EnergyPlus/DataSystemVariables.hh>
      60              : #include <EnergyPlus/EMSManager.hh>
      61              : #include <EnergyPlus/FileSystem.hh>
      62              : #include <EnergyPlus/General.hh>
      63              : // #include <EnergyPlus/GlobalNames.hh>
      64              : #include <EnergyPlus/InputProcessing/CsvParser.hh>
      65              : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      66              : #include <EnergyPlus/OutputProcessor.hh>
      67              : #include <EnergyPlus/ScheduleManager.hh>
      68              : #include <EnergyPlus/StringUtilities.hh>
      69              : #include <EnergyPlus/UtilityRoutines.hh>
      70              : #include <EnergyPlus/WeatherManager.hh>
      71              : 
      72              : namespace EnergyPlus {
      73              : 
      74              : namespace Sched {
      75              :     // Module containing the Schedule Manager routines
      76              : 
      77              :     // MODULE INFORMATION:
      78              :     //       AUTHOR         Linda K. Lawrie
      79              :     //       DATE WRITTEN   September 1997
      80              :     //       MODIFIED       January 2003 -- added sub-hourly schedule possibility (and interval scheduling)
      81              :     //                      J. Glazer January 2005 -- added Schedule:File
      82              :     //                      Michael Wetter February 2010 -- added Schedule for external Interface
      83              :     //                      L Lawrie - October 2012 - added sub-hourly option for Schedule:File
      84              : 
      85              :     // PURPOSE OF THIS MODULE:
      86              :     // To provide the capabilities of getting the schedule data from the input,
      87              :     // validating it, and storing it in such a manner that the schedule manager
      88              :     // can provide the scheduling value needs for the simulation.
      89              : 
      90              :     // REFERENCES:
      91              :     // Proposal for Schedule Manager in EnergyPlus (Rick Strand)
      92              : 
      93              :     // MODULE PARAMETER DEFINITIONS
      94        17647 :     int GetScheduleTypeNum(EnergyPlusData &state, std::string const &name)
      95              :     {
      96        17647 :         auto const &s_sched = state.dataSched;
      97        45536 :         for (int i = 0; i < (int)s_sched->scheduleTypes.size(); ++i) {
      98        45524 :             if (s_sched->scheduleTypes[i]->Name == name) {
      99        17635 :                 return i;
     100              :             }
     101              :         }
     102           12 :         return SchedNum_Invalid;
     103              :     }
     104              : 
     105        26722 :     Real64 ScheduleBase::getMinVal(EnergyPlusData &state)
     106              :     {
     107        26722 :         if (!isMinMaxSet) {
     108            2 :             setMinMaxVals(state);
     109              :         }
     110        26722 :         return minVal;
     111              :     }
     112              : 
     113        26495 :     Real64 ScheduleBase::getMaxVal(EnergyPlusData &state)
     114              :     {
     115        26495 :         if (!isMinMaxSet) {
     116          461 :             setMinMaxVals(state);
     117              :         }
     118        26495 :         return maxVal;
     119              :     }
     120              : 
     121              :     // Day types are 1-based for EMS and output and other uses, so add a dummy
     122              :     constexpr std::array<std::string_view, (int)DayType::Num> dayTypeNames = {"Unused",
     123              :                                                                               "Sunday",
     124              :                                                                               "Monday",
     125              :                                                                               "Tuesday",
     126              :                                                                               "Wednesday",
     127              :                                                                               "Thursday",
     128              :                                                                               "Friday",
     129              :                                                                               "Saturday",
     130              :                                                                               "Holiday",
     131              :                                                                               "SummerDesignDay",
     132              :                                                                               "WinterDesignDay",
     133              :                                                                               "CustomDay1",
     134              :                                                                               "CustomDay2"};
     135              : 
     136              :     constexpr std::array<std::string_view, (int)DayType::Num> dayTypeNamesUC = {"UNUSED",
     137              :                                                                                 "SUNDAY",
     138              :                                                                                 "MONDAY",
     139              :                                                                                 "TUESDAY",
     140              :                                                                                 "WEDNESDAY",
     141              :                                                                                 "THURSDAY",
     142              :                                                                                 "FRIDAY",
     143              :                                                                                 "SATURDAY",
     144              :                                                                                 "HOLIDAY",
     145              :                                                                                 "SUMMERDESIGNDAY",
     146              :                                                                                 "WINTERDESIGNDAY",
     147              :                                                                                 "CUSTOMDAY1",
     148              :                                                                                 "CUSTOMDAY2"};
     149              : 
     150              :     static constexpr std::array<std::string_view, (int)LimitUnits::Num> limitUnitNamesUC = {"DIMENSIONLESS",
     151              :                                                                                             "TEMPERATURE",
     152              :                                                                                             "DELTATEMPERATURE",
     153              :                                                                                             "PRECIPITATIONRATE",
     154              :                                                                                             "ANGLE",
     155              :                                                                                             "CONVECTIONCOEFFICIENT",
     156              :                                                                                             "ACTIVITYLEVEL",
     157              :                                                                                             "VELOCITY",
     158              :                                                                                             "CAPACITY",
     159              :                                                                                             "POWER",
     160              :                                                                                             "AVAILABILITY",
     161              :                                                                                             "PERCENT",
     162              :                                                                                             "CONTROL",
     163              :                                                                                             "MODE"};
     164              : 
     165              :     constexpr std::array<std::string_view, (int)ReportLevel::Num> reportLevelNames = {"Hourly", "Timestep"};
     166              :     constexpr std::array<std::string_view, (int)ReportLevel::Num> reportLevelNamesUC = {"HOURLY", "TIMESTEP"};
     167              :     constexpr std::array<std::string_view, (int)Interpolation::Num> interpolationNames = {"No", "Average", "Linear"};
     168              :     constexpr std::array<std::string_view, (int)Interpolation::Num> interpolationNamesUC = {"NO", "AVERAGE", "LINEAR"};
     169              : 
     170          532 :     bool DaySchedule::checkValsForLimitViolations(EnergyPlusData &state) const
     171              :     {
     172          532 :         auto &s_sched = state.dataSched;
     173              : 
     174          532 :         if (this->schedTypeNum == SchedNum_Invalid) {
     175            0 :             return false;
     176              :         }
     177          532 :         auto *schedType = s_sched->scheduleTypes[this->schedTypeNum];
     178          532 :         if (!schedType->isLimited) {
     179           58 :             return false;
     180              :         }
     181              : 
     182        45642 :         for (int i = 0; i < Constant::iHoursInDay * state.dataGlobal->TimeStepsInHour; ++i) {
     183        45168 :             if (this->tsVals[i] < schedType->minVal || this->tsVals[i] > schedType->maxVal) {
     184            0 :                 return true;
     185              :             }
     186              :         }
     187              : 
     188          474 :         return false;
     189              :     } // ScheduleDay::checkValsForLimitViolations()
     190              : 
     191          532 :     bool DaySchedule::checkValsForBadIntegers(EnergyPlusData &state) const
     192              :     {
     193          532 :         auto &s_sched = state.dataSched;
     194          532 :         if (this->schedTypeNum == SchedNum_Invalid) {
     195            0 :             return false;
     196              :         }
     197          532 :         auto *schedType = s_sched->scheduleTypes[this->schedTypeNum];
     198          532 :         if (schedType->isReal) {
     199          505 :             return false;
     200              :         }
     201              :         // Make sure each is integer
     202         3195 :         for (int i = 0; i < Constant::iHoursInDay * state.dataGlobal->TimeStepsInHour; ++i) {
     203         3168 :             if (this->tsVals[i] != int(this->tsVals[i])) {
     204            0 :                 return true;
     205              :             }
     206              :         }
     207           27 :         return false;
     208              :     } // ScheduleDay::checkValsForBadIntegers()
     209              : 
     210        79686 :     void DaySchedule::populateFromMinuteVals(EnergyPlusData &state, std::array<Real64, Constant::iMinutesInDay> const &minuteVals)
     211              :     {
     212        79686 :         auto &s_glob = state.dataGlobal;
     213        79686 :         if (this->interpolation == Interpolation::Average) {
     214         6200 :             for (int hr = 0; hr < Constant::iHoursInDay; ++hr) {
     215         5952 :                 int begMin = 0;
     216         5952 :                 int endMin = s_glob->MinutesInTimeStep - 1;
     217        37200 :                 for (int ts = 0; ts < s_glob->TimeStepsInHour; ++ts) {
     218        31248 :                     Real64 accum = 0.0;
     219       388368 :                     for (int iMin = begMin; iMin <= endMin; ++iMin) {
     220       357120 :                         accum += minuteVals[hr * Constant::iMinutesInHour + iMin];
     221              :                     }
     222        31248 :                     this->tsVals[hr * s_glob->TimeStepsInHour + ts] = accum / double(s_glob->MinutesInTimeStep);
     223        31248 :                     this->sumTsVals += this->tsVals[hr * s_glob->TimeStepsInHour + ts];
     224        31248 :                     begMin = endMin + 1;
     225        31248 :                     endMin += s_glob->MinutesInTimeStep;
     226              :                 }
     227              :             }
     228              :         } else {
     229      1985950 :             for (int hr = 0; hr < Constant::iHoursInDay; ++hr) {
     230      1906512 :                 int endMinute = s_glob->MinutesInTimeStep - 1;
     231     11262720 :                 for (int ts = 0; ts < s_glob->TimeStepsInHour; ++ts) {
     232      9356208 :                     this->tsVals[hr * s_glob->TimeStepsInHour + ts] = minuteVals[hr * Constant::iMinutesInHour + endMinute];
     233      9356208 :                     this->sumTsVals += this->tsVals[hr * s_glob->TimeStepsInHour + ts];
     234      9356208 :                     endMinute += s_glob->MinutesInTimeStep;
     235              :                 }
     236              :             }
     237              :         }
     238        79686 :     } // ScheduleDay::populateFromHrMinVals()
     239              : 
     240         1867 :     ScheduleConstant *AddScheduleConstant(EnergyPlusData &state, std::string const &name, Real64 value)
     241              :     {
     242         1867 :         auto const &s_sched = state.dataSched;
     243         1867 :         auto const &s_glob = state.dataGlobal;
     244              : 
     245         1867 :         auto *sched = new ScheduleConstant;
     246         1867 :         sched->Name = name;
     247         1867 :         sched->type = SchedType::Constant;
     248         1867 :         sched->Num = (int)s_sched->schedules.size();
     249         1867 :         sched->currentVal = value;
     250              :         // When InitConstantScheduleData is called, TimeStepsInHour is 0, so we ensure 24
     251         1867 :         sched->tsVals.assign(Constant::iHoursInDay * max(1, s_glob->TimeStepsInHour), value);
     252              : 
     253         1867 :         s_sched->schedules.push_back(sched);
     254         1867 :         s_sched->scheduleMap.insert_or_assign(std::move(Util::makeUPPER(sched->Name)), sched->Num);
     255              : 
     256         1867 :         return sched;
     257              :     } // AddScheduleConstant()
     258              : 
     259        16997 :     ScheduleDetailed *AddScheduleDetailed(EnergyPlusData &state, std::string const &name)
     260              :     {
     261        16997 :         auto const &s_sched = state.dataSched;
     262              : 
     263        16997 :         auto *sched = new ScheduleDetailed;
     264        16997 :         sched->Name = name;
     265              : 
     266        16997 :         sched->Num = (int)s_sched->schedules.size();
     267        16997 :         s_sched->schedules.push_back(sched);
     268        16997 :         s_sched->scheduleMap.insert_or_assign(std::move(Util::makeUPPER(sched->Name)), sched->Num);
     269              : 
     270        16997 :         sched->type = SchedType::Year;
     271        16997 :         return sched;
     272              :     } // AddScheduleDetailed()
     273              : 
     274       125121 :     DaySchedule *AddDaySchedule(EnergyPlusData &state, std::string const &name)
     275              :     {
     276       125121 :         auto &s_glob = state.dataGlobal;
     277       125121 :         auto &s_sched = state.dataSched;
     278              : 
     279       125121 :         auto *daySched = new DaySchedule;
     280       125121 :         daySched->Name = name;
     281              : 
     282       125121 :         daySched->Num = (int)s_sched->daySchedules.size();
     283       125121 :         s_sched->daySchedules.push_back(daySched);
     284       125121 :         s_sched->dayScheduleMap.insert_or_assign(std::move(Util::makeUPPER(daySched->Name)), daySched->Num);
     285              : 
     286       125121 :         daySched->tsVals.resize(Constant::iHoursInDay * s_glob->TimeStepsInHour);
     287              : 
     288       125121 :         return daySched;
     289              :     } // AddDaySchedule()
     290              : 
     291       113310 :     WeekSchedule *AddWeekSchedule(EnergyPlusData &state, std::string const &name)
     292              :     {
     293       113310 :         auto const &s_sched = state.dataSched;
     294              : 
     295       113310 :         auto *weekSched = new WeekSchedule;
     296       113310 :         weekSched->Name = name;
     297              : 
     298       113310 :         weekSched->Num = (int)s_sched->weekSchedules.size();
     299       113310 :         s_sched->weekSchedules.push_back(weekSched);
     300       113310 :         s_sched->weekScheduleMap.insert_or_assign(std::move(Util::makeUPPER(weekSched->Name)), weekSched->Num);
     301              : 
     302       113310 :         return weekSched;
     303              :     } // AddWeekSchedule()
     304              : 
     305          801 :     void InitConstantScheduleData(EnergyPlusData &state)
     306              :     {
     307              :         // Create ScheduleAlwaysOn and ScheduleAlwaysOff
     308              :         // Create constant schedules
     309          801 :         auto *schedOff = AddScheduleConstant(state, "Constant-0.0", 0.0);
     310          801 :         assert(schedOff->Num == SchedNum_AlwaysOff);
     311          801 :         schedOff->isUsed = true; // Suppress unused warnings
     312              : 
     313          801 :         auto *schedOn = AddScheduleConstant(state, "Constant-1.0", 1.0);
     314          801 :         assert(schedOn->Num == SchedNum_AlwaysOn);
     315          801 :         schedOn->isUsed = true; // Suppress unused warnings
     316          801 :     }
     317              : 
     318          801 :     void ProcessScheduleInput(EnergyPlusData &state)
     319              :     {
     320              :         // SUBROUTINE INFORMATION:
     321              :         //       AUTHOR         Linda K. Lawrie
     322              :         //       DATE WRITTEN   September 1997
     323              :         //       MODIFIED       Rui Zhang February 2010
     324              : 
     325              :         // PURPOSE OF THIS SUBROUTINE:
     326              :         // This subroutine processes the schedules input for EnergyPlus.
     327              : 
     328              :         // METHODOLOGY EMPLOYED:
     329              :         // Uses the standard get routines in the InputProcessor.
     330              : 
     331              :         // Using/Aliasing
     332              :         using DataStringGlobals::CharComma;
     333              :         using DataStringGlobals::CharSemicolon;
     334              :         using DataStringGlobals::CharSpace;
     335              :         using DataStringGlobals::CharTab;
     336              :         using DataSystemVariables::CheckForActualFilePath;
     337              :         using General::ProcessDateString;
     338              : 
     339              :         // Locals
     340              :         // SUBROUTINE PARAMETER DEFINITIONS:
     341          801 :         constexpr std::string_view routineName = "ProcessScheduleInput";
     342              : 
     343              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     344              : 
     345          801 :         Array1D_string Alphas;
     346          801 :         Array1D_string cAlphaFields;
     347          801 :         Array1D_string cNumericFields;
     348          801 :         Array1D<Real64> Numbers;
     349          801 :         Array1D_bool lAlphaBlanks;
     350          801 :         Array1D_bool lNumericBlanks;
     351              :         int NumAlphas;
     352              :         int NumNumbers;
     353              :         int Status;
     354              : 
     355              :         int EndMonth;
     356              :         int EndDay;
     357              :         int StartPointer;
     358              :         int EndPointer;
     359              :         int NumPointer;
     360          801 :         bool ErrorsFound(false);
     361              :         bool NumErrorFlag;
     362              : 
     363          801 :         std::string CFld; // Character field for error message
     364              :         //  CHARACTER(len=20) CFld1        ! Character field for error message
     365              : 
     366              :         std::array<Real64, Constant::iMinutesInDay> minuteVals;
     367              :         std::array<bool, Constant::iMinutesInDay> setMinuteVals;
     368              : 
     369              :         int NumFields;
     370              :         //  LOGICAL RptSchedule
     371              : 
     372              :         int RptLevel;
     373              :         int MinutesPerItem;
     374              :         int NumExpectedItems;
     375              :         std::array<bool, (int)DayType::Num> allDays;
     376              :         std::array<bool, (int)DayType::Num> theseDays;
     377              :         bool ErrorHere;
     378              :         int SchNum;
     379              :         int WkCount;
     380              :         int DyCount;
     381              :         int NumField;
     382              :         int Count;
     383              :         Weather::DateType PDateType;
     384              :         int PWeekDay;
     385              :         int ThruField;
     386              :         int UntilFld;
     387              :         int xxcount;
     388              :         //  REAL(r64) tempval
     389          801 :         std::string CurrentThrough;
     390          801 :         std::string LastFor;
     391          801 :         std::string errmsg;
     392              :         // for SCHEDULE:FILE
     393              :         int rowCnt;
     394              : 
     395          801 :         std::string subString;
     396              :         int MaxNums1;
     397              :         char ColumnSep;
     398              :         bool FileIntervalInterpolated;
     399              :         int rowLimitCount;
     400              :         int skiprowCount;
     401              :         int curcolCount;
     402          801 :         int numerrors = 0;
     403              : 
     404          801 :         auto const &s_glob = state.dataGlobal;
     405          801 :         auto const &s_ip = state.dataInputProcessing->inputProcessor;
     406          801 :         auto const &s_sched = state.dataSched;
     407              : 
     408          801 :         if (s_sched->ScheduleInputProcessed) {
     409            0 :             return;
     410              :         }
     411              : 
     412          801 :         s_sched->ScheduleInputProcessed = true;
     413              : 
     414          801 :         int MaxNums = 1; // Need at least 1 number because it's used as a local variable in the Schedule Types loop
     415          801 :         int MaxAlps = 0;
     416              : 
     417          801 :         std::string CurrentModuleObject = "ScheduleTypeLimits";
     418          801 :         int NumScheduleTypes = s_ip->getNumObjectsFound(state, CurrentModuleObject);
     419          801 :         if (NumScheduleTypes > 0) {
     420          799 :             s_ip->getObjectDefMaxArgs(state, CurrentModuleObject, Count, NumAlphas, NumNumbers);
     421          799 :             MaxNums = max(MaxNums, NumNumbers);
     422          799 :             MaxAlps = max(MaxAlps, NumAlphas);
     423              :         }
     424          801 :         CurrentModuleObject = "Schedule:Day:Hourly";
     425          801 :         int NumHrDaySchedules = s_ip->getNumObjectsFound(state, CurrentModuleObject);
     426          801 :         if (NumHrDaySchedules > 0) {
     427           17 :             s_ip->getObjectDefMaxArgs(state, CurrentModuleObject, Count, NumAlphas, NumNumbers);
     428           17 :             MaxNums = max(MaxNums, NumNumbers);
     429           17 :             MaxAlps = max(MaxAlps, NumAlphas);
     430              :         }
     431          801 :         CurrentModuleObject = "Schedule:Day:Interval";
     432          801 :         int NumIntDaySchedules = s_ip->getNumObjectsFound(state, CurrentModuleObject);
     433          801 :         if (NumIntDaySchedules > 0) {
     434            9 :             s_ip->getObjectDefMaxArgs(state, CurrentModuleObject, Count, NumAlphas, NumNumbers);
     435            9 :             MaxNums = max(MaxNums, NumNumbers);
     436            9 :             MaxAlps = max(MaxAlps, NumAlphas);
     437              :         }
     438          801 :         CurrentModuleObject = "Schedule:Day:List";
     439          801 :         int NumLstDaySchedules = s_ip->getNumObjectsFound(state, CurrentModuleObject);
     440          801 :         if (NumLstDaySchedules > 0) {
     441            1 :             s_ip->getObjectDefMaxArgs(state, CurrentModuleObject, Count, NumAlphas, NumNumbers);
     442            1 :             MaxNums = max(MaxNums, NumNumbers);
     443            1 :             MaxAlps = max(MaxAlps, NumAlphas);
     444              :         }
     445          801 :         CurrentModuleObject = "Schedule:Week:Daily";
     446          801 :         int NumRegWeekSchedules = s_ip->getNumObjectsFound(state, CurrentModuleObject);
     447          801 :         if (NumRegWeekSchedules > 0) {
     448           19 :             s_ip->getObjectDefMaxArgs(state, CurrentModuleObject, Count, NumAlphas, NumNumbers);
     449           19 :             MaxNums = max(MaxNums, NumNumbers);
     450           19 :             MaxAlps = max(MaxAlps, NumAlphas);
     451              :         }
     452          801 :         CurrentModuleObject = "Schedule:Week:Compact";
     453          801 :         int NumCptWeekSchedules = s_ip->getNumObjectsFound(state, CurrentModuleObject);
     454          801 :         if (NumCptWeekSchedules > 0) {
     455            4 :             s_ip->getObjectDefMaxArgs(state, CurrentModuleObject, Count, NumAlphas, NumNumbers);
     456            4 :             MaxNums = max(MaxNums, NumNumbers);
     457            4 :             MaxAlps = max(MaxAlps, NumAlphas);
     458              :         }
     459          801 :         CurrentModuleObject = "Schedule:Year";
     460          801 :         int NumRegSchedules = s_ip->getNumObjectsFound(state, CurrentModuleObject);
     461          801 :         if (NumRegSchedules > 0) {
     462           23 :             s_ip->getObjectDefMaxArgs(state, CurrentModuleObject, Count, NumAlphas, NumNumbers);
     463           23 :             MaxNums = max(MaxNums, NumNumbers);
     464           23 :             MaxAlps = max(MaxAlps, NumAlphas);
     465              :         }
     466          801 :         CurrentModuleObject = "Schedule:Compact";
     467          801 :         int NumCptSchedules = s_ip->getNumObjectsFound(state, CurrentModuleObject);
     468          801 :         if (NumCptSchedules > 0) {
     469          771 :             s_ip->getObjectDefMaxArgs(state, CurrentModuleObject, Count, NumAlphas, NumNumbers);
     470          771 :             MaxNums = max(MaxNums, NumNumbers);
     471          771 :             MaxAlps = max(MaxAlps, NumAlphas + 1);
     472              :         }
     473          801 :         CurrentModuleObject = "Schedule:File";
     474          801 :         int NumCommaFileSchedules = s_ip->getNumObjectsFound(state, CurrentModuleObject);
     475          801 :         if (NumCommaFileSchedules > 0) {
     476            8 :             s_ip->getObjectDefMaxArgs(state, CurrentModuleObject, Count, NumAlphas, NumNumbers);
     477            8 :             MaxNums = max(MaxNums, NumNumbers);
     478            8 :             MaxAlps = max(MaxAlps, NumAlphas);
     479              :         }
     480              : 
     481          801 :         CurrentModuleObject = "Schedule:Constant";
     482          801 :         int NumConstantSchedules = s_ip->getNumObjectsFound(state, CurrentModuleObject);
     483          801 :         if (NumConstantSchedules > 0) {
     484           95 :             s_ip->getObjectDefMaxArgs(state, CurrentModuleObject, Count, NumAlphas, NumNumbers);
     485           95 :             MaxNums = max(MaxNums, NumNumbers);
     486           95 :             MaxAlps = max(MaxAlps, NumAlphas);
     487              :         }
     488          801 :         CurrentModuleObject = "ExternalInterface:Schedule";
     489          801 :         int NumExternalInterfaceSchedules = s_ip->getNumObjectsFound(state, CurrentModuleObject);
     490              :         // added for FMI
     491          801 :         if (NumExternalInterfaceSchedules > 0) {
     492            0 :             s_ip->getObjectDefMaxArgs(state, CurrentModuleObject, Count, NumAlphas, NumNumbers);
     493            0 :             MaxNums = max(MaxNums, NumNumbers);
     494            0 :             MaxAlps = max(MaxAlps, NumAlphas + 1);
     495              :         }
     496              :         // added for FMU Import
     497          801 :         CurrentModuleObject = "ExternalInterface:FunctionalMockupUnitImport:To:Schedule";
     498          801 :         int NumExternalInterfaceFunctionalMockupUnitImportSchedules = s_ip->getNumObjectsFound(state, CurrentModuleObject);
     499          801 :         if (NumExternalInterfaceFunctionalMockupUnitImportSchedules > 0) {
     500            1 :             s_ip->getObjectDefMaxArgs(state, CurrentModuleObject, Count, NumAlphas, NumNumbers);
     501            1 :             MaxNums = max(MaxNums, NumNumbers);
     502            1 :             MaxAlps = max(MaxAlps, NumAlphas + 1);
     503              :         }
     504              :         // added for FMU Export
     505          801 :         CurrentModuleObject = "ExternalInterface:FunctionalMockupUnitExport:To:Schedule";
     506          801 :         int NumExternalInterfaceFunctionalMockupUnitExportSchedules = s_ip->getNumObjectsFound(state, CurrentModuleObject);
     507          801 :         if (NumExternalInterfaceFunctionalMockupUnitExportSchedules > 0) {
     508            0 :             s_ip->getObjectDefMaxArgs(state, CurrentModuleObject, Count, NumAlphas, NumNumbers);
     509            0 :             MaxNums = max(MaxNums, NumNumbers);
     510            0 :             MaxAlps = max(MaxAlps, NumAlphas + 1);
     511              :         }
     512          801 :         CurrentModuleObject = "Output:Schedules";
     513          801 :         s_ip->getObjectDefMaxArgs(state, CurrentModuleObject, Count, NumAlphas, NumNumbers);
     514          801 :         MaxNums = max(MaxNums, NumNumbers);
     515          801 :         MaxAlps = max(MaxAlps, NumAlphas);
     516              : 
     517          801 :         Alphas.allocate(MaxAlps); // Maximum Alphas possible
     518          801 :         cAlphaFields.allocate(MaxAlps);
     519          801 :         cNumericFields.allocate(MaxNums);
     520          801 :         Numbers.dimension(MaxNums, 0.0); // Maximum Numbers possible
     521          801 :         lAlphaBlanks.dimension(MaxAlps, true);
     522          801 :         lNumericBlanks.dimension(MaxNums, true);
     523              : 
     524              :         // Prescan to determine extra day and week schedules due to compact schedule input
     525          801 :         CurrentModuleObject = "Schedule:Compact";
     526          801 :         MaxNums1 = 0;
     527              : 
     528        17373 :         for (int LoopIndex = 1; LoopIndex <= NumCptSchedules; ++LoopIndex) {
     529        16572 :             s_ip->getObjectItem(state, CurrentModuleObject, LoopIndex, Alphas, NumAlphas, Numbers, NumNumbers, Status);
     530              :             // # 'THROUGH" => Number of additional week schedules
     531              :             // # 'FOR' => Number of additional day schedules
     532       234890 :             for (Count = 3; Count <= NumAlphas; ++Count) {
     533       218318 :                 if (has_prefix(Alphas(Count), "UNTIL")) {
     534        80036 :                     ++MaxNums1;
     535              :                 }
     536              :             }
     537              :         }
     538          801 :         if (MaxNums1 > MaxNums) {
     539          750 :             MaxNums = MaxNums1;
     540          750 :             cNumericFields.deallocate();
     541          750 :             Numbers.deallocate();
     542          750 :             lNumericBlanks.deallocate();
     543          750 :             cNumericFields.allocate(MaxNums);
     544          750 :             Numbers.dimension(MaxNums, 0.0); // Maximum Numbers possible
     545          750 :             lNumericBlanks.dimension(MaxNums, true);
     546              :         }
     547              : 
     548              :         // add week and day schedules for each FILE:COMMA schedule
     549              : 
     550          801 :         CurrentModuleObject = "Schedule:File:Shading";
     551          801 :         int NumCommaFileShading = s_ip->getNumObjectsFound(state, CurrentModuleObject);
     552          801 :         NumAlphas = 0;
     553          801 :         NumNumbers = 0;
     554          801 :         if (NumCommaFileShading > 1) {
     555            0 :             ShowWarningError(state, format("{}: More than 1 occurrence of this object found, only first will be used.", CurrentModuleObject));
     556              :         }
     557              : 
     558          801 :         std::map<fs::path, nlohmann::json>::iterator schedule_file_shading_result;
     559          801 :         if (NumCommaFileShading != 0) {
     560            1 :             s_ip->getObjectItem(state,
     561              :                                 CurrentModuleObject,
     562              :                                 1,
     563              :                                 Alphas,
     564              :                                 NumAlphas,
     565              :                                 Numbers,
     566              :                                 NumNumbers,
     567              :                                 Status,
     568              :                                 lNumericBlanks,
     569              :                                 lAlphaBlanks,
     570              :                                 cAlphaFields,
     571              :                                 cNumericFields);
     572            1 :             std::string ShadingSunlitFracFileName = Alphas(1);
     573              : 
     574            1 :             std::string contextString = CurrentModuleObject + ", " + cAlphaFields(1) + ": ";
     575            1 :             state.files.TempFullFilePath.filePath = CheckForActualFilePath(state, ShadingSunlitFracFileName, contextString);
     576              : 
     577            1 :             if (state.files.TempFullFilePath.filePath.empty()) {
     578            0 :                 ShowFatalError(state, "Program terminates due to previous condition.");
     579              :             }
     580              : 
     581            1 :             if (state.dataEnvrn->CurrentYearIsLeapYear) {
     582            0 :                 rowLimitCount = 366 * Constant::iHoursInDay * s_glob->TimeStepsInHour;
     583              :             } else {
     584            1 :                 rowLimitCount = 365 * Constant::iHoursInDay * s_glob->TimeStepsInHour;
     585              :             }
     586            1 :             ColumnSep = CharComma;
     587              : 
     588            1 :             schedule_file_shading_result = s_sched->UniqueProcessedExternalFiles.find(state.files.TempFullFilePath.filePath);
     589            1 :             if (schedule_file_shading_result == s_sched->UniqueProcessedExternalFiles.end()) {
     590              : 
     591            1 :                 FileSystem::FileTypes const ext = FileSystem::getFileType(state.files.TempFullFilePath.filePath);
     592            1 :                 if (FileSystem::is_flat_file_type(ext)) {
     593            1 :                     auto const schedule_data = FileSystem::readFile(state.files.TempFullFilePath.filePath);
     594            1 :                     CsvParser csvParser;
     595            1 :                     skiprowCount = 1; // make sure to parse header row only for Schedule:File:Shading
     596            1 :                     auto it = s_sched->UniqueProcessedExternalFiles.emplace(state.files.TempFullFilePath.filePath,
     597            1 :                                                                             csvParser.decode(schedule_data, ColumnSep, skiprowCount));
     598            1 :                     if (csvParser.hasErrors()) {
     599            0 :                         for (const auto &[error, isContinued] : csvParser.errors()) {
     600            0 :                             if (isContinued) {
     601            0 :                                 ShowContinueError(state, error);
     602              :                             } else {
     603            0 :                                 ShowSevereError(state, error);
     604              :                             }
     605            0 :                         }
     606            0 :                         ShowContinueError(state, fmt::format("Error Occurred in {}", state.files.TempFullFilePath.filePath));
     607            0 :                         ShowFatalError(state, "Program terminates due to previous condition.");
     608              :                     }
     609            1 :                     schedule_file_shading_result = it.first;
     610            1 :                 } else if (FileSystem::is_all_json_type(ext)) {
     611            0 :                     auto schedule_data = FileSystem::readJSON(state.files.TempFullFilePath.filePath);
     612              :                     auto it = // (AUTO_OK_ITER)
     613            0 :                         s_sched->UniqueProcessedExternalFiles.emplace(state.files.TempFullFilePath.filePath, std::move(schedule_data));
     614            0 :                     schedule_file_shading_result = it.first;
     615            0 :                 } else {
     616            0 :                     ShowSevereError(state,
     617            0 :                                     fmt::format(R"({}: {}="{}", {}="{}" has an unknown file extension and cannot be read by this program.)",
     618              :                                                 routineName,
     619              :                                                 CurrentModuleObject,
     620              :                                                 Alphas(1),
     621              :                                                 cAlphaFields(3),
     622              :                                                 Alphas(3)));
     623            0 :                     ShowFatalError(state, "Program terminates due to previous condition.");
     624              :                 }
     625              :             }
     626              : 
     627            1 :             auto const &column_json = schedule_file_shading_result->second["values"].at(0); // assume there is at least 1 column
     628            1 :             rowCnt = column_json.size();
     629              :             int NumCSVAllColumnsSchedules =
     630            1 :                 schedule_file_shading_result->second["header"].get<std::set<std::string>>().size() - 1; // -1 to account for timestamp column
     631              : 
     632            1 :             if (schedule_file_shading_result->second["header"].back().get<std::string>() == "()") {
     633            0 :                 ShowWarningError(state,
     634            0 :                                  format("{}: {}=\"{}\" Removing last column of the CSV since it has '()' for the surface name.",
     635              :                                         routineName,
     636              :                                         CurrentModuleObject,
     637              :                                         Alphas(1)));
     638            0 :                 ShowContinueError(state, "This was a problem in E+ 22.2.0 and below, consider removing it from the file to suppress this warning.");
     639            0 :                 schedule_file_shading_result->second["header"].erase(NumCSVAllColumnsSchedules);
     640            0 :                 assert(schedule_file_shading_result->second["header"].size() == schedule_file_shading_result->second["values"].size());
     641            0 :                 --NumCSVAllColumnsSchedules;
     642              :             }
     643              : 
     644            1 :             if (rowCnt != rowLimitCount) {
     645            0 :                 if (rowCnt < rowLimitCount) {
     646            0 :                     ShowSevereError(state, format("{}: {}=\"{}\" {} data values read.", routineName, CurrentModuleObject, Alphas(1), rowCnt));
     647            0 :                 } else if (rowCnt > rowLimitCount) {
     648            0 :                     ShowSevereError(state, format("{}: {}=\"{}\" too many data values read.", routineName, CurrentModuleObject, Alphas(1)));
     649              :                 }
     650            0 :                 ShowContinueError(
     651              :                     state,
     652            0 :                     format("Number of rows in the shading file must be a full year multiplied by the simulation TimeStep: {}.", rowLimitCount));
     653            0 :                 ShowFatalError(state, "Program terminates due to previous condition.");
     654              :             }
     655              : 
     656              :             // schedule values have been filled into the CSVAllColumnNameAndValues map.
     657            1 :             s_sched->ScheduleFileShadingProcessed = true;
     658              : 
     659            1 :             if (numerrors > 0) {
     660            0 :                 ShowWarningError(
     661              :                     state,
     662            0 :                     format(
     663              :                         "{}:{}=\"{}\" {} records had errors - these values are set to 0.", routineName, CurrentModuleObject, Alphas(1), numerrors));
     664              :             }
     665            1 :         }
     666              : 
     667              :         //!  Most initializations in the schedule data structures are taken care of in
     668              :         //!  the definitions (see above)
     669              : 
     670         1602 :         print(state.files.audit.ensure_open(state, "ProcessScheduleInput", state.files.outputControl.audit),
     671              :               "{}\n",
     672              :               "  Processing Schedule Input -- Start");
     673              : 
     674              :         //!! Get Schedule Types
     675              : 
     676          801 :         CurrentModuleObject = "ScheduleTypeLimits";
     677         5080 :         for (int Loop = 1; Loop <= NumScheduleTypes; ++Loop) {
     678         4279 :             s_ip->getObjectItem(state,
     679              :                                 CurrentModuleObject,
     680              :                                 Loop,
     681              :                                 Alphas,
     682              :                                 NumAlphas,
     683              :                                 Numbers,
     684              :                                 NumNumbers,
     685              :                                 Status,
     686              :                                 lNumericBlanks,
     687              :                                 lAlphaBlanks,
     688              :                                 cAlphaFields,
     689              :                                 cNumericFields);
     690              : 
     691         4279 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
     692              : 
     693         4279 :             if (s_sched->scheduleTypeMap.find(Alphas(1)) != s_sched->scheduleTypeMap.end()) {
     694            0 :                 ShowSevereDuplicateName(state, eoh);
     695            0 :                 ErrorsFound = true;
     696            0 :                 continue;
     697              :             }
     698              : 
     699         4279 :             auto *schedType = new ScheduleType;
     700         4279 :             schedType->Name = Alphas(1);
     701              : 
     702         4279 :             schedType->Num = (int)s_sched->scheduleTypes.size();
     703         4279 :             s_sched->scheduleTypes.push_back(schedType);
     704         4279 :             s_sched->scheduleTypeMap.insert_or_assign(schedType->Name, schedType->Num);
     705              : 
     706         4279 :             schedType->isLimited = !lNumericBlanks(1) && !lNumericBlanks(2);
     707              : 
     708         4279 :             if (!lNumericBlanks(1)) {
     709         3293 :                 schedType->minVal = Numbers(1);
     710              :             }
     711         4279 :             if (!lNumericBlanks(2)) {
     712         3284 :                 schedType->maxVal = Numbers(2);
     713              :             }
     714              : 
     715         4279 :             if (schedType->isLimited) {
     716         3284 :                 if (Alphas(2) == "DISCRETE" || Alphas(2) == "INTEGER") {
     717         1436 :                     schedType->isReal = false;
     718         1848 :                 } else if (Alphas(2) == "CONTINUOUS" || Alphas(2) == "REAL") {
     719         1848 :                     schedType->isReal = true;
     720              :                 } else {
     721            0 :                     ShowSevereInvalidKey(state, eoh, cAlphaFields(2), Alphas(2));
     722            0 :                     ErrorsFound = true;
     723              :                 }
     724              :             }
     725              : 
     726         4279 :             if (NumAlphas >= 3 && !lAlphaBlanks(3)) {
     727          591 :                 schedType->limitUnits = static_cast<LimitUnits>(getEnumValue(limitUnitNamesUC, Alphas(3)));
     728          591 :                 if (schedType->limitUnits == LimitUnits::Invalid) {
     729            0 :                     ShowSevereInvalidKey(state, eoh, cAlphaFields(3), Alphas(3));
     730            0 :                     ErrorsFound = true;
     731              :                 }
     732              :             }
     733              : 
     734         4279 :             if (schedType->isLimited && schedType->minVal > schedType->maxVal) {
     735            0 :                 if (schedType->isReal) {
     736            0 :                     ShowSevereCustom(
     737            0 :                         state, eoh, format("{} [{:.2R}] > {} [{:.2R}].", cNumericFields(1), schedType->minVal, cNumericFields(2), schedType->maxVal));
     738              :                 } else {
     739            0 :                     ShowSevereCustom(
     740            0 :                         state, eoh, format("{} [{:.0R}] > {} [{:.0R}].", cNumericFields(1), schedType->minVal, cNumericFields(2), schedType->maxVal));
     741              :                 }
     742            0 :                 ShowContinueError(state, "  Other warning/severes about schedule values may appear.");
     743              :             }
     744              :         } // for (Loop)
     745              : 
     746              :         //!! Get Day Schedules (all types)
     747              : 
     748              :         //!!=> Get "DAYSCHEDULE" (Hourly)
     749              : 
     750          801 :         Count = 0;
     751          801 :         CurrentModuleObject = "Schedule:Day:Hourly";
     752          974 :         for (int Loop = 1; Loop <= NumHrDaySchedules; ++Loop) {
     753          173 :             s_ip->getObjectItem(state,
     754              :                                 CurrentModuleObject,
     755              :                                 Loop,
     756              :                                 Alphas,
     757              :                                 NumAlphas,
     758              :                                 Numbers,
     759              :                                 NumNumbers,
     760              :                                 Status,
     761              :                                 lNumericBlanks,
     762              :                                 lAlphaBlanks,
     763              :                                 cAlphaFields,
     764              :                                 cNumericFields);
     765              : 
     766          173 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
     767              : 
     768          173 :             if (s_sched->dayScheduleMap.find(Alphas(1)) != s_sched->dayScheduleMap.end()) {
     769            0 :                 ShowSevereDuplicateName(state, eoh);
     770            0 :                 ErrorsFound = true;
     771            0 :                 continue;
     772              :             }
     773              : 
     774          173 :             auto *daySched = AddDaySchedule(state, Alphas(1));
     775              : 
     776              :             // Validate ScheduleType
     777          173 :             if (lAlphaBlanks(2)) {
     778            0 :                 ShowWarningEmptyField(state, eoh, cAlphaFields(2));
     779            0 :                 ShowContinueError(state, "Schedule will not be validated.");
     780          173 :             } else if ((daySched->schedTypeNum = GetScheduleTypeNum(state, Alphas(2))) == SchedNum_Invalid) {
     781            0 :                 ShowWarningItemNotFound(state, eoh, cAlphaFields(2), Alphas(2));
     782            0 :                 ShowContinueError(state, "Schedule will not be validated.");
     783              :             }
     784              : 
     785          173 :             daySched->interpolation = Interpolation::No;
     786              : 
     787         4325 :             for (int hr = 0; hr < Constant::iHoursInDay; ++hr) {
     788        28104 :                 for (int ts = 0; ts < s_glob->TimeStepsInHour; ++ts) {
     789        23952 :                     daySched->tsVals[hr * s_glob->TimeStepsInHour + ts] = Numbers(hr + 1);
     790        23952 :                     daySched->sumTsVals += daySched->tsVals[hr * s_glob->TimeStepsInHour + ts];
     791              :                 }
     792              :             }
     793              : 
     794          173 :             if (daySched->checkValsForLimitViolations(state)) {
     795            0 :                 ShowWarningCustom(state, eoh, format("Values are outside of range for {}={}", cAlphaFields(2), Alphas(2)));
     796              :             }
     797              : 
     798          173 :             if (daySched->checkValsForBadIntegers(state)) {
     799            0 :                 ShowWarningCustom(state, eoh, format("One or more values are not integer in {}={}", cAlphaFields(2), Alphas(2)));
     800              :             }
     801              : 
     802              :         } // for (Loop)
     803              : 
     804              :         //!! Get "DaySchedule:Interval"
     805              : 
     806          801 :         CurrentModuleObject = "Schedule:Day:Interval";
     807         1154 :         for (int Loop = 1; Loop <= NumIntDaySchedules; ++Loop) {
     808          353 :             s_ip->getObjectItem(state,
     809              :                                 CurrentModuleObject,
     810              :                                 Loop,
     811              :                                 Alphas,
     812              :                                 NumAlphas,
     813              :                                 Numbers,
     814              :                                 NumNumbers,
     815              :                                 Status,
     816              :                                 lNumericBlanks,
     817              :                                 lAlphaBlanks,
     818              :                                 cAlphaFields,
     819              :                                 cNumericFields);
     820              : 
     821          353 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
     822              : 
     823          353 :             if (s_sched->dayScheduleMap.find(Alphas(1)) != s_sched->dayScheduleMap.end()) {
     824            0 :                 ShowSevereDuplicateName(state, eoh);
     825            0 :                 ErrorsFound = true;
     826            0 :                 continue;
     827              :             }
     828              : 
     829          353 :             auto *daySched = AddDaySchedule(state, Alphas(1));
     830              : 
     831              :             // Validate ScheduleType
     832          353 :             if (lAlphaBlanks(2)) {
     833            0 :                 ShowWarningEmptyField(state, eoh, cAlphaFields(2));
     834            0 :                 ShowContinueError(state, "Schedule will not be validated.");
     835          353 :             } else if ((daySched->schedTypeNum = GetScheduleTypeNum(state, Alphas(2))) == SchedNum_Invalid) {
     836            0 :                 ShowWarningItemNotFound(state, eoh, cAlphaFields(2), Alphas(2));
     837            0 :                 ShowContinueError(state, "Schedule will not be validated.");
     838              :             }
     839              : 
     840          353 :             NumFields = NumAlphas - 3;
     841              :             // check to see if numfield=0
     842          353 :             if (NumFields == 0) {
     843            0 :                 ShowSevereCustom(state,
     844              :                                  eoh,
     845            0 :                                  format("Insufficient data entered for a full schedule day."
     846              :                                         "Number of interval fields == [{}].",
     847              :                                         NumFields));
     848            0 :                 ErrorsFound = true;
     849              :             }
     850              : 
     851              :             // Depending on value of "Interpolate" field, the value for each time step in each hour gets processed:
     852          353 :             daySched->interpolation = static_cast<Interpolation>(getEnumValue(interpolationNamesUC, Alphas(3)));
     853          353 :             if (daySched->interpolation == Interpolation::Invalid) {
     854            0 :                 ShowSevereInvalidKey(state, eoh, cAlphaFields(3), Alphas(3));
     855            0 :                 ErrorsFound = true;
     856              :             }
     857              : 
     858          353 :             ProcessIntervalFields(state,
     859         1412 :                                   Alphas({4, _}),
     860              :                                   Numbers,
     861              :                                   NumFields,
     862              :                                   NumNumbers,
     863              :                                   minuteVals,
     864              :                                   setMinuteVals,
     865              :                                   ErrorsFound,
     866          353 :                                   Alphas(1),
     867              :                                   CurrentModuleObject,
     868              :                                   daySched->interpolation);
     869              : 
     870              :             // Now parcel into TS Value.... tsVals.resize() was called in AddDaySchedule()
     871          353 :             daySched->populateFromMinuteVals(state, minuteVals);
     872              : 
     873          353 :             if (daySched->checkValsForLimitViolations(state)) {
     874            0 :                 ShowWarningCustom(state, eoh, format("Values are outside of range for {}={}", cAlphaFields(2), Alphas(2)));
     875              :             }
     876              : 
     877          353 :             if (daySched->checkValsForBadIntegers(state)) {
     878            0 :                 ShowWarningCustom(state, eoh, format("One or more values are not integer in {}={}", cAlphaFields(2), Alphas(2)));
     879              :             }
     880              :         }
     881              : 
     882              :         //!! Get "DaySchedule:List"
     883              : 
     884          801 :         CurrentModuleObject = "Schedule:Day:List";
     885          807 :         for (int Loop = 1; Loop <= NumLstDaySchedules; ++Loop) {
     886            6 :             s_ip->getObjectItem(state,
     887              :                                 CurrentModuleObject,
     888              :                                 Loop,
     889              :                                 Alphas,
     890              :                                 NumAlphas,
     891              :                                 Numbers,
     892              :                                 NumNumbers,
     893              :                                 Status,
     894              :                                 lNumericBlanks,
     895              :                                 lAlphaBlanks,
     896              :                                 cAlphaFields,
     897              :                                 cNumericFields);
     898              : 
     899            6 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
     900              : 
     901            6 :             if (s_sched->dayScheduleMap.find(Alphas(1)) != s_sched->dayScheduleMap.end()) {
     902            0 :                 ShowSevereDuplicateName(state, eoh);
     903            0 :                 ErrorsFound = true;
     904            0 :                 continue;
     905              :             }
     906              : 
     907            6 :             auto *daySched = AddDaySchedule(state, Alphas(1));
     908              : 
     909              :             // Validate ScheduleType
     910            6 :             if (lAlphaBlanks(2)) {
     911            0 :                 ShowWarningEmptyField(state, eoh, cAlphaFields(2));
     912            0 :                 ShowContinueError(state, "Schedule will not be validated.");
     913            6 :             } else if ((daySched->schedTypeNum = GetScheduleTypeNum(state, Alphas(2))) == SchedNum_Invalid) {
     914            0 :                 ShowWarningItemNotFound(state, eoh, cAlphaFields(2), Alphas(2));
     915            0 :                 ShowContinueError(state, "Schedule will not be validated.");
     916              :             }
     917              : 
     918              :             // Depending on value of "Interpolate" field, the value for each time step in each hour gets processed:
     919            6 :             daySched->interpolation = static_cast<Interpolation>(getEnumValue(interpolationNamesUC, Alphas(3)));
     920              : 
     921              :             // check to see if there are any fields
     922            6 :             if (Numbers(1) <= 0.0) {
     923            0 :                 ShowSevereCustom(state,
     924              :                                  eoh,
     925            0 :                                  format("Insufficient data entered for a full schedule day."
     926              :                                         "...Minutes per Item field = [{}].",
     927              :                                         Numbers(1)));
     928            0 :                 ErrorsFound = true;
     929            0 :                 continue;
     930              :             }
     931            6 :             if (NumNumbers < 25) {
     932            0 :                 ShowSevereCustom(state,
     933              :                                  eoh,
     934            0 :                                  format("Insufficient data entered for a full schedule day."
     935              :                                         "...Minutes per Item field = [{}] and only [{}] to apply to list fields.",
     936              :                                         Numbers(1),
     937            0 :                                         NumNumbers - 1));
     938            0 :                 ErrorsFound = true;
     939            0 :                 continue;
     940              :             }
     941              : 
     942            6 :             MinutesPerItem = int(Numbers(1));
     943            6 :             NumExpectedItems = 1440 / MinutesPerItem;
     944            6 :             if ((NumNumbers - 1) != NumExpectedItems) {
     945            0 :                 ShowSevereCustom(state,
     946              :                                  eoh,
     947            0 :                                  format("Number of Entered Items={} not equal number of expected items={}"
     948              :                                         "based on {}={}",
     949            0 :                                         NumNumbers - 1,
     950              :                                         NumExpectedItems,
     951              :                                         cNumericFields(1),
     952              :                                         MinutesPerItem));
     953            0 :                 ErrorsFound = true;
     954            0 :                 continue;
     955              :             }
     956              : 
     957            6 :             if (mod(Constant::iMinutesInHour, MinutesPerItem) != 0) {
     958            0 :                 ShowSevereCustom(state, eoh, format("{}={} not evenly divisible into 60", cNumericFields(1), MinutesPerItem));
     959            0 :                 ErrorsFound = true;
     960            0 :                 continue;
     961              :             }
     962              : 
     963              :             // Number of numbers in the Numbers list okay to process
     964            6 :             int hr = 0;
     965            6 :             int begMin = 0;
     966            6 :             int endMin = MinutesPerItem - 1;
     967          438 :             for (int NumFields = 2; NumFields <= NumNumbers; ++NumFields) {
     968         9072 :                 for (int iMin = begMin; iMin <= endMin; ++iMin) {
     969         8640 :                     minuteVals[hr * Constant::iMinutesInHour + iMin] = Numbers(NumFields);
     970              :                 }
     971          432 :                 begMin = endMin + 1;
     972          432 :                 endMin += MinutesPerItem;
     973          432 :                 if (endMin >= Constant::iMinutesInHour) {
     974          144 :                     endMin = MinutesPerItem - 1;
     975          144 :                     begMin = 0;
     976          144 :                     ++hr;
     977              :                 }
     978              :             }
     979              : 
     980              :             // Now parcel into TS Value.... tsVals.resize() was called in AddDaySchedule()
     981            6 :             daySched->populateFromMinuteVals(state, minuteVals);
     982              : 
     983            6 :             if (daySched->checkValsForLimitViolations(state)) {
     984            0 :                 ShowWarningCustom(state, eoh, format("Values are outside of range for {}={}", cAlphaFields(2), Alphas(2)));
     985              :             }
     986              : 
     987            6 :             if (daySched->checkValsForBadIntegers(state)) {
     988            0 :                 ShowWarningCustom(state, eoh, format("One or more values are not integer for {}={}", cAlphaFields(2), Alphas(2)));
     989              :             }
     990              :         }
     991              : 
     992              :         //!! Get Week Schedules - regular
     993              : 
     994          801 :         CurrentModuleObject = "Schedule:Week:Daily";
     995         1148 :         for (int Loop = 1; Loop <= NumRegWeekSchedules; ++Loop) {
     996          347 :             s_ip->getObjectItem(state,
     997              :                                 CurrentModuleObject,
     998              :                                 Loop,
     999              :                                 Alphas,
    1000              :                                 NumAlphas,
    1001              :                                 Numbers,
    1002              :                                 NumNumbers,
    1003              :                                 Status,
    1004              :                                 lNumericBlanks,
    1005              :                                 lAlphaBlanks,
    1006              :                                 cAlphaFields,
    1007              :                                 cNumericFields);
    1008              : 
    1009          347 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    1010              : 
    1011          347 :             if (s_sched->weekScheduleMap.find(Alphas(1)) != s_sched->weekScheduleMap.end()) {
    1012            0 :                 ShowSevereDuplicateName(state, eoh);
    1013            0 :                 ErrorsFound = true;
    1014            0 :                 continue;
    1015              :             }
    1016              : 
    1017          347 :             auto *weekSched = AddWeekSchedule(state, Alphas(1));
    1018              : 
    1019              :             // Rest of Alphas are processed into schedule nums
    1020         4511 :             for (int iDayType = 1; iDayType < (int)DayType::Num; ++iDayType) {
    1021         4164 :                 if ((weekSched->dayScheds[iDayType] = GetDaySchedule(state, Alphas(iDayType + 1))) == nullptr) {
    1022            0 :                     ShowSevereItemNotFoundAudit(state, eoh, cAlphaFields(iDayType + 1), Alphas(iDayType + 1));
    1023            0 :                     ErrorsFound = true;
    1024              :                 }
    1025              :             } // for (iDayType)
    1026              :         }
    1027              : 
    1028              :         //!! Get Week Schedules - compact
    1029          801 :         Count = NumRegWeekSchedules;
    1030          801 :         CurrentModuleObject = "Schedule:Week:Compact";
    1031          853 :         for (int Loop = 1; Loop <= NumCptWeekSchedules; ++Loop) {
    1032           52 :             s_ip->getObjectItem(state,
    1033              :                                 CurrentModuleObject,
    1034              :                                 Loop,
    1035              :                                 Alphas,
    1036              :                                 NumAlphas,
    1037              :                                 Numbers,
    1038              :                                 NumNumbers,
    1039              :                                 Status,
    1040              :                                 lNumericBlanks,
    1041              :                                 lAlphaBlanks,
    1042              :                                 cAlphaFields,
    1043              :                                 cNumericFields);
    1044              : 
    1045           52 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    1046              : 
    1047           52 :             if (s_sched->weekScheduleMap.find(Alphas(1)) != s_sched->weekScheduleMap.end()) {
    1048            0 :                 ShowSevereDuplicateName(state, eoh);
    1049            0 :                 ErrorsFound = true;
    1050            0 :                 continue;
    1051              :             }
    1052              : 
    1053           52 :             auto *weekSched = AddWeekSchedule(state, Alphas(1));
    1054              : 
    1055           52 :             std::fill(allDays.begin(), allDays.end(), false);
    1056              :             // Rest of Alphas are processed into schedule indices
    1057          140 :             for (int idx = 2; idx <= NumAlphas; idx += 2) {
    1058           88 :                 auto *daySched = GetDaySchedule(state, Alphas(idx + 1));
    1059           88 :                 if (daySched == nullptr) {
    1060            0 :                     ShowSevereItemNotFoundAudit(state, eoh, cAlphaFields(idx + 1), Alphas(idx + 1));
    1061            0 :                     ShowContinueError(state, format("ref: {} \"{}\"", cAlphaFields(idx), Alphas(idx)));
    1062            0 :                     ErrorsFound = true;
    1063              :                 } else {
    1064           88 :                     std::fill(theseDays.begin(), theseDays.end(), false);
    1065           88 :                     ErrorHere = false;
    1066           88 :                     ProcessForDayTypes(state, Alphas(idx), theseDays, allDays, ErrorHere);
    1067           88 :                     if (ErrorHere) {
    1068            0 :                         ShowContinueError(state, format("{}: {}=\"{}", routineName, CurrentModuleObject, Alphas(1)));
    1069            0 :                         ErrorsFound = true;
    1070              :                     } else {
    1071         1144 :                         for (int iDayType = 1; iDayType < (int)DayType::Num; ++iDayType) {
    1072         1056 :                             if (theseDays[iDayType]) {
    1073          624 :                                 weekSched->dayScheds[iDayType] = daySched;
    1074              :                             }
    1075              :                         }
    1076              :                     }
    1077              :                 }
    1078              :             }
    1079              : 
    1080              :             //  Have processed all named days, check to make sure all given
    1081          676 :             for (int iDayType = iDayType_Sun; iDayType < (int)DayType::Num; ++iDayType) {
    1082          624 :                 if (allDays[iDayType] == true) {
    1083          624 :                     continue;
    1084              :                 }
    1085            0 :                 ShowSevereError(state, format("{}: {}=\"{}\", Missing some day assignments", routineName, CurrentModuleObject, Alphas(1)));
    1086            0 :                 ErrorsFound = true;
    1087            0 :                 break;
    1088              :             }
    1089              :         }
    1090          801 :         NumRegWeekSchedules = Count;
    1091              : 
    1092              :         //!! Get Schedules (all types)
    1093              : 
    1094              :         //!! Get Regular Schedules
    1095              : 
    1096          801 :         CurrentModuleObject = "Schedule:Year";
    1097          978 :         for (int Loop = 1; Loop <= NumRegSchedules; ++Loop) {
    1098          177 :             s_ip->getObjectItem(state,
    1099              :                                 CurrentModuleObject,
    1100              :                                 Loop,
    1101              :                                 Alphas,
    1102              :                                 NumAlphas,
    1103              :                                 Numbers,
    1104              :                                 NumNumbers,
    1105              :                                 Status,
    1106              :                                 lNumericBlanks,
    1107              :                                 lAlphaBlanks,
    1108              :                                 cAlphaFields,
    1109              :                                 cNumericFields);
    1110              : 
    1111          177 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    1112              : 
    1113          177 :             if (s_sched->scheduleMap.find(Alphas(1)) != s_sched->scheduleMap.end()) {
    1114            0 :                 ShowSevereDuplicateName(state, eoh);
    1115            0 :                 ErrorsFound = true;
    1116            0 :                 continue;
    1117              :             }
    1118              : 
    1119          177 :             auto *sched = AddScheduleDetailed(state, Alphas(1));
    1120              : 
    1121              :             // Validate ScheduleType
    1122          177 :             if (lAlphaBlanks(2)) {
    1123            0 :                 ShowWarningEmptyField(state, eoh, cAlphaFields(2));
    1124            0 :                 ShowContinueError(state, "Schedule will not be validated.");
    1125          177 :             } else if ((sched->schedTypeNum = GetScheduleTypeNum(state, Alphas(2))) == SchedNum_Invalid) {
    1126            0 :                 ShowWarningItemNotFound(state, eoh, cAlphaFields(2), Alphas(2));
    1127            0 :                 ShowContinueError(state, "Schedule will not be validated.");
    1128              :             }
    1129              : 
    1130          177 :             int NumPointer = 0;
    1131              : 
    1132              :             std::array<int, 367> daysInYear;
    1133          177 :             std::fill(daysInYear.begin(), daysInYear.end(), 0);
    1134              : 
    1135              :             // Rest of Alphas (Weekschedules) are processed into Pointers
    1136          583 :             for (int idx = 3; idx <= NumAlphas; ++idx) {
    1137          406 :                 auto *weekSched = GetWeekSchedule(state, Alphas(idx));
    1138          406 :                 if (weekSched == nullptr) {
    1139            0 :                     ShowSevereItemNotFoundAudit(state, eoh, cAlphaFields(idx), Alphas(idx));
    1140            0 :                     ErrorsFound = true;
    1141            0 :                     continue;
    1142              :                 }
    1143              : 
    1144              :                 // Process for month, day
    1145          406 :                 int StartMonth = int(Numbers(NumPointer + 1));
    1146          406 :                 int StartDay = int(Numbers(NumPointer + 2));
    1147          406 :                 int EndMonth = int(Numbers(NumPointer + 3));
    1148          406 :                 int EndDay = int(Numbers(NumPointer + 4));
    1149          406 :                 NumPointer += 4;
    1150          406 :                 int StartPointer = General::OrdinalDay(StartMonth, StartDay, 1);
    1151          406 :                 int EndPointer = General::OrdinalDay(EndMonth, EndDay, 1);
    1152          406 :                 if (StartPointer <= EndPointer) {
    1153        65188 :                     for (int Count = StartPointer; Count <= EndPointer; ++Count) {
    1154        64782 :                         ++daysInYear[Count];
    1155        64782 :                         sched->weekScheds[Count] = weekSched;
    1156              :                     }
    1157              :                 } else {
    1158            0 :                     for (int Count = StartPointer; Count <= 366; ++Count) {
    1159            0 :                         ++daysInYear[Count];
    1160            0 :                         sched->weekScheds[Count] = weekSched;
    1161              :                     }
    1162            0 :                     for (int Count = 1; Count <= EndPointer; ++Count) {
    1163            0 :                         ++daysInYear[Count];
    1164            0 :                         sched->weekScheds[Count] = weekSched;
    1165              :                     }
    1166              :                 }
    1167              :             }
    1168              : 
    1169              :             // Perform Error checks on this item
    1170              :             // Do special test for Feb 29.  Make equal to Feb 28.
    1171          177 :             if (daysInYear[60] == 0) {
    1172            0 :                 daysInYear[60] = daysInYear[59];
    1173            0 :                 sched->weekScheds[60] = sched->weekScheds[59];
    1174              :             }
    1175              : 
    1176        64959 :             for (int iDay = 1; iDay <= 366; ++iDay) {
    1177        64782 :                 if (daysInYear[iDay] == 0) {
    1178            0 :                     ShowSevereCustomAudit(state, eoh, "has missing days in its schedule pointers");
    1179            0 :                     ErrorsFound = true;
    1180            0 :                     break;
    1181        64782 :                 } else if (daysInYear[iDay] > 1) {
    1182            0 :                     ShowSevereCustomAudit(state, eoh, "has overlapping days in its schedule pointers");
    1183            0 :                     ErrorsFound = true;
    1184            0 :                     break;
    1185              :                 }
    1186              :             }
    1187              : 
    1188              :             // What does it mean to actuate a schedule?
    1189          177 :             if (s_glob->AnyEnergyManagementSystemInModel) { // setup constant schedules as actuators
    1190           70 :                 SetupEMSActuator(state, "Schedule:Year", sched->Name, "Schedule Value", "[ ]", sched->EMSActuatedOn, sched->EMSVal);
    1191              :             }
    1192              :         }
    1193              : 
    1194              :         //!! Get Compact Schedules
    1195              :         // SCHEDULE:COMPACT,
    1196              :         //   \memo Irregular object.  Does not follow the usual definition for fields.  Fields A3... are:
    1197              :         //   \memo Through: Date
    1198              :         //   \memo For: Applicable days (ref: Weekschedule:Compact)
    1199              :         //   \memo Interpolate: Yes/No (ref: Dayschedule:interval) -- optional, if not used will be "No"
    1200              :         //   \memo Until: <Time> (ref: Dayschedule:Interval)
    1201              :         //   \memo <numeric value>
    1202              :         //   \memo words "Through","For","Interpolate","Until" must be included.
    1203              :         //  A1 , \field Name
    1204              :         //       \required-field
    1205              :         //       \type alpha
    1206              :         //       \reference ScheduleNames
    1207              :         //  A2 , \field ScheduleType
    1208              :         //       \type object-list
    1209              :         //       \object-list ScheduleTypeNames
    1210              :         //  A3 , \field Complex Field #1
    1211              :         //  A4 , \field Complex Field #2
    1212              :         //  A5 , \field Complex Field #3
    1213              : 
    1214          801 :         SchNum = NumRegSchedules;
    1215          801 :         CurrentModuleObject = "Schedule:Compact";
    1216        17373 :         for (int Loop = 1; Loop <= NumCptSchedules; ++Loop) {
    1217        16572 :             s_ip->getObjectItem(state,
    1218              :                                 CurrentModuleObject,
    1219              :                                 Loop,
    1220              :                                 Alphas,
    1221              :                                 NumAlphas,
    1222              :                                 Numbers,
    1223              :                                 NumNumbers,
    1224              :                                 Status,
    1225              :                                 lNumericBlanks,
    1226              :                                 lAlphaBlanks,
    1227              :                                 cAlphaFields,
    1228              :                                 cNumericFields);
    1229              : 
    1230        16572 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    1231              : 
    1232        16572 :             if (s_sched->scheduleMap.find(Alphas(1)) != s_sched->scheduleMap.end()) {
    1233            0 :                 ShowSevereDuplicateName(state, eoh);
    1234            0 :                 ErrorsFound = true;
    1235            0 :                 continue;
    1236              :             }
    1237              : 
    1238        16572 :             auto *sched = AddScheduleDetailed(state, Alphas(1));
    1239        16572 :             sched->type = SchedType::Compact;
    1240              : 
    1241              :             // Validate ScheduleType
    1242        16572 :             if (lAlphaBlanks(2)) {
    1243            0 :                 ShowWarningEmptyField(state, eoh, cAlphaFields(2));
    1244            0 :                 ShowContinueError(state, "Schedule will not be validated.");
    1245        16572 :             } else if ((sched->schedTypeNum = GetScheduleTypeNum(state, Alphas(2))) == SchedNum_Invalid) {
    1246           10 :                 ShowWarningItemNotFound(state, eoh, cAlphaFields(2), Alphas(2));
    1247           30 :                 ShowContinueError(state, "Schedule will not be validated.");
    1248              :             }
    1249              : 
    1250        16572 :             NumPointer = 0;
    1251              : 
    1252              :             std::array<int, 367> daysInYear;
    1253        16572 :             std::fill(daysInYear.begin() + 1, daysInYear.end(), 0);
    1254              :             // Process the "complex" fields -- so named because they are not a 1:1 correspondence
    1255              :             // as other objects are
    1256        16572 :             NumField = 3;
    1257        16572 :             StartPointer = 1;
    1258        16572 :             WkCount = 0;
    1259        16572 :             DyCount = 0;
    1260        16572 :             bool FullYearSet = false;
    1261        39691 :             while (NumField < NumAlphas) {
    1262              :                 //   Process "Through"
    1263        23119 :                 if (!has_prefix(Alphas(NumField), "THROUGH:") && !has_prefix(Alphas(NumField), "THROUGH")) {
    1264            0 :                     ShowSevereCustom(state, eoh, format("Expecting \"Through:\" date, instead found entry={}", Alphas(NumField)));
    1265            0 :                     ErrorsFound = true;
    1266            0 :                     goto Through_exit;
    1267              :                 }
    1268              : 
    1269        23119 :                 int sPos = (Alphas(NumField)[7] == ':') ? 8 : 7;
    1270        23119 :                 Alphas(NumField).erase(0, sPos);
    1271        23119 :                 strip(Alphas(NumField));
    1272              : 
    1273        23119 :                 CurrentThrough = Alphas(NumField);
    1274        23119 :                 ErrorHere = false;
    1275        23119 :                 ProcessDateString(state, Alphas(NumField), EndMonth, EndDay, PWeekDay, PDateType, ErrorHere);
    1276        23119 :                 if (PDateType == Weather::DateType::NthDayInMonth || PDateType == Weather::DateType::LastDayInMonth) {
    1277            0 :                     ShowSevereCustom(state, eoh, format("Invalid \"Through:\" date, found entry={}", Alphas(NumField)));
    1278            0 :                     ErrorsFound = true;
    1279            0 :                     goto Through_exit;
    1280              :                 }
    1281              : 
    1282        23119 :                 if (ErrorHere) {
    1283            0 :                     ShowSevereCustom(state, eoh, "Invalid \"Through:\" date");
    1284            0 :                     ErrorsFound = true;
    1285            0 :                     goto Through_exit;
    1286              :                 }
    1287              : 
    1288        23119 :                 EndPointer = General::OrdinalDay(EndMonth, EndDay, 1);
    1289        23119 :                 if (EndPointer == 366) {
    1290        16572 :                     if (FullYearSet) {
    1291            0 :                         ShowSevereCustom(
    1292            0 :                             state, eoh, format("New \"Through\" entry when \"full year\" already set \"Through\" field={}", CurrentThrough));
    1293            0 :                         ErrorsFound = true;
    1294              :                     }
    1295        16572 :                     FullYearSet = true;
    1296              :                 }
    1297              : 
    1298        23119 :                 ++WkCount;
    1299              : 
    1300        23119 :                 auto *weekSched = AddWeekSchedule(state, format("{}_wk_{}", Alphas(1), WkCount));
    1301        23119 :                 weekSched->isUsed = true;
    1302              : 
    1303      6088471 :                 for (int iDay = StartPointer; iDay <= EndPointer; ++iDay) {
    1304      6065352 :                     sched->weekScheds[iDay] = weekSched;
    1305      6065352 :                     ++daysInYear[iDay];
    1306              :                 }
    1307              : 
    1308        23119 :                 StartPointer = EndPointer + 1;
    1309        23119 :                 ThruField = NumField;
    1310        23119 :                 std::fill(allDays.begin(), allDays.end(), false);
    1311        23119 :                 ++NumField;
    1312              : 
    1313        57916 :                 while (NumField < NumAlphas) { // Continues until next "Through"
    1314        41344 :                     if (has_prefix(Alphas(NumField), "THROUGH")) {
    1315         6547 :                         goto For_exit;
    1316              :                     }
    1317              :                     //   "For" must be next, adds to "# Day Schedules"
    1318        34797 :                     if (!has_prefix(Alphas(NumField), "FOR")) {
    1319            0 :                         ShowSevereCustom(state, eoh, format("Looking for \"For\" field, found={}", Alphas(NumField)));
    1320            0 :                         ErrorsFound = true;
    1321            0 :                         goto Through_exit;
    1322              :                     }
    1323              : 
    1324        34797 :                     ++DyCount;
    1325              : 
    1326        34797 :                     auto *daySched = AddDaySchedule(state, format("{}_dy_{}", Alphas(1), DyCount));
    1327              : 
    1328        34797 :                     daySched->schedTypeNum = sched->schedTypeNum;
    1329        34797 :                     daySched->isUsed = true;
    1330              : 
    1331        34797 :                     std::fill(theseDays.begin(), theseDays.end(), false);
    1332        34797 :                     ErrorHere = false;
    1333        34797 :                     LastFor = Alphas(NumField);
    1334        34797 :                     ProcessForDayTypes(state, Alphas(NumField), theseDays, allDays, ErrorHere);
    1335        34797 :                     if (ErrorHere) {
    1336            0 :                         ShowContinueError(state, format("ref {}=\"{}\"", CurrentModuleObject, Alphas(1)));
    1337            0 :                         ShowContinueError(state, format("ref Through field={}", Alphas(ThruField)));
    1338            0 :                         ErrorsFound = true;
    1339              :                     } else {
    1340       452361 :                         for (int iDayType = 1; iDayType < (int)DayType::Num; ++iDayType) {
    1341       417564 :                             if (theseDays[iDayType]) {
    1342       277428 :                                 weekSched->dayScheds[iDayType] = daySched;
    1343              :                             }
    1344              :                         }
    1345              :                     }
    1346              : 
    1347              :                     // Check for "Interpolate"
    1348        34797 :                     ++NumField;
    1349        34797 :                     if (has_prefix(Alphas(NumField), "INTERPOLATE") || !has_prefix(Alphas(NumField), "UNTIL")) {
    1350          330 :                         if (has(Alphas(NumField), "NO")) {
    1351           88 :                             daySched->interpolation = Interpolation::No;
    1352          242 :                         } else if (has(Alphas(NumField), "AVERAGE")) {
    1353          242 :                             daySched->interpolation = Interpolation::Average;
    1354            0 :                         } else if (has(Alphas(NumField), "LINEAR")) {
    1355            0 :                             daySched->interpolation = Interpolation::Linear;
    1356              :                         } else {
    1357            0 :                             ShowSevereInvalidKey(state, eoh, cAlphaFields(NumField), Alphas(NumField));
    1358            0 :                             ErrorsFound = true;
    1359              :                         }
    1360          330 :                         ++NumField;
    1361              :                     }
    1362              : 
    1363        34797 :                     NumNumbers = 0;
    1364        34797 :                     xxcount = 0;
    1365        34797 :                     UntilFld = NumField;
    1366              :                     while (true) {
    1367        98261 :                         if (has_prefix(Alphas(NumField), "FOR")) {
    1368        11678 :                             break;
    1369              :                         }
    1370        86583 :                         if (has_prefix(Alphas(NumField), "THROUGH")) {
    1371         6547 :                             break;
    1372              :                         }
    1373        80036 :                         if (has_prefix(Alphas(NumField), "UNTIL")) {
    1374              :                             // Process Until/Value pairs for later processing by other routine.
    1375        80036 :                             ++NumField;
    1376        80036 :                             ++xxcount;
    1377        80036 :                             ++NumNumbers;
    1378        80036 :                             Numbers(NumNumbers) = Util::ProcessNumber(Alphas(NumField), ErrorHere);
    1379        80036 :                             if (ErrorHere) {
    1380            0 :                                 ShowSevereCustom(
    1381            0 :                                     state, eoh, format("Until field=[{}] has illegal value field=[{}].", Alphas(NumField - 1), Alphas(NumField)));
    1382            0 :                                 ErrorsFound = true;
    1383              :                             }
    1384        80036 :                             ++NumField;
    1385        80036 :                             Alphas(UntilFld + xxcount) = Alphas(NumField); // In case next is "until"
    1386              :                         } else {
    1387            0 :                             ShowSevereCustom(state, eoh, format("Looking for \"Until\" field, found={}", Alphas(NumField)));
    1388            0 :                             ErrorsFound = true;
    1389            0 :                             goto Through_exit;
    1390              :                         }
    1391        80036 :                         if (Alphas(NumField).empty()) {
    1392        16572 :                             break;
    1393              :                         }
    1394              :                     }
    1395              : 
    1396              :                     // Process Untils, Numbers
    1397        34797 :                     if (NumNumbers > 0) {
    1398        34797 :                         NumFields = NumNumbers;
    1399        34797 :                         ErrorHere = false;
    1400        34797 :                         ProcessIntervalFields(state,
    1401       139188 :                                               Alphas({UntilFld, _}),
    1402              :                                               Numbers,
    1403              :                                               NumFields,
    1404              :                                               NumNumbers,
    1405              :                                               minuteVals,
    1406              :                                               setMinuteVals,
    1407              :                                               ErrorHere,
    1408        34797 :                                               daySched->Name,
    1409        69594 :                                               CurrentModuleObject + " DaySchedule Fields",
    1410              :                                               daySched->interpolation);
    1411              :                         // Depending on value of "Interpolate" field, the value for each time step in each hour gets processed:
    1412        34797 :                         if (ErrorHere) {
    1413            0 :                             ShowContinueError(state, format("ref {}=\"{}\"", CurrentModuleObject, Alphas(1)));
    1414            0 :                             ErrorsFound = true;
    1415              :                         }
    1416              : 
    1417        34797 :                         daySched->populateFromMinuteVals(state, minuteVals);
    1418              :                     }
    1419              :                 }
    1420              : 
    1421        16572 :             For_exit:;
    1422       300547 :                 for (int iDayType = iDayType_Sun; iDayType < (int)DayType::Num; ++iDayType) {
    1423       277428 :                     if (allDays[iDayType] == true) {
    1424       277428 :                         continue;
    1425              :                     }
    1426              : 
    1427            0 :                     ShowWarningCustom(state, eoh, format("has missing day types in Through={}", CurrentThrough));
    1428            0 :                     ShowContinueError(state, format("Last \"For\" field={}", LastFor));
    1429            0 :                     std::string errmsg = "Missing day types=,";
    1430            0 :                     for (int kDayType = iDayType_Sun; kDayType < (int)DayType::Num; ++kDayType) {
    1431            0 :                         if (allDays[kDayType]) {
    1432            0 :                             continue;
    1433              :                         }
    1434            0 :                         errmsg.erase(errmsg.length() - 1);
    1435            0 :                         errmsg = format("{} \"{}\",-", errmsg, dayTypeNames[kDayType]);
    1436              :                     }
    1437            0 :                     errmsg.erase(errmsg.length() - 2);
    1438            0 :                     ShowContinueError(state, errmsg);
    1439            0 :                     ShowContinueError(state, "Missing day types will have 0.0 as Schedule Values");
    1440            0 :                     break;
    1441            0 :                 }
    1442              :             }
    1443              : 
    1444        16572 :         Through_exit:;
    1445        16572 :             if (daysInYear[60] == 0) {
    1446            0 :                 daysInYear[60] = daysInYear[59];
    1447            0 :                 sched->weekScheds[60] = sched->weekScheds[59];
    1448              :             }
    1449              : 
    1450        16572 :             if (std::find(daysInYear.begin() + 1, daysInYear.end(), 0) != daysInYear.end()) {
    1451            0 :                 ShowSevereCustomAudit(state, eoh, "has missing days in its schedule pointers");
    1452            0 :                 ErrorsFound = true;
    1453              :             }
    1454      6081924 :             if (std::find_if(daysInYear.begin() + 1, daysInYear.end(), [](int i) { return i > 1; }) != daysInYear.end()) {
    1455            0 :                 ShowSevereCustomAudit(state, eoh, "has overlapping days in its schedule pointers");
    1456            0 :                 ErrorsFound = true;
    1457              :             }
    1458              : 
    1459        16572 :             if (s_glob->AnyEnergyManagementSystemInModel) { // setup constant schedules as actuators
    1460         3860 :                 SetupEMSActuator(state, "Schedule:Compact", sched->Name, "Schedule Value", "[ ]", sched->EMSActuatedOn, sched->EMSVal);
    1461              :             }
    1462              :         }
    1463              : 
    1464              :         //  Schedule:File,
    1465              :         //   \min-fields 5
    1466              :         //         \memo A Schedule:File points to a text computer file that has 8760-8784 hours of data.
    1467              :         //    A1 , \field Name
    1468              :         //         \required-field
    1469              :         //         \type alpha
    1470              :         //         \reference ScheduleNames
    1471              :         //    A2 , \field Schedule Type Limits Name
    1472              :         //         \type object-list
    1473              :         //         \object-list ScheduleTypeLimitsNames
    1474              :         //    A3 , \field File Name
    1475              :         //         \required-field
    1476              :         //         \retaincase
    1477              :         //    N1 , \field Column Number
    1478              :         //         \required-field
    1479              :         //         \type integer
    1480              :         //         \minimum 1
    1481              :         //    N2 , \field Rows to Skip at Top
    1482              :         //         \required-field
    1483              :         //         \type integer
    1484              :         //         \minimum 0
    1485              :         //    N3 , \field Number of Hours of Data
    1486              :         //         \note 8760 hours does not account for leap years, 8784 does.
    1487              :         //         \note should be either 8760 or 8784
    1488              :         //         \default 8760
    1489              :         //         \minimum 8760
    1490              :         //         \maximum 8784
    1491              :         //    A4 , \field Column Separator
    1492              :         //         \type choice
    1493              :         //         \key Comma
    1494              :         //         \key Tab
    1495              :         //         \key Space
    1496              :         //         \key Semicolon
    1497              :         //         \default Comma
    1498              :         //    A5 , \field Interpolate to Timestep
    1499              :         //         \note when the interval does not match the user specified timestep a "Yes" choice will average between the intervals request (to
    1500              :         //         \note timestep resolution.  a "No" choice will use the interval value at the simulation timestep without regard to if it matches
    1501              :         //         \note the boundary or not.
    1502              :         //         \type choice
    1503              :         //         \key Yes
    1504              :         //         \key No
    1505              :         //         \default No
    1506              :         //    N4 ; \field Minutes per Item
    1507              :         //         \note Must be evenly divisible into 60
    1508              :         //         \type integer
    1509              :         //         \minimum 1
    1510              :         //         \maximum 60
    1511              : 
    1512              :         // continue adding to SchNum,AddWeekSch,AddDaySch
    1513              : 
    1514          801 :         CurrentModuleObject = "Schedule:File";
    1515          934 :         for (int Loop = 1; Loop <= NumCommaFileSchedules; ++Loop) {
    1516          133 :             s_ip->getObjectItem(state,
    1517              :                                 CurrentModuleObject,
    1518              :                                 Loop,
    1519              :                                 Alphas,
    1520              :                                 NumAlphas,
    1521              :                                 Numbers,
    1522              :                                 NumNumbers,
    1523              :                                 Status,
    1524              :                                 lNumericBlanks,
    1525              :                                 lAlphaBlanks,
    1526              :                                 cAlphaFields,
    1527              :                                 cNumericFields);
    1528              : 
    1529          133 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    1530              : 
    1531          133 :             if (s_sched->scheduleMap.find(Alphas(1)) != s_sched->scheduleMap.end()) {
    1532            0 :                 ShowSevereDuplicateName(state, eoh);
    1533            0 :                 ErrorsFound = true;
    1534            0 :                 continue;
    1535              :             }
    1536              : 
    1537          133 :             auto *sched = AddScheduleDetailed(state, Alphas(1));
    1538          133 :             sched->type = SchedType::File;
    1539              : 
    1540              :             // Validate ScheduleType
    1541          133 :             if (lAlphaBlanks(2)) {
    1542            0 :                 ShowWarningEmptyField(state, eoh, cAlphaFields(2));
    1543            0 :                 ShowContinueError(state, "Schedule will not be validated.");
    1544          133 :             } else if ((sched->schedTypeNum = GetScheduleTypeNum(state, Alphas(2))) == SchedNum_Invalid) {
    1545            0 :                 ShowWarningItemNotFound(state, eoh, cAlphaFields(2), Alphas(2));
    1546            0 :                 ShowContinueError(state, "Schedule will not be validated.");
    1547              :             }
    1548              : 
    1549              :             // Numbers(1) - which column
    1550          133 :             curcolCount = Numbers(1);
    1551              :             // Numbers(2) - number of rows to skip
    1552          133 :             skiprowCount = Numbers(2);
    1553          133 :             if (Numbers(3) == 0) {
    1554            0 :                 Numbers(3) = 8760.0;
    1555              :             }
    1556          133 :             if (Numbers(3) != 8760 && Numbers(3) != 8784) {
    1557            0 :                 ShowSevereCustom(
    1558              :                     state,
    1559              :                     eoh,
    1560            0 :                     format("{} must = 8760 or 8784 (for a leap year).  Value = {:.0T}, Schedule not processed.", cNumericFields(3), Numbers(3)));
    1561            0 :                 ErrorsFound = true;
    1562            0 :                 continue;
    1563              :             }
    1564              : 
    1565          133 :             if (lAlphaBlanks(4) || Util::SameString(Alphas(4), "comma")) {
    1566          133 :                 ColumnSep = CharComma;
    1567          133 :                 Alphas(4) = "comma";
    1568            0 :             } else if (Util::SameString(Alphas(4), "semicolon")) {
    1569            0 :                 ColumnSep = CharSemicolon;
    1570            0 :             } else if (Util::SameString(Alphas(4), "tab")) {
    1571            0 :                 ColumnSep = CharTab;
    1572            0 :             } else if (Util::SameString(Alphas(4), "space")) {
    1573            0 :                 ColumnSep = CharSpace;
    1574              :             } else {
    1575            0 :                 ShowSevereInvalidKey(state, eoh, cAlphaFields(4), Alphas(4), "..must be Comma, Semicolon, Tab, or Space.");
    1576            0 :                 ErrorsFound = true;
    1577            0 :                 continue;
    1578              :             }
    1579              : 
    1580              :             // Depending on value of "Interpolate" field, the value for each time step in each hour gets processed:
    1581          133 :             Interpolation interp = Interpolation::No;
    1582              : 
    1583          133 :             if (!lAlphaBlanks(5)) {
    1584            4 :                 if (BooleanSwitch bs = getYesNoValue(Alphas(5)); bs != BooleanSwitch::Invalid) {
    1585            4 :                     interp = static_cast<bool>(bs) ? Interpolation::Average : Interpolation::Linear;
    1586              :                 } else {
    1587            0 :                     ShowSevereInvalidKey(state, eoh, cAlphaFields(5), Alphas(5));
    1588            0 :                     ErrorsFound = true;
    1589              :                 }
    1590              :             }
    1591              : 
    1592          133 :             sched->UseDaylightSaving = true;
    1593          133 :             if ((Alphas(6)) == "NO") {
    1594            2 :                 sched->UseDaylightSaving = false;
    1595              :             }
    1596              : 
    1597              :             // is it a sub-hourly schedule or not?
    1598          133 :             int MinutesPerItem = Constant::iMinutesInHour;
    1599          133 :             if (NumNumbers > 3) {
    1600          133 :                 MinutesPerItem = int(Numbers(4));
    1601              :                 // int NumExpectedItems = 1440 / MinutesPerItem;
    1602          133 :                 if (mod(Constant::iMinutesInHour, MinutesPerItem) != 0) {
    1603            0 :                     ShowSevereCustom(
    1604            0 :                         state, eoh, format("Requested {} field value ({}) not evenly divisible into 60", cNumericFields(4), MinutesPerItem));
    1605            0 :                     ErrorsFound = true;
    1606            0 :                     continue;
    1607              :                 }
    1608              :             }
    1609              : 
    1610          133 :             int numHourlyValues = Numbers(3);
    1611          133 :             int rowLimitCount = (Numbers(3) * Constant::rMinutesInHour) / MinutesPerItem;
    1612          133 :             int hrLimitCount = Constant::iMinutesInHour / MinutesPerItem;
    1613              : 
    1614          133 :             std::string contextString = format("{}=\"{}\", {}: ", CurrentModuleObject, Alphas(1), cAlphaFields(3));
    1615              : 
    1616          133 :             state.files.TempFullFilePath.filePath = CheckForActualFilePath(state, Alphas(3), contextString);
    1617              :             // Setup file reading parameters
    1618          133 :             if (state.files.TempFullFilePath.filePath.empty()) {
    1619            0 :                 ErrorsFound = true;
    1620              :             } else {
    1621          133 :                 auto result = s_sched->UniqueProcessedExternalFiles.find(state.files.TempFullFilePath.filePath);
    1622          133 :                 if (result == s_sched->UniqueProcessedExternalFiles.end()) {
    1623            9 :                     FileSystem::FileTypes const ext = FileSystem::getFileType(state.files.TempFullFilePath.filePath);
    1624            9 :                     if (FileSystem::is_flat_file_type(ext)) {
    1625            9 :                         auto const schedule_data = FileSystem::readFile(state.files.TempFullFilePath.filePath);
    1626            9 :                         CsvParser csvParser;
    1627            9 :                         auto it = s_sched->UniqueProcessedExternalFiles.emplace(state.files.TempFullFilePath.filePath,
    1628            9 :                                                                                 csvParser.decode(schedule_data, ColumnSep, skiprowCount));
    1629            9 :                         if (csvParser.hasErrors()) {
    1630            0 :                             for (const auto &[error, isContinued] : csvParser.errors()) {
    1631            0 :                                 if (isContinued) {
    1632            0 :                                     ShowContinueError(state, error);
    1633              :                                 } else {
    1634            0 :                                     ShowSevereError(state, error);
    1635              :                                 }
    1636            0 :                             }
    1637            0 :                             ShowContinueError(state, fmt::format("Error Occurred in {}", state.files.TempFullFilePath.filePath));
    1638            0 :                             ShowFatalError(state, "Program terminates due to previous condition.");
    1639              :                         }
    1640            9 :                         result = it.first;
    1641            9 :                     } else if (FileSystem::is_all_json_type(ext)) {
    1642            0 :                         auto it = s_sched->UniqueProcessedExternalFiles.emplace(state.files.TempFullFilePath.filePath,
    1643            0 :                                                                                 FileSystem::readJSON(state.files.TempFullFilePath.filePath));
    1644            0 :                         result = it.first;
    1645            0 :                     } else {
    1646            0 :                         ShowSevereCustom(
    1647              :                             state,
    1648              :                             eoh,
    1649            0 :                             format("{} = {} has an unknown file extension and cannot be read by this program.", cAlphaFields(3), Alphas(3)));
    1650            0 :                         ShowFatalError(state, "Program terminates due to previous condition.");
    1651              :                     }
    1652              :                 }
    1653              : 
    1654          133 :                 auto const &column_json = result->second["values"][curcolCount - 1];
    1655          133 :                 rowCnt = column_json.size();
    1656          133 :                 auto const column_values = column_json.get<std::vector<Real64>>(); // (AUTO_OK_OBJ)
    1657              : 
    1658              :                 // schedule values have been filled into the hourlyFileValues array.
    1659              : 
    1660          133 :                 if (numerrors > 0) {
    1661            0 :                     ShowWarningCustom(state,
    1662              :                                       eoh,
    1663            0 :                                       format("{} records had errors - these values are set to 0."
    1664              :                                              "Use Output:Diagnostics,DisplayExtraWarnings; to see individual records in error.",
    1665              :                                              numerrors));
    1666              :                 }
    1667              : 
    1668          133 :                 if (rowCnt < rowLimitCount) {
    1669            0 :                     ShowWarningCustom(state,
    1670              :                                       eoh,
    1671            0 :                                       format("less than {} hourly values read from file."
    1672              :                                              "..Number read={}.",
    1673              :                                              numHourlyValues,
    1674            0 :                                              (rowCnt * Constant::iMinutesInHour) / MinutesPerItem));
    1675              :                 }
    1676              : 
    1677              :                 // process the data into the normal schedule data structures
    1678              :                 // note -- schedules are ALWAYS 366 days so some special measures have to be done at 29 Feb "day of year" (60)
    1679          133 :                 int iDay = 0;
    1680          133 :                 int hDay = 0;
    1681          133 :                 int ifld = 0;
    1682              :                 while (true) {
    1683              :                     // create string of which day of year
    1684        48678 :                     ++iDay;
    1685        48678 :                     ++hDay;
    1686        48678 :                     if (iDay > 366) {
    1687          133 :                         break;
    1688              :                     }
    1689              :                     // increment both since a week schedule is being defined for each day so that a day is valid
    1690              :                     // no matter what the day type that is used in a design day.
    1691              : 
    1692              :                     // define day schedule
    1693        48545 :                     auto *daySched = AddDaySchedule(state, format("{}_dy_{}", Alphas(1), iDay));
    1694        48545 :                     daySched->schedTypeNum = sched->schedTypeNum;
    1695              : 
    1696              :                     // define week schedule
    1697        48545 :                     auto *weekSched = AddWeekSchedule(state, format("{}_wk_{}", Alphas(1), iDay));
    1698              : 
    1699              :                     // for all day types point the week schedule to the newly defined day schedule
    1700       631085 :                     for (int kDayType = 1; kDayType < (int)DayType::Num; ++kDayType) {
    1701       582540 :                         weekSched->dayScheds[kDayType] = daySched;
    1702              :                     }
    1703              : 
    1704              :                     // schedule is pointing to the week schedule
    1705        48545 :                     sched->weekScheds[iDay] = weekSched;
    1706              : 
    1707        48545 :                     if (MinutesPerItem == Constant::iMinutesInHour) {
    1708       100375 :                         for (int hr = 0; hr < Constant::iHoursInDay; ++hr) {
    1709        96360 :                             Real64 curHrVal = column_values[ifld]; // hourlyFileValues((hDay - 1) * 24 + jHour)
    1710        96360 :                             ++ifld;
    1711       481800 :                             for (int ts = 0; ts < s_glob->TimeStepsInHour; ++ts) {
    1712       385440 :                                 daySched->tsVals[hr * s_glob->TimeStepsInHour + ts] = curHrVal;
    1713       385440 :                                 daySched->sumTsVals += daySched->tsVals[hr * s_glob->TimeStepsInHour + ts];
    1714              :                             }
    1715              :                         }
    1716              :                     } else { // Minutes Per Item < 60
    1717      1113250 :                         for (int hr = 0; hr < Constant::iHoursInDay; ++hr) {
    1718      1068720 :                             int endMin = MinutesPerItem - 1;
    1719      1068720 :                             int begMin = 0;
    1720      5694000 :                             for (int NumFields = 1; NumFields <= hrLimitCount; ++NumFields) {
    1721     68748480 :                                 for (int iMin = begMin; iMin <= endMin; ++iMin) {
    1722     64123200 :                                     minuteVals[hr * Constant::iMinutesInHour + iMin] = column_values[ifld];
    1723              :                                 }
    1724              : 
    1725      4625280 :                                 ++ifld;
    1726      4625280 :                                 begMin = endMin + 1;
    1727      4625280 :                                 endMin += MinutesPerItem;
    1728              :                             }
    1729              :                         }
    1730              : 
    1731        44530 :                         daySched->interpolation = interp;
    1732        44530 :                         daySched->populateFromMinuteVals(state, minuteVals);
    1733              :                     }
    1734        48545 :                     if (iDay == 59 && rowCnt < 8784 * hrLimitCount) { // 28 Feb
    1735              :                         // Dup 28 Feb to 29 Feb (60)
    1736          133 :                         ++iDay;
    1737          133 :                         sched->weekScheds[iDay] = sched->weekScheds[iDay - 1];
    1738              :                     }
    1739        48545 :                 }
    1740          133 :             }
    1741              : 
    1742          133 :             if (s_glob->AnyEnergyManagementSystemInModel) { // setup constant schedules as actuators
    1743            0 :                 SetupEMSActuator(state, "Schedule:File", sched->Name, "Schedule Value", "[ ]", sched->EMSActuatedOn, sched->EMSVal);
    1744              :             }
    1745          133 :         }
    1746              : 
    1747          801 :         if (NumCommaFileShading != 0) {
    1748            1 :             auto const &values_json = schedule_file_shading_result->second["values"];
    1749            1 :             auto const headers = schedule_file_shading_result->second["header"].get<std::vector<std::string>>();  // (AUTO_OK_OBJ)
    1750            1 :             auto const headers_set = schedule_file_shading_result->second["header"].get<std::set<std::string>>(); // (AUTO_OK_OBJ)
    1751              : 
    1752          115 :             for (auto const &header : headers_set) {
    1753          114 :                 size_t column = 0;
    1754          114 :                 auto column_it = std::find(headers.begin(), headers.end(), header);
    1755          114 :                 if (column_it != headers.end()) {
    1756          228 :                     column = std::distance(headers.begin(), column_it);
    1757              :                 }
    1758          114 :                 if (column == 0) {
    1759            1 :                     continue; // Skip timestamp column and any duplicate column, which will be 0 as well since it won't be found.
    1760              :                 }
    1761          113 :                 auto const column_values = values_json.at(column).get<std::vector<Real64>>(); // (AUTO_OK_OBJ)
    1762              : 
    1763          113 :                 std::string curName = format("{}_shading", header);
    1764          113 :                 std::string curNameUC = Util::makeUPPER(curName);
    1765              : 
    1766          113 :                 if (s_sched->scheduleMap.find(curNameUC) != s_sched->scheduleMap.end()) {
    1767            0 :                     ShowSevereError(state, format("Duplicate schedule name {}", curName));
    1768            0 :                     ErrorsFound = true;
    1769            0 :                     continue;
    1770              :                 }
    1771              : 
    1772          113 :                 auto *schedShading = AddScheduleDetailed(state, curName);
    1773          113 :                 schedShading->type = SchedType::File;
    1774              : 
    1775          113 :                 int iDay = 0;
    1776          113 :                 int ifld = 0;
    1777              :                 while (true) {
    1778              :                     // create string of which day of year
    1779        41358 :                     ++iDay;
    1780        41358 :                     if (iDay > 366) {
    1781          113 :                         break;
    1782              :                     }
    1783              : 
    1784              :                     // day schedule
    1785        41245 :                     auto *daySched = AddDaySchedule(state, format("{}_dy_{}", curName, iDay));
    1786        41245 :                     daySched->schedTypeNum = schedShading->schedTypeNum;
    1787              : 
    1788              :                     // define week schedule
    1789        41245 :                     auto *weekSched = AddWeekSchedule(state, format("{}_wk_{}", curName, iDay));
    1790              : 
    1791              :                     // for all day types point the week schedule to the newly defined day schedule
    1792       536185 :                     for (int kDayType = 1; kDayType < (int)DayType::Num; ++kDayType) {
    1793       494940 :                         weekSched->dayScheds[kDayType] = daySched;
    1794              :                     }
    1795              : 
    1796              :                     // schedule is pointing to the week schedule
    1797        41245 :                     schedShading->weekScheds[iDay] = weekSched;
    1798              : 
    1799      1031125 :                     for (int hr = 0; hr < Constant::iHoursInDay; ++hr) {
    1800      4949400 :                         for (int ts = 0; ts < s_glob->TimeStepsInHour; ++ts) {
    1801      3959520 :                             daySched->tsVals[hr * s_glob->TimeStepsInHour + ts] = column_values[ifld];
    1802      3959520 :                             ++ifld;
    1803              :                         }
    1804              :                     }
    1805              : 
    1806        41245 :                     if (iDay == 59 && !state.dataEnvrn->CurrentYearIsLeapYear) { // 28 Feb
    1807              :                         // Dup 28 Feb to 29 Feb (60)
    1808          113 :                         ++iDay;
    1809          113 :                         schedShading->weekScheds[iDay] = schedShading->weekScheds[iDay - 1];
    1810              :                     }
    1811        41245 :                 }
    1812          115 :             }
    1813            1 :         }
    1814              : 
    1815              :         // Constant Schedules
    1816          801 :         CurrentModuleObject = "Schedule:Constant";
    1817         1066 :         for (int Loop = 1; Loop <= NumConstantSchedules; ++Loop) {
    1818          265 :             s_ip->getObjectItem(state,
    1819              :                                 CurrentModuleObject,
    1820              :                                 Loop,
    1821              :                                 Alphas,
    1822              :                                 NumAlphas,
    1823              :                                 Numbers,
    1824              :                                 NumNumbers,
    1825              :                                 Status,
    1826              :                                 lNumericBlanks,
    1827              :                                 lAlphaBlanks,
    1828              :                                 cAlphaFields,
    1829              :                                 cNumericFields);
    1830              : 
    1831          265 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    1832              : 
    1833          265 :             if (s_sched->scheduleMap.find(Alphas(1)) != s_sched->scheduleMap.end()) {
    1834            0 :                 ShowSevereDuplicateName(state, eoh);
    1835            0 :                 ErrorsFound = true;
    1836            0 :                 continue;
    1837              :             }
    1838              : 
    1839          265 :             auto *sched = AddScheduleConstant(state, Alphas(1), Numbers(1));
    1840              : 
    1841              :             // Validate ScheduleType
    1842          265 :             if (lAlphaBlanks(2)) { // No warning here for constant schedules
    1843           34 :                 ShowWarningEmptyField(state, eoh, cAlphaFields(2));
    1844          102 :                 ShowContinueError(state, "Schedule will not be validated.");
    1845          231 :             } else if ((sched->schedTypeNum = GetScheduleTypeNum(state, Alphas(2))) == SchedNum_Invalid) {
    1846            2 :                 ShowWarningItemNotFound(state, eoh, cAlphaFields(2), Alphas(2));
    1847            6 :                 ShowContinueError(state, "Schedule will not be validated.");
    1848              :             }
    1849              : 
    1850          265 :             if (s_glob->AnyEnergyManagementSystemInModel) { // setup constant schedules as actuators
    1851           94 :                 SetupEMSActuator(state, "Schedule:Constant", sched->Name, "Schedule Value", "[ ]", sched->EMSActuatedOn, sched->EMSVal);
    1852              :             }
    1853              :         }
    1854              :         // When InitConstantScheduleData is called, TimeStepsInHour is 0, so we delay it here
    1855          801 :         static_cast<ScheduleConstant *>(s_sched->schedules[SchedNum_AlwaysOff])->tsVals.assign(Constant::iHoursInDay * s_glob->TimeStepsInHour, 0.0);
    1856          801 :         static_cast<ScheduleConstant *>(s_sched->schedules[SchedNum_AlwaysOn])->tsVals.assign(Constant::iHoursInDay * s_glob->TimeStepsInHour, 1.0);
    1857              : 
    1858          801 :         CurrentModuleObject = "ExternalInterface:Schedule";
    1859          801 :         for (int Loop = 1; Loop <= NumExternalInterfaceSchedules; ++Loop) {
    1860            0 :             s_ip->getObjectItem(state,
    1861              :                                 CurrentModuleObject,
    1862              :                                 Loop,
    1863              :                                 Alphas,
    1864              :                                 NumAlphas,
    1865              :                                 Numbers,
    1866              :                                 NumNumbers,
    1867              :                                 Status,
    1868              :                                 lNumericBlanks,
    1869              :                                 lAlphaBlanks,
    1870              :                                 cAlphaFields,
    1871              :                                 cNumericFields);
    1872              : 
    1873            0 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    1874              : 
    1875            0 :             if (s_sched->scheduleMap.find(Alphas(1)) != s_sched->scheduleMap.end()) {
    1876            0 :                 ShowSevereDuplicateName(state, eoh);
    1877            0 :                 ErrorsFound = true;
    1878            0 :                 continue;
    1879              :             }
    1880              : 
    1881            0 :             auto *sched = AddScheduleDetailed(state, Alphas(1));
    1882            0 :             sched->type = SchedType::External;
    1883              : 
    1884              :             // Validate ScheduleType
    1885            0 :             if (lAlphaBlanks(2)) {
    1886            0 :                 ShowWarningEmptyField(state, eoh, cAlphaFields(2));
    1887            0 :                 ShowContinueError(state, "Schedule will not be validated.");
    1888            0 :             } else if ((sched->schedTypeNum = GetScheduleTypeNum(state, Alphas(2))) == SchedNum_Invalid) {
    1889            0 :                 ShowWarningItemNotFound(state, eoh, cAlphaFields(2), Alphas(2));
    1890            0 :                 ShowContinueError(state, "Schedule will not be validated.");
    1891              :             }
    1892              : 
    1893              :             // TODO: I'm not sure this Jazz is necessary
    1894              :             // Add day schedule
    1895            0 :             auto *daySched = AddDaySchedule(state, format("{}_xi_dy_", Alphas(1)));
    1896            0 :             daySched->isUsed = true;
    1897            0 :             daySched->schedTypeNum = sched->schedTypeNum;
    1898              : 
    1899              :             //   Initialize the ExternalInterface day schedule for the ExternalInterface compact schedule.
    1900              :             //   It will be overwritten during run time stepping after the warm up period
    1901            0 :             if (NumNumbers < 1) {
    1902            0 :                 ShowWarningCustom(state, eoh, "Initial value is not numeric or is missing. Fix idf file.");
    1903            0 :                 NumErrorFlag = true;
    1904              :             }
    1905            0 :             ExternalInterfaceSetSchedule(state, daySched->Num, Numbers(1));
    1906              : 
    1907            0 :             auto *weekSched = AddWeekSchedule(state, format("{}_xi_wk_", Alphas(1)));
    1908            0 :             weekSched->isUsed = true;
    1909            0 :             for (int iDayType = 1; iDayType < (int)DayType::Num; ++iDayType) {
    1910            0 :                 weekSched->dayScheds[iDayType] = daySched;
    1911              :             }
    1912              : 
    1913            0 :             for (int iDay = 1; iDay <= 366; ++iDay) {
    1914            0 :                 sched->weekScheds[iDay] = weekSched;
    1915              :             }
    1916              :         } // for (Loop)
    1917              : 
    1918              :         // added for FMU Import
    1919          801 :         CurrentModuleObject = "ExternalInterface:FunctionalMockupUnitImport:To:Schedule";
    1920          803 :         for (int Loop = 1; Loop <= NumExternalInterfaceFunctionalMockupUnitImportSchedules; ++Loop) {
    1921            2 :             s_ip->getObjectItem(state,
    1922              :                                 CurrentModuleObject,
    1923              :                                 Loop,
    1924              :                                 Alphas,
    1925              :                                 NumAlphas,
    1926              :                                 Numbers,
    1927              :                                 NumNumbers,
    1928              :                                 Status,
    1929              :                                 lNumericBlanks,
    1930              :                                 lAlphaBlanks,
    1931              :                                 cAlphaFields,
    1932              :                                 cNumericFields);
    1933              : 
    1934            2 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    1935              : 
    1936            2 :             if (s_sched->scheduleMap.find(Alphas(1)) != s_sched->scheduleMap.end()) {
    1937            0 :                 ShowSevereDuplicateName(state, eoh);
    1938            0 :                 if (NumExternalInterfaceSchedules >= 1) {
    1939            0 :                     ShowContinueError(
    1940              :                         state,
    1941            0 :                         format("{} defined as an ExternalInterface:Schedule and ExternalInterface:FunctionalMockupUnitImport:To:Schedule."
    1942              :                                "This will cause the schedule to be overwritten by PtolemyServer and FunctionalMockUpUnitImport)",
    1943              :                                cAlphaFields(1)));
    1944              :                 }
    1945            0 :                 ErrorsFound = true;
    1946            0 :                 continue;
    1947              :             }
    1948              : 
    1949            2 :             auto *sched = AddScheduleDetailed(state, Alphas(1));
    1950            2 :             sched->type = SchedType::External;
    1951              : 
    1952              :             // Validate ScheduleType
    1953            2 :             if (lAlphaBlanks(2)) {
    1954            0 :                 ShowWarningEmptyField(state, eoh, cAlphaFields(2));
    1955            0 :                 ShowContinueError(state, "Schedule will not be validated.");
    1956            2 :             } else if ((sched->schedTypeNum = GetScheduleTypeNum(state, Alphas(2))) == SchedNum_Invalid) {
    1957            0 :                 ShowWarningItemNotFound(state, eoh, cAlphaFields(2), Alphas(2));
    1958            0 :                 ShowContinueError(state, "Schedule will not be validated.");
    1959              :             }
    1960              : 
    1961              :             // TODO: I'm not sure this Jazz is necessary
    1962              :             // Add day schedule
    1963            2 :             auto *daySched = AddDaySchedule(state, format("{}_xi_dy_", Alphas(1)));
    1964            2 :             daySched->isUsed = true;
    1965            2 :             daySched->schedTypeNum = sched->schedTypeNum;
    1966              : 
    1967              :             //   Initialize the ExternalInterface day schedule for the ExternalInterface compact schedule.
    1968              :             //   It will be overwritten during run time stepping after the warm up period
    1969            2 :             if (NumNumbers < 1) {
    1970            0 :                 ShowWarningCustom(state, eoh, "Initial value is not numeric or is missing. Fix idf file.");
    1971            0 :                 NumErrorFlag = true;
    1972              :             }
    1973            2 :             ExternalInterfaceSetSchedule(state, daySched->Num, Numbers(1));
    1974              : 
    1975            2 :             auto *weekSched = AddWeekSchedule(state, format("{}_xi_wk_", Alphas(1)));
    1976            2 :             weekSched->isUsed = true;
    1977           26 :             for (int iDayType = 1; iDayType < (int)DayType::Num; ++iDayType) {
    1978           24 :                 weekSched->dayScheds[iDayType] = daySched;
    1979              :             }
    1980              : 
    1981          734 :             for (int iDay = 1; iDay <= 366; ++iDay) {
    1982          732 :                 sched->weekScheds[iDay] = weekSched;
    1983              :             }
    1984              :         }
    1985              : 
    1986              :         // added for FMU Export
    1987          801 :         CurrentModuleObject = "ExternalInterface:FunctionalMockupUnitExport:To:Schedule";
    1988          801 :         for (int Loop = 1; Loop <= NumExternalInterfaceFunctionalMockupUnitExportSchedules; ++Loop) {
    1989            0 :             s_ip->getObjectItem(state,
    1990              :                                 CurrentModuleObject,
    1991              :                                 Loop,
    1992              :                                 Alphas,
    1993              :                                 NumAlphas,
    1994              :                                 Numbers,
    1995              :                                 NumNumbers,
    1996              :                                 Status,
    1997              :                                 lNumericBlanks,
    1998              :                                 lAlphaBlanks,
    1999              :                                 cAlphaFields,
    2000              :                                 cNumericFields);
    2001              : 
    2002            0 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    2003              : 
    2004            0 :             if (s_sched->scheduleMap.find(Alphas(1)) != s_sched->scheduleMap.end()) {
    2005            0 :                 ShowSevereDuplicateName(state, eoh);
    2006            0 :                 if (NumExternalInterfaceSchedules >= 1) {
    2007            0 :                     ShowContinueError(
    2008              :                         state,
    2009            0 :                         format("{} defined as an ExternalInterface:Schedule and ExternalInterface:FunctionalMockupUnitImport:To:Schedule."
    2010              :                                "This will cause the schedule to be overwritten by PtolemyServer and FunctionalMockUpUnitImport)",
    2011              :                                cAlphaFields(1)));
    2012              :                 }
    2013            0 :                 ErrorsFound = true;
    2014            0 :                 continue;
    2015              :             }
    2016              : 
    2017            0 :             auto *sched = AddScheduleDetailed(state, Alphas(1));
    2018            0 :             sched->type = SchedType::External;
    2019              : 
    2020              :             // Validate ScheduleType
    2021            0 :             if (lAlphaBlanks(2)) {
    2022            0 :                 ShowWarningEmptyField(state, eoh, cAlphaFields(2));
    2023            0 :                 ShowContinueError(state, "Schedule will not be validated.");
    2024            0 :             } else if ((sched->schedTypeNum = GetScheduleTypeNum(state, Alphas(2))) == SchedNum_Invalid) {
    2025            0 :                 ShowWarningItemNotFound(state, eoh, cAlphaFields(2), Alphas(2));
    2026            0 :                 ShowContinueError(state, "Schedule will not be validated.");
    2027              :             }
    2028              : 
    2029              :             // TODO: I'm not sure this Jazz is necessary
    2030              :             // Add day schedule
    2031            0 :             auto *daySched = AddDaySchedule(state, format("{}_xi_dy_", Alphas(1)));
    2032            0 :             daySched->isUsed = true;
    2033            0 :             daySched->schedTypeNum = sched->schedTypeNum;
    2034              : 
    2035              :             //   Initialize the ExternalInterface day schedule for the ExternalInterface compact schedule.
    2036              :             //   It will be overwritten during run time stepping after the warm up period
    2037            0 :             if (NumNumbers < 1) {
    2038            0 :                 ShowWarningCustom(state, eoh, "Initial value is not numeric or is missing. Fix idf file.");
    2039            0 :                 NumErrorFlag = true;
    2040              :             }
    2041            0 :             ExternalInterfaceSetSchedule(state, daySched->Num, Numbers(1));
    2042              : 
    2043            0 :             auto *weekSched = AddWeekSchedule(state, format("{}_xi_wk_", Alphas(1)));
    2044            0 :             weekSched->isUsed = true;
    2045            0 :             for (int iDayType = 1; iDayType < (int)DayType::Num; ++iDayType) {
    2046            0 :                 weekSched->dayScheds[iDayType] = daySched;
    2047              :             }
    2048              : 
    2049            0 :             std::fill(sched->weekScheds.begin() + 1, sched->weekScheds.end(), weekSched);
    2050              :         } // for (Loop)
    2051              : 
    2052              :         // Validate by ScheduleLimitsType
    2053        19665 :         for (auto *sched : s_sched->schedules) {
    2054              : 
    2055        18864 :             if (sched->schedTypeNum == SchedNum_Invalid) {
    2056         1761 :                 continue;
    2057              :             }
    2058              : 
    2059        17103 :             auto const *schedType = s_sched->scheduleTypes[sched->schedTypeNum];
    2060        17103 :             if (!schedType->isLimited) {
    2061         3546 :                 continue;
    2062              :             }
    2063              : 
    2064        13557 :             if (!sched->checkMinMaxVals(state, Clusive::In, schedType->minVal, Clusive::In, schedType->maxVal)) {
    2065            0 :                 ErrorObjectHeader eoh{routineName, "Schedule", sched->Name};
    2066            0 :                 ShowSevereBadMinMax(state, eoh, "", "", Clusive::In, schedType->minVal, Clusive::In, schedType->maxVal);
    2067            0 :                 ErrorsFound = true;
    2068              :             }
    2069          801 :         }
    2070              : 
    2071          801 :         if (ErrorsFound) {
    2072            0 :             ShowFatalError(state, format("{}: Preceding Errors cause termination.", routineName));
    2073              :         }
    2074              : 
    2075          801 :         if (s_sched->scheduleTypes.size() + s_sched->daySchedules.size() + s_sched->weekSchedules.size() + s_sched->schedules.size() > 0) {
    2076          801 :             CurrentModuleObject = "Output:Schedules";
    2077          801 :             NumFields = s_ip->getNumObjectsFound(state, CurrentModuleObject);
    2078              : 
    2079              :             //    RptSchedule=.FALSE.
    2080          801 :             RptLevel = 1;
    2081          824 :             for (int Count = 1; Count <= NumFields; ++Count) {
    2082           23 :                 s_ip->getObjectItem(state, CurrentModuleObject, Count, Alphas, NumAlphas, Numbers, NumNumbers, Status);
    2083              : 
    2084           23 :                 ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    2085              : 
    2086              :                 // IDD only allows Hourly or Timestep as valid values on the required field, anything else should be an error in the input processor
    2087           23 :                 ReportLevel reportLevel = static_cast<ReportLevel>(getEnumValue(reportLevelNamesUC, Alphas(1)));
    2088           23 :                 if (reportLevel == ReportLevel::Invalid) {
    2089            0 :                     ShowWarningInvalidKey(state, eoh, cAlphaFields(1), Alphas(1), "HOURLY report will be done");
    2090            0 :                     reportLevel = ReportLevel::Hourly;
    2091              :                 }
    2092           23 :                 ReportScheduleDetails(state, reportLevel);
    2093              :             }
    2094              :         }
    2095              : 
    2096          801 :         Alphas.deallocate();
    2097          801 :         cAlphaFields.deallocate();
    2098          801 :         cNumericFields.deallocate();
    2099          801 :         Numbers.deallocate();
    2100          801 :         lAlphaBlanks.deallocate();
    2101          801 :         lNumericBlanks.deallocate();
    2102              : 
    2103          801 :         print(state.files.audit, "{}\n", "  Processing Schedule Input -- Complete");
    2104        35951 :     } // ProcessScheduleInput()
    2105              : 
    2106           23 :     void ReportScheduleDetails(EnergyPlusData &state,
    2107              :                                ReportLevel const LevelOfDetail) // =1: hourly; =2: timestep; = 3: make IDF excerpt
    2108              :     {
    2109              :         // SUBROUTINE INFORMATION:
    2110              :         //       AUTHOR         Linda K. Lawrie
    2111              :         //       DATE WRITTEN   January 2003
    2112              :         //       MODIFIED       February 2008 - add IDF outputs (compact schedules)
    2113              : 
    2114              :         // PURPOSE OF THIS SUBROUTINE:
    2115              :         // This subroutine puts the details of the Schedules on the .eio file (Inits file).
    2116              : 
    2117              :         // SUBROUTINE PARAMETER DEFINITIONS:
    2118           23 :         constexpr std::array<std::string_view, 12> Months = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
    2119           23 :         constexpr std::array<std::string_view, 25> HrField = {"00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12",
    2120              :                                                               "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24"};
    2121              : 
    2122              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2123              :         int NumF;
    2124              :         int PMon;
    2125              :         int PDay;
    2126           23 :         Array1D_string ShowMinute;
    2127           23 :         Array1D_string TimeHHMM;
    2128           23 :         std::string NoAverageLinear;
    2129           23 :         std::string YesNo2;
    2130           23 :         std::string Num1;
    2131           23 :         std::string Num2;
    2132           23 :         Array2D_string RoundTSValue;
    2133           23 :         std::string_view constexpr SchDFmtdata{",{}"};
    2134              : 
    2135           23 :         auto const &s_glob = state.dataGlobal;
    2136           23 :         auto const &s_sched = state.dataSched;
    2137              : 
    2138           23 :         ShowMinute.allocate(s_glob->TimeStepsInHour);
    2139           23 :         TimeHHMM.allocate(s_glob->TimeStepsInHour * Constant::iHoursInDay);
    2140           23 :         RoundTSValue.allocate(s_glob->TimeStepsInHour, Constant::iHoursInDay);
    2141           23 :         ShowMinute = std::string{};
    2142           23 :         TimeHHMM = std::string{};
    2143           23 :         RoundTSValue = std::string{};
    2144              : 
    2145           23 :         int CurMinute = s_glob->MinutesInTimeStep;
    2146          128 :         for (int Count = 1; Count <= s_glob->TimeStepsInHour - 1; ++Count) {
    2147          105 :             ShowMinute(Count) = format("{:02}", CurMinute);
    2148          105 :             CurMinute += s_glob->MinutesInTimeStep;
    2149              :         }
    2150           23 :         ShowMinute(s_glob->TimeStepsInHour) = "00";
    2151              : 
    2152           23 :         switch (LevelOfDetail) {
    2153           23 :         case ReportLevel::Hourly:
    2154              :         case ReportLevel::TimeStep: {
    2155           23 :             NumF = 1;
    2156          575 :             for (int hr = 0; hr < Constant::iHoursInDay; ++hr) {
    2157          552 :                 if (LevelOfDetail == ReportLevel::TimeStep) {
    2158         2784 :                     for (int ts = 1; ts <= s_glob->TimeStepsInHour - 1; ++ts) {
    2159         2304 :                         TimeHHMM(NumF) = format("{}:{}", HrField[hr], ShowMinute(ts));
    2160         2304 :                         ++NumF;
    2161              :                     }
    2162              :                 }
    2163          552 :                 TimeHHMM(NumF) = format("{}:{}", HrField[hr + 1], ShowMinute(s_glob->TimeStepsInHour));
    2164          552 :                 ++NumF;
    2165              :             }
    2166           23 :             --NumF;
    2167              : 
    2168              :             // SchTFmt Schedule Types Header
    2169              :             {
    2170           23 :                 std::string_view constexpr SchTFmt0("! Schedule Details Report={} =====================\n");
    2171           23 :                 std::string_view constexpr SchDFmt{",{}"};
    2172           23 :                 print(state.files.eio, SchTFmt0, reportLevelNames[(int)LevelOfDetail]);
    2173              : 
    2174           23 :                 std::string_view constexpr SchTFmt("! <ScheduleType>,Name,Limited? {Yes/No},Minimum,Maximum,Continuous? {Yes/No - Discrete}");
    2175           23 :                 print(state.files.eio, "{}\n", SchTFmt);
    2176           23 :                 std::string_view constexpr SchDFmt0("! <DaySchedule>,Name,ScheduleType,Interpolated {Yes/No},Time (HH:MM) =>");
    2177           23 :                 print(state.files.eio, "{}", SchDFmt0);
    2178         2879 :                 for (int Count = 1; Count <= NumF; ++Count) {
    2179         2856 :                     print(state.files.eio, SchDFmt, TimeHHMM(Count));
    2180              :                 }
    2181           23 :                 print(state.files.eio, "\n");
    2182              :                 // SchWFmt Header (WeekSchedule)
    2183           23 :                 std::string SchWFmt("! <WeekSchedule>,Name");
    2184          299 :                 for (int Count = 1; Count < (int)DayType::Num; ++Count) {
    2185          276 :                     SchWFmt = format("{},{}", SchWFmt, dayTypeNames[Count]);
    2186              :                 }
    2187           23 :                 print(state.files.eio, "{}\n", SchWFmt);
    2188           23 :                 std::string_view constexpr SchSFmt("! <Schedule>,Name,ScheduleType,{Until Date,WeekSchedule}** Repeated until Dec 31");
    2189           23 :                 print(state.files.eio, "{}\n", SchSFmt);
    2190           23 :             }
    2191              : 
    2192          164 :             for (auto const *schedType : s_sched->scheduleTypes) {
    2193          141 :                 if (schedType->isLimited) {
    2194          103 :                     NoAverageLinear = "Average";
    2195          103 :                     Num1 = format("{:.2R}", schedType->minVal);
    2196          103 :                     strip(Num1);
    2197          103 :                     Num2 = format("{:.2R}", schedType->maxVal);
    2198          103 :                     strip(Num2);
    2199          103 :                     if (schedType->isReal) {
    2200           66 :                         YesNo2 = "Yes";
    2201              :                     } else {
    2202           37 :                         YesNo2 = "No";
    2203           37 :                         Num1 = fmt::to_string((int)schedType->minVal);
    2204           37 :                         Num2 = fmt::to_string((int)schedType->maxVal);
    2205              :                     }
    2206              :                 } else {
    2207           38 :                     NoAverageLinear = "No";
    2208           38 :                     Num1 = "N/A";
    2209           38 :                     Num2 = "N/A";
    2210           38 :                     YesNo2 = "N/A";
    2211              :                 }
    2212          141 :                 std::string_view constexpr SchTFmtdata("ScheduleTypeLimits,{},{},{},{},{}\n");
    2213          141 :                 print(state.files.eio, SchTFmtdata, schedType->Name, NoAverageLinear, Num1, Num2, YesNo2);
    2214           23 :             }
    2215              : 
    2216          944 :             for (auto *daySched : s_sched->daySchedules) {
    2217              : 
    2218          921 :                 NoAverageLinear = interpolationNames[(int)daySched->interpolation];
    2219        23025 :                 for (int hr = 0; hr < Constant::iHoursInDay; ++hr) {
    2220       152760 :                     for (int ts = 0; ts < s_glob->TimeStepsInHour; ++ts) {
    2221       130656 :                         RoundTSValue(ts + 1, hr + 1) = format("{:.2R}", daySched->tsVals[hr * s_glob->TimeStepsInHour + ts]);
    2222              :                     }
    2223              :                 }
    2224          921 :                 std::string_view constexpr SchDFmtdata0("DaySchedule,{},{},{},{}");
    2225          921 :                 print(state.files.eio,
    2226              :                       SchDFmtdata0,
    2227          921 :                       daySched->Name,
    2228         1842 :                       (daySched->schedTypeNum == SchedNum_Invalid) ? "" : s_sched->scheduleTypes[daySched->schedTypeNum]->Name,
    2229              :                       NoAverageLinear,
    2230              :                       "Values:");
    2231              : 
    2232          921 :                 switch (LevelOfDetail) {
    2233           23 :                 case ReportLevel::Hourly: {
    2234          575 :                     for (int hr = 0; hr < Constant::iHoursInDay; ++hr) {
    2235          552 :                         print(state.files.eio, SchDFmtdata, RoundTSValue(s_glob->TimeStepsInHour, hr + 1));
    2236              :                     }
    2237           23 :                 } break;
    2238              : 
    2239          898 :                 case ReportLevel::TimeStep: {
    2240        22450 :                     for (int hr = 0; hr < Constant::iHoursInDay; ++hr) {
    2241       150000 :                         for (int ts = 0; ts < s_glob->TimeStepsInHour; ++ts) {
    2242       128448 :                             print(state.files.eio, SchDFmtdata, RoundTSValue(ts + 1, hr + 1));
    2243              :                         }
    2244              :                     }
    2245          898 :                 } break;
    2246            0 :                 default:
    2247            0 :                     assert(false);
    2248              :                 }
    2249          921 :                 print(state.files.eio, "\n");
    2250           23 :             }
    2251              : 
    2252          672 :             for (auto *weekSched : s_sched->weekSchedules) {
    2253              : 
    2254          649 :                 std::string_view constexpr SchWFmtdata("Schedule:Week:Daily,{}");
    2255          649 :                 print(state.files.eio, SchWFmtdata, weekSched->Name);
    2256              : 
    2257         8437 :                 for (int NumF = 1; NumF < (int)DayType::Num; ++NumF) {
    2258         7788 :                     print(state.files.eio, ",{}", weekSched->dayScheds[NumF]->Name);
    2259              :                 }
    2260          649 :                 print(state.files.eio, "\n");
    2261           23 :             }
    2262              : 
    2263          712 :             for (auto *sched : s_sched->schedules) {
    2264              : 
    2265          689 :                 if (sched->type == SchedType::Constant) {
    2266           48 :                     continue;
    2267              :                 }
    2268              : 
    2269          641 :                 auto *schedDetailed = dynamic_cast<ScheduleDetailed *>(sched);
    2270          641 :                 assert(schedDetailed != nullptr);
    2271              : 
    2272          641 :                 int NumF = 1;
    2273          641 :                 print(state.files.eio,
    2274              :                       "Schedule,{},{}",
    2275          641 :                       schedDetailed->Name,
    2276         1282 :                       (sched->schedTypeNum == SchedNum_Invalid) ? "" : s_sched->scheduleTypes[sched->schedTypeNum]->Name);
    2277              : 
    2278         1290 :                 while (NumF <= 366) {
    2279              : 
    2280          649 :                     auto *weekSched = schedDetailed->weekScheds[NumF];
    2281          649 :                     std::string_view constexpr ThruFmt(",Through {} {:02},{}");
    2282       234614 :                     while (schedDetailed->weekScheds[NumF] == weekSched && NumF <= 366) {
    2283       234606 :                         if (NumF == 366) {
    2284          641 :                             General::InvOrdinalDay(NumF, PMon, PDay, 1);
    2285          641 :                             print(state.files.eio, ThruFmt, Months[PMon - 1], PDay, weekSched->Name);
    2286              :                         }
    2287       234606 :                         ++NumF;
    2288       234606 :                         if (NumF > 366) {
    2289          641 :                             break; // compound If might have a problem unless this included.
    2290              :                         }
    2291              :                     }
    2292          649 :                     if (NumF <= 366) {
    2293            8 :                         General::InvOrdinalDay(NumF - 1, PMon, PDay, 1);
    2294            8 :                         print(state.files.eio, ThruFmt, Months[PMon - 1], PDay, weekSched->Name);
    2295              :                     }
    2296              :                 }
    2297          641 :                 print(state.files.eio, "\n");
    2298           23 :             }
    2299           23 :         } break;
    2300              : 
    2301            0 :         default:
    2302            0 :             break;
    2303              :         }
    2304              : 
    2305              :         // So this section of the code was not accessible.  The input processor would never have let anything but hourly or timestep on the object
    2306              :         // This code is obviously not covered by any of our integration or unit tests.
    2307              :         //            for (Count = 1; Count <= s_sched->NumSchedules; ++Count) {
    2308              :         //                print(state.files.debug, "\n");
    2309              :         //                print(state.files.debug, "  Schedule:Compact,\n");
    2310              :         //                print(state.files.debug, "    {},           !- Name\n", s_sched->Schedule(Count).Name);
    2311              :         //                print(state.files.debug,
    2312              :         //                      "    {},          !- ScheduleTypeLimits\n",
    2313              :         //                      s_sched->ScheduleType(s_sched->Schedule(Count).ScheduleTypePtr).Name);
    2314              :         //                NumF = 1;
    2315              :         //                while (NumF <= 366) {
    2316              :         //                    TS = s_sched->Schedule(Count).WeekSchedulePointer(NumF);
    2317              :         //                    while (s_sched->Schedule(Count).WeekSchedulePointer(NumF) == TS && NumF <= 366) {
    2318              :         //                        if (NumF == 366) {
    2319              :         //                            General::InvOrdinalDay(NumF, PMon, PDay, 1);
    2320              :         //                            print(state.files.debug, "    Through: {}/{},\n", PMon, PDay);
    2321              :         //                            iDayP = 0;
    2322              :         //                            for (DT = 2; DT <= 6; ++DT) {
    2323              :         //                                print(state.files.debug, "    For: {},\n", ValidDayTypes(DT));
    2324              :         //                                iWeek = s_sched->Schedule(Count).WeekSchedulePointer(NumF - 1);
    2325              :         //                                iDay = s_sched->WeekSchedule(iWeek).DaySchedulePointer(DT);
    2326              :         //                                if (iDay != iDayP) {
    2327              :         //                                    for (Hr = 1; Hr <= 24; ++Hr) {
    2328              :         //                                        print(state.files.debug,
    2329              :         //                                              "    Until: {}:{},{:.2R},\n",
    2330              :         //                                              Hr,
    2331              :         //                                              ShowMinute(s_glob->NumOfTimeStepInHour),
    2332              :         //                                              s_sched->DaySchedule(iDay).TSValue(s_glob->NumOfTimeStepInHour, Hr));
    2333              :         //                                    }
    2334              :         //                                } else {
    2335              :         //                                    print(state.files.debug, "    Same as previous\n");
    2336              :         //                                }
    2337              :         //                                iDayP = iDay;
    2338              :         //                            }
    2339              :         //                            DT = 1;
    2340              :         //                            print(state.files.debug, "    For: {},\n", ValidDayTypes(DT));
    2341              :         //                            iWeek = s_sched->Schedule(Count).WeekSchedulePointer(NumF - 1);
    2342              :         //                            iDay = s_sched->WeekSchedule(iWeek).DaySchedulePointer(DT);
    2343              :         //                            if (iDay != iDayP) {
    2344              :         //                                for (Hr = 1; Hr <= 24; ++Hr) {
    2345              :         //                                    print(state.files.debug,
    2346              :         //                                          "    Until: {}:{},{:.2R},\n",
    2347              :         //                                          Hr,
    2348              :         //                                          ShowMinute(s_glob->NumOfTimeStepInHour),
    2349              :         //                                          s_sched->DaySchedule(iDay).TSValue(s_glob->NumOfTimeStepInHour, Hr));
    2350              :         //                                }
    2351              :         //                            } else {
    2352              :         //                                print(state.files.debug, "    Same as previous\n");
    2353              :         //                            }
    2354              :         //                            iDayP = iDay;
    2355              :         //                            for (DT = 7; DT <= MaxDayTypes; ++DT) {
    2356              :         //                                print(state.files.debug, "    For: {},\n", ValidDayTypes(DT));
    2357              :         //                                iWeek = s_sched->Schedule(Count).WeekSchedulePointer(NumF - 1);
    2358              :         //                                iDay = s_sched->WeekSchedule(iWeek).DaySchedulePointer(DT);
    2359              :         //                                if (iDay != iDayP) {
    2360              :         //                                    for (Hr = 1; Hr <= 24; ++Hr) {
    2361              :         //                                        print(state.files.debug,
    2362              :         //                                              "    Until: {}:{},{:.2R},\n",
    2363              :         //                                              Hr,
    2364              :         //                                              ShowMinute(s_glob->NumOfTimeStepInHour),
    2365              :         //                                              s_sched->DaySchedule(iDay).TSValue(s_glob->NumOfTimeStepInHour, Hr));
    2366              :         //                                    }
    2367              :         //                                } else {
    2368              :         //                                    print(state.files.debug, "    Same as previous\n");
    2369              :         //                                }
    2370              :         //                                iDayP = iDay;
    2371              :         //                            }
    2372              :         //                        }
    2373              :         //                        ++NumF;
    2374              :         //                        if (NumF > 366) break; // compound If might have a problem unless this included.
    2375              :         //                    }
    2376              :         //                    if (NumF <= 366) {
    2377              :         //                        General::InvOrdinalDay(NumF - 1, PMon, PDay, 1);
    2378              :         //                        print(state.files.debug, "    Through: {}/{},\n", PMon, PDay);
    2379              :         //                        iDayP = 0;
    2380              :         //                        for (DT = 2; DT <= 6; ++DT) {
    2381              :         //                            print(state.files.debug, "    For: {},\n", ValidDayTypes(DT));
    2382              :         //                            iWeek = s_sched->Schedule(Count).WeekSchedulePointer(NumF - 1);
    2383              :         //                            iDay = s_sched->WeekSchedule(iWeek).DaySchedulePointer(DT);
    2384              :         //                            if (iDay != iDayP) {
    2385              :         //                                for (Hr = 1; Hr <= 24; ++Hr) {
    2386              :         //                                    print(state.files.debug,
    2387              :         //                                          "    Until: {}:{},{:.2R},\n",
    2388              :         //                                          Hr,
    2389              :         //                                          ShowMinute(s_glob->NumOfTimeStepInHour),
    2390              :         //                                          s_sched->DaySchedule(iDay).TSValue(s_glob->NumOfTimeStepInHour, Hr));
    2391              :         //                                }
    2392              :         //                            } else {
    2393              :         //                                print(state.files.debug, "    Same as previous\n");
    2394              :         //                            }
    2395              :         //                            iDayP = iDay;
    2396              :         //                        }
    2397              :         //                        DT = 1;
    2398              :         //                        print(state.files.debug, "    For: {},\n", ValidDayTypes(DT));
    2399              :         //                        iWeek = s_sched->Schedule(Count).WeekSchedulePointer(NumF - 1);
    2400              :         //                        iDay = s_sched->WeekSchedule(iWeek).DaySchedulePointer(DT);
    2401              :         //                        if (iDay != iDayP) {
    2402              :         //                            for (Hr = 1; Hr <= 24; ++Hr) {
    2403              :         //                                print(state.files.debug,
    2404              :         //                                      "    Until: {}:{},{:.2R},\n",
    2405              :         //                                      Hr,
    2406              :         //                                      ShowMinute(s_glob->NumOfTimeStepInHour),
    2407              :         //                                      s_sched->DaySchedule(iDay).TSValue(s_glob->NumOfTimeStepInHour, Hr));
    2408              :         //                            }
    2409              :         //                        } else {
    2410              :         //                            print(state.files.debug, "    Same as previous\n");
    2411              :         //                        }
    2412              :         //                        iDayP = iDay;
    2413              :         //                        for (DT = 7; DT <= MaxDayTypes; ++DT) {
    2414              :         //                            print(state.files.debug, "    For: {},\n", ValidDayTypes(DT));
    2415              :         //                            iWeek = s_sched->Schedule(Count).WeekSchedulePointer(NumF - 1);
    2416              :         //                            iDay = s_sched->WeekSchedule(iWeek).DaySchedulePointer(DT);
    2417              :         //                            if (iDay != iDayP) {
    2418              :         //                                for (Hr = 1; Hr <= 24; ++Hr) {
    2419              :         //                                    print(state.files.debug,
    2420              :         //                                          "    Until: {}:{},{:.2R},\n",
    2421              :         //                                          Hr,
    2422              :         //                                          ShowMinute(s_glob->NumOfTimeStepInHour),
    2423              :         //                                          s_sched->DaySchedule(iDay).TSValue(s_glob->NumOfTimeStepInHour, Hr));
    2424              :         //                                }
    2425              :         //                            } else {
    2426              :         //                                print(state.files.debug, "    Same as previous\n");
    2427              :         //                            }
    2428              :         //                            iDayP = iDay;
    2429              :         //                        }
    2430              :         //                    }
    2431              :         //                }
    2432              :         //            }
    2433              : 
    2434           23 :         ShowMinute.deallocate();
    2435           23 :         TimeHHMM.deallocate();
    2436           23 :         RoundTSValue.deallocate();
    2437           23 :     } // ReportScheduleDetails()
    2438              : 
    2439            0 :     Real64 GetCurrentScheduleValue(EnergyPlusData const &state, int const schedNum)
    2440              :     {
    2441              :         // Wrapper for method
    2442            0 :         return state.dataSched->schedules[schedNum]->getCurrentVal();
    2443              :     }
    2444              : 
    2445      5753551 :     void UpdateScheduleVals(EnergyPlusData &state)
    2446              :     {
    2447              :         // SUBROUTINE INFORMATION:
    2448              :         //       AUTHOR         Linda Lawrie
    2449              :         //       DATE WRITTEN   August 2011; adapted from Autodesk (time reduction)
    2450              : 
    2451              :         // PURPOSE OF THIS SUBROUTINE:
    2452              :         // This routine calculates all the scheduled values as a time reduction measure and
    2453              :         // stores them in the CurrentValue item of the schedule data structure.
    2454              : 
    2455              :         // METHODOLOGY EMPLOYED:
    2456              :         // Use internal Schedule data structure to calculate current value.  Note that missing values in
    2457              : 
    2458      5753551 :         auto const &s_sched = state.dataSched;
    2459      5753551 :         auto const &s_glob = state.dataGlobal;
    2460              : 
    2461    148780373 :         for (auto *sched : s_sched->schedules) {
    2462    143026822 :             if (sched->EMSActuatedOn) {
    2463       185990 :                 sched->currentVal = sched->EMSVal;
    2464              :             } else {
    2465    142840832 :                 sched->currentVal = sched->getHrTsVal(state, s_glob->HourOfDay, s_glob->TimeStep);
    2466              :             }
    2467      5753551 :         }
    2468      5753551 :     }
    2469              : 
    2470    133585508 :     Real64 ScheduleDetailed::getHrTsVal(EnergyPlusData &state,
    2471              :                                         int hr,
    2472              :                                         int ts // Negative => unspecified
    2473              :     ) const
    2474              :     {
    2475              :         // FUNCTION INFORMATION:
    2476              :         //       AUTHOR         Linda K. Lawrie
    2477              :         //       DATE WRITTEN   January 2003
    2478              :         // PURPOSE OF THIS FUNCTION:
    2479              :         // This function provides a method to look up schedule values for any hour, timestep, day
    2480              :         // of the year (rather than just the "current time").
    2481    133585508 :         auto const &s_glob = state.dataGlobal;
    2482              : 
    2483    133585508 :         if (this->EMSActuatedOn) {
    2484            0 :             return this->EMSVal;
    2485              :         }
    2486              : 
    2487              :         //  so, current date, but maybe TimeStep added
    2488              : 
    2489              :         // Hourly Value
    2490    133585508 :         if (hr > Constant::iHoursInDay) {
    2491            0 :             ShowFatalError(state, format("LookUpScheduleValue called with thisHour={}", hr));
    2492              :         }
    2493              : 
    2494    133585508 :         int thisHr = hr + state.dataEnvrn->DSTIndicator * this->UseDaylightSaving;
    2495              : 
    2496    133585508 :         int thisDayOfYear = state.dataEnvrn->DayOfYear_Schedule;
    2497    133585508 :         int thisDayOfWeek = state.dataEnvrn->DayOfWeek;
    2498    133585508 :         int thisHolidayNum = state.dataEnvrn->HolidayIndex;
    2499    133585508 :         if (thisHr > Constant::iHoursInDay) { // In case HourOfDay is 24 and DSTIndicator is 1, you're actually the next day
    2500        51146 :             thisDayOfYear += 1;
    2501        51146 :             thisHr -= Constant::iHoursInDay;
    2502        51146 :             thisDayOfWeek = state.dataEnvrn->DayOfWeekTomorrow;
    2503        51146 :             thisHolidayNum = state.dataEnvrn->HolidayIndexTomorrow;
    2504              :         }
    2505              : 
    2506              :         // In the case where DST is applied on 12/31 at 24:00, which is the case for a Southern Hemisphere location for eg
    2507              :         // (DayOfYear_Schedule is a bit weird, ScheduleManager always assumes LeapYear)
    2508    133585508 :         if (thisDayOfYear == 367) {
    2509            0 :             thisDayOfYear = 1;
    2510              :         }
    2511              : 
    2512    133585508 :         auto const *weekSched = this->weekScheds[thisDayOfYear];
    2513    133585508 :         auto const *daySched = (thisHolidayNum > 0) ? weekSched->dayScheds[thisHolidayNum] : weekSched->dayScheds[thisDayOfWeek];
    2514    133585508 :         if (daySched == nullptr) {
    2515              :             // We already warned in ProcessScheduleInput that there were missing days: Missing day types will have 0.0 as Schedule Values
    2516            0 :             return 0.0;
    2517              :         }
    2518              : 
    2519              :         // If Unspecified or equal to zero, use NumOfTimeStepInHour, otherwise use supplied
    2520    133585508 :         if (ts <= 0) {
    2521      1159867 :             ts = s_glob->TimeStepsInHour;
    2522              :         }
    2523              : 
    2524    133585508 :         return daySched->tsVals[(thisHr - 1) * s_glob->TimeStepsInHour + (ts - 1)];
    2525              :     } // ScheduleDetailed::getHrTsVal()
    2526              : 
    2527     13288746 :     Real64 ScheduleConstant::getHrTsVal([[maybe_unused]] EnergyPlusData &state, [[maybe_unused]] int hr, [[maybe_unused]] int ts) const
    2528              :     {
    2529              :         // cf #10962 - We can't use currentValue as it could be overwritten by the EMS Sensor
    2530     13288746 :         return this->tsVals.front();
    2531              :     } // ScheduleConstant::getHrTsVal()
    2532              : 
    2533        22539 :     Sched::Schedule *GetScheduleAlwaysOn(EnergyPlusData &state)
    2534              :     {
    2535        22539 :         return state.dataSched->schedules[SchedNum_AlwaysOn];
    2536              :     }
    2537              : 
    2538           16 :     Sched::Schedule *GetScheduleAlwaysOff(EnergyPlusData &state)
    2539              :     {
    2540           16 :         return state.dataSched->schedules[SchedNum_AlwaysOff];
    2541              :     }
    2542              : 
    2543       130092 :     Sched::Schedule *GetSchedule(EnergyPlusData &state, std::string const &name)
    2544              :     {
    2545              :         // FUNCTION INFORMATION:
    2546              :         //       AUTHOR         Linda K. Lawrie
    2547              :         //       DATE WRITTEN   September 1997
    2548              : 
    2549              :         // PURPOSE OF THIS FUNCTION:
    2550              :         // This function returns the internal pointer to Schedule "ScheduleName".
    2551       130092 :         auto const &s_sched = state.dataSched;
    2552              : 
    2553       130092 :         auto found = s_sched->scheduleMap.find(name);
    2554       130092 :         if (found == s_sched->scheduleMap.end()) {
    2555        58719 :             return nullptr;
    2556              :         }
    2557              : 
    2558        71373 :         int schedNum = found->second;
    2559              : 
    2560        71373 :         auto *sched = s_sched->schedules[schedNum];
    2561              : 
    2562        71373 :         if (!sched->isUsed) {
    2563        16406 :             sched->isUsed = true;
    2564              : 
    2565        16406 :             if (sched->type != SchedType::Constant) {
    2566              : 
    2567        16181 :                 auto *schedDetailed = dynamic_cast<ScheduleDetailed *>(sched);
    2568        16181 :                 assert(schedDetailed != nullptr);
    2569              : 
    2570        16181 :                 schedDetailed->isUsed = true;
    2571      5938427 :                 for (int iWeek = 1; iWeek <= 366; ++iWeek) {
    2572      5922246 :                     if (auto *weekSched = schedDetailed->weekScheds[iWeek]; weekSched != nullptr) {
    2573      5922246 :                         if (weekSched->isUsed) {
    2574      5873701 :                             continue;
    2575              :                         }
    2576              : 
    2577        48545 :                         weekSched->isUsed = true;
    2578       631085 :                         for (int iDayType = 1; iDayType < (int)DayType::Num; ++iDayType) {
    2579       582540 :                             auto *daySched = weekSched->dayScheds[iDayType];
    2580       582540 :                             daySched->isUsed = true;
    2581              :                         }
    2582              :                     }
    2583              :                 }
    2584              :             }
    2585              :         }
    2586        71373 :         return sched;
    2587       130092 :     } // GetSchedule()
    2588              : 
    2589            2 :     int GetScheduleNum(EnergyPlusData &state, std::string const &name)
    2590              :     {
    2591            2 :         auto *sched = GetSchedule(state, name);
    2592            2 :         return (sched == nullptr) ? -1 : sched->Num;
    2593              :     }
    2594              : 
    2595          406 :     Sched::WeekSchedule *GetWeekSchedule(EnergyPlusData &state, std::string const &name)
    2596              :     {
    2597          406 :         auto const &s_sched = state.dataSched;
    2598              : 
    2599          406 :         auto found = s_sched->weekScheduleMap.find(name);
    2600          406 :         if (found == s_sched->weekScheduleMap.end()) {
    2601            0 :             return nullptr;
    2602              :         }
    2603              : 
    2604          406 :         int weekSchedNum = found->second;
    2605              : 
    2606          406 :         auto *weekSched = s_sched->weekSchedules[weekSchedNum];
    2607              : 
    2608          406 :         if (!weekSched->isUsed) {
    2609          399 :             weekSched->isUsed = true;
    2610         5187 :             for (int iDayType = 1; iDayType < (int)DayType::Num; ++iDayType) {
    2611         4788 :                 auto *daySched = weekSched->dayScheds[iDayType];
    2612         4788 :                 if (daySched == nullptr) {
    2613            0 :                     continue;
    2614              :                 }
    2615         4788 :                 daySched->isUsed = true;
    2616              :             }
    2617              :         }
    2618          406 :         return weekSched;
    2619          406 :     } // GetWeekSchedule()
    2620              : 
    2621            0 :     int GetWeekScheduleNum(EnergyPlusData &state, std::string const &name)
    2622              :     {
    2623            0 :         auto *weekSched = GetWeekSchedule(state, name);
    2624            0 :         return (weekSched == nullptr) ? -1 : weekSched->Num;
    2625              :     }
    2626              : 
    2627         4271 :     Sched::DaySchedule *GetDaySchedule(EnergyPlusData &state, std::string const &name)
    2628              :     {
    2629              :         // FUNCTION INFORMATION:
    2630              :         //       AUTHOR         Linda K. Lawrie
    2631              :         //       DATE WRITTEN   September 1997
    2632              : 
    2633              :         // PURPOSE OF THIS FUNCTION:
    2634              :         // This function returns the internal pointer to Schedule "ScheduleName".
    2635         4271 :         auto const &s_sched = state.dataSched;
    2636              : 
    2637         4271 :         auto found = s_sched->dayScheduleMap.find(name);
    2638         4271 :         if (found == s_sched->dayScheduleMap.end()) {
    2639            0 :             return nullptr;
    2640              :         }
    2641              : 
    2642         4271 :         int daySchedNum = found->second;
    2643              : 
    2644         4271 :         auto *daySched = s_sched->daySchedules[daySchedNum];
    2645              : 
    2646         4271 :         daySched->isUsed = true;
    2647              : 
    2648         4271 :         return daySched;
    2649         4271 :     } // GetDaySchedule()
    2650              : 
    2651            0 :     int GetDayScheduleNum(EnergyPlusData &state, std::string const &name)
    2652              :     {
    2653            0 :         auto *daySched = GetDaySchedule(state, name);
    2654            0 :         return (daySched == nullptr) ? -1 : daySched->Num;
    2655              :     }
    2656              : 
    2657          470 :     void ScheduleConstant::setMinMaxVals([[maybe_unused]] EnergyPlusData &state)
    2658              :     {
    2659          470 :         assert(!isMinMaxSet);
    2660          470 :         minVal = maxVal = currentVal;
    2661          470 :         isMinMaxSet = true;
    2662          470 :     }
    2663              : 
    2664            0 :     std::vector<Real64> const &ScheduleConstant::getDayVals(EnergyPlusData &state, [[maybe_unused]] int jDay, [[maybe_unused]] int dayofWeek)
    2665              :     {
    2666            0 :         assert((int)tsVals.size() == Constant::iHoursInDay * state.dataGlobal->TimeStepsInHour);
    2667            0 :         return this->tsVals;
    2668              :     } // ScheduleConstant::getDayVals()
    2669              : 
    2670        33269 :     std::vector<Real64> const &ScheduleDetailed::getDayVals(EnergyPlusData &state, int jDay, int dayOfWeek)
    2671              :     {
    2672              :         // PURPOSE OF THIS SUBROUTINE:
    2673              :         // This subroutine returns an entire day's worth of schedule values.
    2674        33269 :         auto const &s_env = state.dataEnvrn;
    2675              : 
    2676              :         // Determine which Week Schedule is used
    2677        33269 :         auto const *weekSched = this->weekScheds[(jDay == -1) ? state.dataEnvrn->DayOfYear_Schedule : jDay];
    2678              : 
    2679        33269 :         DaySchedule *daySched = nullptr;
    2680              :         // Now, which day?
    2681        33269 :         if (dayOfWeek == -1) {
    2682        28227 :             daySched = weekSched->dayScheds[(s_env->HolidayIndex > 0) ? s_env->HolidayIndex : s_env->DayOfWeek];
    2683         5042 :         } else if (dayOfWeek <= 7 && s_env->HolidayIndex > 0) {
    2684         5042 :             daySched = weekSched->dayScheds[s_env->HolidayIndex];
    2685              :         } else {
    2686            0 :             daySched = weekSched->dayScheds[dayOfWeek];
    2687              :         }
    2688              : 
    2689        33269 :         return daySched->getDayVals(state);
    2690              :     } // ScheduleDetailed::getDayVals()
    2691              : 
    2692        73538 :     void ExternalInterfaceSetSchedule(EnergyPlusData &state,
    2693              :                                       int schedNum,
    2694              :                                       Real64 value // The new value for the schedule
    2695              :     )
    2696              :     {
    2697              :         // FUNCTION INFORMATION:
    2698              :         //       AUTHOR         Michael Wetter
    2699              :         //       DATE WRITTEN   February 2010
    2700              : 
    2701              :         // PURPOSE OF THIS SUBROUTINE:
    2702              :         // This subroutine sets all values of the schedule referenced by 'ScheduleIndex'
    2703              :         // to the value specified by 'Value'. The subroutine is used by the ExternalInterface to
    2704              :         // write real-time data into a schedule so that EnergyPlus modules can use
    2705              :         // real-time data by referencing a schedule. This allows overwriting setpoint
    2706              :         // for supervisory controls or internal gains obtained from real-time occupancy
    2707              :         // measurements.
    2708        73538 :         auto const &s_glob = state.dataGlobal;
    2709        73538 :         auto const &s_sched = state.dataSched;
    2710        73538 :         auto *daySched = s_sched->daySchedules[schedNum];
    2711              : 
    2712      1838450 :         for (int hr = 0; hr < Constant::iHoursInDay; ++hr) {
    2713      8824560 :             for (int ts = 0; ts < s_glob->TimeStepsInHour; ++ts) {
    2714      7059648 :                 daySched->tsVals[hr * s_glob->TimeStepsInHour + ts] = value;
    2715              :             }
    2716              :         }
    2717        73538 :     } // ExternalInterfaceSetSchedule()
    2718              : 
    2719        35150 :     void ProcessIntervalFields(EnergyPlusData &state,
    2720              :                                Array1S_string const Untils,
    2721              :                                Array1S<Real64> const Numbers,
    2722              :                                int const NumUntils,
    2723              :                                int const NumNumbers,
    2724              :                                std::array<Real64, Constant::iMinutesInDay> &minuteVals,
    2725              :                                std::array<bool, Constant::iMinutesInDay> &setMinuteVals,
    2726              :                                bool &ErrorsFound,
    2727              :                                std::string const &DayScheduleName, // Name (used for errors)
    2728              :                                std::string const &ErrContext,      // Context (used for errors)
    2729              :                                Interpolation interpolation         // enumeration on how to interpolate values in schedule
    2730              :     )
    2731              :     {
    2732              :         // SUBROUTINE INFORMATION:
    2733              :         //       AUTHOR         <author>
    2734              :         //       DATE WRITTEN   <date_written>
    2735              : 
    2736              :         // PURPOSE OF THIS SUBROUTINE:
    2737              :         // This subroutine processes the "interval" fields with/without optional "until" in front of
    2738              :         // time (hh:mm).
    2739              : 
    2740              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2741              :         int HHField;
    2742              :         int MMField;
    2743              : 
    2744        35150 :         int begHr = 0;   // starting hour
    2745        35150 :         int begMin = 0;  // starting minute
    2746        35150 :         int endHr = -1;  // ending hour
    2747        35150 :         int endMin = -1; // ending minute
    2748              :         std::string::size_type sFld;
    2749              : 
    2750              :         int totalMinutes;
    2751              :         Real64 incrementPerMinute;
    2752              :         Real64 curValue;
    2753              : 
    2754        35150 :         std::fill(minuteVals.begin(), minuteVals.end(), 0.0);
    2755        35150 :         std::fill(setMinuteVals.begin(), setMinuteVals.end(), false);
    2756              : 
    2757        35150 :         sFld = 0;
    2758              : 
    2759        35150 :         Real64 StartValue = 0;
    2760        35150 :         Real64 EndValue = 0;
    2761              : 
    2762        35150 :         if (NumUntils != NumNumbers) {
    2763            0 :             ShowSevereError(state,
    2764            0 :                             format("ProcessScheduleInput: ProcessIntervalFields, number of Time fields does not match number of value fields, {}={}",
    2765              :                                    ErrContext,
    2766              :                                    DayScheduleName));
    2767            0 :             ErrorsFound = true;
    2768            0 :             return;
    2769              :         }
    2770              : 
    2771       120169 :         for (int Count = 1; Count <= NumUntils; ++Count) {
    2772        85019 :             std::string const &until = Untils(Count);
    2773        85019 :             int Pos = index(until, "UNTIL");
    2774        85019 :             if (Pos == 0) {
    2775        80258 :                 if (until[5] == ':') {
    2776        80236 :                     sFld = 6;
    2777              :                 } else {
    2778           22 :                     sFld = 5;
    2779              :                 }
    2780        80258 :                 DecodeHHMMField(state, until.substr(sFld), HHField, MMField, ErrorsFound, DayScheduleName, until, interpolation);
    2781         4761 :             } else if (Pos == (int)std::string::npos) {
    2782         4761 :                 DecodeHHMMField(state, until, HHField, MMField, ErrorsFound, DayScheduleName, until, interpolation);
    2783              :             } else { // Until found but wasn't first field
    2784            0 :                 ShowSevereError(state, format("ProcessScheduleInput: ProcessIntervalFields, Invalid \"Until\" field encountered={}", until));
    2785            0 :                 ShowContinueError(state, format("Occurred in Day Schedule={}", DayScheduleName));
    2786            0 :                 ErrorsFound = true;
    2787            0 :                 continue;
    2788              :             }
    2789              :             // Field decoded
    2790        85019 :             if (HHField < 0 || HHField > Constant::iHoursInDay || MMField < 0 || MMField > Constant::iMinutesInHour) {
    2791            0 :                 ShowSevereError(state, format("ProcessScheduleInput: ProcessIntervalFields, Invalid \"Until\" field encountered={}", until));
    2792            0 :                 ShowContinueError(state, format("Occurred in Day Schedule={}", DayScheduleName));
    2793            0 :                 ErrorsFound = true;
    2794            0 :                 continue;
    2795              :             }
    2796        85019 :             if (HHField == Constant::iHoursInDay && MMField > 0 && MMField < Constant::iMinutesInHour) {
    2797            0 :                 ShowWarningError(state, format("ProcessScheduleInput: ProcessIntervalFields, Invalid \"Until\" field encountered={}", Untils(Count)));
    2798            0 :                 ShowContinueError(state, format("Occurred in Day Schedule={}", DayScheduleName));
    2799            0 :                 ShowContinueError(state, "Terminating the field at 24:00");
    2800            0 :                 MMField = 0;
    2801              :             }
    2802              : 
    2803              :             // Fill in values
    2804        85019 :             if (MMField == 0) {
    2805        84175 :                 endHr = HHField - 1;
    2806        84175 :                 endMin = Constant::iMinutesInHour - 1;
    2807          844 :             } else if (MMField < Constant::iMinutesInHour) {
    2808          844 :                 endHr = HHField;
    2809          844 :                 endMin = MMField - 1;
    2810              :             }
    2811              : 
    2812        85019 :             if (interpolation == Interpolation::Linear) {
    2813            0 :                 totalMinutes = (endHr - begHr) * Constant::iMinutesInHour + (endMin - begMin) + 1;
    2814            0 :                 if (totalMinutes == 0) {
    2815            0 :                     totalMinutes = 1; // protect future division
    2816              :                 }
    2817            0 :                 if (Count == 1) {
    2818            0 :                     StartValue = Numbers(Count); // assume first period is flat
    2819            0 :                     EndValue = Numbers(Count);
    2820              :                 } else {
    2821            0 :                     StartValue = EndValue;
    2822            0 :                     EndValue = Numbers(Count);
    2823              :                 }
    2824            0 :                 incrementPerMinute = (EndValue - StartValue) / totalMinutes;
    2825            0 :                 curValue = StartValue + incrementPerMinute;
    2826              :             }
    2827              : 
    2828        85019 :             if (begHr > endHr) {
    2829            8 :                 if (begHr == endHr + 1 && begMin == 0 && endMin == Constant::iMinutesInHour - 1) {
    2830           16 :                     ShowWarningError(state,
    2831           16 :                                      format("ProcessScheduleInput: ProcessIntervalFields, Processing time fields, zero time interval detected, {}={}",
    2832              :                                             ErrContext,
    2833              :                                             DayScheduleName));
    2834              :                 } else {
    2835            0 :                     ShowSevereError(state,
    2836            0 :                                     format("ProcessScheduleInput: ProcessIntervalFields, Processing time fields, overlapping times detected, {}={}",
    2837              :                                            ErrContext,
    2838              :                                            DayScheduleName));
    2839            0 :                     ErrorsFound = true;
    2840              :                 }
    2841              : 
    2842        85011 :             } else if (begHr == endHr) {
    2843      1545749 :                 for (int iMin = begMin; iMin <= endMin; ++iMin) {
    2844      1519888 :                     if (setMinuteVals[begHr * Constant::iMinutesInHour + iMin] == true) {
    2845            0 :                         ShowSevereError(
    2846              :                             state,
    2847            0 :                             format("ProcessScheduleInput: ProcessIntervalFields, Processing time fields, overlapping times detected, {}={}",
    2848              :                                    ErrContext,
    2849              :                                    DayScheduleName));
    2850            0 :                         ErrorsFound = true;
    2851            0 :                         goto UntilLoop_exit;
    2852              :                     }
    2853              :                 }
    2854              : 
    2855        25861 :                 if (interpolation == Interpolation::Linear) {
    2856            0 :                     for (int iMin = begMin; iMin <= endMin; ++iMin) {
    2857            0 :                         minuteVals[begHr * Constant::iMinutesInHour + iMin] = curValue;
    2858            0 :                         curValue += incrementPerMinute;
    2859            0 :                         setMinuteVals[begHr * Constant::iMinutesInHour + iMin] = true;
    2860              :                     }
    2861              :                 } else {
    2862      1545749 :                     for (int iMin = begMin; iMin <= endMin; ++iMin) {
    2863      1519888 :                         minuteVals[begHr * Constant::iMinutesInHour + iMin] = Numbers(Count);
    2864      1519888 :                         setMinuteVals[begHr * Constant::iMinutesInHour + iMin] = true;
    2865              :                     }
    2866              :                 }
    2867              : 
    2868        25861 :                 begMin = endMin + 1;
    2869        25861 :                 if (begMin >= Constant::iMinutesInHour) {
    2870        25169 :                     ++begHr;
    2871        25169 :                     begMin = 0;
    2872              :                 }
    2873              : 
    2874              :             } else { // begHr < endHr
    2875        59150 :                 if (interpolation == Interpolation::Linear) {
    2876            0 :                     for (int iMin = begMin; iMin <= Constant::iMinutesInHour - 1; ++iMin) { // for portion of starting hour
    2877            0 :                         minuteVals[begHr * Constant::iMinutesInHour + iMin] = curValue;
    2878            0 :                         curValue += incrementPerMinute;
    2879            0 :                         setMinuteVals[begHr * Constant::iMinutesInHour + iMin] = true;
    2880              :                     }
    2881              : 
    2882            0 :                     for (int iHr = begHr + 1; iHr <= endHr - 1; ++iHr) { // for intermediate hours
    2883            0 :                         for (int iMin = 0; iMin <= Constant::iMinutesInHour - 1; ++iMin) {
    2884            0 :                             minuteVals[iHr * Constant::iMinutesInHour + iMin] = curValue;
    2885            0 :                             curValue += incrementPerMinute;
    2886            0 :                             setMinuteVals[iHr * Constant::iMinutesInHour + iMin] = true;
    2887              :                         }
    2888              :                     }
    2889              : 
    2890            0 :                     for (int iMin = 0; iMin <= endMin; ++iMin) { // for ending hour
    2891            0 :                         minuteVals[endHr * Constant::iMinutesInHour + iMin] = curValue;
    2892            0 :                         curValue += incrementPerMinute;
    2893            0 :                         setMinuteVals[endHr * Constant::iMinutesInHour + iMin] = true;
    2894              :                     }
    2895              : 
    2896              :                 } else { // either no interpolation or "average" interpolation (average just is when the interval does not match the timestep)
    2897              :                          // Fill values for first hour (which may not start at minute 0)
    2898              :                          // For std::fill the end marker has to be 1 past the last position you want to fill
    2899      3653318 :                     for (int iMin = begMin; iMin <= Constant::iMinutesInHour; ++iMin) {
    2900      3594168 :                         minuteVals[begHr * Constant::iMinutesInHour + iMin] = Numbers(Count);
    2901      3594168 :                         setMinuteVals[begHr * Constant::iMinutesInHour + iMin] = true;
    2902              :                     }
    2903              : 
    2904              :                     // Fill values for middle hours (which start at minute 0 and end in minute 59)
    2905        59150 :                     if ((begHr + 1) <= (endHr - 1)) {
    2906       754563 :                         for (int iHr = begHr + 1; iHr <= endHr - 1; ++iHr) {
    2907     42717263 :                             for (int iMin = 0; iMin <= Constant::iMinutesInHour - 1; ++iMin) {
    2908     42016980 :                                 minuteVals[iHr * Constant::iMinutesInHour + iMin] = Numbers(Count);
    2909     42016980 :                                 setMinuteVals[iHr * Constant::iMinutesInHour + iMin] = true;
    2910              :                             }
    2911              :                         }
    2912              :                     }
    2913              : 
    2914              :                     // Fill values for last hour (which starts at minute 0 but may end on minute that isn't 59)
    2915      3603264 :                     for (int iMin = 0; iMin <= endMin; ++iMin) {
    2916      3544114 :                         minuteVals[endHr * Constant::iMinutesInHour + iMin] = Numbers(Count);
    2917      3544114 :                         setMinuteVals[endHr * Constant::iMinutesInHour + iMin] = true;
    2918              :                     }
    2919              :                 }
    2920              : 
    2921        59150 :                 begHr = endHr;
    2922        59150 :                 begMin = endMin + 1;
    2923        59150 :                 if (begMin >= Constant::iMinutesInHour) {
    2924        58998 :                     ++begHr;
    2925        58998 :                     begMin = 0;
    2926              :                 }
    2927              :             }
    2928              :         }
    2929        35150 :     UntilLoop_exit:;
    2930              : 
    2931     50651150 :         for (int iMin = 0; iMin < Constant::iMinutesInDay; ++iMin) {
    2932     50616000 :             if (setMinuteVals[iMin] == false) {
    2933            0 :                 ShowSevereError(state,
    2934            0 :                                 format("ProcessScheduleInput: ProcessIntervalFields, Processing time fields, incomplete day detected, {}={}",
    2935              :                                        ErrContext,
    2936              :                                        DayScheduleName));
    2937            0 :                 ErrorsFound = true;
    2938              :             }
    2939              :         }
    2940              :     }
    2941              : 
    2942        85019 :     void DecodeHHMMField(EnergyPlusData &state,
    2943              :                          std::string const &FieldValue,      // Input field value
    2944              :                          int &RetHH,                         // Returned "hour"
    2945              :                          int &RetMM,                         // Returned "minute"
    2946              :                          bool &ErrorsFound,                  // True if errors found in this field
    2947              :                          std::string const &DayScheduleName, // originating day schedule name
    2948              :                          std::string const &FullFieldValue,  // Full Input field value
    2949              :                          Interpolation interpolation         // enumeration on how to interpolate values in schedule
    2950              :     )
    2951              :     {
    2952              :         // SUBROUTINE INFORMATION:
    2953              :         //       AUTHOR         Linda K Lawrie
    2954              :         //       DATE WRITTEN   January 2003
    2955              : 
    2956              :         // PURPOSE OF THIS SUBROUTINE:
    2957              : 
    2958              :         // This subroutine decodes a hhmm date field input as part of the "until" time in a schedule
    2959              :         // representation.
    2960              : 
    2961              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2962              :         Real64 rRetHH; // real Returned "hour"
    2963        85019 :         std::string hHour;
    2964        85019 :         std::string mMinute;
    2965              : 
    2966        85019 :         std::string String = stripped(FieldValue);
    2967        85019 :         std::string::size_type const Pos = index(String, ':');
    2968        85019 :         bool nonIntegral = false;
    2969              : 
    2970        85019 :         auto const &s_glob = state.dataGlobal;
    2971        85019 :         if (Pos == std::string::npos) {
    2972            0 :             ShowSevereError(state,
    2973            0 :                             format("ProcessScheduleInput: DecodeHHMMField, Invalid \"until\" field submitted (no : separator in hh:mm)={}",
    2974            0 :                                    stripped(FullFieldValue)));
    2975            0 :             ShowContinueError(state, format("Occurred in Day Schedule={}", DayScheduleName));
    2976            0 :             ErrorsFound = true;
    2977            0 :             return;
    2978        85019 :         } else if (Pos == 0) {
    2979            0 :             RetHH = 0;
    2980              :         } else {
    2981        85019 :             bool error = false;
    2982        85019 :             Real64 rRetHH = Util::ProcessNumber(String.substr(0, Pos), error);
    2983        85019 :             RetHH = int(rRetHH);
    2984        85019 :             if (double(RetHH) != rRetHH || error || rRetHH < 0.0) {
    2985            0 :                 if (double(RetHH) != rRetHH && rRetHH >= 0.0) {
    2986            0 :                     ShowWarningError(state,
    2987            0 :                                      format("ProcessScheduleInput: DecodeHHMMField, Invalid \"until\" field submitted (non-integer numeric in HH)={}",
    2988            0 :                                             stripped(FullFieldValue)));
    2989            0 :                     ShowContinueError(state, format("Other errors may result. Occurred in Day Schedule={}", DayScheduleName));
    2990            0 :                     nonIntegral = true;
    2991              :                 } else {
    2992            0 :                     ShowSevereError(state,
    2993            0 :                                     format("ProcessScheduleInput: DecodeHHMMField, Invalid \"until\" field submitted (invalid numeric in HH)={}",
    2994            0 :                                            stripped(FullFieldValue)));
    2995            0 :                     ShowContinueError(
    2996            0 :                         state, format("Field values must be integer and represent hours:minutes. Occurred in Day Schedule={}", DayScheduleName));
    2997            0 :                     ErrorsFound = true;
    2998            0 :                     return;
    2999              :                 }
    3000              :             }
    3001              :         }
    3002              : 
    3003        85019 :         String.erase(0, Pos + 1);
    3004        85019 :         bool error = false;
    3005        85019 :         Real64 rRetMM = Util::ProcessNumber(String, error);
    3006        85019 :         RetMM = int(rRetMM);
    3007        85019 :         if (double(RetMM) != rRetMM || error || rRetMM < 0.0) {
    3008            0 :             if (double(RetMM) != rRetMM && rRetMM >= 0.0) {
    3009            0 :                 ShowWarningError(state,
    3010            0 :                                  format("ProcessScheduleInput: DecodeHHMMField, Invalid \"until\" field submitted (non-integer numeric in MM)={}",
    3011            0 :                                         stripped(FullFieldValue)));
    3012            0 :                 ShowContinueError(state, format("Other errors may result. Occurred in Day Schedule={}", DayScheduleName));
    3013            0 :                 nonIntegral = true;
    3014              :             } else {
    3015            0 :                 ShowSevereError(state,
    3016            0 :                                 format("ProcessScheduleInput: DecodeHHMMField, Invalid \"until\" field submitted (invalid numeric in MM)={}",
    3017            0 :                                        stripped(FullFieldValue)));
    3018            0 :                 ShowContinueError(state,
    3019            0 :                                   format("Field values must be integer and represent hours:minutes. Occurred in Day Schedule={}", DayScheduleName));
    3020            0 :                 ErrorsFound = true;
    3021            0 :                 return;
    3022              :             }
    3023              :         }
    3024              : 
    3025        85019 :         if (nonIntegral) {
    3026            0 :             std::string hHour; // these haven't been initialized?
    3027            0 :             std::string mMinute;
    3028            0 :             ShowContinueError(state, format("Until value to be used will be: {:2.2F}:{:2.2F}", hHour, mMinute));
    3029            0 :         }
    3030        85019 :         if (interpolation == Interpolation::No) {
    3031        83697 :             if (!isMinuteMultipleOfTimestep(RetMM, s_glob->MinutesInTimeStep)) {
    3032           82 :                 ShowWarningError(
    3033              :                     state,
    3034           82 :                     format(
    3035              :                         "ProcessScheduleInput: DecodeHHMMField, Invalid \"until\" field value is not a multiple of the minutes for each timestep: {}",
    3036           82 :                         stripped(FullFieldValue)));
    3037           41 :                 ShowContinueError(state, format("Other errors may result. Occurred in Day Schedule={}", DayScheduleName));
    3038              :             }
    3039              :         }
    3040        85019 :     }
    3041              : 
    3042        83697 :     bool isMinuteMultipleOfTimestep(int minute, int numMinutesPerTimestep)
    3043              :     {
    3044        83697 :         if (minute != 0) {
    3045          252 :             return (minute % numMinutesPerTimestep == 0);
    3046              :         } else {
    3047        83445 :             return true;
    3048              :         }
    3049              :     }
    3050              : 
    3051        34885 :     void ProcessForDayTypes(EnergyPlusData &state,
    3052              :                             std::string const &ForDayField,               // Field containing the "FOR:..."
    3053              :                             std::array<bool, (int)DayType::Num> &these,   // Array to contain returned "true" days
    3054              :                             std::array<bool, (int)DayType::Num> &already, // Array of days already done
    3055              :                             bool &ErrorsFound                             // Will be true if error found.
    3056              :     )
    3057              :     {
    3058              :         // SUBROUTINE INFORMATION:
    3059              :         //       AUTHOR         Linda K. Lawrie
    3060              :         //       DATE WRITTEN   February 2003
    3061              : 
    3062              :         // PURPOSE OF THIS SUBROUTINE:
    3063              :         // This subroutine processes a field "For: day types" and returns
    3064              :         // those day types (can be multiple) from field.
    3065              :         // Argument array dimensioning
    3066              : 
    3067              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    3068        34885 :         bool OneValid = false;
    3069        34885 :         bool DupAssignment = false;
    3070              : 
    3071              :         // Just test for specific days
    3072        34885 :         if (has(ForDayField, "WEEKDAY")) {
    3073         4894 :             these[iDayType_Mon] = these[iDayType_Tue] = these[iDayType_Wed] = these[iDayType_Thu] = these[iDayType_Fri] = true;
    3074         4894 :             if (already[iDayType_Mon] || already[iDayType_Tue] || already[iDayType_Wed] || already[iDayType_Thu] || already[iDayType_Fri]) {
    3075            0 :                 DupAssignment = true;
    3076              :             }
    3077         4894 :             already[iDayType_Mon] = already[iDayType_Tue] = already[iDayType_Wed] = already[iDayType_Thu] = already[iDayType_Fri] = true;
    3078         4894 :             OneValid = true;
    3079              :         }
    3080        34885 :         if (has(ForDayField, "MONDAY")) { // Should this be an else-if
    3081          106 :             these[iDayType_Mon] = true;
    3082          106 :             if (already[iDayType_Mon]) {
    3083            0 :                 DupAssignment = true;
    3084              :             } else {
    3085          106 :                 already[iDayType_Mon] = true;
    3086              :             }
    3087          106 :             OneValid = true;
    3088              :         }
    3089        34885 :         if (has(ForDayField, "TUESDAY")) {
    3090          144 :             these[iDayType_Tue] = true;
    3091          144 :             if (already[iDayType_Tue]) {
    3092            0 :                 DupAssignment = true;
    3093              :             } else {
    3094          144 :                 already[iDayType_Tue] = true;
    3095              :             }
    3096          144 :             OneValid = true;
    3097              :         }
    3098        34885 :         if (has(ForDayField, "WEDNESDAY")) {
    3099           88 :             these[iDayType_Wed] = true;
    3100           88 :             if (already[iDayType_Wed]) {
    3101            0 :                 DupAssignment = true;
    3102              :             } else {
    3103           88 :                 already[iDayType_Wed] = true;
    3104              :             }
    3105           88 :             OneValid = true;
    3106              :         }
    3107        34885 :         if (has(ForDayField, "THURSDAY")) {
    3108           88 :             these[iDayType_Thu] = true;
    3109           88 :             if (already[iDayType_Thu]) {
    3110            0 :                 DupAssignment = true;
    3111              :             } else {
    3112           88 :                 already[iDayType_Thu] = true;
    3113              :             }
    3114           88 :             OneValid = true;
    3115              :         }
    3116        34885 :         if (has(ForDayField, "FRIDAY")) {
    3117          126 :             these[iDayType_Fri] = true;
    3118          126 :             if (already[iDayType_Fri]) {
    3119            0 :                 DupAssignment = true;
    3120              :             } else {
    3121          126 :                 already[iDayType_Fri] = true;
    3122              :             }
    3123          126 :             OneValid = true;
    3124              :         }
    3125        34885 :         if (has(ForDayField, "WEEKEND")) {
    3126         2061 :             these[iDayType_Sun] = these[iDayType_Sat] = true;
    3127         2061 :             if (already[iDayType_Sun] || already[iDayType_Sat]) {
    3128            0 :                 DupAssignment = true;
    3129              :             }
    3130         2061 :             already[iDayType_Sun] = already[iDayType_Sat] = true;
    3131         2061 :             OneValid = true;
    3132              :         }
    3133              : 
    3134        34885 :         if (has(ForDayField, "SATURDAY")) {
    3135         1715 :             these[iDayType_Sat] = true;
    3136         1715 :             if (already[iDayType_Sat]) {
    3137            0 :                 DupAssignment = true;
    3138              :             } else {
    3139         1715 :                 already[iDayType_Sat] = true;
    3140              :             }
    3141         1715 :             OneValid = true;
    3142              :         }
    3143        34885 :         if (has(ForDayField, "SUNDAY")) {
    3144         1204 :             these[iDayType_Sun] = true;
    3145         1204 :             if (already[iDayType_Sun]) {
    3146            0 :                 DupAssignment = true;
    3147              :             } else {
    3148         1204 :                 already[iDayType_Sun] = true;
    3149              :             }
    3150         1204 :             OneValid = true;
    3151              :         }
    3152        34885 :         if (has(ForDayField, "CUSTOMDAY1")) {
    3153         1770 :             these[iDayType_Cus1] = true;
    3154         1770 :             if (already[iDayType_Cus1]) {
    3155            0 :                 DupAssignment = true;
    3156              :             } else {
    3157         1770 :                 already[iDayType_Cus1] = true;
    3158              :             }
    3159         1770 :             OneValid = true;
    3160              :         }
    3161        34885 :         if (has(ForDayField, "CUSTOMDAY2")) {
    3162         1752 :             these[iDayType_Cus2] = true;
    3163         1752 :             if (already[iDayType_Cus2]) {
    3164            0 :                 DupAssignment = true;
    3165              :             } else {
    3166         1752 :                 already[iDayType_Cus2] = true;
    3167              :             }
    3168         1752 :             OneValid = true;
    3169              :         }
    3170        34885 :         if (has(ForDayField, "ALLDAY")) {
    3171       247450 :             for (int iDay = 0; iDay < (int)DayType::Num; ++iDay) {
    3172       229775 :                 these[iDay] = true;
    3173       229775 :                 if (already[iDay]) {
    3174            0 :                     DupAssignment = true;
    3175              :                 } else {
    3176       229775 :                     already[iDay] = true;
    3177              :                 }
    3178              :             }
    3179        17675 :             OneValid = true;
    3180              :         }
    3181        34885 :         if (has(ForDayField, "HOLIDAY")) {
    3182         3232 :             these[iDayType_Hol] = true;
    3183         3232 :             if (already[iDayType_Hol]) {
    3184            0 :                 DupAssignment = true;
    3185              :             } else {
    3186         3232 :                 already[iDayType_Hol] = true;
    3187              :             }
    3188         3232 :             OneValid = true;
    3189              :         }
    3190        34885 :         if (has(ForDayField, "SUMMER")) {
    3191         4834 :             these[iDayType_SumDes] = true;
    3192         4834 :             if (already[iDayType_SumDes]) {
    3193            0 :                 DupAssignment = true;
    3194              :             } else {
    3195         4834 :                 already[iDayType_SumDes] = true;
    3196              :             }
    3197         4834 :             OneValid = true;
    3198              :         }
    3199        34885 :         if (has(ForDayField, "WINTER")) {
    3200         4546 :             these[iDayType_WinDes] = true;
    3201         4546 :             if (already[iDayType_WinDes]) {
    3202            0 :                 DupAssignment = true;
    3203              :             } else {
    3204         4546 :                 already[iDayType_WinDes] = true;
    3205              :             }
    3206         4546 :             OneValid = true;
    3207              :         }
    3208        34885 :         if (has(ForDayField, "ALLOTHERDAY")) {
    3209        53326 :             for (int iDay = 0; iDay < (int)DayType::Num; ++iDay) {
    3210        49517 :                 if (!already[iDay]) {
    3211        21562 :                     these[iDay] = already[iDay] = true;
    3212              :                 }
    3213              :             }
    3214         3809 :             OneValid = true;
    3215              :         }
    3216              : 
    3217        34885 :         if (DupAssignment) {
    3218            0 :             ShowSevereError(state, format("ProcessForDayTypes: Duplicate assignment attempted in \"for\" days field={}", ForDayField));
    3219            0 :             ErrorsFound = true;
    3220              :         }
    3221        34885 :         if (!OneValid) {
    3222            0 :             ShowSevereError(state, format("ProcessForDayTypes: No valid day assignments found in \"for\" days field={}", ForDayField));
    3223            0 :             ErrorsFound = true;
    3224              :         }
    3225        34885 :     } // ProcessScheduleInput()
    3226              : 
    3227        74023 :     void DaySchedule::setMinMaxVals([[maybe_unused]] EnergyPlusData &state)
    3228              :     {
    3229        74023 :         assert(!this->isMinMaxSet);
    3230              : 
    3231        74023 :         auto const &s_glob = state.dataGlobal;
    3232              : 
    3233        74023 :         this->minVal = this->maxVal = this->tsVals[0];
    3234      8603887 :         for (int i = 0; i < Constant::iHoursInDay * s_glob->TimeStepsInHour; ++i) {
    3235      8529864 :             Real64 value = this->tsVals[i];
    3236      8529864 :             if (value < this->minVal) {
    3237        11692 :                 this->minVal = value;
    3238      8518172 :             } else if (value > this->maxVal) {
    3239       257804 :                 this->maxVal = value;
    3240              :             }
    3241              :         }
    3242              : 
    3243        74023 :         this->isMinMaxSet = true;
    3244        74023 :     }
    3245              : 
    3246        62365 :     void WeekSchedule::setMinMaxVals(EnergyPlusData &state)
    3247              :     {
    3248        62365 :         assert(!this->isMinMaxSet);
    3249              : 
    3250        62365 :         auto *daySched1 = this->dayScheds[1];
    3251        62365 :         if (!daySched1->isMinMaxSet) {
    3252        62171 :             daySched1->setMinMaxVals(state);
    3253              :         }
    3254              : 
    3255        62365 :         this->minVal = daySched1->minVal;
    3256        62365 :         this->maxVal = daySched1->maxVal;
    3257              : 
    3258        62365 :         auto *daySchedPrev = daySched1;
    3259       748380 :         for (int iDay = 2; iDay < (int)DayType::Num; ++iDay) {
    3260       686015 :             auto *daySched = this->dayScheds[iDay];
    3261       686015 :             if (daySched == daySchedPrev) {
    3262       661041 :                 continue;
    3263              :             }
    3264              : 
    3265        24974 :             if (!daySched->isMinMaxSet) {
    3266        11838 :                 daySched->setMinMaxVals(state);
    3267              :             }
    3268        24974 :             if (daySched->minVal < this->minVal) {
    3269         1805 :                 this->minVal = daySched->minVal;
    3270              :             }
    3271        24974 :             if (daySched->maxVal > this->maxVal) {
    3272         4526 :                 this->maxVal = daySched->maxVal;
    3273              :             }
    3274        24974 :             daySchedPrev = daySched;
    3275              :         }
    3276              : 
    3277        62365 :         this->isMinMaxSet = true;
    3278        62365 :     } // ScheduleWeek::setMinMaxVals()
    3279              : 
    3280        16088 :     void ScheduleDetailed::setMinMaxVals(EnergyPlusData &state)
    3281              :     {
    3282        16088 :         assert(!this->isMinMaxSet);
    3283              : 
    3284        16088 :         auto *weekSched1 = this->weekScheds[1];
    3285        16088 :         if (!weekSched1->isMinMaxSet) {
    3286        16084 :             weekSched1->setMinMaxVals(state);
    3287              :         }
    3288              : 
    3289        16088 :         this->minVal = weekSched1->minVal;
    3290        16088 :         this->maxVal = weekSched1->maxVal;
    3291              : 
    3292        16088 :         auto *weekSchedPrev = weekSched1;
    3293              : 
    3294      5888208 :         for (int iWeek = 2; iWeek <= 366; ++iWeek) {
    3295      5872120 :             auto *weekSched = this->weekScheds[iWeek];
    3296      5872120 :             if (iWeek == 366 && weekSched == nullptr) {
    3297            0 :                 continue;
    3298              :             }
    3299      5872120 :             if (weekSched == weekSchedPrev) {
    3300      5825836 :                 continue;
    3301              :             }
    3302        46284 :             if (!weekSched->isMinMaxSet) {
    3303        46281 :                 weekSched->setMinMaxVals(state);
    3304              :             }
    3305              : 
    3306        46284 :             if (weekSched->minVal < this->minVal) {
    3307         1139 :                 this->minVal = weekSched->minVal;
    3308              :             }
    3309        46284 :             if (weekSched->maxVal > this->maxVal) {
    3310         2719 :                 this->maxVal = weekSched->maxVal;
    3311              :             }
    3312        46284 :             weekSchedPrev = weekSched;
    3313              :         }
    3314              : 
    3315        16088 :         this->isMinMaxSet = true;
    3316        16088 :     }
    3317              : 
    3318            0 :     bool CheckScheduleValueMin(EnergyPlusData &state,
    3319              :                                int const schedNum, // Which Schedule being tested
    3320              :                                Clusive clu,
    3321              :                                Real64 const min // Minimum desired value
    3322              :     )
    3323              :     {
    3324              :         // FUNCTION INFORMATION:
    3325              :         //       AUTHOR         Linda K. Lawrie
    3326              :         //       DATE WRITTEN   February 2003
    3327              : 
    3328              :         // PURPOSE OF THIS FUNCTION:
    3329              :         // This function checks the indicated schedule values for validity.
    3330              : 
    3331              :         // METHODOLOGY EMPLOYED:
    3332              :         // Schedule data structure stores this on first validity check.  If there, then is returned else
    3333              :         // looks up minimum and maximum values for the schedule and then sets result of function based on
    3334              :         // requested minimum/maximum checks.
    3335              : 
    3336            0 :         return state.dataSched->schedules[schedNum]->checkMinVal(state, clu, min);
    3337              :     }
    3338              : 
    3339        22815 :     bool ScheduleBase::checkMinVal(EnergyPlusData &state, Clusive clu, Real64 min)
    3340              :     {
    3341        22815 :         if (!this->isMinMaxSet) { // Set Minimum/Maximums for this schedule
    3342         1937 :             this->setMinMaxVals(state);
    3343              :         }
    3344              : 
    3345              :         //  Min/max for schedule has been set.  Test.
    3346        22815 :         return (clu == Clusive::In) ? (FLT_EPSILON >= min - this->minVal) : (this->minVal > min);
    3347              :     } // ScheduleDetailed::checkMinVal()
    3348              : 
    3349         2670 :     bool ScheduleBase::checkMaxVal(EnergyPlusData &state, Clusive cluMax, Real64 const max)
    3350              :     {
    3351         2670 :         if (!this->isMinMaxSet) {
    3352            0 :             this->setMinMaxVals(state);
    3353              :         }
    3354              : 
    3355         2670 :         return (cluMax == Clusive::Ex) ? (this->maxVal < max) : (this->maxVal - max <= FLT_EPSILON);
    3356              :     }
    3357              : 
    3358        28102 :     bool ScheduleBase::checkMinMaxVals(EnergyPlusData &state,
    3359              :                                        Clusive cluMin,   // Minimum indicator ('>', '>=')
    3360              :                                        Real64 const min, // Minimum desired value
    3361              :                                        Clusive cluMax,   // Maximum indicator ('<', ',=')
    3362              :                                        Real64 const max) // Maximum desired value
    3363              :     {
    3364              :         // FUNCTION INFORMATION:
    3365              :         //       AUTHOR         Linda K. Lawrie
    3366              :         //       DATE WRITTEN   February 2003
    3367              : 
    3368              :         // PURPOSE OF THIS FUNCTION:
    3369              :         // This function checks the indicated schedule values for validity.
    3370              : 
    3371              :         // METHODOLOGY EMPLOYED:
    3372              :         // Schedule data structure stores this on first validity check.  If there, then is returned else
    3373              :         // looks up minimum and maximum values for the schedule and then sets result of function based on
    3374              :         // requested minimum/maximum checks.
    3375              : 
    3376        28102 :         if (!this->isMinMaxSet) {
    3377        14172 :             this->setMinMaxVals(state);
    3378              :         }
    3379              : 
    3380        28102 :         bool minOk = (cluMin == Clusive::Ex) ? (this->minVal > min) : (FLT_EPSILON >= min - this->minVal);
    3381        28102 :         bool maxOk = (cluMax == Clusive::Ex) ? (this->maxVal < max) : (this->maxVal - max <= FLT_EPSILON);
    3382              : 
    3383        28102 :         return (minOk && maxOk);
    3384              :     } // ScheduleBase::checkMinMaxVals()
    3385              : 
    3386            0 :     bool CheckScheduleValueMinMax(EnergyPlusData &state,
    3387              :                                   int const schedNum, // Which Schedule being tested
    3388              :                                   Clusive cluMin,     // Minimum indicator ('>', '>=')
    3389              :                                   Real64 const min,   // Minimum desired value
    3390              :                                   Clusive cluMax,     // Maximum indicator ('<', ',=')
    3391              :                                   Real64 const max    // Maximum desired value
    3392              :     )
    3393              :     {
    3394              :         // Wrapper for method
    3395            0 :         return state.dataSched->schedules[schedNum]->checkMinMaxVals(state, cluMin, min, cluMax, max);
    3396              :     } // CheckScheduleValueMinMax()
    3397              : 
    3398           59 :     bool ScheduleConstant::hasVal([[maybe_unused]] EnergyPlusData &state, Real64 const value) const
    3399              :     {
    3400           59 :         return value == this->currentVal;
    3401              :     } // ScheduleConstant::hasVal()
    3402              : 
    3403        11758 :     bool ScheduleDetailed::hasVal(EnergyPlusData &state, Real64 const value) const
    3404              :     {
    3405        11758 :         auto const &s_sched = state.dataSched;
    3406        11758 :         auto const &s_glob = state.dataGlobal;
    3407              : 
    3408              :         // These arrays make sure you don't check the same day or week schedule twice
    3409        11758 :         std::vector<bool> weekSchedChecked;
    3410        11758 :         weekSchedChecked.resize(s_sched->weekSchedules.size());
    3411        11758 :         std::fill(weekSchedChecked.begin(), weekSchedChecked.end(), false);
    3412              : 
    3413        11758 :         std::vector<bool> daySchedChecked;
    3414        11758 :         daySchedChecked.resize(s_sched->daySchedules.size());
    3415        11758 :         std::fill(daySchedChecked.begin(), daySchedChecked.end(), false);
    3416              : 
    3417      4172080 :         for (int iWeek = 1; iWeek <= 366; ++iWeek) {
    3418      4160713 :             auto const *weekSched = this->weekScheds[iWeek];
    3419      4160713 :             if (weekSchedChecked[weekSched->Num]) {
    3420      4147041 :                 continue;
    3421              :             }
    3422              : 
    3423       173046 :             for (int iDay = 1; iDay < (int)DayType::Num; ++iDay) {
    3424       159765 :                 auto const *daySched = weekSched->dayScheds[iDay];
    3425       159765 :                 if (daySchedChecked[daySched->Num]) {
    3426       144403 :                     continue;
    3427              :                 }
    3428              : 
    3429      1928210 :                 for (int i = 0; i < Constant::iHoursInDay * s_glob->TimeStepsInHour; ++i) {
    3430      1913239 :                     if (daySched->tsVals[i] == value) {
    3431          391 :                         return true;
    3432              :                     }
    3433              :                 }
    3434        14971 :                 daySchedChecked[daySched->Num] = true;
    3435              :             }
    3436        13281 :             weekSchedChecked[weekSched->Num] = true;
    3437              :         }
    3438              : 
    3439        11367 :         return false;
    3440        11758 :     } // ScheduleDetailed::hasVal()
    3441              : 
    3442            0 :     bool CheckScheduleValue(EnergyPlusData &state,
    3443              :                             int const schedNum, // Which Schedule being tested
    3444              :                             Real64 const value  // Actual desired value
    3445              :     )
    3446              :     {
    3447              :         // Method wrapper
    3448            0 :         return state.dataSched->schedules[schedNum]->hasVal(state, value);
    3449              :     }
    3450              : 
    3451            0 :     bool CheckDayScheduleMinValues(EnergyPlusData &state,
    3452              :                                    int const schedNum, // Which Day Schedule being tested
    3453              :                                    Clusive cluMin,
    3454              :                                    Real64 const min)
    3455              :     {
    3456              :         // Method wrapper
    3457            0 :         return state.dataSched->daySchedules[schedNum]->checkMinVal(state, cluMin, min);
    3458              :     } // CheckDayScheduleMinValues()
    3459              : 
    3460            0 :     bool ScheduleConstant::hasFractionalVal([[maybe_unused]] EnergyPlusData &state) const
    3461              :     {
    3462            0 :         return (this->currentVal > 0.0) && (this->currentVal < 1.0);
    3463              :     } // ScheduleYear::hasFractionalVal()
    3464              : 
    3465          160 :     bool ScheduleDetailed::hasFractionalVal(EnergyPlusData &state) const
    3466              :     {
    3467          160 :         auto const &s_sched = state.dataSched;
    3468          160 :         auto const &s_glob = state.dataGlobal;
    3469              : 
    3470              :         // These arrays make sure you don't check the same day or week schedule twice
    3471          160 :         std::vector<bool> weekSchedChecked;
    3472          160 :         weekSchedChecked.resize(s_sched->weekSchedules.size());
    3473          160 :         std::fill(weekSchedChecked.begin(), weekSchedChecked.end(), false);
    3474              : 
    3475          160 :         std::vector<bool> daySchedChecked;
    3476          160 :         daySchedChecked.resize(s_sched->daySchedules.size());
    3477          160 :         std::fill(daySchedChecked.begin(), daySchedChecked.end(), false);
    3478              : 
    3479        58720 :         for (int iWeek = 1; iWeek <= 366; ++iWeek) {
    3480        58560 :             auto const *weekSched = this->weekScheds[iWeek];
    3481        58560 :             if (weekSchedChecked[weekSched->Num]) {
    3482        58350 :                 continue;
    3483              :             }
    3484              : 
    3485         2730 :             for (int iDay = 1; iDay < (int)DayType::Num; ++iDay) {
    3486         2520 :                 auto const *daySched = weekSched->dayScheds[iDay];
    3487         2520 :                 if (daySchedChecked[daySched->Num]) {
    3488         2188 :                     continue;
    3489              :                 }
    3490              : 
    3491        38060 :                 for (int i = 0; i < Constant::iHoursInDay * s_glob->TimeStepsInHour; ++i) {
    3492        37728 :                     if (daySched->tsVals[i] > 0.0 && daySched->tsVals[i] < 1.0) {
    3493            0 :                         return true;
    3494              :                     }
    3495              :                 }
    3496          332 :                 daySchedChecked[daySched->Num] = true;
    3497              :             }
    3498          210 :             weekSchedChecked[weekSched->Num] = true;
    3499              :         }
    3500              : 
    3501          160 :         return false;
    3502          160 :     } // ScheduleDetailed::hasFractionalVal()
    3503              : 
    3504          332 :     std::pair<Real64, Real64> ScheduleConstant::getMinMaxValsByDayType([[maybe_unused]] EnergyPlusData &state,
    3505              :                                                                        [[maybe_unused]] DayTypeGroup const days)
    3506              :     {
    3507          332 :         return std::make_pair(this->currentVal, this->currentVal);
    3508              :     } // ScheduleConstant::getMinMaxValsByDayType()
    3509              : 
    3510        53628 :     std::pair<Real64, Real64> ScheduleDetailed::getMinMaxValsByDayType(EnergyPlusData &state, DayTypeGroup const days)
    3511              :     {
    3512              :         // J. Glazer - March 2024
    3513              :         // finds the minimum and maximum for a specific set of day types for a given schedule
    3514        53628 :         constexpr std::array<std::array<bool, (int)DayType::Num>, (int)DayTypeGroup::Num> dayTypeFilters = {{
    3515              :             //  Unused    Sun    Mon    Tues   Wed    Thur   Fri    Sat    Hol    Summer Winter Cust1  Cust2
    3516              :             {false, false, true, true, true, true, true, false, false, false, false, false, false},     // Weekday
    3517              :             {false, true, false, false, false, false, false, true, true, false, false, false, false},   // WeekendHoliday
    3518              :             {false, false, false, false, false, false, false, false, false, true, false, false, false}, // SummerDesign
    3519              :             {false, false, false, false, false, false, false, false, false, false, true, false, false}  // WinterDesign
    3520              :         }};
    3521              : 
    3522        53628 :         auto const &s_sched = state.dataSched;
    3523              : 
    3524        53628 :         if (!this->isMinMaxSet) {
    3525            0 :             this->setMinMaxVals(state);
    3526              :         }
    3527              : 
    3528        53628 :         if (!this->MaxMinByDayTypeSet[(int)days]) {
    3529              : 
    3530         9568 :             bool firstSet = true;
    3531         9568 :             std::array<bool, (int)DayType::Num> const &dayTypeFilter = dayTypeFilters[(int)days];
    3532              : 
    3533              :             // These arrays make sure you don't check the same day or week schedule twice
    3534         9568 :             std::vector<bool> weekSchedChecked;
    3535         9568 :             weekSchedChecked.resize(s_sched->weekSchedules.size());
    3536         9568 :             std::fill(weekSchedChecked.begin(), weekSchedChecked.end(), false);
    3537              : 
    3538         9568 :             std::vector<bool> daySchedChecked;
    3539         9568 :             daySchedChecked.resize(s_sched->daySchedules.size());
    3540         9568 :             std::fill(daySchedChecked.begin(), daySchedChecked.end(), false);
    3541              : 
    3542         9568 :             this->MinByDayType[(int)days] = this->MaxByDayType[(int)days] = 0.0;
    3543              : 
    3544      3511456 :             for (int iDay = 1; iDay <= 366; ++iDay) {
    3545      3501888 :                 auto const *weekSched = this->weekScheds[iDay];
    3546      3501888 :                 if (weekSchedChecked[weekSched->Num]) {
    3547      3488104 :                     continue;
    3548              :                 }
    3549              : 
    3550       179192 :                 for (int jDayType = 1; jDayType < (int)DayType::Num; ++jDayType) {
    3551       165408 :                     if (!dayTypeFilter[jDayType]) {
    3552       130948 :                         continue;
    3553              :                     }
    3554              : 
    3555        34460 :                     auto *daySched = weekSched->dayScheds[jDayType];
    3556        34460 :                     if (daySchedChecked[daySched->Num]) {
    3557        20437 :                         continue;
    3558              :                     }
    3559              : 
    3560        14023 :                     if (!daySched->isMinMaxSet) {
    3561            0 :                         daySched->setMinMaxVals(state);
    3562              :                     }
    3563              : 
    3564        14023 :                     if (firstSet) {
    3565         9568 :                         this->MinByDayType[(int)days] = daySched->minVal;
    3566         9568 :                         this->MaxByDayType[(int)days] = daySched->maxVal;
    3567         9568 :                         firstSet = false;
    3568              :                     } else {
    3569         4455 :                         this->MinByDayType[(int)days] = min(this->MinByDayType[(int)days], daySched->minVal);
    3570         4455 :                         this->MaxByDayType[(int)days] = max(this->MaxByDayType[(int)days], daySched->maxVal);
    3571              :                     }
    3572              : 
    3573        14023 :                     daySchedChecked[daySched->Num] = true;
    3574              :                 }
    3575        13784 :                 weekSchedChecked[weekSched->Num] = true;
    3576              :             }
    3577         9568 :             this->MaxMinByDayTypeSet[(int)days] = true;
    3578         9568 :         }
    3579       107256 :         return std::make_pair(this->MinByDayType[(int)days], this->MaxByDayType[(int)days]);
    3580              :     } // ScheduleDetailed::getMinMaxValsByDayType()
    3581              : 
    3582      2828211 :     void ReportScheduleVals(EnergyPlusData &state)
    3583              :     {
    3584              :         // SUBROUTINE INFORMATION:
    3585              :         //       AUTHOR         Linda Lawrie
    3586              :         //       DATE WRITTEN   February 2004
    3587              : 
    3588              :         // PURPOSE OF THIS SUBROUTINE:
    3589              :         // This subroutine puts the proper current schedule values into the "reporting"
    3590              :         // slot for later reporting.
    3591      2828211 :         auto const &s_sched = state.dataSched;
    3592              : 
    3593      2828211 :         if (s_sched->DoScheduleReportingSetup) { // CurrentModuleObject='Any Schedule'
    3594        19665 :             for (auto *sched : s_sched->schedules) {
    3595              :                 // No variables for the built-in AlwaysOn and AlwaysOff schedules
    3596        18864 :                 if (sched->Num == SchedNum_AlwaysOff || sched->Num == SchedNum_AlwaysOn) {
    3597         1602 :                     continue;
    3598              :                 }
    3599              : 
    3600              :                 // Set Up Reporting
    3601        34524 :                 SetupOutputVariable(state,
    3602              :                                     "Schedule Value",
    3603              :                                     Constant::Units::None,
    3604        17262 :                                     sched->currentVal,
    3605              :                                     OutputProcessor::TimeStepType::Zone,
    3606              :                                     OutputProcessor::StoreType::Average,
    3607        17262 :                                     sched->Name);
    3608          801 :             }
    3609          801 :             s_sched->DoScheduleReportingSetup = false;
    3610              :         }
    3611              : 
    3612      2828211 :         UpdateScheduleVals(state);
    3613      2828211 :     }
    3614              : 
    3615          799 :     void ReportOrphanSchedules(EnergyPlusData &state)
    3616              :     {
    3617              :         // SUBROUTINE INFORMATION:
    3618              :         //       AUTHOR         Linda Lawrie
    3619              :         //       DATE WRITTEN   April 2008
    3620              : 
    3621              :         // PURPOSE OF THIS SUBROUTINE:
    3622              :         // In response to CR7498, report orphan (unused) schedule items.
    3623              : 
    3624          799 :         bool NeedOrphanMessage = true;
    3625          799 :         bool NeedUseMessage = false;
    3626          799 :         int NumCount = 0;
    3627              : 
    3628          799 :         auto const &s_sched = state.dataSched;
    3629          799 :         auto const &s_glob = state.dataGlobal;
    3630              : 
    3631        19583 :         for (auto const *sched : s_sched->schedules) {
    3632        18784 :             if (sched->isUsed) {
    3633        17960 :                 continue;
    3634              :             }
    3635          824 :             if (NeedOrphanMessage && s_glob->DisplayUnusedSchedules) {
    3636            2 :                 ShowWarningError(state, "The following schedule names are \"Unused Schedules\".  These schedules are in the idf");
    3637            2 :                 ShowContinueError(state, " file but are never obtained by the simulation and therefore are NOT used.");
    3638            1 :                 NeedOrphanMessage = false;
    3639              :             }
    3640          824 :             if (s_glob->DisplayUnusedSchedules) {
    3641            1 :                 ShowMessage(state, format("Schedule:Year or Schedule:Compact or Schedule:File or Schedule:Constant={}", sched->Name));
    3642              :             } else {
    3643          823 :                 ++NumCount;
    3644              :             }
    3645          799 :         }
    3646              : 
    3647          799 :         if (NumCount > 0) {
    3648          102 :             ShowMessage(state, format("There are {} unused schedules in input.", NumCount));
    3649          102 :             NeedUseMessage = true;
    3650              :         }
    3651              : 
    3652          799 :         NeedOrphanMessage = true;
    3653          799 :         NumCount = 0;
    3654              : 
    3655       114025 :         for (auto *weekSched : s_sched->weekSchedules) {
    3656       113226 :             if (weekSched->isUsed) {
    3657        71981 :                 continue;
    3658              :             }
    3659        41245 :             if (weekSched->Name.empty()) {
    3660            0 :                 continue;
    3661              :             }
    3662        41245 :             if (NeedOrphanMessage && s_glob->DisplayUnusedSchedules) {
    3663            0 :                 ShowWarningError(state, "The following week schedule names are \"Unused Schedules\".  These schedules are in the idf");
    3664            0 :                 ShowContinueError(state, " file but are never obtained by the simulation and therefore are NOT used.");
    3665            0 :                 NeedOrphanMessage = false;
    3666              :             }
    3667        41245 :             if (s_glob->DisplayUnusedSchedules) {
    3668            0 :                 ShowMessage(state, format("Schedule:Week:Daily or Schedule:Week:Compact={}", weekSched->Name));
    3669              :             } else {
    3670        41245 :                 ++NumCount;
    3671              :             }
    3672          799 :         }
    3673              : 
    3674          799 :         if (NumCount > 0) {
    3675            2 :             ShowMessage(state, fmt::format("There are {} unused week schedules in input.", NumCount));
    3676            1 :             NeedUseMessage = true;
    3677              :         }
    3678              : 
    3679          799 :         NeedOrphanMessage = true;
    3680          799 :         NumCount = 0;
    3681              : 
    3682       125762 :         for (auto *daySched : s_sched->daySchedules) {
    3683       124963 :             if (daySched->isUsed) {
    3684        83708 :                 continue;
    3685              :             }
    3686        41255 :             if (daySched->Name.empty()) {
    3687            0 :                 continue;
    3688              :             }
    3689        41255 :             if (NeedOrphanMessage && s_glob->DisplayUnusedSchedules) {
    3690            0 :                 ShowWarningError(state, "The following day schedule names are \"Unused Schedules\".  These schedules are in the idf");
    3691            0 :                 ShowContinueError(state, " file but are never obtained by the simulation and therefore are NOT used.");
    3692            0 :                 NeedOrphanMessage = false;
    3693              :             }
    3694              : 
    3695        41255 :             if (s_glob->DisplayUnusedSchedules) {
    3696            0 :                 ShowMessage(state, format("Schedule:Day:Hourly or Schedule:Day:Interval or Schedule:Day:List={}", daySched->Name));
    3697              :             } else {
    3698        41255 :                 ++NumCount;
    3699              :             }
    3700          799 :         }
    3701              : 
    3702          799 :         if (NumCount > 0) {
    3703            6 :             ShowMessage(state, format("There are {} unused day schedules in input.", NumCount));
    3704            6 :             NeedUseMessage = true;
    3705              :         }
    3706              : 
    3707          799 :         if (NeedUseMessage) {
    3708          309 :             ShowMessage(state, "Use Output:Diagnostics,DisplayUnusedSchedules; to see them.");
    3709              :         }
    3710          799 :     } // ReportOrphanSchedules()
    3711              : 
    3712              :     // returns the annual full load hours for a schedule - essentially the sum of the hourly values
    3713           44 :     Real64 ScheduleConstant::getAnnualHoursFullLoad([[maybe_unused]] EnergyPlusData &state,
    3714              :                                                     int const StartDayOfWeek, // Day of week for start of year
    3715              :                                                     bool const isLeapYear     // true if it is a leap year containing February 29
    3716              :     )
    3717              :     {
    3718           44 :         if (StartDayOfWeek < iDayType_Sun || StartDayOfWeek > iDayType_Sat) {
    3719            0 :             return 0.0; // Assert this instead?
    3720              :         }
    3721              : 
    3722           44 :         int DaysInYear = (isLeapYear) ? 366 : 365;
    3723           44 :         return DaysInYear * Constant::iHoursInDay * this->currentVal;
    3724              :     }
    3725              : 
    3726              :     // returns the annual full load hours for a schedule - essentially the sum of the hourly values
    3727        11363 :     Real64 ScheduleDetailed::getAnnualHoursFullLoad(EnergyPlusData &state,
    3728              :                                                     int const StartDayOfWeek, // Day of week for start of year
    3729              :                                                     bool const isLeapYear     // true if it is a leap year containing February 29
    3730              :     )
    3731              :     {
    3732              :         // J. Glazer - July 2017
    3733              :         // adapted from Linda K. Lawrie original code for ScheduleAverageHoursPerWeek()
    3734        11363 :         auto const &s_glob = state.dataGlobal;
    3735              : 
    3736        11363 :         int DaysInYear = (isLeapYear) ? 366 : 365;
    3737              : 
    3738        11363 :         int DayT = StartDayOfWeek;
    3739        11363 :         Real64 TotalHours = 0.0;
    3740              : 
    3741        11363 :         if (DayT < iDayType_Sun || DayT > iDayType_Sat) {
    3742            0 :             return TotalHours;
    3743              :         }
    3744              : 
    3745      4158874 :         for (int iDay = 1; iDay <= DaysInYear; ++iDay) {
    3746      4147511 :             auto const *weekSched = this->weekScheds[iDay];
    3747      4147511 :             auto const *daySched = weekSched->dayScheds[DayT];
    3748              : 
    3749      4147511 :             TotalHours += daySched->sumTsVals / double(s_glob->TimeStepsInHour);
    3750      4147511 :             ++DayT;
    3751      4147511 :             if (DayT > iDayType_Sat) {
    3752       590892 :                 DayT = iDayType_Sun;
    3753              :             }
    3754              :         }
    3755              : 
    3756        11363 :         return TotalHours;
    3757              :     }
    3758              : 
    3759              :     // returns the average number of hours per week based on the schedule index provided
    3760         4482 :     Real64 Schedule::getAverageWeeklyHoursFullLoad(EnergyPlusData &state,
    3761              :                                                    int const StartDayOfWeek, // Day of week for start of year
    3762              :                                                    bool const isLeapYear     // true if it is a leap year containing February 29
    3763              :     )
    3764              :     {
    3765              :         // FUNCTION INFORMATION:
    3766              :         //       AUTHOR         Linda K. Lawrie
    3767              :         //       DATE WRITTEN   August 2006
    3768              :         //       MODIFIED       September 2012; Glazer - CR8849
    3769              : 
    3770              :         // PURPOSE OF THIS FUNCTION:
    3771              :         // This function returns the "average" hours per week for a schedule over
    3772              :         // the entire year.
    3773              : 
    3774         4482 :         Real64 WeeksInYear = (isLeapYear) ? (366.0 / 7.0) : (365.0 / 7.0);
    3775         4482 :         return this->getAnnualHoursFullLoad(state, StartDayOfWeek, isLeapYear) / WeeksInYear;
    3776              :     }
    3777              : 
    3778              :     // returns the annual hours greater than 1% for a schedule - essentially the number of hours with any operation
    3779         6884 :     Real64 ScheduleDetailed::getAnnualHoursGreaterThan1Percent(EnergyPlusData &state,
    3780              :                                                                int const StartDayOfWeek, // Day of week for start of year
    3781              :                                                                bool const isItLeapYear   // true if it is a leap year containing February 29
    3782              :     )
    3783              :     {
    3784              :         // J. Glazer - July 2017
    3785              :         // adapted from Linda K. Lawrie original code for ScheduleAverageHoursPerWeek()
    3786         6884 :         auto const &s_glob = state.dataGlobal;
    3787              : 
    3788         6884 :         int DaysInYear = (isItLeapYear) ? 366 : 365;
    3789              : 
    3790         6884 :         int DayT = StartDayOfWeek;
    3791         6884 :         Real64 TotalHours = 0.0;
    3792              : 
    3793         6884 :         if (DayT < iDayType_Sun || DayT > iDayType_Sat) {
    3794            0 :             return TotalHours;
    3795              :         }
    3796              : 
    3797      2519555 :         for (int iDay = 1; iDay <= DaysInYear; ++iDay) {
    3798      2512671 :             auto const *weekSched = this->weekScheds[iDay];
    3799      2512671 :             auto const *daySched = weekSched->dayScheds[DayT];
    3800    307475607 :             for (int i = 0; i < Constant::iHoursInDay * s_glob->TimeStepsInHour; ++i) {
    3801    304962936 :                 if (daySched->tsVals[i] > 0.0) {
    3802    224264355 :                     TotalHours += s_glob->TimeStepZone;
    3803              :                 }
    3804              :             }
    3805              : 
    3806      2512671 :             ++DayT;
    3807      2512671 :             if (DayT > iDayType_Sat) {
    3808       357979 :                 DayT = iDayType_Sun;
    3809              :             }
    3810              :         }
    3811              : 
    3812         6884 :         return TotalHours;
    3813              :     } // ScheduleDetailed::getAnnualHoursGreaterThan1Percent()
    3814              : 
    3815              :     // returns the annual hours greater than 1% for a schedule - essentially the number of hours with any operation
    3816           41 :     Real64 ScheduleConstant::getAnnualHoursGreaterThan1Percent([[maybe_unused]] EnergyPlusData &state,
    3817              :                                                                int const StartDayOfWeek, // Day of week for start of year
    3818              :                                                                bool const isItLeapYear   // true if it is a leap year containing February 29
    3819              :     )
    3820              :     {
    3821           41 :         int DaysInYear = (isItLeapYear) ? 366 : 365;
    3822              : 
    3823           41 :         if (StartDayOfWeek < iDayType_Sun || StartDayOfWeek > iDayType_Sat) {
    3824            0 :             return 0.0; // Assert this instead?
    3825              :         }
    3826              : 
    3827           41 :         return (this->currentVal > 0.0) ? (Constant::rHoursInDay * DaysInYear) : 0;
    3828              :     } // ScheduleConstant::getHoursGreaterThan1Percent()
    3829              : 
    3830              :     // returns the temperature value from a schedule at a certain time for the first day of the week in either January or July
    3831              :     std::tuple<Real64, int, std::string>
    3832         3736 :     ScheduleDetailed::getValAndCountOnDay(EnergyPlusData &state, bool const isSummer, DayType const dayOfWeek, int const hourOfDay)
    3833              :     {
    3834              :         // J.Glazer - Aug 2017
    3835              : 
    3836         3736 :         auto const &s_glob = state.dataGlobal;
    3837              : 
    3838              :         // determine month to use based on hemiphere and season
    3839              :         int month;
    3840         3736 :         if (isSummer) {
    3841         1850 :             month = (state.dataEnvrn->Latitude > 0.) ? 7 : 1;
    3842              :         } else {
    3843         1886 :             month = (state.dataEnvrn->Latitude > 0.) ? 1 : 7;
    3844              :         }
    3845              : 
    3846         3736 :         std::string monthName = (month == 1) ? "January" : "July";
    3847              : 
    3848         3736 :         int jdateSelect = General::nthDayOfWeekOfMonth(state, (int)dayOfWeek, 1, month);
    3849              : 
    3850              :         // determine number of days in year
    3851         3736 :         int DaysInYear = (state.dataEnvrn->CurrentYearIsLeapYear) ? 366 : 365;
    3852              : 
    3853              :         // should adjust date if lands on a holiday but for now assume that it does not
    3854              : 
    3855              :         // adjust time of day for daylight savings time
    3856         3736 :         int hourSelect = hourOfDay + state.dataWeather->DSTIndex(jdateSelect);
    3857              : 
    3858              :         // get the value at the selected time
    3859         3736 :         int constexpr firstTimeStep = 1;
    3860         3736 :         auto const *weekSched = this->weekScheds[jdateSelect];
    3861         3736 :         auto const *daySched = weekSched->dayScheds[(int)dayOfWeek];
    3862              : 
    3863         3736 :         Real64 value = daySched->tsVals[(hourSelect - 1) * state.dataGlobal->TimeStepsInHour + (firstTimeStep - 1)];
    3864         3736 :         int countOfSame = 0;
    3865              : 
    3866              :         // count the number of times with that same value
    3867      1367384 :         for (int jdateOfYear = 1; jdateOfYear <= DaysInYear; ++jdateOfYear) {
    3868      1363648 :             auto const *wSched = this->weekScheds[jdateOfYear];
    3869      1363648 :             if (wSched == weekSched) { // if same week schedule can short circuit rest of testing and increment counter
    3870      1350820 :                 ++countOfSame;
    3871      1350820 :                 continue;
    3872              :             }
    3873              : 
    3874        12828 :             auto const *dSched = wSched->dayScheds[(int)dayOfWeek];
    3875        12828 :             if (dSched == daySched) { // if same day schedule can short circuit rest of testing and increment counter
    3876           12 :                 ++countOfSame;
    3877           12 :                 continue;
    3878              :             }
    3879              : 
    3880        12816 :             if (dSched->tsVals[(hourSelect - 1) * s_glob->TimeStepsInHour + (firstTimeStep - 1)] == value) {
    3881         6250 :                 ++countOfSame;
    3882              :             }
    3883              :         }
    3884              : 
    3885         7472 :         return std::make_tuple(value, countOfSame, monthName);
    3886         3736 :     } // ScheduleDetailed::getValAndCountOnDay()
    3887              : 
    3888              :     // returns the temperature value from a schedule at a certain time for the first day of the week in either January or July
    3889           18 :     std::tuple<Real64, int, std::string> ScheduleConstant::getValAndCountOnDay(EnergyPlusData &state,
    3890              :                                                                                bool const isSummer,
    3891              :                                                                                [[maybe_unused]] DayType const dayOfWeek,
    3892              :                                                                                [[maybe_unused]] int const hourOfDay)
    3893              :     {
    3894              :         // determine month to use based on hemiphere and season
    3895              :         int month;
    3896           18 :         if (isSummer) {
    3897           10 :             month = (state.dataEnvrn->Latitude > 0.) ? 7 : 1;
    3898              :         } else {
    3899            8 :             month = (state.dataEnvrn->Latitude > 0.) ? 1 : 7;
    3900              :         }
    3901              : 
    3902           18 :         std::string monthName = (month == 1) ? "January" : "July";
    3903           18 :         int DaysInYear = (state.dataEnvrn->CurrentYearIsLeapYear) ? 366 : 365;
    3904           36 :         return std::make_tuple(this->currentVal, DaysInYear, monthName);
    3905           18 :     } // ScheduleConstant::getValAndCountOnDay()
    3906              : 
    3907            0 :     void ShowSevereBadMin(EnergyPlusData &state,
    3908              :                           ErrorObjectHeader const &eoh,
    3909              :                           std::string_view fieldName,
    3910              :                           std::string_view fieldVal,
    3911              :                           Clusive cluMin,
    3912              :                           Real64 minVal,
    3913              :                           std::string_view msg)
    3914              :     {
    3915            0 :         ShowSevereError(state, format("{}: {} = {}", eoh.routineName, eoh.objectType, eoh.objectName));
    3916            0 :         ShowContinueError(
    3917            0 :             state, format("{} = {}, schedule contains values that are {} {}", fieldName, fieldVal, cluMin == Clusive::In ? "<" : "<=", minVal));
    3918            0 :         if (!msg.empty()) {
    3919            0 :             ShowContinueError(state, format("{}", msg));
    3920              :         }
    3921            0 :     }
    3922              : 
    3923            0 :     void ShowSevereBadMax(EnergyPlusData &state,
    3924              :                           ErrorObjectHeader const &eoh,
    3925              :                           std::string_view fieldName,
    3926              :                           std::string_view fieldVal,
    3927              :                           Clusive cluMax,
    3928              :                           Real64 maxVal,
    3929              :                           std::string_view msg)
    3930              :     {
    3931            0 :         ShowSevereError(state, format("{}: {} = {}", eoh.routineName, eoh.objectType, eoh.objectName));
    3932            0 :         ShowContinueError(
    3933            0 :             state, format("{} = {}, schedule contains values that are {} {}", fieldName, fieldVal, cluMax == Clusive::In ? ">" : ">=", maxVal));
    3934            0 :         if (!msg.empty()) {
    3935            0 :             ShowContinueError(state, format("{}", msg));
    3936              :         }
    3937            0 :     }
    3938              : 
    3939            0 :     void ShowSevereBadMinMax(EnergyPlusData &state,
    3940              :                              ErrorObjectHeader const &eoh,
    3941              :                              std::string_view fieldName,
    3942              :                              std::string_view fieldVal,
    3943              :                              Clusive cluMin,
    3944              :                              Real64 minVal,
    3945              :                              Clusive cluMax,
    3946              :                              Real64 maxVal,
    3947              :                              std::string_view msg)
    3948              :     {
    3949            0 :         ShowSevereError(state, format("{}: {} = {}", eoh.routineName, eoh.objectType, eoh.objectName));
    3950            0 :         ShowContinueError(state,
    3951            0 :                           format("{} = {}, schedule contains values that are {} {} and/or {} {}",
    3952              :                                  fieldName,
    3953              :                                  fieldVal,
    3954            0 :                                  cluMin == Clusive::In ? "<" : "<=",
    3955              :                                  minVal,
    3956            0 :                                  cluMax == Clusive::In ? ">" : ">=",
    3957              :                                  maxVal));
    3958            0 :         if (!msg.empty()) {
    3959            0 :             ShowContinueError(state, format("{}", msg));
    3960              :         }
    3961            0 :     }
    3962              : 
    3963            0 :     void ShowWarningBadMin(EnergyPlusData &state,
    3964              :                            ErrorObjectHeader const &eoh,
    3965              :                            std::string_view fieldName,
    3966              :                            std::string_view fieldVal,
    3967              :                            Clusive cluMin,
    3968              :                            Real64 minVal,
    3969              :                            std::string_view msg)
    3970              :     {
    3971            0 :         ShowWarningError(state, format("{}: {} = {}", eoh.routineName, eoh.objectType, eoh.objectName));
    3972            0 :         ShowContinueError(
    3973            0 :             state, format("{} = {}, schedule contains values that are {} {}", fieldName, fieldVal, cluMin == Clusive::In ? "<" : "<=", minVal));
    3974            0 :         if (!msg.empty()) {
    3975            0 :             ShowContinueError(state, format("{}", msg));
    3976              :         }
    3977            0 :     }
    3978              : 
    3979            0 :     void ShowWarningBadMax(EnergyPlusData &state,
    3980              :                            ErrorObjectHeader const &eoh,
    3981              :                            std::string_view fieldName,
    3982              :                            std::string_view fieldVal,
    3983              :                            Clusive cluMax,
    3984              :                            Real64 maxVal,
    3985              :                            std::string_view msg)
    3986              :     {
    3987            0 :         ShowWarningError(state, format("{}: {} = {}", eoh.routineName, eoh.objectType, eoh.objectName));
    3988            0 :         ShowContinueError(
    3989            0 :             state, format("{} = {}, schedule contains values that are {} {}", fieldName, fieldVal, cluMax == Clusive::In ? ">" : ">=", maxVal));
    3990            0 :         if (!msg.empty()) {
    3991            0 :             ShowContinueError(state, format("{}", msg));
    3992              :         }
    3993            0 :     }
    3994              : 
    3995            0 :     void ShowWarningBadMinMax(EnergyPlusData &state,
    3996              :                               ErrorObjectHeader const &eoh,
    3997              :                               std::string_view fieldName,
    3998              :                               std::string_view fieldVal,
    3999              :                               Clusive cluMin,
    4000              :                               Real64 minVal,
    4001              :                               Clusive cluMax,
    4002              :                               Real64 maxVal,
    4003              :                               std::string_view msg)
    4004              :     {
    4005            0 :         ShowWarningError(state, format("{}: {} = {}", eoh.routineName, eoh.objectType, eoh.objectName));
    4006            0 :         ShowContinueError(state,
    4007            0 :                           format("{} = {}, schedule contains values that are {} {} and/or {} {}",
    4008              :                                  fieldName,
    4009              :                                  fieldVal,
    4010            0 :                                  cluMin == Clusive::In ? "<" : "<=",
    4011              :                                  minVal,
    4012            0 :                                  cluMax == Clusive::In ? ">" : ">=",
    4013              :                                  maxVal));
    4014            0 :         if (!msg.empty()) {
    4015            0 :             ShowContinueError(state, format("{}", msg));
    4016              :         }
    4017            0 :     }
    4018              : 
    4019              : } // namespace Sched
    4020              : 
    4021              : } // namespace EnergyPlus
        

Generated by: LCOV version 2.0-1