LCOV - code coverage report
Current view: top level - EnergyPlus - General.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 79.0 % 639 505
Test Date: 2025-06-02 07:23:51 Functions: 91.3 % 23 21

            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 <cassert>
      50              : #include <cmath>
      51              : #include <cstdlib>
      52              : 
      53              : // ObjexxFCL Headers
      54              : #include <ObjexxFCL/Fmath.hh>
      55              : #include <ObjexxFCL/string.functions.hh>
      56              : 
      57              : // EnergyPlus Headers
      58              : #include <EnergyPlus/Data/EnergyPlusData.hh>
      59              : #include <EnergyPlus/DataEnvironment.hh>
      60              : #include <EnergyPlus/DataHVACGlobals.hh>
      61              : #include <EnergyPlus/DataIPShortCuts.hh>
      62              : #include <EnergyPlus/DataRuntimeLanguage.hh>
      63              : #include <EnergyPlus/DataSurfaces.hh>
      64              : #include <EnergyPlus/General.hh>
      65              : #include <EnergyPlus/HVACSystemRootFindingAlgorithm.hh>
      66              : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      67              : #include <EnergyPlus/UtilityRoutines.hh>
      68              : #include <EnergyPlus/WeatherManager.hh>
      69              : 
      70              : #if defined(_WIN32) && _MSC_VER < 1900
      71              : #    define snprintf _snprintf
      72              : #endif
      73              : 
      74              : namespace EnergyPlus::General {
      75              : 
      76              : // Module containing routines for general use
      77              : 
      78              : // MODULE INFORMATION:
      79              : //       AUTHOR         Fred Buhl, Linda Lawrie
      80              : //       DATE WRITTEN   December 2001
      81              : 
      82              : // PURPOSE OF THIS MODULE:
      83              : // contains routines (most likely numeric) that may be needed in several parts
      84              : // of EnergyPlus
      85              : 
      86              : // MODULE PARAMETER DEFINITIONS
      87              : static constexpr std::string_view BlankString;
      88              : 
      89              : enum class ReportType
      90              : {
      91              :     Invalid = -1,
      92              :     DXF,
      93              :     DXFWireFrame,
      94              :     VRML,
      95              :     Num
      96              : };
      97              : 
      98              : constexpr std::array<std::string_view, static_cast<int>(ReportType::Num)> ReportTypeNamesUC{"DXF", "DXF:WIREFRAME", "VRML"};
      99              : 
     100              : enum class AvailRpt
     101              : {
     102              :     Invalid = -1,
     103              :     None,
     104              :     NotByUniqueKeyNames,
     105              :     Verbose,
     106              :     Num
     107              : };
     108              : 
     109              : constexpr std::array<std::string_view, static_cast<int>(AvailRpt::Num)> AvailRptNamesUC{"NONE", "NOTBYUNIQUEKEYNAMES", "VERBOSE"};
     110              : 
     111              : enum class ERLdebugOutputLevel
     112              : {
     113              :     Invalid = -1,
     114              :     None,
     115              :     ErrorsOnly,
     116              :     Verbose,
     117              :     Num
     118              : };
     119              : 
     120              : constexpr std::array<std::string_view, static_cast<int>(ERLdebugOutputLevel::Num)> ERLdebugOutputLevelNamesUC{"NONE", "ERRORSONLY", "VERBOSE"};
     121              : 
     122              : enum class ReportName
     123              : {
     124              :     Invalid = -1,
     125              :     Constructions,
     126              :     Viewfactorinfo,
     127              :     Variabledictionary,
     128              :     Surfaces,
     129              :     Energymanagementsystem,
     130              :     Num
     131              : };
     132              : 
     133              : constexpr std::array<std::string_view, static_cast<int>(ReportName::Num)> ReportNamesUC{
     134              :     "CONSTRUCTIONS", "VIEWFACTORINFO", "VARIABLEDICTIONARY", "SURFACES", "ENERGYMANAGEMENTSYSTEM"};
     135              : 
     136              : enum class RptKey
     137              : {
     138              :     Invalid = -1,
     139              :     Costinfo,
     140              :     DXF,
     141              :     DXFwireframe,
     142              :     VRML,
     143              :     Vertices,
     144              :     Details,
     145              :     DetailsWithVertices,
     146              :     Lines,
     147              :     Num
     148              : };
     149              : 
     150              : constexpr std::array<std::string_view, static_cast<int>(RptKey::Num)> RptKeyNamesUC{
     151              :     "COSTINFO", "DXF", "DXF:WIREFRAME", "VRML", "VERTICES", "DETAILS", "DETAILSWITHVERTICES", "LINES"};
     152              : 
     153              : // A second version that does not require a payload -- use lambdas
     154     18226338 : void SolveRoot(const EnergyPlusData &state,
     155              :                Real64 Eps,   // required absolute accuracy
     156              :                int MaxIte,   // maximum number of allowed iterations
     157              :                int &Flag,    // integer storing exit status
     158              :                Real64 &XRes, // value of x that solves f(x,Par) = 0
     159              :                const std::function<Real64(Real64)> &f,
     160              :                Real64 X_0, // 1st bound of interval that contains the solution
     161              :                Real64 X_1) // 2nd bound of interval that contains the solution
     162              : {
     163              :     // SUBROUTINE INFORMATION:
     164              :     //       AUTHOR         Michael Wetter
     165              :     //       DATE WRITTEN   March 1999
     166              :     //       MODIFIED       Fred Buhl November 2000, R. Raustad October 2006 - made subroutine RECURSIVE
     167              :     //                      L. Gu, May 2017 - allow both Bisection and RegulaFalsi
     168              : 
     169              :     // PURPOSE OF THIS SUBROUTINE:
     170              :     // Find the value of x between x0 and x1 such that f(x,Par)
     171              :     // is equal to zero.
     172              : 
     173              :     // METHODOLOGY EMPLOYED:
     174              :     // Uses the Regula Falsi (false position) method (similar to secant method)
     175              : 
     176              :     // REFERENCES:
     177              :     // See Press et al., Numerical Recipes in Fortran, Cambridge University Press,
     178              :     // 2nd edition, 1992. Page 347 ff.
     179              : 
     180              :     // SUBROUTINE ARGUMENT DEFINITIONS:
     181              :     // = -2: f(x0) and f(x1) have the same sign
     182              :     // = -1: no convergence
     183              :     // >  0: number of iterations performed
     184              : 
     185     18226338 :     Real64 constexpr SMALL(1.e-10);
     186     18226338 :     Real64 X0 = X_0;   // present 1st bound
     187     18226338 :     Real64 X1 = X_1;   // present 2nd bound
     188     18226338 :     Real64 XTemp = X0; // new estimate
     189     18226338 :     int NIte = 0;      // number of iterations
     190     18226338 :     int AltIte = 0;    // an accounter used for Alternation choice
     191              : 
     192     18226338 :     Real64 Y0 = f(X0); // f at X0
     193     18226338 :     Real64 Y1 = f(X1); // f at X1
     194              :     // check initial values
     195     18226338 :     if (Y0 * Y1 > 0) {
     196      1116597 :         Flag = -2;
     197      1116597 :         XRes = X0;
     198      1116597 :         return;
     199              :     }
     200     17109741 :     XRes = XTemp;
     201              : 
     202              :     while (true) {
     203              : 
     204     34983156 :         Real64 DY = Y0 - Y1;
     205     34983156 :         if (std::abs(DY) < SMALL) {
     206            0 :             DY = SMALL;
     207              :         }
     208     34983156 :         if (std::abs(X1 - X0) < SMALL) {
     209         5802 :             break;
     210              :         }
     211              :         // new estimation
     212     34977354 :         switch (state.dataRootFinder->HVACSystemRootFinding.HVACSystemRootSolverMethod) {
     213     34971848 :         case HVACSystemRootSolverAlgorithm::RegulaFalsi: {
     214     34971848 :             XTemp = (Y0 * X1 - Y1 * X0) / DY;
     215     34971848 :             break;
     216              :         }
     217            0 :         case HVACSystemRootSolverAlgorithm::Bisection: {
     218            0 :             XTemp = (X1 + X0) / 2.0;
     219            0 :             break;
     220              :         }
     221         5506 :         case HVACSystemRootSolverAlgorithm::RegulaFalsiThenBisection: {
     222         5506 :             if (NIte > state.dataRootFinder->HVACSystemRootFinding.NumOfIter) {
     223           71 :                 XTemp = (X1 + X0) / 2.0;
     224              :             } else {
     225         5435 :                 XTemp = (Y0 * X1 - Y1 * X0) / DY;
     226              :             }
     227         5506 :             break;
     228              :         }
     229            0 :         case HVACSystemRootSolverAlgorithm::BisectionThenRegulaFalsi: {
     230            0 :             if (NIte <= state.dataRootFinder->HVACSystemRootFinding.NumOfIter) {
     231            0 :                 XTemp = (X1 + X0) / 2.0;
     232              :             } else {
     233            0 :                 XTemp = (Y0 * X1 - Y1 * X0) / DY;
     234              :             }
     235            0 :             break;
     236              :         }
     237            0 :         case HVACSystemRootSolverAlgorithm::Alternation: {
     238            0 :             if (AltIte > state.dataRootFinder->HVACSystemRootFinding.NumOfIter) {
     239            0 :                 XTemp = (X1 + X0) / 2.0;
     240            0 :                 if (AltIte >= 2 * state.dataRootFinder->HVACSystemRootFinding.NumOfIter) {
     241            0 :                     AltIte = 0;
     242              :                 }
     243              :             } else {
     244            0 :                 XTemp = (Y0 * X1 - Y1 * X0) / DY;
     245              :             }
     246            0 :             break;
     247              :         }
     248            0 :         case HVACSystemRootSolverAlgorithm::ShortBisectionThenRegulaFalsi: {
     249            0 :             if (NIte < 3) {
     250            0 :                 XTemp = (X1 + X0) / 2.0;
     251              :             } else {
     252            0 :                 XTemp = (Y0 * X1 - Y1 * X0) / DY;
     253              :             }
     254            0 :             break;
     255              :         }
     256            0 :         default: {
     257            0 :             XTemp = (Y0 * X1 - Y1 * X0) / DY;
     258              :         }
     259              :         }
     260              : 
     261     34977354 :         Real64 const YTemp = f(XTemp);
     262              : 
     263     34977354 :         ++NIte;
     264     34977354 :         ++AltIte;
     265              : 
     266              :         // check convergence
     267     34977354 :         if (std::abs(YTemp) < Eps) {
     268     17103742 :             Flag = NIte;
     269     17103742 :             XRes = XTemp;
     270     17103742 :             return;
     271              :         };
     272              : 
     273              :         // OK, so we didn't converge, lets check max iterations to see if we should break early
     274     17873612 :         if (NIte > MaxIte) {
     275          197 :             break;
     276              :         }
     277              : 
     278              :         // Finally, if we make it here, we have not converged, and we still have iterations left, so continue
     279              :         // and reassign values (only if further iteration required)
     280     17873415 :         if (Y0 < 0.0) {
     281     15728400 :             if (YTemp < 0.0) {
     282      7388830 :                 X0 = XTemp;
     283      7388830 :                 Y0 = YTemp;
     284              :             } else {
     285      8339570 :                 X1 = XTemp;
     286      8339570 :                 Y1 = YTemp;
     287              :             }
     288              :         } else {
     289      2145015 :             if (YTemp < 0.0) {
     290      1249186 :                 X1 = XTemp;
     291      1249186 :                 Y1 = YTemp;
     292              :             } else {
     293       895829 :                 X0 = XTemp;
     294       895829 :                 Y0 = YTemp;
     295              :             }
     296              :         } // ( Y0 < 0 )
     297     17873415 :     } // Cont
     298              : 
     299              :     // if we make it here we haven't converged, so just set the flag and leave
     300         5999 :     Flag = -1;
     301         5999 :     XRes = XTemp;
     302              : }
     303              : 
     304       214804 : void MovingAvg(Array1D<Real64> &DataIn, int const NumItemsInAvg)
     305              : {
     306       214804 :     if (NumItemsInAvg <= 1) {
     307         2208 :         return; // no need to average/smooth
     308              :     }
     309              : 
     310       212596 :     Array1D<Real64> TempData(2 * DataIn.size()); // a scratch array twice the size, bottom end duplicate of top end
     311              : 
     312     25756852 :     for (std::size_t i = 1; i <= DataIn.size(); ++i) {
     313     25544256 :         TempData(i) = TempData(DataIn.size() + i) = DataIn(i); // initialize both bottom and top end
     314     25544256 :         DataIn(i) = 0.0;
     315              :     }
     316              : 
     317     25756852 :     for (std::size_t i = 1; i <= DataIn.size(); ++i) {
     318    238904256 :         for (int j = 1; j <= NumItemsInAvg; ++j) {
     319    213360000 :             DataIn(i) += TempData(DataIn.size() - NumItemsInAvg + i + j); // sum top end including NumItemsInAvg history terms
     320              :         }
     321     25544256 :         DataIn(i) /= NumItemsInAvg; // average to smooth over NumItemsInAvg window
     322              :     }
     323       212596 : }
     324              : 
     325        37235 : void ProcessDateString(EnergyPlusData &state,
     326              :                        std::string const &String,
     327              :                        int &PMonth,
     328              :                        int &PDay,
     329              :                        int &PWeekDay,
     330              :                        Weather::DateType &DateType, // DateType found (-1=invalid, 1=month/day, 2=nth day in month, 3=last day in month)
     331              :                        bool &ErrorsFound,
     332              :                        ObjexxFCL::Optional_int PYear)
     333              : {
     334              : 
     335              :     // SUBROUTINE INFORMATION:
     336              :     //       AUTHOR         Linda Lawrie
     337              :     //       DATE WRITTEN   December 1999
     338              : 
     339              :     // PURPOSE OF THIS SUBROUTINE:
     340              :     // This subroutine will process a date from a string and determine
     341              :     // the proper month and day for that date string.
     342              : 
     343              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     344              :     bool errFlag;
     345              : 
     346        37235 :     int FstNum = int(Util::ProcessNumber(String, errFlag));
     347        37235 :     DateType = Weather::DateType::Invalid;
     348        37235 :     if (!errFlag) {
     349              :         // Entered single number, do inverse JDay
     350         1584 :         if (FstNum == 0) {
     351         1584 :             PMonth = 0;
     352         1584 :             PDay = 0;
     353         1584 :             DateType = Weather::DateType::MonthDay;
     354            0 :         } else if (FstNum < 0 || FstNum > 366) {
     355            0 :             ShowSevereError(state, format("Invalid Julian date Entered={}", String));
     356            0 :             ErrorsFound = true;
     357              :         } else {
     358            0 :             InvOrdinalDay(FstNum, PMonth, PDay, 0);
     359            0 :             DateType = Weather::DateType::LastDayInMonth;
     360              :         }
     361              :     } else {
     362        35651 :         int NumTokens = 0;
     363        35651 :         int TokenDay = 0;
     364        35651 :         int TokenMonth = 0;
     365        35651 :         int TokenWeekday = 0;
     366              :         // Error when processing as number, try x/x
     367        35651 :         if (!present(PYear)) {
     368        34065 :             DetermineDateTokens(state, String, NumTokens, TokenDay, TokenMonth, TokenWeekday, DateType, ErrorsFound);
     369              :         } else {
     370         1586 :             int TokenYear = 0;
     371         1586 :             DetermineDateTokens(state, String, NumTokens, TokenDay, TokenMonth, TokenWeekday, DateType, ErrorsFound, TokenYear);
     372         1586 :             PYear = TokenYear;
     373              :         }
     374        35651 :         if (DateType == Weather::DateType::MonthDay) {
     375        34507 :             PDay = TokenDay;
     376        34507 :             PMonth = TokenMonth;
     377         1144 :         } else if (DateType == Weather::DateType::NthDayInMonth || DateType == Weather::DateType::LastDayInMonth) {
     378              :             // interpret as TokenDay TokenWeekday in TokenMonth
     379         1144 :             PDay = TokenDay;
     380         1144 :             PMonth = TokenMonth;
     381         1144 :             PWeekDay = TokenWeekday;
     382              :         }
     383              :     }
     384        37235 : }
     385              : 
     386        35651 : void DetermineDateTokens(EnergyPlusData &state,
     387              :                          std::string const &String,
     388              :                          int &NumTokens,                   // Number of tokens found in string
     389              :                          int &TokenDay,                    // Value of numeric field found
     390              :                          int &TokenMonth,                  // Value of Month field found (1=Jan, 2=Feb, etc)
     391              :                          int &TokenWeekday,                // Value of Weekday field found (1=Sunday, 2=Monday, etc), 0 if none
     392              :                          Weather::DateType &DateType,      // DateType found (-1=invalid, 1=month/day, 2=nth day in month, 3=last day in month)
     393              :                          bool &ErrorsFound,                // Set to true if cannot process this string as a date
     394              :                          ObjexxFCL::Optional_int TokenYear // Value of Year if one appears to be present and this argument is present
     395              : )
     396              : {
     397              : 
     398              :     // SUBROUTINE INFORMATION:
     399              :     //       AUTHOR         Linda Lawrie
     400              :     //       DATE WRITTEN   August 2000
     401              : 
     402              :     // PURPOSE OF THIS SUBROUTINE:
     403              :     // This subroutine is invoked for date fields that appear to be strings (give
     404              :     // error when ProcessNumber is used).
     405              : 
     406              :     // METHODOLOGY EMPLOYED:
     407              :     // Delete everything that is extraneous to the date information needed.  Process what
     408              :     // is left.
     409              : 
     410              :     // SUBROUTINE PARAMETER DEFINITIONS:
     411              :     static constexpr int NumSingleChars(3);
     412              :     static constexpr std::array<std::string_view, NumSingleChars> SingleChars{"/", ":", "-"};
     413              :     static constexpr int NumDoubleChars(6);
     414              :     static constexpr std::array<std::string_view, NumDoubleChars> DoubleChars{
     415              :         "ST ", "ND ", "RD ", "TH ", "OF ", "IN "}; // Need trailing spaces: Want these only at end of words
     416              :     static constexpr std::array<std::string_view, 12> Months{"JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"};
     417              :     static constexpr std::array<std::string_view, 7> Weekdays{"SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"};
     418              : 
     419              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     420        35651 :     std::string CurrentString = String;
     421        35651 :     Array1D_string Fields(3);
     422        35651 :     bool InternalError = false;
     423        35651 :     bool WkDayInMonth = false;
     424              : 
     425        35651 :     NumTokens = 0;
     426        35651 :     TokenDay = 0;
     427        35651 :     TokenMonth = 0;
     428        35651 :     TokenWeekday = 0;
     429        35651 :     DateType = Weather::DateType::Invalid;
     430        35651 :     if (present(TokenYear)) {
     431         1586 :         TokenYear = 0;
     432              :     }
     433              :     // Take out separator characters, other extraneous stuff
     434              : 
     435       142604 :     for (int Loop = 0; Loop < NumSingleChars; ++Loop) {
     436       106953 :         size_t Pos = index(CurrentString, SingleChars[Loop]);
     437       140930 :         while (Pos != std::string::npos) {
     438        33977 :             CurrentString[Pos] = ' ';
     439        33977 :             Pos = index(CurrentString, SingleChars[Loop]);
     440              :         }
     441              :     }
     442              : 
     443       249557 :     for (int Loop = 0; Loop < NumDoubleChars; ++Loop) {
     444       213906 :         size_t Pos = index(CurrentString, DoubleChars[Loop]);
     445       216194 :         while (Pos != std::string::npos) {
     446         2288 :             CurrentString.replace(Pos, 2, "  ");
     447         2288 :             Pos = index(CurrentString, DoubleChars[Loop]);
     448         2288 :             WkDayInMonth = true;
     449              :         }
     450              :     }
     451              : 
     452        35651 :     strip(CurrentString);
     453        35651 :     if (CurrentString == BlankString) {
     454            0 :         ShowSevereError(state, format("Invalid date field={}", String));
     455            0 :         ErrorsFound = true;
     456              :     } else {
     457        35651 :         int Loop = 0;
     458        35651 :         bool errFlag = false;
     459              :         int NumField1;
     460              :         int NumField2;
     461              :         int NumField3;
     462       108097 :         while (Loop < 3) { // Max of 3 fields
     463       106953 :             if (CurrentString == BlankString) {
     464        34507 :                 break;
     465              :             }
     466        72446 :             size_t Pos = index(CurrentString, ' ');
     467        72446 :             ++Loop;
     468        72446 :             if (Pos == std::string::npos) {
     469        35651 :                 Pos = CurrentString.length();
     470              :             }
     471        72446 :             Fields(Loop) = CurrentString.substr(0, Pos);
     472        72446 :             CurrentString.erase(0, Pos);
     473        72446 :             strip(CurrentString);
     474              :         }
     475        35651 :         if (not_blank(CurrentString)) {
     476            0 :             ShowSevereError(state, format("Invalid date field={}", String));
     477            0 :             ErrorsFound = true;
     478        35651 :         } else if (Loop == 2) {
     479              :             // Field must be Day Month or Month Day (if both numeric, mon / day)
     480        34507 :             InternalError = false;
     481        34507 :             NumField1 = int(Util::ProcessNumber(Fields(1), errFlag));
     482        34507 :             if (errFlag) {
     483              :                 // Month day, but first field is not numeric, 2nd must be
     484          511 :                 NumField2 = int(Util::ProcessNumber(Fields(2), errFlag));
     485          511 :                 if (errFlag) {
     486            0 :                     ShowSevereError(state, format("Invalid date field={}", String));
     487            0 :                     InternalError = true;
     488              :                 } else {
     489          511 :                     TokenDay = NumField2;
     490              :                 }
     491          511 :                 TokenMonth = Util::FindItemInList(Fields(1).substr(0, 3), Months.begin(), Months.end());
     492          511 :                 ValidateMonthDay(state, String, TokenDay, TokenMonth, InternalError);
     493          511 :                 if (!InternalError) {
     494          511 :                     DateType = Weather::DateType::MonthDay;
     495              :                 } else {
     496            0 :                     ErrorsFound = true;
     497              :                 }
     498              :             } else {
     499              :                 // Month Day, first field was numeric, if 2nd is, then it's month<num> day<num>
     500        33996 :                 NumField2 = int(Util::ProcessNumber(Fields(2), errFlag));
     501        33996 :                 if (!errFlag) {
     502        33971 :                     TokenMonth = NumField1;
     503        33971 :                     TokenDay = NumField2;
     504        33971 :                     ValidateMonthDay(state, String, TokenDay, TokenMonth, InternalError);
     505        33971 :                     if (!InternalError) {
     506        33971 :                         DateType = Weather::DateType::MonthDay;
     507              :                     } else {
     508            0 :                         ErrorsFound = true;
     509              :                     }
     510              :                 } else { // 2nd field was not numeric.  Must be Month
     511           25 :                     TokenDay = NumField1;
     512           25 :                     TokenMonth = Util::FindItemInList(Fields(2).substr(0, 3), Months.begin(), Months.end());
     513           25 :                     ValidateMonthDay(state, String, TokenDay, TokenMonth, InternalError);
     514           25 :                     if (!InternalError) {
     515           25 :                         DateType = Weather::DateType::MonthDay;
     516           25 :                         NumTokens = 2;
     517              :                     } else {
     518            0 :                         ErrorsFound = true;
     519              :                     }
     520              :                 }
     521              :             }
     522         1144 :         } else if (Loop == 3) {
     523              :             // Field must be some combination of <num> Weekday Month (if WkDayInMonth true)
     524         1144 :             if (WkDayInMonth) {
     525         1144 :                 NumField1 = int(Util::ProcessNumber(Fields(1), errFlag));
     526         1144 :                 if (!errFlag) { // the expected result
     527          944 :                     TokenDay = NumField1;
     528          944 :                     TokenWeekday = Util::FindItemInList(Fields(2).substr(0, 3), Weekdays.begin(), Weekdays.end());
     529          944 :                     if (TokenWeekday == 0) {
     530            0 :                         TokenMonth = Util::FindItemInList(Fields(2).substr(0, 3), Months.begin(), Months.end());
     531            0 :                         TokenWeekday = Util::FindItemInList(Fields(3).substr(0, 3), Weekdays.begin(), Weekdays.end());
     532            0 :                         if (TokenMonth == 0 || TokenWeekday == 0) {
     533            0 :                             InternalError = true;
     534              :                         }
     535              :                     } else {
     536          944 :                         TokenMonth = Util::FindItemInList(Fields(3).substr(0, 3), Months.begin(), Months.end());
     537          944 :                         if (TokenMonth == 0) {
     538            0 :                             InternalError = true;
     539              :                         }
     540              :                     }
     541          944 :                     DateType = Weather::DateType::NthDayInMonth;
     542          944 :                     NumTokens = 3;
     543          944 :                     if (TokenDay < 0 || TokenDay > 5) {
     544            0 :                         InternalError = true;
     545              :                     }
     546              :                 } else { // first field was not numeric....
     547          200 :                     if (Fields(1) == "LA") {
     548          200 :                         DateType = Weather::DateType::LastDayInMonth;
     549          200 :                         NumTokens = 3;
     550          200 :                         TokenWeekday = Util::FindItemInList(Fields(2).substr(0, 3), Weekdays.begin(), Weekdays.end());
     551          200 :                         if (TokenWeekday == 0) {
     552            0 :                             TokenMonth = Util::FindItemInList(Fields(2).substr(0, 3), Months.begin(), Months.end());
     553            0 :                             TokenWeekday = Util::FindItemInList(Fields(3).substr(0, 3), Weekdays.begin(), Weekdays.end());
     554            0 :                             if (TokenMonth == 0 || TokenWeekday == 0) {
     555            0 :                                 InternalError = true;
     556              :                             }
     557              :                         } else {
     558          200 :                             TokenMonth = Util::FindItemInList(Fields(3).substr(0, 3), Months.begin(), Months.end());
     559          200 :                             if (TokenMonth == 0) {
     560            0 :                                 InternalError = true;
     561              :                             }
     562              :                         }
     563              :                     } else { // error....
     564            0 :                         ShowSevereError(state, format("First date field not numeric, field={}", String));
     565              :                     }
     566              :                 }
     567              :             } else { // mm/dd/yyyy or yyyy/mm/dd
     568            0 :                 NumField1 = int(Util::ProcessNumber(Fields(1), errFlag));
     569            0 :                 NumField2 = int(Util::ProcessNumber(Fields(2), errFlag));
     570            0 :                 NumField3 = int(Util::ProcessNumber(Fields(3), errFlag));
     571            0 :                 DateType = Weather::DateType::MonthDay;
     572              :                 // error detection later..
     573            0 :                 if (NumField1 > 100) {
     574            0 :                     if (present(TokenYear)) {
     575            0 :                         TokenYear = NumField1;
     576              :                     }
     577            0 :                     TokenMonth = NumField2;
     578            0 :                     TokenDay = NumField3;
     579            0 :                 } else if (NumField3 > 100) {
     580            0 :                     if (present(TokenYear)) {
     581            0 :                         TokenYear = NumField3;
     582              :                     }
     583            0 :                     TokenMonth = NumField1;
     584            0 :                     TokenDay = NumField2;
     585              :                 }
     586              :             }
     587              :         } else {
     588              :             // Not enough or too many fields
     589            0 :             ShowSevereError(state, format("Invalid date field={}", String));
     590            0 :             ErrorsFound = true;
     591              :         }
     592              :     }
     593              : 
     594        35651 :     if (InternalError) {
     595            0 :         DateType = Weather::DateType::Invalid;
     596            0 :         ErrorsFound = true;
     597              :     }
     598        35651 : }
     599              : 
     600        34507 : void ValidateMonthDay(EnergyPlusData &state,
     601              :                       std::string const &String, // REAL(r64) string being processed
     602              :                       int const Day,
     603              :                       int const Month,
     604              :                       bool &ErrorsFound)
     605              : {
     606              : 
     607              :     // SUBROUTINE INFORMATION:
     608              :     //       AUTHOR         Linda Lawrie
     609              :     //       DATE WRITTEN   August 2000
     610              : 
     611              :     // PURPOSE OF THIS SUBROUTINE:
     612              :     // This subroutine validates a potential Day, Month values, produces an error
     613              :     // message when not valid, and sets error flag.
     614              : 
     615              :     // SUBROUTINE PARAMETER DEFINITIONS:
     616              :     static constexpr std::array<int, 12> EndMonthDay = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
     617              : 
     618        34507 :     bool InternalError = false;
     619        34507 :     if (Month < 1 || Month > 12) {
     620            0 :         InternalError = true;
     621              :     }
     622        34507 :     if (!InternalError) {
     623        34507 :         if (Day < 1 || Day > EndMonthDay[Month - 1]) {
     624            0 :             InternalError = true;
     625              :         }
     626              :     }
     627        34507 :     if (InternalError) {
     628            0 :         ShowSevereError(state, format("Invalid Month Day date format={}", String));
     629            0 :         ErrorsFound = true;
     630              :     } else {
     631        34507 :         ErrorsFound = false;
     632              :     }
     633        34507 : }
     634              : 
     635       193976 : int OrdinalDay(int const Month,        // Month, 1..12
     636              :                int const Day,          // Day of Month, not validated by month
     637              :                int const LeapYearValue // 1 if leap year indicated, 0 if not
     638              : )
     639              : {
     640              : 
     641              :     // FUNCTION INFORMATION:
     642              :     //       AUTHOR         Linda K. Lawrie
     643              :     //       DATE WRITTEN   September 1997
     644              :     //       RE-ENGINEERED  from JDAYF in BLAST/IBLAST
     645              : 
     646              :     // PURPOSE OF THIS SUBROUTINE:
     647              :     // This subroutine returns the appropriate Julian Day value for the input
     648              :     // Month and Day.
     649              : 
     650              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     651              :     static constexpr std::array<int, 12> EndDayofMonth = {31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};
     652              :     // End day numbers of each month (without Leap Year)
     653              : 
     654       193976 :     if (Month == 1) {
     655              :         //                                       CASE 1: JANUARY
     656        61790 :         return Day;
     657              : 
     658       132186 :     } else if (Month == 2) {
     659              :         //                                       CASE 2: FEBRUARY
     660         3191 :         return Day + EndDayofMonth[0];
     661              : 
     662       128995 :     } else if ((Month >= 3) && (Month <= 12)) {
     663              :         //                                       CASE 3: REMAINING MONTHS
     664       128995 :         return Day + EndDayofMonth[Month - 2] + LeapYearValue;
     665              : 
     666              :     } else {
     667            0 :         return 0;
     668              :     }
     669              : }
     670              : 
     671        76763 : void InvOrdinalDay(int const Number, int &PMonth, int &PDay, int const LeapYr)
     672              : {
     673              : 
     674              :     // SUBROUTINE INFORMATION:
     675              :     //       AUTHOR         Linda Lawrie
     676              :     //       DATE WRITTEN   December 1999
     677              : 
     678              :     // PURPOSE OF THIS SUBROUTINE:
     679              :     // This subroutine performs and inverse Julian Day
     680              :     // calculation, using an input JulianDay and returning
     681              :     // appropriate Month and Day.
     682              : 
     683              :     // SUBROUTINE PARAMETER DEFINITIONS:
     684              :     static constexpr std::array<int, 13> EndOfMonth = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};
     685              : 
     686              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     687              :     int WMonth;
     688              :     int LeapAddPrev;
     689              :     int LeapAddCur;
     690              : 
     691        76763 :     if (Number < 0 || Number > 366) {
     692            0 :         return;
     693              :     }
     694       496281 :     for (WMonth = 1; WMonth <= 12; ++WMonth) {
     695       496281 :         if (WMonth == 1) {
     696        76763 :             LeapAddPrev = 0;
     697        76763 :             LeapAddCur = 0;
     698       419518 :         } else if (WMonth == 2) {
     699        69418 :             LeapAddPrev = 0;
     700        69418 :             LeapAddCur = LeapYr;
     701              :         } else {
     702       350100 :             LeapAddPrev = LeapYr;
     703       350100 :             LeapAddCur = LeapYr;
     704              :         }
     705       496281 :         if (Number > (EndOfMonth[WMonth - 1] + LeapAddPrev) && Number <= (EndOfMonth[WMonth] + LeapAddCur)) {
     706        76763 :             break;
     707              :         }
     708              :     }
     709        76763 :     PMonth = WMonth;
     710        76763 :     PDay = Number - (EndOfMonth[WMonth - 1] + LeapAddCur);
     711              : }
     712              : 
     713         6912 : bool BetweenDateHoursLeftInclusive(
     714              :     int const TestDate, int const TestHour, int const StartDate, int const StartHour, int const EndDate, int const EndHour)
     715              : {
     716         6912 :     Real64 TestRatioOfDay = TestHour / 24.0;
     717         6912 :     Real64 StartRatioOfDay = StartHour / 24.0;
     718         6912 :     Real64 EndRatioOfDay = EndHour / 24.0;
     719              : 
     720         6912 :     if (StartDate + StartRatioOfDay <= EndDate + EndRatioOfDay) { // Start Date <= End Date
     721         5376 :         return (StartDate + StartRatioOfDay <= TestDate + TestRatioOfDay) && (TestDate + TestRatioOfDay <= EndDate + EndRatioOfDay);
     722              :     } else { // EndDate < StartDate
     723         1536 :         return (EndDate + EndRatioOfDay <= TestDate + TestRatioOfDay) && (TestDate + TestRatioOfDay <= StartDate + StartRatioOfDay);
     724              :     }
     725              : }
     726              : 
     727           16 : bool BetweenDates(int const TestDate,  // Date to test
     728              :                   int const StartDate, // Start date in sequence
     729              :                   int const EndDate    // End date in sequence
     730              : )
     731              : {
     732              : 
     733              :     // FUNCTION INFORMATION:
     734              :     //       AUTHOR         Linda K. Lawrie
     735              :     //       DATE WRITTEN   June 2000
     736              : 
     737              :     // PURPOSE OF THIS FUNCTION:
     738              :     // This function returns true if the TestDate is between
     739              :     // (StartDate <= TestDate <= EndDate).
     740              : 
     741              :     // METHODOLOGY EMPLOYED:
     742              :     // The input dates are Julian Day format, year is irrelevant.
     743              :     // Thus, if StartDate > EndDate (i.e. StartDate = 1Dec and EndDate = 31Jan),
     744              :     // this routine accommodates.
     745              : 
     746              :     // REFERENCES:
     747              :     // Adapted from BLAST BTWEEN function.
     748              : 
     749           16 :     bool BetweenDates = false; // Default case
     750              : 
     751           16 :     if (StartDate <= EndDate) { // Start Date <= End Date
     752            0 :         if (TestDate >= StartDate && TestDate <= EndDate) {
     753            0 :             BetweenDates = true;
     754              :         }
     755              :     } else { // EndDate < StartDate
     756           16 :         if (TestDate <= EndDate || TestDate >= StartDate) {
     757            8 :             BetweenDates = true;
     758              :         }
     759              :     }
     760              : 
     761           16 :     return BetweenDates;
     762              : }
     763              : 
     764      2247702 : std::string CreateSysTimeIntervalString(EnergyPlusData &state)
     765              : {
     766              : 
     767              :     // FUNCTION INFORMATION:
     768              :     //       AUTHOR         Linda K. Lawrie
     769              :     //       DATE WRITTEN   April 2003
     770              : 
     771              :     // PURPOSE OF THIS FUNCTION:
     772              :     // This function creates the current time interval of the system time step.
     773              : 
     774              :     // Using/Aliasing
     775      2247702 :     Real64 SysTimeElapsed = state.dataHVACGlobal->SysTimeElapsed;
     776      2247702 :     Real64 TimeStepSys = state.dataHVACGlobal->TimeStepSys;
     777              : 
     778      2247702 :     Real64 constexpr FracToMin(60.0);
     779              : 
     780              :     //  ActualTimeS=INT(CurrentTime)+(SysTimeElapsed+(CurrentTime - INT(CurrentTime)))
     781              :     // CR6902  ActualTimeS=INT(CurrentTime-TimeStepZone)+SysTimeElapsed
     782              :     // [DC] TODO: Improve display accuracy up to fractional seconds using hh:mm:ss.0 format
     783      2247702 :     Real64 ActualTimeS = state.dataGlobal->CurrentTime - state.dataGlobal->TimeStepZone + SysTimeElapsed;
     784      2247702 :     Real64 ActualTimeE = ActualTimeS + TimeStepSys;
     785      2247702 :     int ActualTimeHrS = int(ActualTimeS);
     786              :     //  ActualTimeHrE=INT(ActualTimeE)
     787      2247702 :     int ActualTimeMinS = nint((ActualTimeS - ActualTimeHrS) * FracToMin);
     788              : 
     789      2247702 :     if (ActualTimeMinS == 60) {
     790         6458 :         ++ActualTimeHrS;
     791         6458 :         ActualTimeMinS = 0;
     792              :     }
     793      2247702 :     const std::string TimeStmpS = format("{:02}:{:02}", ActualTimeHrS, ActualTimeMinS);
     794      2247702 :     Real64 minutes = ((ActualTimeE - static_cast<int>(ActualTimeE)) * FracToMin);
     795              : 
     796      2247702 :     std::string TimeStmpE = format("{:02}:{:2.0F}", static_cast<int>(ActualTimeE), minutes);
     797              : 
     798      2247702 :     if (TimeStmpE[3] == ' ') {
     799       396430 :         TimeStmpE[3] = '0';
     800              :     }
     801      4495404 :     return TimeStmpS + " - " + TimeStmpE;
     802      2247702 : }
     803              : 
     804              : // returns the Julian date for the first, second, etc. day of week for a given month
     805         3736 : int nthDayOfWeekOfMonth(const EnergyPlusData &state,
     806              :                         int const dayOfWeek,  // day of week (Sunday=1, Monday=2, ...)
     807              :                         int const nthTime,    // nth time the day of the week occurs (first monday, third tuesday, ..)
     808              :                         int const monthNumber // January = 1
     809              : )
     810              : {
     811              :     // J. Glazer - August 2017
     812         3736 :     int firstDayOfMonth = OrdinalDay(monthNumber, 1, state.dataEnvrn->CurrentYearIsLeapYear);
     813         3736 :     int dayOfWeekForFirstDay = (state.dataEnvrn->RunPeriodStartDayOfWeek + firstDayOfMonth - 1) % 7;
     814         3736 :     if (dayOfWeek >= dayOfWeekForFirstDay) {
     815         1894 :         return firstDayOfMonth + (dayOfWeek - dayOfWeekForFirstDay) + 7 * (nthTime - 1);
     816              :     } else {
     817         1842 :         return firstDayOfMonth + ((dayOfWeek + 7) - dayOfWeekForFirstDay) + 7 * (nthTime - 1);
     818              :     }
     819              : }
     820              : 
     821     12572670 : Real64 SafeDivide(Real64 const a, Real64 const b)
     822              : {
     823              : 
     824              :     // returns a / b while preventing division by zero
     825              : 
     826              :     // Locals
     827     12572670 :     Real64 constexpr SMALL(1.E-10);
     828              : 
     829     12572670 :     if (std::abs(b) >= SMALL) {
     830     12571504 :         return a / b;
     831              :     } else {
     832         1166 :         return a / sign(SMALL, b);
     833              :     }
     834              : }
     835              : 
     836    317089875 : void Iterate(Real64 &ResultX,  // ResultX is the final Iteration result passed back to the calling routine
     837              :              Real64 const Tol, // Tolerance for Convergence
     838              :              Real64 const X0,  // Current value of X
     839              :              Real64 const Y0,  // Current value of the function Y(X)
     840              :              Real64 &X1,       // First Previous values of X
     841              :              Real64 &Y1,       // First Previous values of Y(X1)
     842              :              int const Iter,   // Number of iterations
     843              :              int &Cnvg         // Convergence flag  Cnvg = 0:  Not converged
     844              : )
     845              : {
     846              : 
     847              :     // SUBROUTINE INFORMATION:
     848              :     //       AUTHOR         Richard Liesen
     849              :     //       DATE WRITTEN   March 2004
     850              : 
     851              :     // PURPOSE OF THIS SUBROUTINE:
     852              :     // Iteratively solves for the value of X which satisfies Y(X)=0.
     853              :     // The subroutine tests for convergence and provides a new guess for the value of the
     854              :     // independent variable X.
     855              : 
     856              :     // REFERENCES:
     857              :     // Linear Correction based on the RegulaFalsi routine in EnergyPlus
     858              : 
     859              :     // SUBROUTINE PARAMETER DEFINITIONS:
     860    317089875 :     Real64 constexpr small(1.e-9); // Small Number used to approximate zero
     861    317089875 :     Real64 constexpr Perturb(0.1); // Perturbation applied to X to initialize iteration
     862              : 
     863              :     // Check for convergence by comparing change in X
     864    317089875 :     if (Iter != 1) {
     865    285410396 :         if (std::abs(X0 - X1) < Tol || Y0 == 0.0) {
     866     31679417 :             ResultX = X0;
     867     31679417 :             Cnvg = 1;
     868     31679417 :             return;
     869              :         }
     870              :     }
     871              : 
     872              :     // Not converged.
     873    285410458 :     Cnvg = 0;
     874    285410458 :     if (Iter == 1) {
     875              : 
     876              :         // New guess is specified by Perturb
     877     31679479 :         if (std::abs(X0) > small) {
     878     31677564 :             ResultX = X0 * (1.0 + Perturb);
     879              :         } else {
     880         1915 :             ResultX = Perturb;
     881              :         }
     882              : 
     883              :     } else {
     884              : 
     885              :         // New guess calculated from LINEAR FIT of most recent two points
     886    253730979 :         Real64 DY = Y0 - Y1;
     887    253730979 :         if (std::abs(DY) < small) {
     888            0 :             DY = small;
     889              :         }
     890              :         // new estimation
     891              : 
     892    253730979 :         ResultX = (Y0 * X1 - Y1 * X0) / DY;
     893              :     }
     894              : 
     895    285410458 :     X1 = X0;
     896    285410458 :     Y1 = Y0;
     897              : }
     898              : 
     899        39873 : int FindNumberInList(int const WhichNumber, Array1A_int const ListOfItems, int const NumItems)
     900              : {
     901              : 
     902              :     // FUNCTION INFORMATION:
     903              :     //       AUTHOR         Linda K. Lawrie
     904              :     //       DATE WRITTEN   September 2001
     905              : 
     906              :     // PURPOSE OF THIS FUNCTION:
     907              :     // This function looks up a number(integer) in a similar list of
     908              :     // items and returns the index of the item in the list, if found.
     909              : 
     910              :     // Argument array dimensioning
     911        39873 :     ListOfItems.dim(_);
     912              : 
     913       359954 :     for (int Count = 1; Count <= NumItems; ++Count) {
     914       327634 :         if (WhichNumber == ListOfItems(Count)) {
     915         7553 :             return Count;
     916              :         }
     917              :     }
     918              : 
     919        32320 :     return 0;
     920              : }
     921              : 
     922       315296 : void DecodeMonDayHrMin(int const Item, // word containing encoded month, day, hour, minute
     923              :                        int &Month,     // month in integer format (1-12)
     924              :                        int &Day,       // day in integer format (1-31)
     925              :                        int &Hour,      // hour in integer format (1-24)
     926              :                        int &Minute     // minute in integer format (0:59)
     927              : )
     928              : {
     929              : 
     930              :     // SUBROUTINE INFORMATION:
     931              :     //       AUTHOR         Linda Lawrie
     932              :     //       DATE WRITTEN   March 2000
     933              : 
     934              :     // PURPOSE OF THIS SUBROUTINE:
     935              :     // This subroutine decodes the "packed" integer representation of
     936              :     // the Month, Day, Hour, and Minute.  Packed integers are used to
     937              :     // save memory allocation.  Original idea for this routine is contained
     938              :     // in DECMDH, BLAST code, by Jean Baugh.
     939              : 
     940              :     // METHODOLOGY EMPLOYED:
     941              :     // Using maximum integer concept the original date can be decoded
     942              :     // from the packed single word.  This relies on 4 byte integer representation
     943              :     // as a minimum (capable of representing up to 2,147,483,647).
     944              : 
     945              :     // SUBROUTINE PARAMETER DEFINITIONS:
     946              :     static constexpr int DecMon(100 * 100 * 100);
     947              :     static constexpr int DecDay(100 * 100);
     948              :     static constexpr int DecHr(100);
     949              : 
     950       315296 :     int TmpItem = Item;
     951       315296 :     Month = TmpItem / DecMon;
     952       315296 :     TmpItem = (TmpItem - Month * DecMon);
     953       315296 :     Day = TmpItem / DecDay;
     954       315296 :     TmpItem -= Day * DecDay;
     955       315296 :     Hour = TmpItem / DecHr;
     956       315296 :     Minute = mod(TmpItem, DecHr);
     957       315296 : }
     958              : 
     959      1171756 : void EncodeMonDayHrMin(int &Item,       // word containing encoded month, day, hour, minute
     960              :                        int const Month, // month in integer format (1:12)
     961              :                        int const Day,   // day in integer format (1:31)
     962              :                        int const Hour,  // hour in integer format (1:24)
     963              :                        int const Minute // minute in integer format (0:59)
     964              : )
     965              : {
     966              : 
     967              :     // SUBROUTINE INFORMATION:
     968              :     //       AUTHOR         Linda Lawrie
     969              :     //       DATE WRITTEN   March 2000
     970              : 
     971              :     // PURPOSE OF THIS SUBROUTINE:
     972              :     // This subroutine encodes the "packed" integer representation of
     973              :     // the Month, Day, Hour, and Minute.  Packed integers are used to
     974              :     // save memory allocation.  Original idea for this routine is contained
     975              :     // in DECMDH, BLAST code, by Jean Baugh.
     976              : 
     977              :     // METHODOLOGY EMPLOYED:
     978              :     // Using maximum integer concept the original date can be decoded
     979              :     // from the packed single word.  This relies on 4 byte integer representation
     980              :     // as a minimum (capable of representing up to 2,147,483,647).
     981              : 
     982      1171756 :     Item = ((Month * 100 + Day) * 100 + Hour) * 100 + Minute;
     983      1171756 : }
     984              : 
     985            0 : std::string CreateTimeString(Real64 const Time) // Time in seconds
     986              : {
     987              : 
     988              :     // FUNCTION INFORMATION:
     989              :     //       AUTHOR         Dimitri Curtil
     990              :     //       DATE WRITTEN   January 2005
     991              : 
     992              :     // PURPOSE OF THIS FUNCTION:
     993              :     // This function creates the time stamp string from the time value specified in seconds.
     994              :     // Inspired by similar function CreateSysTimeIntervalString() in General.cc
     995              :     // However, this function provides better accuracy for sub-minute time steps
     996              :     // by also showing information down to the 10th of a second.
     997              :     // Note that Time is expected to be specified in REAL(r64).
     998              : 
     999              :     // FUNCTION LOCAL VARIABLE DECLARATIONS:
    1000              :     int Hours;      // Number of hours <= 24
    1001              :     int Minutes;    // Remaining minutes < 60
    1002              :     Real64 Seconds; // Remaining seconds < 60
    1003              : 
    1004            0 :     ParseTime(Time, Hours, Minutes, Seconds);
    1005              : 
    1006              :     // TimeStamp written with formatting
    1007              :     // "hh:mm:ss.s"
    1008            0 :     return fmt::format("{:02d}:{:02d}:{:04.1f}", Hours, Minutes, Seconds);
    1009              : }
    1010              : 
    1011        14736 : void ParseTime(Real64 const Time, // Time value in seconds
    1012              :                int &Hours,        // Number of hours
    1013              :                int &Minutes,      // Number of minutes < 60
    1014              :                Real64 &Seconds    // Number of seconds < 60
    1015              : )
    1016              : {
    1017              :     // FUNCTION INFORMATION:
    1018              :     //       AUTHOR         Dimitri Curtil
    1019              :     //       DATE WRITTEN   January 2005
    1020              : 
    1021              :     // PURPOSE OF THIS FUNCTION:
    1022              :     // This subroutine decomposes a time value specified in seconds
    1023              :     // into a triplet { hours : minutes : seconds } such that
    1024              :     // - minutes < 60
    1025              :     // - seconds < 60
    1026              : 
    1027              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1028        14736 :     int constexpr MinToSec = 60;
    1029        14736 :     int constexpr HourToSec = 60 * 60;
    1030              : 
    1031              :     // Get number of hours
    1032              :     // This might undershoot the actual number of hours. See DO WHILE loop.
    1033        14736 :     Hours = int(Time) / HourToSec;
    1034              : 
    1035              :     // Compute remainder in seconds
    1036        14736 :     Real64 Remainder = (Time - Hours * HourToSec);
    1037              : 
    1038              :     // Compute minutes
    1039        14736 :     Minutes = int(Remainder) / MinToSec;
    1040              : 
    1041              :     // Compute remainder in seconds
    1042        14736 :     Remainder -= Minutes * MinToSec;
    1043              : 
    1044              :     // Compute seconds
    1045        14736 :     Seconds = Remainder;
    1046        14736 : }
    1047              : 
    1048        13617 : void ScanForReports(EnergyPlusData &state,
    1049              :                     std::string const &reportName,
    1050              :                     bool &DoReport,
    1051              :                     ObjexxFCL::Optional_string_const ReportKey,
    1052              :                     ObjexxFCL::Optional_string Option1,
    1053              :                     ObjexxFCL::Optional_string Option2)
    1054              : {
    1055              : 
    1056              :     // SUBROUTINE INFORMATION:
    1057              :     //       AUTHOR         Linda Lawrie
    1058              :     //       DATE WRITTEN   March 2009
    1059              : 
    1060              :     // PURPOSE OF THIS SUBROUTINE:
    1061              :     // This routine scans for the global "reports" settings, such as Variable Dictionary,
    1062              :     // Surfaces (and options), Constructions, etc.
    1063              : 
    1064              :     // METHODOLOGY EMPLOYED:
    1065              :     // First time routine is called, all the viable combinations/settings for the reports are
    1066              :     // stored in SAVEd variables.  Later callings will retrieve those.
    1067              : 
    1068        13617 :     if (state.dataGeneral->GetReportInput) {
    1069              : 
    1070              :         int NumNames;
    1071              :         int NumNumbers;
    1072              :         int IOStat;
    1073              :         int RepNum;
    1074              : 
    1075          801 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    1076          801 :         cCurrentModuleObject = "Output:Surfaces:List";
    1077              : 
    1078          801 :         int NumReports = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    1079              : 
    1080              :         enum
    1081              :         {
    1082              :             EMPTY,
    1083              :             LINES,
    1084              :             VERTICES,
    1085              :             DETAILS,
    1086              :             DETAILSWITHVERTICES,
    1087              :             COSTINFO,
    1088              :             VIEWFACTORINFO,
    1089              :             DECAYCURVESFROMCOMPONENTLOADSSUMMARY
    1090              :         };
    1091            0 :         std::map<std::string, int> localMap = {{"", EMPTY},
    1092            0 :                                                {"LINES", LINES},
    1093            0 :                                                {"VERTICES", VERTICES},
    1094            0 :                                                {"DETAILS", DETAILS},
    1095            0 :                                                {"DETAILED", DETAILS},
    1096            0 :                                                {"DETAIL", DETAILS},
    1097            0 :                                                {"DETAILSWITHVERTICES", DETAILSWITHVERTICES},
    1098            0 :                                                {"DETAILVERTICES", DETAILSWITHVERTICES},
    1099            0 :                                                {"COSTINFO", COSTINFO},
    1100            0 :                                                {"VIEWFACTORINFO", VIEWFACTORINFO},
    1101        10413 :                                                {"DECAYCURVESFROMCOMPONENTLOADSSUMMARY", DECAYCURVESFROMCOMPONENTLOADSSUMMARY}};
    1102              : 
    1103         1064 :         for (RepNum = 1; RepNum <= NumReports; ++RepNum) {
    1104          526 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1105              :                                                                      cCurrentModuleObject,
    1106              :                                                                      RepNum,
    1107          263 :                                                                      state.dataIPShortCut->cAlphaArgs,
    1108              :                                                                      NumNames,
    1109          263 :                                                                      state.dataIPShortCut->rNumericArgs,
    1110              :                                                                      NumNumbers,
    1111              :                                                                      IOStat,
    1112          263 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    1113          263 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    1114          263 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    1115          263 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    1116              : 
    1117              :             try {
    1118          263 :                 int value = localMap[state.dataIPShortCut->cAlphaArgs(1)];
    1119          263 :                 switch (value) {
    1120           52 :                 case LINES:
    1121           52 :                     state.dataGeneral->LineRpt = true;
    1122           52 :                     state.dataGeneral->LineRptOption1 = state.dataIPShortCut->cAlphaArgs(2);
    1123           52 :                     break;
    1124            5 :                 case VERTICES:
    1125            5 :                     state.dataGeneral->SurfVert = true;
    1126            5 :                     break;
    1127          149 :                 case DETAILS:
    1128          149 :                     state.dataGeneral->SurfDet = true;
    1129          149 :                     break;
    1130           31 :                 case DETAILSWITHVERTICES:
    1131           31 :                     state.dataGeneral->SurfDetWVert = true;
    1132           31 :                     break;
    1133            7 :                 case COSTINFO:
    1134              :                     //   Custom case for reporting surface info for cost estimates (for first costs in optimizing)
    1135            7 :                     state.dataGeneral->CostInfo = true;
    1136            7 :                     break;
    1137           10 :                 case VIEWFACTORINFO: // actual reporting is in HeatBalanceIntRadExchange
    1138           10 :                     state.dataGeneral->ViewFactorInfo = true;
    1139           10 :                     state.dataGeneral->ViewRptOption1 = state.dataIPShortCut->cAlphaArgs(2);
    1140           10 :                     break;
    1141            9 :                 case DECAYCURVESFROMCOMPONENTLOADSSUMMARY: // Should the Radiant to Convective Decay Curves from the
    1142              :                                                            // load component report appear in the EIO file
    1143            9 :                     state.dataGlobal->ShowDecayCurvesInEIO = true;
    1144            9 :                     break;
    1145            0 :                 default: // including empty
    1146            0 :                     ShowWarningError(state, format("{}: No {} supplied.", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(1)));
    1147            0 :                     ShowContinueError(state,
    1148              :                                       R"( Legal values are: "Lines", "Vertices", "Details", "DetailsWithVertices", "CostInfo", "ViewFactorIinfo".)");
    1149              :                 }
    1150            0 :             } catch (int e) {
    1151            0 :                 ShowWarningError(state,
    1152            0 :                                  format("{}: Invalid {}=\"{}\" supplied.",
    1153              :                                         cCurrentModuleObject,
    1154            0 :                                         state.dataIPShortCut->cAlphaFieldNames(1),
    1155            0 :                                         state.dataIPShortCut->cAlphaArgs(1)));
    1156            0 :                 ShowContinueError(state,
    1157              :                                   R"( Legal values are: "Lines", "Vertices", "Details", "DetailsWithVertices", "CostInfo", "ViewFactorIinfo".)");
    1158            0 :             }
    1159              :         }
    1160              : 
    1161          801 :         cCurrentModuleObject = "Output:Surfaces:Drawing";
    1162              : 
    1163          801 :         NumReports = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    1164         1349 :         for (RepNum = 1; RepNum <= NumReports; ++RepNum) {
    1165         1096 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1166              :                                                                      cCurrentModuleObject,
    1167              :                                                                      RepNum,
    1168          548 :                                                                      state.dataIPShortCut->cAlphaArgs,
    1169              :                                                                      NumNames,
    1170          548 :                                                                      state.dataIPShortCut->rNumericArgs,
    1171              :                                                                      NumNumbers,
    1172              :                                                                      IOStat,
    1173          548 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    1174          548 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    1175          548 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    1176          548 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    1177              : 
    1178              :             ReportType checkReportType =
    1179          548 :                 static_cast<ReportType>(getEnumValue(ReportTypeNamesUC, Util::makeUPPER(state.dataIPShortCut->cAlphaArgs(1))));
    1180              : 
    1181          548 :             switch (checkReportType) {
    1182          483 :             case ReportType::DXF: {
    1183          483 :                 state.dataGeneral->DXFReport = true;
    1184          483 :                 state.dataGeneral->DXFOption1 = state.dataIPShortCut->cAlphaArgs(2);
    1185          483 :                 state.dataGeneral->DXFOption2 = state.dataIPShortCut->cAlphaArgs(3);
    1186          483 :             } break;
    1187           29 :             case ReportType::DXFWireFrame: {
    1188           29 :                 state.dataGeneral->DXFWFReport = true;
    1189           29 :                 state.dataGeneral->DXFWFOption1 = state.dataIPShortCut->cAlphaArgs(2);
    1190           29 :                 state.dataGeneral->DXFWFOption2 = state.dataIPShortCut->cAlphaArgs(3);
    1191           29 :             } break;
    1192           36 :             case ReportType::VRML: {
    1193           36 :                 state.dataGeneral->VRMLReport = true;
    1194           36 :                 state.dataGeneral->VRMLOption1 = state.dataIPShortCut->cAlphaArgs(2);
    1195           36 :                 state.dataGeneral->VRMLOption2 = state.dataIPShortCut->cAlphaArgs(3);
    1196           36 :             } break;
    1197            0 :             default:
    1198            0 :                 break;
    1199              :             }
    1200              :         }
    1201              : 
    1202         1602 :         RepNum = state.dataInputProcessing->inputProcessor->getNumSectionsFound("Report Variable Dictionary");
    1203          801 :         if (RepNum > 0) {
    1204            0 :             state.dataGeneral->VarDict = true;
    1205            0 :             state.dataGeneral->VarDictOption1 = "REGULAR";
    1206            0 :             state.dataGeneral->VarDictOption2 = "";
    1207              :         }
    1208              : 
    1209          801 :         cCurrentModuleObject = "Output:VariableDictionary";
    1210              : 
    1211          801 :         NumReports = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    1212         1597 :         for (RepNum = 1; RepNum <= NumReports; ++RepNum) {
    1213         1592 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1214              :                                                                      cCurrentModuleObject,
    1215              :                                                                      RepNum,
    1216          796 :                                                                      state.dataIPShortCut->cAlphaArgs,
    1217              :                                                                      NumNames,
    1218          796 :                                                                      state.dataIPShortCut->rNumericArgs,
    1219              :                                                                      NumNumbers,
    1220              :                                                                      IOStat,
    1221          796 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    1222          796 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    1223          796 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    1224          796 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    1225          796 :             state.dataGeneral->VarDict = true;
    1226          796 :             state.dataGeneral->VarDictOption1 = state.dataIPShortCut->cAlphaArgs(1);
    1227          796 :             state.dataGeneral->VarDictOption2 = state.dataIPShortCut->cAlphaArgs(2);
    1228              :         }
    1229              : 
    1230          801 :         cCurrentModuleObject = "Output:Constructions";
    1231          801 :         NumReports = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    1232         1121 :         for (RepNum = 1; RepNum <= NumReports; ++RepNum) {
    1233          640 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1234              :                                                                      cCurrentModuleObject,
    1235              :                                                                      RepNum,
    1236          320 :                                                                      state.dataIPShortCut->cAlphaArgs,
    1237              :                                                                      NumNames,
    1238          320 :                                                                      state.dataIPShortCut->rNumericArgs,
    1239              :                                                                      NumNumbers,
    1240              :                                                                      IOStat,
    1241          320 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    1242          320 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    1243          320 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    1244          320 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    1245          320 :             if (Util::SameString(state.dataIPShortCut->cAlphaArgs(1), "CONSTRUCTIONS")) {
    1246          309 :                 state.dataGeneral->Constructions = true;
    1247           11 :             } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(1), "MATERIALS")) {
    1248           11 :                 state.dataGeneral->Materials = true;
    1249              :             }
    1250          320 :             if (NumNames > 1) {
    1251            3 :                 if (Util::SameString(state.dataIPShortCut->cAlphaArgs(2), "CONSTRUCTIONS")) {
    1252            0 :                     state.dataGeneral->Constructions = true;
    1253            3 :                 } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(2), "MATERIALS")) {
    1254            3 :                     state.dataGeneral->Materials = true;
    1255              :                 }
    1256              :             }
    1257              :         }
    1258              : 
    1259          801 :         cCurrentModuleObject = "Output:EnergyManagementSystem";
    1260          801 :         NumReports = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    1261          842 :         for (RepNum = 1; RepNum <= NumReports; ++RepNum) {
    1262           82 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1263              :                                                                      cCurrentModuleObject,
    1264              :                                                                      RepNum,
    1265           41 :                                                                      state.dataIPShortCut->cAlphaArgs,
    1266              :                                                                      NumNames,
    1267           41 :                                                                      state.dataIPShortCut->rNumericArgs,
    1268              :                                                                      NumNumbers,
    1269              :                                                                      IOStat,
    1270           41 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    1271           41 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    1272           41 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    1273           41 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    1274              : 
    1275           41 :             state.dataGeneral->EMSoutput = true;
    1276              : 
    1277           41 :             AvailRpt CheckAvailRpt = static_cast<AvailRpt>(getEnumValue(AvailRptNamesUC, Util::makeUPPER(state.dataIPShortCut->cAlphaArgs(1))));
    1278           41 :             state.dataRuntimeLang->OutputEMSActuatorAvailSmall = (CheckAvailRpt == AvailRpt::NotByUniqueKeyNames);
    1279           41 :             state.dataRuntimeLang->OutputEMSActuatorAvailFull = (CheckAvailRpt == AvailRpt::Verbose);
    1280              : 
    1281           41 :             CheckAvailRpt = static_cast<AvailRpt>(getEnumValue(AvailRptNamesUC, Util::makeUPPER(state.dataIPShortCut->cAlphaArgs(2))));
    1282           41 :             state.dataRuntimeLang->OutputEMSInternalVarsSmall = (CheckAvailRpt == AvailRpt::NotByUniqueKeyNames);
    1283           41 :             state.dataRuntimeLang->OutputEMSInternalVarsFull = (CheckAvailRpt == AvailRpt::Verbose);
    1284              : 
    1285              :             ERLdebugOutputLevel CheckERLlevel =
    1286           41 :                 static_cast<ERLdebugOutputLevel>(getEnumValue(ERLdebugOutputLevelNamesUC, Util::makeUPPER(state.dataIPShortCut->cAlphaArgs(3))));
    1287           41 :             state.dataRuntimeLang->OutputEMSErrors =
    1288           41 :                 (CheckERLlevel == ERLdebugOutputLevel::ErrorsOnly || CheckERLlevel == ERLdebugOutputLevel::Verbose);
    1289           41 :             state.dataRuntimeLang->OutputFullEMSTrace = (CheckERLlevel == ERLdebugOutputLevel::Verbose);
    1290              :         }
    1291              : 
    1292          801 :         state.dataGeneral->GetReportInput = false;
    1293          801 :     }
    1294              : 
    1295              :     // Process the Scan Request
    1296        13617 :     DoReport = false;
    1297              : 
    1298        13617 :     ReportName rptName = static_cast<ReportName>(getEnumValue(ReportNamesUC, Util::makeUPPER(Util::makeUPPER(reportName))));
    1299        13617 :     switch (rptName) {
    1300         2404 :     case ReportName::Constructions: {
    1301         2404 :         if (present(ReportKey)) {
    1302         2404 :             if (Util::SameString(ReportKey(), "Constructions")) {
    1303         1603 :                 DoReport = state.dataGeneral->Constructions;
    1304              :             }
    1305         2404 :             if (Util::SameString(ReportKey(), "Materials")) {
    1306          801 :                 DoReport = state.dataGeneral->Materials;
    1307              :             }
    1308              :         }
    1309         2404 :     } break;
    1310         1602 :     case ReportName::Viewfactorinfo: {
    1311         1602 :         DoReport = state.dataGeneral->ViewFactorInfo;
    1312         1602 :         if (present(Option1)) {
    1313         1602 :             Option1 = state.dataGeneral->ViewRptOption1;
    1314              :         }
    1315         1602 :     } break;
    1316          800 :     case ReportName::Variabledictionary: {
    1317          800 :         DoReport = state.dataGeneral->VarDict;
    1318          800 :         if (present(Option1)) {
    1319          800 :             Option1 = state.dataGeneral->VarDictOption1;
    1320              :         }
    1321          800 :         if (present(Option2)) {
    1322          800 :             Option2 = state.dataGeneral->VarDictOption2;
    1323              :         }
    1324              :         //    CASE ('SCHEDULES')
    1325              :         //     DoReport=SchRpt
    1326              :         //      IF (PRESENT(Option1)) Option1=SchRptOption
    1327          800 :     } break;
    1328         7209 :     case ReportName::Surfaces: {
    1329         7209 :         RptKey rptKey = static_cast<RptKey>(getEnumValue(RptKeyNamesUC, Util::makeUPPER(ReportKey())));
    1330         7209 :         switch (rptKey) { // Autodesk:OPTIONAL ReportKey used without PRESENT check
    1331          801 :         case RptKey::Costinfo: {
    1332          801 :             DoReport = state.dataGeneral->CostInfo;
    1333          801 :         } break;
    1334          801 :         case RptKey::DXF: {
    1335          801 :             DoReport = state.dataGeneral->DXFReport;
    1336          801 :             if (present(Option1)) {
    1337          801 :                 Option1 = state.dataGeneral->DXFOption1;
    1338              :             }
    1339          801 :             if (present(Option2)) {
    1340          801 :                 Option2 = state.dataGeneral->DXFOption2;
    1341              :             }
    1342          801 :         } break;
    1343          801 :         case RptKey::DXFwireframe: {
    1344          801 :             DoReport = state.dataGeneral->DXFWFReport;
    1345          801 :             if (present(Option1)) {
    1346          801 :                 Option1 = state.dataGeneral->DXFWFOption1;
    1347              :             }
    1348          801 :             if (present(Option2)) {
    1349          801 :                 Option2 = state.dataGeneral->DXFWFOption2;
    1350              :             }
    1351          801 :         } break;
    1352          801 :         case RptKey::VRML: {
    1353          801 :             DoReport = state.dataGeneral->VRMLReport;
    1354          801 :             if (present(Option1)) {
    1355          801 :                 Option1 = state.dataGeneral->VRMLOption1;
    1356              :             }
    1357          801 :             if (present(Option2)) {
    1358          801 :                 Option2 = state.dataGeneral->VRMLOption2;
    1359              :             }
    1360          801 :         } break;
    1361          801 :         case RptKey::Vertices: {
    1362          801 :             DoReport = state.dataGeneral->SurfVert;
    1363          801 :         } break;
    1364         1602 :         case RptKey::Details: {
    1365         1602 :             DoReport = state.dataGeneral->SurfDet;
    1366         1602 :         } break;
    1367          801 :         case RptKey::DetailsWithVertices: {
    1368          801 :             DoReport = state.dataGeneral->SurfDetWVert;
    1369          801 :         } break;
    1370          801 :         case RptKey::Lines: {
    1371          801 :             DoReport = state.dataGeneral->LineRpt;
    1372          801 :             if (present(Option1)) {
    1373          801 :                 Option1 = state.dataGeneral->LineRptOption1;
    1374              :             }
    1375          801 :         } break;
    1376            0 :         default:
    1377            0 :             break;
    1378              :         }
    1379         7209 :     } break;
    1380         1602 :     case ReportName::Energymanagementsystem: {
    1381         1602 :         DoReport = state.dataGeneral->EMSoutput;
    1382         1602 :     } break;
    1383            0 :     default:
    1384            0 :         break;
    1385              :     }
    1386        14418 : }
    1387              : 
    1388           54 : void CheckCreatedZoneItemName(EnergyPlusData &state,
    1389              :                               std::string_view const calledFrom,              // routine called from
    1390              :                               std::string const &CurrentObject,               // object being parsed
    1391              :                               std::string const &ZoneName,                    // Zone Name associated
    1392              :                               std::string::size_type const MaxZoneNameLength, // maximum length of zonelist zone names
    1393              :                               std::string const &ItemName,                    // Item name (People, Lights, etc object)
    1394              :                               Array1_string const &ItemNames,                 // Item Names to check for duplication
    1395              :                               int const NumItems,                             // Number of items in ItemNames array
    1396              :                               std::string &ResultName,                        // Resultant name
    1397              :                               bool &errFlag                                   // Error flag set to true if error found here.
    1398              : )
    1399              : {
    1400              : 
    1401              :     // SUBROUTINE INFORMATION:
    1402              :     //       AUTHOR         Linda Lawrie
    1403              :     //       DATE WRITTEN   December 2012
    1404              : 
    1405              :     // PURPOSE OF THIS SUBROUTINE:
    1406              :     // This routine checks "global" objects (that is, ones with ZoneList used in the name
    1407              :     // specification) along with a specific name for the current object for length and duplication
    1408              :     // with previous objects of that class.
    1409              : 
    1410           54 :     errFlag = false;
    1411           54 :     std::string::size_type const ItemNameLength = len(ItemName);
    1412           54 :     std::string::size_type const ItemLength = len(ZoneName) + ItemNameLength;
    1413           54 :     ResultName = ZoneName + ' ' + ItemName;
    1414           54 :     bool TooLong = false;
    1415           54 :     if (ItemLength > Constant::MaxNameLength) {
    1416            0 :         ShowWarningError(state, fmt::format("{}{} Combination of ZoneList and Object Name generate a name too long.", calledFrom, CurrentObject));
    1417            0 :         ShowContinueError(state, format("Object Name=\"{}\".", ItemName));
    1418            0 :         ShowContinueError(state, format("ZoneList/Zone Name=\"{}\".", ZoneName));
    1419            0 :         ShowContinueError(state,
    1420            0 :                           format("Item length=[{}] > Maximum Length=[{}]. You may need to shorten the names.", ItemLength, Constant::MaxNameLength));
    1421            0 :         ShowContinueError(state,
    1422            0 :                           format("Shortening the Object Name by [{}] characters will assure uniqueness for this ZoneList.",
    1423            0 :                                  MaxZoneNameLength + 1 + ItemNameLength - Constant::MaxNameLength));
    1424            0 :         ShowContinueError(state, format("name that will be used (may be needed in reporting)=\"{}\".", ResultName));
    1425            0 :         TooLong = true;
    1426              :     }
    1427              : 
    1428           54 :     int FoundItem = Util::FindItemInList(ResultName, ItemNames, NumItems);
    1429              : 
    1430           54 :     if (FoundItem != 0) {
    1431            0 :         ShowSevereError(state, fmt::format("{}{}=\"{}\", Duplicate Generated name encountered.", calledFrom, CurrentObject, ItemName));
    1432            0 :         ShowContinueError(state, format("name=\"{}\" has already been generated or entered as {} item=[{}].", ResultName, CurrentObject, FoundItem));
    1433            0 :         if (TooLong) {
    1434            0 :             ShowContinueError(state, "Duplicate name likely caused by the previous \"too long\" warning.");
    1435              :         }
    1436            0 :         ResultName = "xxxxxxx";
    1437            0 :         errFlag = true;
    1438              :     }
    1439           54 : }
    1440              : 
    1441            0 : bool isReportPeriodBeginning(EnergyPlusData &state, const int periodIdx)
    1442              : {
    1443              :     int currentDate;
    1444            0 :     int reportStartDate = state.dataWeather->ReportPeriodInput(periodIdx).startJulianDate;
    1445            0 :     int reportStartHour = state.dataWeather->ReportPeriodInput(periodIdx).startHour;
    1446            0 :     if (state.dataWeather->ReportPeriodInput(periodIdx).startYear > 0) {
    1447            0 :         currentDate = Weather::computeJulianDate(state.dataEnvrn->Year, state.dataEnvrn->Month, state.dataEnvrn->DayOfMonth);
    1448              :     } else {
    1449            0 :         currentDate = Weather::computeJulianDate(0, state.dataEnvrn->Month, state.dataEnvrn->DayOfMonth);
    1450              :     }
    1451            0 :     return (currentDate == reportStartDate && state.dataGlobal->HourOfDay == reportStartHour);
    1452              : }
    1453              : 
    1454         5376 : void findReportPeriodIdx(EnergyPlusData &state,
    1455              :                          const Array1D<Weather::ReportPeriodData> &ReportPeriodInputData,
    1456              :                          const int nReportPeriods,
    1457              :                          Array1D_bool &inReportPeriodFlags)
    1458              : {
    1459              :     // return an array of flags, indicating whether the current time is in reporting period i
    1460              :     int currentDate;
    1461        12288 :     for (int i = 1; i <= nReportPeriods; i++) {
    1462         6912 :         int reportStartDate = ReportPeriodInputData(i).startJulianDate;
    1463         6912 :         int reportStartHour = ReportPeriodInputData(i).startHour;
    1464         6912 :         int reportEndDate = ReportPeriodInputData(i).endJulianDate;
    1465         6912 :         int reportEndHour = ReportPeriodInputData(i).endHour;
    1466         6912 :         if (ReportPeriodInputData(i).startYear > 0) {
    1467            0 :             currentDate = Weather::computeJulianDate(state.dataEnvrn->Year, state.dataEnvrn->Month, state.dataEnvrn->DayOfMonth);
    1468              :         } else {
    1469         6912 :             currentDate = Weather::computeJulianDate(0, state.dataEnvrn->Month, state.dataEnvrn->DayOfMonth);
    1470              :         }
    1471         6912 :         if (General::BetweenDateHoursLeftInclusive(
    1472         6912 :                 currentDate, state.dataGlobal->HourOfDay, reportStartDate, reportStartHour, reportEndDate, reportEndHour)) {
    1473            0 :             inReportPeriodFlags(i) = true;
    1474              :         }
    1475              :     }
    1476         5376 : }
    1477              : 
    1478          255 : Real64 rotAzmDiffDeg(Real64 AzmA, Real64 AzmB)
    1479              : {
    1480              :     // This function takes two (azimuth) angles in Degree(s),
    1481              :     // and returns the rotational angle difference in Degree(s).
    1482              : 
    1483          255 :     Real64 diff = AzmB - AzmA;
    1484          255 :     if (diff > 180.0) {
    1485           12 :         diff = 360.0 - diff;
    1486          243 :     } else if (diff < -180.0) {
    1487           14 :         diff = 360.0 + diff;
    1488              :     }
    1489          255 :     return std::abs(diff);
    1490              : }
    1491              : 
    1492              : } // namespace EnergyPlus::General
        

Generated by: LCOV version 2.0-1