LCOV - code coverage report
Current view: top level - EnergyPlus - UtilityRoutines.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 62.0 % 810 502
Test Date: 2025-07-17 05:04:31 Functions: 56.1 % 66 37

            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              : // FMI-Related Headers
      49              : extern "C" {
      50              : #include <FMI/main.h>
      51              : }
      52              : 
      53              : // C++ Headers
      54              : #include <cstdlib>
      55              : #include <iostream>
      56              : 
      57              : // ObjexxFCL Headers
      58              : #include <ObjexxFCL/Array1D.hh>
      59              : #include <ObjexxFCL/Array1S.hh>
      60              : #include <ObjexxFCL/char.functions.hh>
      61              : #include <ObjexxFCL/string.functions.hh>
      62              : 
      63              : // EnergyPlus Headers
      64              : #include <EnergyPlus/BranchInputManager.hh>
      65              : #include <EnergyPlus/BranchNodeConnections.hh>
      66              : // #include <EnergyPlus/Data/EnergyPlusData.hh>
      67              : #include <EnergyPlus/DataEnvironment.hh>
      68              : #include <EnergyPlus/DataErrorTracking.hh>
      69              : // #include <EnergyPlus/DataGlobalConstants.hh>
      70              : #include <EnergyPlus/DataReportingFlags.hh>
      71              : #include <EnergyPlus/DataStringGlobals.hh>
      72              : #include <EnergyPlus/DataSystemVariables.hh>
      73              : // #include <EnergyPlus/DataTimings.hh>
      74              : #include <EnergyPlus/DaylightingManager.hh>
      75              : // #include <EnergyPlus/DisplayRoutines.hh>
      76              : #include <EnergyPlus/ExternalInterface.hh>
      77              : #include <EnergyPlus/FileSystem.hh>
      78              : #include <EnergyPlus/General.hh>
      79              : #include <EnergyPlus/GeneralRoutines.hh>
      80              : // #include <EnergyPlus/IOFiles.hh>
      81              : #include <EnergyPlus/NodeInputManager.hh>
      82              : #include <EnergyPlus/OutputReports.hh>
      83              : #include <EnergyPlus/Plant/PlantManager.hh>
      84              : #include <EnergyPlus/ResultsFramework.hh>
      85              : #include <EnergyPlus/SQLiteProcedures.hh>
      86              : #include <EnergyPlus/SimulationManager.hh>
      87              : #include <EnergyPlus/SolarShading.hh>
      88              : #include <EnergyPlus/SystemReports.hh>
      89              : #include <EnergyPlus/Timer.hh>
      90              : #include <EnergyPlus/UtilityRoutines.hh>
      91              : // Third Party Headers
      92              : #include <fast_float/fast_float.h>
      93              : 
      94              : namespace EnergyPlus {
      95              : 
      96              : namespace Util {
      97              : 
      98      2082737 :     Real64 ProcessNumber(std::string_view String, bool &ErrorFlag)
      99              :     {
     100              : 
     101              :         // FUNCTION INFORMATION:
     102              :         //       AUTHOR         Linda K. Lawrie
     103              :         //       DATE WRITTEN   September 1997
     104              : 
     105              :         // PURPOSE OF THIS FUNCTION:
     106              :         // This function processes a string that should be numeric and
     107              :         // returns the real value of the string.
     108              : 
     109              :         // METHODOLOGY EMPLOYED:
     110              :         // FUNCTION ProcessNumber translates the argument (a string)
     111              :         // into a real number.  The string should consist of all
     112              :         // numeric characters (except a decimal point).  Numerics
     113              :         // with exponentiation (i.e. 1.2345E+03) are allowed but if
     114              :         // it is not a valid number an error message along with the
     115              :         // string causing the error is printed out and 0.0 is returned
     116              :         // as the value.
     117              : 
     118              :         // REFERENCES:
     119              :         // List directed Fortran input/output.
     120              : 
     121              :         // SUBROUTINE PARAMETER DEFINITIONS:
     122      2082737 :         Real64 rProcessNumber = 0.0;
     123      2082737 :         ErrorFlag = false;
     124              : 
     125      2082737 :         if (String.empty()) {
     126            9 :             return rProcessNumber;
     127              :         }
     128              : 
     129      2082728 :         size_t const front_trim = String.find_first_not_of(' ');
     130      2082728 :         size_t const back_trim = String.find_last_not_of(' ');
     131      2082728 :         if (front_trim == std::string::npos || back_trim == std::string::npos) {
     132            0 :             return rProcessNumber;
     133              :         } else {
     134      2082728 :             String = String.substr(front_trim, back_trim - front_trim + 1);
     135              :         }
     136              : 
     137      2082728 :         auto result = fast_float::from_chars(String.data(), String.data() + String.size(), rProcessNumber); // (AUTO_OK_OBJ)
     138      2082728 :         size_t remaining_size = result.ptr - String.data();
     139      2082728 :         if (result.ec == std::errc::result_out_of_range || result.ec == std::errc::invalid_argument) {
     140         6534 :             rProcessNumber = 0.0;
     141         6534 :             ErrorFlag = true;
     142      2076194 :         } else if (remaining_size != String.size()) {
     143        35023 :             if (*result.ptr == '+' || *result.ptr == '-') {
     144            0 :                 ++result.ptr;
     145            0 :                 remaining_size = result.ptr - String.data();
     146            0 :                 if (remaining_size == String.size()) {
     147            0 :                     rProcessNumber = 0.0;
     148            0 :                     ErrorFlag = true;
     149              :                 }
     150              :             }
     151        35023 :             if (*result.ptr == 'd' || *result.ptr == 'D') {
     152              :                 // make FORTRAN floating point number (containing 'd' or 'D')
     153              :                 // standardized by replacing 'd' or 'D' with 'e'
     154           25 :                 std::string str{String};
     155          210 :                 std::replace_if(str.begin(), str.end(), [](const char c) { return c == 'D' || c == 'd'; }, 'e');
     156           25 :                 return ProcessNumber(str, ErrorFlag);
     157        35023 :             } else if (*result.ptr == 'e' || *result.ptr == 'E') {
     158            0 :                 ++result.ptr;
     159            0 :                 remaining_size = result.ptr - String.data();
     160            0 :                 for (size_t i = remaining_size; i < String.size(); ++i, ++result.ptr) {
     161            0 :                     if (!std::isdigit(*result.ptr)) {
     162            0 :                         rProcessNumber = 0.0;
     163            0 :                         ErrorFlag = true;
     164            0 :                         return rProcessNumber;
     165              :                     }
     166              :                 }
     167            0 :             } else {
     168        34998 :                 rProcessNumber = 0.0;
     169        34998 :                 ErrorFlag = true;
     170              :             }
     171      2041171 :         } else if (!std::isfinite(rProcessNumber)) {
     172            0 :             rProcessNumber = 0.0;
     173            0 :             ErrorFlag = true;
     174              :         }
     175              : 
     176      2082703 :         return rProcessNumber;
     177              :     }
     178              : 
     179      1454183 :     int FindItemInList(std::string_view const String, Array1_string const &ListOfItems, int const NumItems)
     180              :     {
     181              : 
     182              :         // FUNCTION INFORMATION:
     183              :         //       AUTHOR         Linda K. Lawrie
     184              :         //       DATE WRITTEN   September 1997
     185              : 
     186              :         // PURPOSE OF THIS FUNCTION:
     187              :         // This function looks up a string in a similar list of
     188              :         // items and returns the index of the item in the list, if
     189              :         // found.  This routine is not case insensitive and doesn't need
     190              :         // for most inputs -- they are automatically turned to UPPERCASE.
     191              :         // If you need case insensitivity use FindItem.
     192              : 
     193     13118060 :         for (int Count = 1; Count <= NumItems; ++Count) {
     194     11765515 :             if (String == ListOfItems(Count)) {
     195       101638 :                 return Count;
     196              :             }
     197              :         }
     198      1352545 :         return 0; // Not found
     199              :     }
     200              : 
     201       298815 :     int FindItemInList(std::string_view const String, Array1S_string const ListOfItems, int const NumItems)
     202              :     {
     203              : 
     204              :         // FUNCTION INFORMATION:
     205              :         //       AUTHOR         Linda K. Lawrie
     206              :         //       DATE WRITTEN   September 1997
     207              : 
     208              :         // PURPOSE OF THIS FUNCTION:
     209              :         // This function looks up a string in a similar list of
     210              :         // items and returns the index of the item in the list, if
     211              :         // found.  This routine is not case insensitive and doesn't need
     212              :         // for most inputs -- they are automatically turned to UPPERCASE.
     213              :         // If you need case insensitivity use FindItem.
     214              : 
     215     37396714 :         for (int Count = 1; Count <= NumItems; ++Count) {
     216     37326822 :             if (String == ListOfItems(Count)) {
     217       228923 :                 return Count;
     218              :             }
     219              :         }
     220        69892 :         return 0; // Not found
     221              :     }
     222              : 
     223         1946 :     int FindItemInSortedList(std::string_view const String, Array1S_string const ListOfItems, int const NumItems)
     224              :     {
     225              : 
     226              :         // FUNCTION INFORMATION:
     227              :         //       AUTHOR         Linda K. Lawrie
     228              :         //       DATE WRITTEN   September 1997
     229              : 
     230              :         // PURPOSE OF THIS FUNCTION:
     231              :         // This function looks up a string in a similar list of
     232              :         // items and returns the index of the item in the list, if
     233              :         // found.  This routine is case insensitive.
     234              : 
     235              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     236         1946 :         int Probe = 0;
     237         1946 :         int LBnd = 0;
     238         1946 :         int UBnd = NumItems + 1;
     239         1946 :         bool Found = false;
     240         4062 :         while ((!Found) || (Probe != 0)) {
     241         4062 :             Probe = (UBnd - LBnd) / 2;
     242         4062 :             if (Probe == 0) {
     243            0 :                 break;
     244              :             }
     245         4062 :             Probe += LBnd;
     246         4062 :             if (equali(String, ListOfItems(Probe))) {
     247         1946 :                 Found = true;
     248         1946 :                 break;
     249         2116 :             } else if (lessthani(String, ListOfItems(Probe))) {
     250         1955 :                 UBnd = Probe;
     251              :             } else {
     252          161 :                 LBnd = Probe;
     253              :             }
     254              :         }
     255         1946 :         return Probe;
     256              :     }
     257              : 
     258         4304 :     int FindItem(std::string_view const String, Array1D_string const &ListOfItems, int const NumItems)
     259              :     {
     260              : 
     261              :         // FUNCTION INFORMATION:
     262              :         //       AUTHOR         Linda K. Lawrie
     263              :         //       DATE WRITTEN   April 1999
     264              : 
     265              :         // PURPOSE OF THIS FUNCTION:
     266              :         // This function looks up a string in a similar list of
     267              :         // items and returns the index of the item in the list, if
     268              :         // found.  This routine is case insensitive.
     269              : 
     270         4304 :         int FindItem = Util::FindItemInList(String, ListOfItems, NumItems);
     271         4304 :         if (FindItem != 0) {
     272           23 :             return FindItem;
     273              :         }
     274              : 
     275        27944 :         for (int Count = 1; Count <= NumItems; ++Count) {
     276        27944 :             if (equali(String, ListOfItems(Count))) {
     277         4281 :                 return Count;
     278              :             }
     279              :         }
     280            0 :         return 0; // Not found
     281              :     }
     282              : 
     283            0 :     int FindItem(std::string_view const String, Array1S_string const ListOfItems, int const NumItems)
     284              :     {
     285              : 
     286              :         // FUNCTION INFORMATION:
     287              :         //       AUTHOR         Linda K. Lawrie
     288              :         //       DATE WRITTEN   April 1999
     289              : 
     290              :         // PURPOSE OF THIS FUNCTION:
     291              :         // This function looks up a string in a similar list of
     292              :         // items and returns the index of the item in the list, if
     293              :         // found.  This routine is case insensitive.
     294              : 
     295              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     296              : 
     297            0 :         int FindItem = Util::FindItemInList(String, ListOfItems, NumItems);
     298            0 :         if (FindItem != 0) {
     299            0 :             return FindItem;
     300              :         }
     301              : 
     302            0 :         for (int Count = 1; Count <= NumItems; ++Count) {
     303            0 :             if (equali(String, ListOfItems(Count))) {
     304            0 :                 return Count;
     305              :             }
     306              :         }
     307            0 :         return 0; // Not found
     308              :     }
     309              : 
     310            0 :     void VerifyName(EnergyPlusData &state,
     311              :                     std::string const &NameToVerify,
     312              :                     Array1D_string const &NamesList,
     313              :                     int const NumOfNames,
     314              :                     bool &ErrorFound,
     315              :                     bool &IsBlank,
     316              :                     std::string const &StringToDisplay)
     317              :     {
     318              : 
     319              :         // SUBROUTINE INFORMATION:
     320              :         //       AUTHOR         Linda Lawrie
     321              :         //       DATE WRITTEN   February 2000
     322              : 
     323              :         // PURPOSE OF THIS SUBROUTINE:
     324              :         // This subroutine verifys that a new name can be added to the
     325              :         // list of names for this item (i.e., that there isn't one of that
     326              :         // name already and that this name is not blank).
     327              : 
     328            0 :         ErrorFound = false;
     329            0 :         if (NumOfNames > 0) {
     330            0 :             int Found = FindItem(NameToVerify, NamesList, NumOfNames);
     331            0 :             if (Found != 0) {
     332            0 :                 ShowSevereError(state, format("{}, duplicate name={}", StringToDisplay, NameToVerify));
     333            0 :                 ErrorFound = true;
     334              :             }
     335              :         }
     336              : 
     337            0 :         if (NameToVerify.empty()) {
     338            0 :             ShowSevereError(state, format("{}, cannot be blank", StringToDisplay));
     339            0 :             ErrorFound = true;
     340            0 :             IsBlank = true;
     341              :         } else {
     342            0 :             IsBlank = false;
     343              :         }
     344            0 :     }
     345              : 
     346            0 :     void VerifyName(EnergyPlusData &state,
     347              :                     std::string const &NameToVerify,
     348              :                     Array1S_string const NamesList,
     349              :                     int const NumOfNames,
     350              :                     bool &ErrorFound,
     351              :                     bool &IsBlank,
     352              :                     std::string const &StringToDisplay)
     353              :     {
     354              : 
     355              :         // SUBROUTINE INFORMATION:
     356              :         //       AUTHOR         Linda Lawrie
     357              :         //       DATE WRITTEN   February 2000
     358              : 
     359              :         // PURPOSE OF THIS SUBROUTINE:
     360              :         // This subroutine verifys that a new name can be added to the
     361              :         // list of names for this item (i.e., that there isn't one of that
     362              :         // name already and that this name is not blank).
     363              : 
     364            0 :         ErrorFound = false;
     365            0 :         if (NumOfNames > 0) {
     366            0 :             int Found = FindItem(NameToVerify, NamesList, NumOfNames);
     367            0 :             if (Found != 0) {
     368            0 :                 ShowSevereError(state, format("{}, duplicate name={}", StringToDisplay, NameToVerify));
     369            0 :                 ErrorFound = true;
     370              :             }
     371              :         }
     372              : 
     373            0 :         if (NameToVerify.empty()) {
     374            0 :             ShowSevereError(state, format("{}, cannot be blank", StringToDisplay));
     375            0 :             ErrorFound = true;
     376            0 :             IsBlank = true;
     377              :         } else {
     378            0 :             IsBlank = false;
     379              :         }
     380            0 :     }
     381              : 
     382        49877 :     bool IsNameEmpty(EnergyPlusData &state, std::string &NameToVerify, std::string_view StringToDisplay, bool &ErrorFound)
     383              :     {
     384        49877 :         if (NameToVerify.empty()) {
     385            0 :             ShowSevereError(state, format("{} Name, cannot be blank", StringToDisplay));
     386            0 :             ErrorFound = true;
     387            0 :             NameToVerify = "xxxxx";
     388            0 :             return true;
     389              :         }
     390        49877 :         return false;
     391              :     }
     392              : 
     393           92 :     void setDesignObjectNameAndPointer(EnergyPlusData &state,
     394              :                                        std::string &nameToBeSet,
     395              :                                        int &ptrToBeSet,
     396              :                                        std::string const userName,
     397              :                                        Array1S_string const listOfNames,
     398              :                                        std::string const itemType,
     399              :                                        std::string const itemName,
     400              :                                        bool &errorFound)
     401              :     {
     402           92 :         nameToBeSet = userName;
     403           92 :         ptrToBeSet = FindItemInList(nameToBeSet, listOfNames);
     404              :         // If ptrToBeSet is greater than zero, everything is fine--a valid match was found, continue on.
     405              :         // If ptrToBeSet is less than or equal to zero, either the user entered a blank or an invalid name.  When this
     406              :         // happens, error out and provide user with some indication as to what the problem was using the type and names
     407              :         // sent to this routine.
     408           92 :         if (ptrToBeSet <= 0) { // No valid pointer--error in user input
     409            0 :             errorFound = true;
     410            0 :             ShowSevereError(state, format("Object = {} with the Name = {} has an invalid Design Object Name = {}.", itemType, itemName, nameToBeSet));
     411            0 :             ShowContinueError(state, "  The Design Object Name was not found or was left blank.  This is not allowed.");
     412            0 :             ShowContinueError(state, format("  A valid Design Object Name must be provided for any {} object.", itemType));
     413              :         }
     414           92 :     }
     415              : 
     416            0 :     size_t case_insensitive_hasher::operator()(std::string_view const key) const noexcept
     417              :     {
     418            0 :         std::string keyCopy = makeUPPER(key);
     419            0 :         return std::hash<std::string>()(keyCopy);
     420            0 :     }
     421              : 
     422     43127621 :     bool case_insensitive_comparator::operator()(std::string_view const a, std::string_view const b) const noexcept
     423              :     {
     424     43127621 :         return lessthani(a, b); // SameString(a, b);
     425              :     }
     426              : 
     427          138 :     void appendPerfLog(EnergyPlusData &state, std::string const &colHeader, std::string const &colValue, bool finalColumn)
     428              :     // Add column to the performance log file (comma separated) which is appended to existing log.
     429              :     // The finalColumn (an optional argument) being true triggers the actual file to be written or appended.
     430              :     // J.Glazer February 2020
     431              :     {
     432              :         // the following was added for unit testing to clear the static strings
     433          138 :         if (colHeader == "RESET" && colValue == "RESET") {
     434            0 :             state.dataUtilityRoutines->appendPerfLog_headerRow = "";
     435            0 :             state.dataUtilityRoutines->appendPerfLog_valuesRow = "";
     436            0 :             return;
     437              :         }
     438              : 
     439              :         // accumulate the row until ready to be written to the file.
     440          138 :         state.dataUtilityRoutines->appendPerfLog_headerRow = state.dataUtilityRoutines->appendPerfLog_headerRow + colHeader + ",";
     441          138 :         state.dataUtilityRoutines->appendPerfLog_valuesRow = state.dataUtilityRoutines->appendPerfLog_valuesRow + colValue + ",";
     442              : 
     443          138 :         if (finalColumn) {
     444            4 :             std::fstream fsPerfLog;
     445            4 :             if (!FileSystem::fileExists(state.dataStrGlobals->outputPerfLogFilePath)) {
     446            4 :                 if (state.files.outputControl.perflog) {
     447            3 :                     fsPerfLog.open(state.dataStrGlobals->outputPerfLogFilePath, std::fstream::out); // open file normally
     448            3 :                     if (!fsPerfLog) {
     449            0 :                         ShowFatalError(
     450              :                             state,
     451            0 :                             format("appendPerfLog: Could not open file \"{}\" for output (write).", state.dataStrGlobals->outputPerfLogFilePath));
     452              :                     }
     453            3 :                     fsPerfLog << state.dataUtilityRoutines->appendPerfLog_headerRow << std::endl;
     454            3 :                     fsPerfLog << state.dataUtilityRoutines->appendPerfLog_valuesRow << std::endl;
     455              :                 }
     456              :             } else {
     457            0 :                 if (state.files.outputControl.perflog) {
     458            0 :                     fsPerfLog.open(state.dataStrGlobals->outputPerfLogFilePath, std::fstream::app); // append to already existing file
     459            0 :                     if (!fsPerfLog) {
     460            0 :                         ShowFatalError(
     461              :                             state,
     462            0 :                             format("appendPerfLog: Could not open file \"{}\" for output (append).", state.dataStrGlobals->outputPerfLogFilePath));
     463              :                     }
     464            0 :                     fsPerfLog << state.dataUtilityRoutines->appendPerfLog_valuesRow << std::endl;
     465              :                 }
     466              :             }
     467            4 :             fsPerfLog.close();
     468            4 :         }
     469              :     }
     470              : } // namespace Util
     471              : 
     472           23 : int AbortEnergyPlus(EnergyPlusData &state)
     473              : {
     474              : 
     475              :     // SUBROUTINE INFORMATION:
     476              :     //       AUTHOR         Linda K. Lawrie
     477              :     //       DATE WRITTEN   December 1997
     478              : 
     479              :     // PURPOSE OF THIS SUBROUTINE:
     480              :     // This subroutine causes the program to halt due to a fatal error.
     481              : 
     482              :     // METHODOLOGY EMPLOYED:
     483              :     // Puts a message on output files. Closes files. Stops the program.
     484              : 
     485              :     // SUBROUTINE PARAMETER DEFINITIONS:
     486           23 :     std::string NumWarnings;
     487           23 :     std::string NumSevere;
     488           23 :     std::string NumWarningsDuringWarmup;
     489           23 :     std::string NumSevereDuringWarmup;
     490           23 :     std::string NumWarningsDuringSizing;
     491           23 :     std::string NumSevereDuringSizing;
     492              : 
     493           23 :     if (state.dataSQLiteProcedures->sqlite) {
     494            9 :         state.dataSQLiteProcedures->sqlite->updateSQLiteSimulationRecord(true, false);
     495              :     }
     496              : 
     497           23 :     state.dataErrTracking->AbortProcessing = true;
     498           23 :     if (state.dataErrTracking->AskForConnectionsReport) {
     499            0 :         state.dataErrTracking->AskForConnectionsReport = false; // Set false here in case any further fatal errors in below processing...
     500              : 
     501            0 :         ShowMessage(state, "Fatal error -- final processing.  More error messages may appear.");
     502            0 :         NodeInputManager::SetupNodeVarsForReporting(state);
     503              : 
     504            0 :         bool ErrFound = false;
     505            0 :         bool TerminalError = false;
     506            0 :         BranchInputManager::TestBranchIntegrity(state, ErrFound);
     507            0 :         if (ErrFound) {
     508            0 :             TerminalError = true;
     509              :         }
     510            0 :         TestAirPathIntegrity(state, ErrFound);
     511            0 :         if (ErrFound) {
     512            0 :             TerminalError = true;
     513              :         }
     514            0 :         NodeInputManager::CheckMarkedNodes(state, ErrFound);
     515            0 :         if (ErrFound) {
     516            0 :             TerminalError = true;
     517              :         }
     518            0 :         BranchNodeConnections::CheckNodeConnections(state, ErrFound);
     519            0 :         if (ErrFound) {
     520            0 :             TerminalError = true;
     521              :         }
     522            0 :         BranchNodeConnections::TestCompSetInletOutletNodes(state, ErrFound);
     523            0 :         if (ErrFound) {
     524            0 :             TerminalError = true;
     525              :         }
     526              : 
     527            0 :         if (!TerminalError) {
     528            0 :             SystemReports::ReportAirLoopConnections(state);
     529            0 :             SimulationManager::ReportLoopConnections(state);
     530              :         }
     531              : 
     532           23 :     } else if (!state.dataErrTracking->ExitDuringSimulations) {
     533           42 :         ShowMessage(state, "Warning:  Node connection errors not checked - most system input has not been read (see previous warning).");
     534           63 :         ShowMessage(state, "Fatal error -- final processing.  Program exited before simulations began.  See previous error messages.");
     535              :     }
     536              : 
     537           23 :     if (state.dataErrTracking->AskForSurfacesReport) {
     538           21 :         ReportSurfaces(state);
     539              :     }
     540              : 
     541           23 :     SolarShading::ReportSurfaceErrors(state);
     542           23 :     PlantManager::CheckPlantOnAbort(state);
     543           23 :     ShowRecurringErrors(state);
     544           23 :     SummarizeErrors(state);
     545           23 :     CloseMiscOpenFiles(state);
     546           23 :     NumWarnings = fmt::to_string(state.dataErrTracking->TotalWarningErrors);
     547           23 :     NumSevere = fmt::to_string(state.dataErrTracking->TotalSevereErrors);
     548           23 :     NumWarningsDuringWarmup = fmt::to_string(state.dataErrTracking->TotalWarningErrorsDuringWarmup);
     549           23 :     NumSevereDuringWarmup = fmt::to_string(state.dataErrTracking->TotalSevereErrorsDuringWarmup);
     550           23 :     NumWarningsDuringSizing = fmt::to_string(state.dataErrTracking->TotalWarningErrorsDuringSizing);
     551           23 :     NumSevereDuringSizing = fmt::to_string(state.dataErrTracking->TotalSevereErrorsDuringSizing);
     552              : 
     553              :     // catch up with timings if in middle
     554           23 :     state.dataSysVars->runtimeTimer.tock();
     555           23 :     const std::string Elapsed = state.dataSysVars->runtimeTimer.formatAsHourMinSecs();
     556              : 
     557           23 :     state.dataResultsFramework->resultsFramework->SimulationInformation.setRunTime(Elapsed);
     558           23 :     state.dataResultsFramework->resultsFramework->SimulationInformation.setNumErrorsWarmup(NumWarningsDuringWarmup, NumSevereDuringWarmup);
     559           23 :     state.dataResultsFramework->resultsFramework->SimulationInformation.setNumErrorsSizing(NumWarningsDuringSizing, NumSevereDuringSizing);
     560           23 :     state.dataResultsFramework->resultsFramework->SimulationInformation.setNumErrorsSummary(NumWarnings, NumSevere);
     561              : 
     562           46 :     ShowMessage(
     563              :         state,
     564           46 :         format("EnergyPlus Warmup Error Summary. During Warmup: {} Warning; {} Severe Errors.", NumWarningsDuringWarmup, NumSevereDuringWarmup));
     565           46 :     ShowMessage(
     566              :         state,
     567           46 :         format("EnergyPlus Sizing Error Summary. During Sizing: {} Warning; {} Severe Errors.", NumWarningsDuringSizing, NumSevereDuringSizing));
     568           46 :     ShowMessage(
     569           46 :         state, format("EnergyPlus Terminated--Fatal Error Detected. {} Warning; {} Severe Errors; Elapsed Time={}", NumWarnings, NumSevere, Elapsed));
     570           23 :     DisplayString(state, "EnergyPlus Run Time=" + Elapsed);
     571              : 
     572              :     {
     573           23 :         auto tempfl = state.files.endFile.try_open(state.files.outputControl.end);
     574              : 
     575           23 :         if (!tempfl.good()) {
     576            0 :             DisplayString(state, fmt::format("AbortEnergyPlus: Could not open file {} for output (write).", tempfl.filePath));
     577              :         }
     578           23 :         print(
     579              :             tempfl, "EnergyPlus Terminated--Fatal Error Detected. {} Warning; {} Severe Errors; Elapsed Time={}\n", NumWarnings, NumSevere, Elapsed);
     580           23 :     }
     581              : 
     582           23 :     state.dataResultsFramework->resultsFramework->writeOutputs(state);
     583              : 
     584           23 :     std::cerr << "Program terminated: " << "EnergyPlus Terminated--Error(s) Detected." << std::endl;
     585              :     // Close the socket used by ExternalInterface. This call also sends the flag "-1" to the ExternalInterface,
     586              :     // indicating that E+ terminated with an error.
     587           23 :     if (state.dataExternalInterface->NumExternalInterfaces > 0) {
     588            0 :         ExternalInterface::CloseSocket(state, -1);
     589              :     }
     590              : 
     591           23 :     if (state.dataGlobal->eplusRunningViaAPI) {
     592            0 :         state.files.flushAll();
     593              :     }
     594              : 
     595              :     // The audit file seems to be held open in some cases, make sure it is closed before leaving.
     596              :     // EnergyPlus can close through two paths: EndEnergyPlus and AbortEnergyPlus, so do the same thing there.
     597           23 :     state.files.audit.close();
     598              : 
     599           23 :     return EXIT_FAILURE;
     600           23 : }
     601              : 
     602          803 : void CloseMiscOpenFiles(EnergyPlusData &state)
     603              : {
     604              : 
     605              :     // SUBROUTINE INFORMATION:
     606              :     //       AUTHOR         Linda K. Lawrie
     607              :     //       DATE WRITTEN   December 1997
     608              : 
     609              :     // PURPOSE OF THIS SUBROUTINE:
     610              :     // This subroutine scans potential unit numbers and closes
     611              :     // any that are still open.
     612              : 
     613              :     // METHODOLOGY EMPLOYED:
     614              :     // Use INQUIRE to determine if file is open.
     615              : 
     616          803 :     Dayltg::CloseReportIllumMaps(state);
     617          803 :     Dayltg::CloseDFSFile(state);
     618              : 
     619          803 :     if (state.dataReportFlag->DebugOutput || (state.files.debug.good() && state.files.debug.position() > 0)) {
     620            2 :         state.files.debug.close();
     621              :     } else {
     622          801 :         state.files.debug.del();
     623              :     }
     624          803 : }
     625              : 
     626          780 : int EndEnergyPlus(EnergyPlusData &state)
     627              : {
     628              : 
     629              :     // SUBROUTINE INFORMATION:
     630              :     //       AUTHOR         Linda K. Lawrie
     631              :     //       DATE WRITTEN   December 1997
     632              : 
     633              :     // PURPOSE OF THIS SUBROUTINE:
     634              :     // This subroutine causes the program to terminate when complete (no errors).
     635              : 
     636              :     // METHODOLOGY EMPLOYED:
     637              :     // Puts a message on output files. Closes files. Stops the program.
     638              : 
     639          780 :     std::string NumWarnings;
     640          780 :     std::string NumSevere;
     641          780 :     std::string NumWarningsDuringWarmup;
     642          780 :     std::string NumSevereDuringWarmup;
     643          780 :     std::string NumWarningsDuringSizing;
     644          780 :     std::string NumSevereDuringSizing;
     645              : 
     646          780 :     if (state.dataSQLiteProcedures->sqlite) {
     647            0 :         state.dataSQLiteProcedures->sqlite->updateSQLiteSimulationRecord(true, true);
     648              :     }
     649              : 
     650          780 :     SolarShading::ReportSurfaceErrors(state);
     651          780 :     ShowRecurringErrors(state);
     652          780 :     SummarizeErrors(state);
     653          780 :     CloseMiscOpenFiles(state);
     654          780 :     NumWarnings = fmt::to_string(state.dataErrTracking->TotalWarningErrors);
     655          780 :     strip(NumWarnings);
     656          780 :     NumSevere = fmt::to_string(state.dataErrTracking->TotalSevereErrors);
     657          780 :     strip(NumSevere);
     658          780 :     NumWarningsDuringWarmup = fmt::to_string(state.dataErrTracking->TotalWarningErrorsDuringWarmup);
     659          780 :     strip(NumWarningsDuringWarmup);
     660          780 :     NumSevereDuringWarmup = fmt::to_string(state.dataErrTracking->TotalSevereErrorsDuringWarmup);
     661          780 :     strip(NumSevereDuringWarmup);
     662          780 :     NumWarningsDuringSizing = fmt::to_string(state.dataErrTracking->TotalWarningErrorsDuringSizing);
     663          780 :     strip(NumWarningsDuringSizing);
     664          780 :     NumSevereDuringSizing = fmt::to_string(state.dataErrTracking->TotalSevereErrorsDuringSizing);
     665          780 :     strip(NumSevereDuringSizing);
     666              : 
     667          780 :     state.dataSysVars->runtimeTimer.tock();
     668          780 :     if (state.dataGlobal->createPerfLog) {
     669           12 :         Util::appendPerfLog(state, "Run Time [seconds]", format("{:.2R}", state.dataSysVars->runtimeTimer.elapsedSeconds()));
     670              :     }
     671          780 :     const std::string Elapsed = state.dataSysVars->runtimeTimer.formatAsHourMinSecs();
     672          780 :     state.dataResultsFramework->resultsFramework->SimulationInformation.setRunTime(Elapsed);
     673          780 :     state.dataResultsFramework->resultsFramework->SimulationInformation.setNumErrorsWarmup(NumWarningsDuringWarmup, NumSevereDuringWarmup);
     674          780 :     state.dataResultsFramework->resultsFramework->SimulationInformation.setNumErrorsSizing(NumWarningsDuringSizing, NumSevereDuringSizing);
     675          780 :     state.dataResultsFramework->resultsFramework->SimulationInformation.setNumErrorsSummary(NumWarnings, NumSevere);
     676              : 
     677          780 :     if (state.dataGlobal->createPerfLog) {
     678            8 :         Util::appendPerfLog(state, "Run Time [string]", Elapsed);
     679            8 :         Util::appendPerfLog(state, "Number of Warnings", NumWarnings);
     680            8 :         Util::appendPerfLog(state, "Number of Severe", NumSevere, true); // last item so write the perfLog file
     681              :     }
     682         1560 :     ShowMessage(
     683              :         state,
     684         1560 :         format("EnergyPlus Warmup Error Summary. During Warmup: {} Warning; {} Severe Errors.", NumWarningsDuringWarmup, NumSevereDuringWarmup));
     685         1560 :     ShowMessage(
     686              :         state,
     687         1560 :         format("EnergyPlus Sizing Error Summary. During Sizing: {} Warning; {} Severe Errors.", NumWarningsDuringSizing, NumSevereDuringSizing));
     688          780 :     ShowMessage(state, format("EnergyPlus Completed Successfully-- {} Warning; {} Severe Errors; Elapsed Time={}", NumWarnings, NumSevere, Elapsed));
     689          780 :     DisplayString(state, "EnergyPlus Run Time=" + Elapsed);
     690              : 
     691              :     {
     692          780 :         auto tempfl = state.files.endFile.try_open(state.files.outputControl.end);
     693          780 :         if (!tempfl.good()) {
     694            0 :             DisplayString(state, fmt::format("EndEnergyPlus: Could not open file {} for output (write).", tempfl.filePath));
     695              :         }
     696          780 :         print(tempfl, "EnergyPlus Completed Successfully-- {} Warning; {} Severe Errors; Elapsed Time={}\n", NumWarnings, NumSevere, Elapsed);
     697          780 :     }
     698              : 
     699          780 :     state.dataResultsFramework->resultsFramework->writeOutputs(state);
     700              : 
     701          780 :     if (state.dataGlobal->printConsoleOutput) {
     702          780 :         std::cerr << "EnergyPlus Completed Successfully." << std::endl;
     703              :     }
     704              :     // Close the ExternalInterface socket. This call also sends the flag "1" to the ExternalInterface,
     705              :     // indicating that E+ finished its simulation
     706          780 :     if ((state.dataExternalInterface->NumExternalInterfaces > 0) && state.dataExternalInterface->haveExternalInterfaceBCVTB) {
     707            0 :         ExternalInterface::CloseSocket(state, 1);
     708              :     }
     709              : 
     710          780 :     if (state.dataGlobal->fProgressPtr) {
     711            0 :         state.dataGlobal->fProgressPtr(100);
     712              :     }
     713          780 :     if (state.dataGlobal->progressCallback) {
     714            0 :         state.dataGlobal->progressCallback(100);
     715              :     }
     716              : 
     717          780 :     if (state.dataGlobal->eplusRunningViaAPI) {
     718            0 :         state.files.flushAll();
     719              :     }
     720              : 
     721              :     // The audit file seems to be held open in some cases, make sure it is closed before leaving.
     722              :     // EnergyPlus can close through two paths: EndEnergyPlus and AbortEnergyPlus, so do the same thing there.
     723          780 :     state.files.audit.close();
     724              : 
     725          780 :     return EXIT_SUCCESS;
     726          780 : }
     727              : 
     728            0 : void ConvertCaseToUpper(std::string_view InputString, // Input string
     729              :                         std::string &OutputString     // Output string (in UpperCase)
     730              : )
     731              : {
     732              : 
     733              :     // SUBROUTINE INFORMATION:
     734              :     //       AUTHOR         Linda K. Lawrie
     735              :     //       DATE WRITTEN   September 1997
     736              : 
     737              :     // PURPOSE OF THIS SUBROUTINE:
     738              :     // Convert a string to upper case
     739              : 
     740              :     // METHODOLOGY EMPLOYED:
     741              :     // This routine is not dependant upon the ASCII
     742              :     // code.  It works by storing the upper and lower case alphabet.  It
     743              :     // scans the whole input string.  If it finds a character in the lower
     744              :     // case alphabet, it makes an appropriate substitution.
     745              : 
     746              :     // Using/Aliasing
     747              :     static constexpr std::string_view UpperCase("ABCDEFGHIJKLMNOPQRSTUVWXYZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝ");
     748              :     static constexpr std::string_view LowerCase("abcdefghijklmnopqrstuvwxyzàáâãäåæçèéêëìíîïðñòóôõöøùúûüý");
     749              : 
     750            0 :     OutputString = InputString;
     751              : 
     752            0 :     for (std::string::size_type A = 0; A < len(InputString); ++A) {
     753            0 :         std::string::size_type const B = index(LowerCase, InputString[A]);
     754            0 :         if (B != std::string::npos) {
     755            0 :             OutputString[A] = UpperCase[B];
     756              :         }
     757              :     }
     758            0 : }
     759              : 
     760           32 : void ConvertCaseToLower(std::string_view InputString, // Input string
     761              :                         std::string &OutputString     // Output string (in LowerCase)
     762              : )
     763              : {
     764              : 
     765              :     // SUBROUTINE INFORMATION:
     766              :     //       AUTHOR         Linda K. Lawrie
     767              :     //       DATE WRITTEN   September 1997
     768              : 
     769              :     // PURPOSE OF THIS SUBROUTINE:
     770              :     // Convert a string to lower case
     771              : 
     772              :     // METHODOLOGY EMPLOYED:
     773              :     // This routine is not dependant upon the ASCII
     774              :     // code.  It works by storing the upper and lower case alphabet.  It
     775              :     // scans the whole input string.  If it finds a character in the lower
     776              :     // case alphabet, it makes an appropriate substitution.
     777              : 
     778              :     // Using/Aliasing
     779              :     static constexpr std::string_view UpperCase("ABCDEFGHIJKLMNOPQRSTUVWXYZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝ");
     780              :     static constexpr std::string_view LowerCase("abcdefghijklmnopqrstuvwxyzàáâãäåæçèéêëìíîïðñòóôõöøùúûüý");
     781              : 
     782           32 :     OutputString = InputString;
     783              : 
     784          347 :     for (std::string::size_type A = 0; A < len(InputString); ++A) {
     785          315 :         std::string::size_type const B = index(UpperCase, InputString[A]);
     786          315 :         if (B != std::string::npos) {
     787          315 :             OutputString[A] = LowerCase[B];
     788              :         }
     789              :     }
     790           32 : }
     791              : 
     792         6440 : std::string::size_type FindNonSpace(std::string const &String) // String to be scanned
     793              : {
     794              : 
     795              :     // FUNCTION INFORMATION:
     796              :     //       AUTHOR         Linda K. Lawrie
     797              :     //       DATE WRITTEN   September 1997
     798              : 
     799              :     // PURPOSE OF THIS FUNCTION:
     800              :     // This function finds the first non-space character in the passed string
     801              :     // and returns that position as the result to the calling program.
     802              : 
     803              :     // METHODOLOGY EMPLOYED:
     804              :     // Scan string for character not equal to blank.
     805              : 
     806         6440 :     return String.find_first_not_of(' ');
     807              : }
     808              : 
     809         4015 : bool env_var_on(std::string const &env_var_str)
     810              : {
     811              : 
     812              :     // FUNCTION INFORMATION:
     813              :     //       AUTHOR         Stuart G. Mentzer
     814              :     //       DATE WRITTEN   April 2014
     815              : 
     816              :     // PURPOSE OF THIS FUNCTION:
     817              :     // Test if a boolean environment variable value is "on" (has value starting with Y or T)
     818              : 
     819         4015 :     return ((!env_var_str.empty()) && is_any_of(env_var_str[0], "YyTt"));
     820              : }
     821              : 
     822            0 : void emitErrorMessage(EnergyPlusData &state, [[maybe_unused]] ErrorMessageCategory category, std::string const &msg, bool shouldFatal)
     823              : {
     824            0 :     if (!shouldFatal) {
     825            0 :         ShowSevereError(state, msg);
     826              :     } else { // should fatal
     827            0 :         ShowFatalError(state, msg);
     828              :     }
     829            0 : }
     830            0 : void emitErrorMessages(EnergyPlusData &state,
     831              :                        [[maybe_unused]] ErrorMessageCategory category,
     832              :                        std::initializer_list<std::string> const &msgs,
     833              :                        bool const shouldFatal,
     834              :                        int const zeroBasedTimeStampIndex)
     835              : {
     836            0 :     for (auto msg = msgs.begin(); msg != msgs.end(); ++msg) {
     837            0 :         if (msg - msgs.begin() == zeroBasedTimeStampIndex) {
     838            0 :             ShowContinueErrorTimeStamp(state, *msg);
     839            0 :             continue;
     840              :         }
     841            0 :         if (msg == msgs.begin()) {
     842            0 :             ShowSevereError(state, *msg);
     843            0 :         } else if (std::next(msg) == msgs.end() && shouldFatal) {
     844            0 :             ShowFatalError(state, *msg);
     845              :         } else { // should be an intermediate message, or a final one where there is no fatal
     846            0 :             ShowContinueError(state, *msg);
     847              :         }
     848              :     }
     849            0 : }
     850            0 : void emitWarningMessage(EnergyPlusData &state, [[maybe_unused]] ErrorMessageCategory category, std::string const &msg, bool const countAsError)
     851              : {
     852            0 :     if (countAsError) { // ideally this path goes away and we just have distinct warnings and errors
     853            0 :         ShowWarningError(state, msg);
     854              :     } else {
     855            0 :         ShowWarningMessage(state, msg);
     856              :     }
     857            0 : }
     858            0 : void emitWarningMessages(EnergyPlusData &state,
     859              :                          [[maybe_unused]] ErrorMessageCategory category,
     860              :                          std::initializer_list<std::string> const &msgs,
     861              :                          bool const countAsError)
     862              : {
     863            0 :     for (auto msg = msgs.begin(); msg != msgs.end(); ++msg) {
     864            0 :         if (msg == msgs.begin()) {
     865            0 :             if (countAsError) { // ideally this path goes away and we just have distinct warnings and errors
     866            0 :                 ShowWarningError(state, *msg);
     867              :             } else {
     868            0 :                 ShowWarningMessage(state, *msg);
     869              :             }
     870              :         } else {
     871            0 :             ShowContinueError(state, *msg);
     872              :         }
     873              :     }
     874            0 : }
     875              : 
     876            2 : void ShowFatalError(EnergyPlusData &state, std::string const &ErrorMessage, OptionalOutputFileRef OutUnit1, OptionalOutputFileRef OutUnit2)
     877              : {
     878              : 
     879              :     // SUBROUTINE INFORMATION:
     880              :     //       AUTHOR         Linda K. Lawrie
     881              :     //       DATE WRITTEN   September 1997
     882              :     //       MODIFIED       Kyle Benne August 2010 Added sqlite output
     883              : 
     884              :     // PURPOSE OF THIS SUBROUTINE:
     885              :     // This subroutine puts ErrorMessage with a Fatal designation on
     886              :     // designated output files.  Then, the program is aborted.
     887              : 
     888              :     // METHODOLOGY EMPLOYED:
     889              :     // Calls ShowErrorMessage utility routine.
     890              :     // Calls AbortEnergyPlus
     891              : 
     892              :     using namespace DataErrorTracking;
     893              : 
     894            2 :     ShowErrorMessage(state, format(" **  Fatal  ** {}", ErrorMessage), OutUnit1, OutUnit2);
     895            2 :     DisplayString(state, "**FATAL:" + ErrorMessage);
     896              : 
     897            2 :     ShowErrorMessage(state, " ...Summary of Errors that led to program termination:", OutUnit1, OutUnit2);
     898            2 :     ShowErrorMessage(state, format(" ..... Reference severe error count={}", state.dataErrTracking->TotalSevereErrors), OutUnit1, OutUnit2);
     899            2 :     ShowErrorMessage(state, format(" ..... Last severe error={}", state.dataErrTracking->LastSevereError), OutUnit1, OutUnit2);
     900            2 :     if (state.dataSQLiteProcedures->sqlite) {
     901            0 :         state.dataSQLiteProcedures->sqlite->createSQLiteErrorRecord(1, 2, ErrorMessage, 1);
     902            0 :         if (state.dataSQLiteProcedures->sqlite->sqliteWithinTransaction()) {
     903            0 :             state.dataSQLiteProcedures->sqlite->sqliteCommit();
     904              :         }
     905              :     }
     906            2 :     if (state.dataGlobal->errorCallback) {
     907            0 :         state.dataGlobal->errorCallback(Error::Fatal, ErrorMessage);
     908              :     }
     909            2 :     throw FatalError(ErrorMessage);
     910              : }
     911              : 
     912           82 : void ShowSevereError(EnergyPlusData &state, std::string const &ErrorMessage, OptionalOutputFileRef OutUnit1, OptionalOutputFileRef OutUnit2)
     913              : {
     914              : 
     915              :     // SUBROUTINE INFORMATION:
     916              :     //       AUTHOR         Linda K. Lawrie
     917              :     //       DATE WRITTEN   September 1997
     918              : 
     919              :     // PURPOSE OF THIS SUBROUTINE:
     920              :     // This subroutine puts ErrorMessage with a Severe designation on
     921              :     // designated output files.
     922              : 
     923              :     // METHODOLOGY EMPLOYED:
     924              :     // Calls ShowErrorMessage utility routine.
     925              : 
     926         1722 :     for (int Loop = 1; Loop <= DataErrorTracking::SearchCounts; ++Loop) {
     927         1640 :         if (has(ErrorMessage, DataErrorTracking::MessageSearch[Loop])) {
     928           25 :             ++state.dataErrTracking->MatchCounts(Loop);
     929              :         }
     930              :     }
     931              : 
     932           82 :     ++state.dataErrTracking->TotalSevereErrors;
     933          106 :     if (state.dataGlobal->WarmupFlag && !state.dataGlobal->DoingSizing && !state.dataGlobal->KickOffSimulation &&
     934           24 :         !state.dataErrTracking->AbortProcessing) {
     935           24 :         ++state.dataErrTracking->TotalSevereErrorsDuringWarmup;
     936              :     }
     937           82 :     if (state.dataGlobal->DoingSizing) {
     938           20 :         ++state.dataErrTracking->TotalSevereErrorsDuringSizing;
     939              :     }
     940           82 :     ShowErrorMessage(state, format(" ** Severe  ** {}", ErrorMessage), OutUnit1, OutUnit2);
     941           82 :     state.dataErrTracking->LastSevereError = ErrorMessage;
     942              : 
     943              :     //  Could set a variable here that gets checked at some point?
     944              : 
     945           82 :     if (state.dataSQLiteProcedures->sqlite) {
     946            5 :         state.dataSQLiteProcedures->sqlite->createSQLiteErrorRecord(1, 1, ErrorMessage, 1);
     947              :     }
     948           82 :     if (state.dataGlobal->errorCallback) {
     949            0 :         state.dataGlobal->errorCallback(Error::Severe, ErrorMessage);
     950              :     }
     951           82 : }
     952              : 
     953            5 : void ShowSevereMessage(EnergyPlusData &state, std::string const &ErrorMessage, OptionalOutputFileRef OutUnit1, OptionalOutputFileRef OutUnit2)
     954              : {
     955              : 
     956              :     // SUBROUTINE INFORMATION:
     957              :     //       AUTHOR         Linda K. Lawrie
     958              :     //       DATE WRITTEN   September 2009
     959              : 
     960              :     // PURPOSE OF THIS SUBROUTINE:
     961              :     // This subroutine puts ErrorMessage with a Severe designation on designated output files.
     962              :     // But does not bump the error count so can be used in conjunction with recurring error calls.
     963              : 
     964              :     // METHODOLOGY EMPLOYED:
     965              :     // Calls ShowErrorMessage utility routine.
     966              : 
     967          105 :     for (int Loop = 1; Loop <= DataErrorTracking::SearchCounts; ++Loop) {
     968          100 :         if (has(ErrorMessage, DataErrorTracking::MessageSearch[Loop])) {
     969            0 :             ++state.dataErrTracking->MatchCounts(Loop);
     970              :         }
     971              :     }
     972              : 
     973            5 :     ShowErrorMessage(state, format(" ** Severe  ** {}", ErrorMessage), OutUnit1, OutUnit2);
     974            5 :     state.dataErrTracking->LastSevereError = ErrorMessage;
     975              : 
     976              :     //  Could set a variable here that gets checked at some point?
     977              : 
     978            5 :     if (state.dataSQLiteProcedures->sqlite) {
     979            1 :         state.dataSQLiteProcedures->sqlite->createSQLiteErrorRecord(1, 1, ErrorMessage, 0);
     980              :     }
     981            5 :     if (state.dataGlobal->errorCallback) {
     982            0 :         state.dataGlobal->errorCallback(Error::Severe, ErrorMessage);
     983              :     }
     984            5 : }
     985              : 
     986         4932 : void ShowContinueError(EnergyPlusData &state, std::string const &Message, OptionalOutputFileRef OutUnit1, OptionalOutputFileRef OutUnit2)
     987              : {
     988              : 
     989              :     // SUBROUTINE INFORMATION:
     990              :     //       AUTHOR         Linda K. Lawrie
     991              :     //       DATE WRITTEN   October 2001
     992              : 
     993              :     // PURPOSE OF THIS SUBROUTINE:
     994              :     // This subroutine displays a 'continued error' message on designated output files.
     995              : 
     996              :     // METHODOLOGY EMPLOYED:
     997              :     // Calls ShowErrorMessage utility routine.
     998              : 
     999         4932 :     ShowErrorMessage(state, format(" **   ~~~   ** {}", Message), OutUnit1, OutUnit2);
    1000         4932 :     if (state.dataSQLiteProcedures->sqlite) {
    1001          880 :         state.dataSQLiteProcedures->sqlite->updateSQLiteErrorRecord(Message);
    1002              :     }
    1003         4932 :     if (state.dataGlobal->errorCallback) {
    1004            0 :         state.dataGlobal->errorCallback(Error::Continue, Message);
    1005              :     }
    1006         4932 : }
    1007              : 
    1008          210 : void ShowContinueErrorTimeStamp(EnergyPlusData &state, std::string const &Message, OptionalOutputFileRef OutUnit1, OptionalOutputFileRef OutUnit2)
    1009              : {
    1010              : 
    1011              :     // SUBROUTINE INFORMATION:
    1012              :     //       AUTHOR         Linda K. Lawrie
    1013              :     //       DATE WRITTEN   February 2004
    1014              : 
    1015              :     // PURPOSE OF THIS SUBROUTINE:
    1016              :     // This subroutine displays a 'continued error' timestamp message on designated output files.
    1017              : 
    1018              :     // METHODOLOGY EMPLOYED:
    1019              :     // Calls ShowErrorMessage utility routine.
    1020              : 
    1021          210 :     std::string cEnvHeader;
    1022              : 
    1023          210 :     if (state.dataGlobal->WarmupFlag) {
    1024           96 :         if (!state.dataGlobal->DoingSizing) {
    1025           96 :             cEnvHeader = " During Warmup, Environment=";
    1026              :         } else {
    1027            0 :             cEnvHeader = " During Warmup & Sizing, Environment=";
    1028              :         }
    1029              :     } else {
    1030          114 :         if (!state.dataGlobal->DoingSizing) {
    1031          114 :             cEnvHeader = " Environment=";
    1032              :         } else {
    1033            0 :             cEnvHeader = " During Sizing, Environment=";
    1034              :         }
    1035              :     }
    1036              : 
    1037          210 :     if (len(Message) < 50) {
    1038          197 :         const std::string m = format("{}{}{}, at Simulation time={} {}",
    1039              :                                      Message,
    1040              :                                      cEnvHeader,
    1041          197 :                                      state.dataEnvrn->EnvironmentName,
    1042          197 :                                      state.dataEnvrn->CurMnDy,
    1043          394 :                                      General::CreateSysTimeIntervalString(state));
    1044              : 
    1045          197 :         ShowErrorMessage(state, format(" **   ~~~   ** {}", m), OutUnit1, OutUnit2);
    1046          197 :         if (state.dataSQLiteProcedures->sqlite) {
    1047           31 :             state.dataSQLiteProcedures->sqlite->updateSQLiteErrorRecord(m);
    1048              :         }
    1049          197 :         if (state.dataGlobal->errorCallback) {
    1050            0 :             state.dataGlobal->errorCallback(Error::Continue, m);
    1051              :         }
    1052          197 :     } else {
    1053           13 :         const std::string postfix = format("{}{}, at Simulation time={} {}",
    1054              :                                            cEnvHeader,
    1055           13 :                                            state.dataEnvrn->EnvironmentName,
    1056           13 :                                            state.dataEnvrn->CurMnDy,
    1057           26 :                                            General::CreateSysTimeIntervalString(state));
    1058           13 :         ShowErrorMessage(state, format(" **   ~~~   ** {}", Message));
    1059           13 :         ShowErrorMessage(state, format(" **   ~~~   ** {}", postfix), OutUnit1, OutUnit2);
    1060           13 :         if (state.dataSQLiteProcedures->sqlite) {
    1061            1 :             state.dataSQLiteProcedures->sqlite->updateSQLiteErrorRecord(Message);
    1062              :         }
    1063           13 :         if (state.dataGlobal->errorCallback) {
    1064            0 :             state.dataGlobal->errorCallback(Error::Continue, Message);
    1065            0 :             state.dataGlobal->errorCallback(Error::Continue, postfix);
    1066              :         }
    1067           13 :     }
    1068          210 : }
    1069              : 
    1070        13729 : void ShowMessage(EnergyPlusData &state, std::string const &Message, OptionalOutputFileRef OutUnit1, OptionalOutputFileRef OutUnit2)
    1071              : {
    1072              : 
    1073              :     // SUBROUTINE INFORMATION:
    1074              :     //       AUTHOR         Linda K. Lawrie
    1075              :     //       DATE WRITTEN   September 1997
    1076              : 
    1077              :     // PURPOSE OF THIS SUBROUTINE:
    1078              :     // This subroutine displays a simple message on designated output files.
    1079              : 
    1080              :     // METHODOLOGY EMPLOYED:
    1081              :     // Calls ShowErrorMessage utility routine.
    1082              : 
    1083        13729 :     if (Message.empty()) {
    1084         1196 :         ShowErrorMessage(state, " *************", OutUnit1, OutUnit2);
    1085              :     } else {
    1086        13131 :         ShowErrorMessage(state, format(" ************* {}", Message), OutUnit1, OutUnit2);
    1087        13131 :         if (state.dataSQLiteProcedures->sqlite) {
    1088         1548 :             state.dataSQLiteProcedures->sqlite->createSQLiteErrorRecord(1, -1, Message, 0);
    1089              :         }
    1090        13131 :         if (state.dataGlobal->errorCallback) {
    1091            0 :             state.dataGlobal->errorCallback(Error::Info, Message);
    1092              :         }
    1093              :     }
    1094        13729 : }
    1095              : 
    1096         2291 : void ShowWarningError(EnergyPlusData &state, std::string const &ErrorMessage, OptionalOutputFileRef OutUnit1, OptionalOutputFileRef OutUnit2)
    1097              : {
    1098              : 
    1099              :     // SUBROUTINE INFORMATION:
    1100              :     //       AUTHOR         Linda K. Lawrie
    1101              :     //       DATE WRITTEN   September 1997
    1102              : 
    1103              :     // PURPOSE OF THIS SUBROUTINE:
    1104              :     // This subroutine puts ErrorMessage with a Warning designation on
    1105              :     // designated output files.
    1106              : 
    1107              :     // METHODOLOGY EMPLOYED:
    1108              :     // Calls ShowErrorMessage utility routine.
    1109              : 
    1110        48111 :     for (int Loop = 1; Loop <= DataErrorTracking::SearchCounts; ++Loop) {
    1111        45820 :         if (has(ErrorMessage, DataErrorTracking::MessageSearch[Loop])) {
    1112           31 :             ++state.dataErrTracking->MatchCounts(Loop);
    1113              :         }
    1114              :     }
    1115              : 
    1116         2291 :     ++state.dataErrTracking->TotalWarningErrors;
    1117         2303 :     if (state.dataGlobal->WarmupFlag && !state.dataGlobal->DoingSizing && !state.dataGlobal->KickOffSimulation &&
    1118           12 :         !state.dataErrTracking->AbortProcessing) {
    1119           12 :         ++state.dataErrTracking->TotalWarningErrorsDuringWarmup;
    1120              :     }
    1121         2291 :     if (state.dataGlobal->DoingSizing) {
    1122          815 :         ++state.dataErrTracking->TotalWarningErrorsDuringSizing;
    1123              :     }
    1124         2291 :     ShowErrorMessage(state, format(" ** Warning ** {}", ErrorMessage), OutUnit1, OutUnit2);
    1125              : 
    1126         2291 :     if (state.dataSQLiteProcedures->sqlite) {
    1127          474 :         state.dataSQLiteProcedures->sqlite->createSQLiteErrorRecord(1, 0, ErrorMessage, 1);
    1128              :     }
    1129         2291 :     if (state.dataGlobal->errorCallback) {
    1130            0 :         state.dataGlobal->errorCallback(Error::Warning, ErrorMessage);
    1131              :     }
    1132         2291 : }
    1133              : 
    1134          204 : void ShowWarningMessage(EnergyPlusData &state, std::string const &ErrorMessage, OptionalOutputFileRef OutUnit1, OptionalOutputFileRef OutUnit2)
    1135              : {
    1136              : 
    1137              :     // SUBROUTINE INFORMATION:
    1138              :     //       AUTHOR         Linda K. Lawrie
    1139              :     //       DATE WRITTEN   September 2009
    1140              : 
    1141              :     // PURPOSE OF THIS SUBROUTINE:
    1142              :     // This subroutine puts ErrorMessage with a Warning designation on
    1143              :     // designated output files.
    1144              :     // But does not bump the error count so can be used in conjunction with recurring
    1145              :     // error calls.
    1146              : 
    1147              :     // METHODOLOGY EMPLOYED:
    1148              :     // Calls ShowErrorMessage utility routine.
    1149              : 
    1150         4284 :     for (int Loop = 1; Loop <= DataErrorTracking::SearchCounts; ++Loop) {
    1151         4080 :         if (has(ErrorMessage, DataErrorTracking::MessageSearch[Loop])) {
    1152           14 :             ++state.dataErrTracking->MatchCounts(Loop);
    1153              :         }
    1154              :     }
    1155              : 
    1156          204 :     ShowErrorMessage(state, format(" ** Warning ** {}", ErrorMessage), OutUnit1, OutUnit2);
    1157          204 :     if (state.dataSQLiteProcedures->sqlite) {
    1158           44 :         state.dataSQLiteProcedures->sqlite->createSQLiteErrorRecord(1, 0, ErrorMessage, 0);
    1159              :     }
    1160          204 :     if (state.dataGlobal->errorCallback) {
    1161            0 :         state.dataGlobal->errorCallback(Error::Warning, ErrorMessage);
    1162              :     }
    1163          204 : }
    1164              : 
    1165        29040 : void ShowRecurringSevereErrorAtEnd(EnergyPlusData &state,
    1166              :                                    std::string const &Message, // Message automatically written to "error file" at end of simulation
    1167              :                                    int &MsgIndex,              // Recurring message index, if zero, next available index is assigned
    1168              :                                    ObjexxFCL::Optional<Real64 const> ReportMaxOf, // Track and report the max of the values passed to this argument
    1169              :                                    ObjexxFCL::Optional<Real64 const> ReportMinOf, // Track and report the min of the values passed to this argument
    1170              :                                    ObjexxFCL::Optional<Real64 const> ReportSumOf, // Track and report the sum of the values passed to this argument
    1171              :                                    std::string const &ReportMaxUnits,             // optional char string (<=15 length) of units for max value
    1172              :                                    std::string const &ReportMinUnits,             // optional char string (<=15 length) of units for min value
    1173              :                                    std::string const &ReportSumUnits              // optional char string (<=15 length) of units for sum value
    1174              : )
    1175              : {
    1176              : 
    1177              :     // SUBROUTINE INFORMATION:
    1178              :     //       AUTHOR         Michael J. Witte
    1179              :     //       DATE WRITTEN   August 2004
    1180              : 
    1181              :     // PURPOSE OF THIS SUBROUTINE:
    1182              :     // This subroutine stores a recurring ErrorMessage with a Severe designation
    1183              :     // for output at the end of the simulation with automatic tracking of number
    1184              :     // of occurrences and optional tracking of associated min, max, and sum values
    1185              : 
    1186              :     // METHODOLOGY EMPLOYED:
    1187              :     // Calls StoreRecurringErrorMessage utility routine.
    1188              : 
    1189              :     // INTERFACE BLOCK SPECIFICATIONS
    1190              :     //  Use for recurring "severe" error messages shown once at end of simulation
    1191              :     //  with count of occurrences and optional max, min, sum
    1192              : 
    1193       609840 :     for (int Loop = 1; Loop <= DataErrorTracking::SearchCounts; ++Loop) {
    1194       580800 :         if (has(Message, DataErrorTracking::MessageSearch[Loop])) {
    1195            0 :             ++state.dataErrTracking->MatchCounts(Loop);
    1196            0 :             break;
    1197              :         }
    1198              :     }
    1199        29040 :     bool bNewMessageFound = true;
    1200        33777 :     for (int Loop = 1; Loop <= state.dataErrTracking->NumRecurringErrors; ++Loop) {
    1201        33772 :         if (Util::SameString(state.dataErrTracking->RecurringErrors(Loop).Message, " ** Severe  ** " + Message)) {
    1202        29035 :             bNewMessageFound = false;
    1203        29035 :             MsgIndex = Loop;
    1204        29035 :             break;
    1205              :         }
    1206              :     }
    1207        29040 :     if (bNewMessageFound) {
    1208            5 :         MsgIndex = 0;
    1209              :     }
    1210              : 
    1211        29040 :     ++state.dataErrTracking->TotalSevereErrors;
    1212        87120 :     StoreRecurringErrorMessage(
    1213        58080 :         state, " ** Severe  ** " + Message, MsgIndex, ReportMaxOf, ReportMinOf, ReportSumOf, ReportMaxUnits, ReportMinUnits, ReportSumUnits);
    1214        29040 : }
    1215              : 
    1216            0 : void ShowRecurringSevereErrorAtEnd(EnergyPlusData &state,
    1217              :                                    std::string const &Message, // Message automatically written to "error file" at end of simulation
    1218              :                                    int &MsgIndex,              // Recurring message index, if zero, next available index is assigned
    1219              :                                    Real64 const val,
    1220              :                                    std::string const &units // optional char string (<=15 length) of units for sum value
    1221              : )
    1222              : {
    1223              : 
    1224              :     // SUBROUTINE INFORMATION:
    1225              :     //       AUTHOR         Michael J. Witte
    1226              :     //       DATE WRITTEN   August 2004
    1227              : 
    1228              :     // PURPOSE OF THIS SUBROUTINE:
    1229              :     // This subroutine stores a recurring ErrorMessage with a Severe designation
    1230              :     // for output at the end of the simulation with automatic tracking of number
    1231              :     // of occurrences and optional tracking of associated min, max, and sum values
    1232              : 
    1233              :     // METHODOLOGY EMPLOYED:
    1234              :     // Calls StoreRecurringErrorMessage utility routine.
    1235              : 
    1236              :     // INTERFACE BLOCK SPECIFICATIONS
    1237              :     //  Use for recurring "severe" error messages shown once at end of simulation
    1238              :     //  with count of occurrences and optional max, min, sum
    1239              : 
    1240            0 :     for (int Loop = 1; Loop <= DataErrorTracking::SearchCounts; ++Loop) {
    1241            0 :         if (has(Message, DataErrorTracking::MessageSearch[Loop])) {
    1242            0 :             ++state.dataErrTracking->MatchCounts(Loop);
    1243            0 :             break;
    1244              :         }
    1245              :     }
    1246            0 :     bool bNewMessageFound = true;
    1247            0 :     for (int Loop = 1; Loop <= state.dataErrTracking->NumRecurringErrors; ++Loop) {
    1248            0 :         if (Util::SameString(state.dataErrTracking->RecurringErrors(Loop).Message, " ** Severe  ** " + Message)) {
    1249            0 :             bNewMessageFound = false;
    1250            0 :             MsgIndex = Loop;
    1251            0 :             break;
    1252              :         }
    1253              :     }
    1254            0 :     if (bNewMessageFound) {
    1255            0 :         MsgIndex = 0;
    1256              :     }
    1257              : 
    1258            0 :     ++state.dataErrTracking->TotalSevereErrors;
    1259            0 :     StoreRecurringErrorMessage(state, " ** Severe  ** " + Message, MsgIndex, val, val, _, units, units, "");
    1260            0 : }
    1261              : 
    1262      4231430 : void ShowRecurringWarningErrorAtEnd(EnergyPlusData &state,
    1263              :                                     std::string const &Message, // Message automatically written to "error file" at end of simulation
    1264              :                                     int &MsgIndex,              // Recurring message index, if zero, next available index is assigned
    1265              :                                     ObjexxFCL::Optional<Real64 const> ReportMaxOf, // Track and report the max of the values passed to this argument
    1266              :                                     ObjexxFCL::Optional<Real64 const> ReportMinOf, // Track and report the min of the values passed to this argument
    1267              :                                     ObjexxFCL::Optional<Real64 const> ReportSumOf, // Track and report the sum of the values passed to this argument
    1268              :                                     std::string const &ReportMaxUnits,             // optional char string (<=15 length) of units for max value
    1269              :                                     std::string const &ReportMinUnits,             // optional char string (<=15 length) of units for min value
    1270              :                                     std::string const &ReportSumUnits              // optional char string (<=15 length) of units for sum value
    1271              : )
    1272              : {
    1273              : 
    1274              :     // SUBROUTINE INFORMATION:
    1275              :     //       AUTHOR         Michael J. Witte
    1276              :     //       DATE WRITTEN   August 2004
    1277              : 
    1278              :     // PURPOSE OF THIS SUBROUTINE:
    1279              :     // This subroutine stores a recurring ErrorMessage with a Warning designation
    1280              :     // for output at the end of the simulation with automatic tracking of number
    1281              :     // of occurrences and optional tracking of associated min, max, and sum values
    1282              : 
    1283              :     // METHODOLOGY EMPLOYED:
    1284              :     // Calls StoreRecurringErrorMessage utility routine.
    1285              : 
    1286              :     // INTERFACE BLOCK SPECIFICATIONS
    1287              :     //  Use for recurring "warning" error messages shown once at end of simulation
    1288              :     //  with count of occurrences and optional max, min, sum
    1289              : 
    1290     88854458 :     for (int Loop = 1; Loop <= DataErrorTracking::SearchCounts; ++Loop) {
    1291     84623824 :         if (has(Message, DataErrorTracking::MessageSearch[Loop])) {
    1292          796 :             ++state.dataErrTracking->MatchCounts(Loop);
    1293          796 :             break;
    1294              :         }
    1295              :     }
    1296      4231430 :     bool bNewMessageFound = true;
    1297      8121654 :     for (int Loop = 1; Loop <= state.dataErrTracking->NumRecurringErrors; ++Loop) {
    1298      8121363 :         if (Util::SameString(state.dataErrTracking->RecurringErrors(Loop).Message, " ** Warning ** " + Message)) {
    1299      4231139 :             bNewMessageFound = false;
    1300      4231139 :             MsgIndex = Loop;
    1301      4231139 :             break;
    1302              :         }
    1303              :     }
    1304      4231430 :     if (bNewMessageFound) {
    1305          291 :         MsgIndex = 0;
    1306              :     }
    1307              : 
    1308      4231430 :     ++state.dataErrTracking->TotalWarningErrors;
    1309     12694290 :     StoreRecurringErrorMessage(
    1310      8462860 :         state, " ** Warning ** " + Message, MsgIndex, ReportMaxOf, ReportMinOf, ReportSumOf, ReportMaxUnits, ReportMinUnits, ReportSumUnits);
    1311      4231430 : }
    1312              : 
    1313        10438 : void ShowRecurringWarningErrorAtEnd(EnergyPlusData &state,
    1314              :                                     std::string const &Message, // Message automatically written to "error file" at end of simulation
    1315              :                                     int &MsgIndex,              // Recurring message index, if zero, next available index is assigned
    1316              :                                     Real64 const val,
    1317              :                                     std::string const &units // optional char string (<=15 length) of units for sum value
    1318              : )
    1319              : {
    1320              : 
    1321              :     // SUBROUTINE INFORMATION:
    1322              :     //       AUTHOR         Michael J. Witte
    1323              :     //       DATE WRITTEN   August 2004
    1324              : 
    1325              :     // PURPOSE OF THIS SUBROUTINE:
    1326              :     // This subroutine stores a recurring ErrorMessage with a Warning designation
    1327              :     // for output at the end of the simulation with automatic tracking of number
    1328              :     // of occurrences and optional tracking of associated min, max, and sum values
    1329              : 
    1330              :     // METHODOLOGY EMPLOYED:
    1331              :     // Calls StoreRecurringErrorMessage utility routine.
    1332              : 
    1333              :     // INTERFACE BLOCK SPECIFICATIONS
    1334              :     //  Use for recurring "warning" error messages shown once at end of simulation
    1335              :     //  with count of occurrences and optional max, min, sum
    1336              : 
    1337       219198 :     for (int Loop = 1; Loop <= DataErrorTracking::SearchCounts; ++Loop) {
    1338       208760 :         if (has(Message, DataErrorTracking::MessageSearch[Loop])) {
    1339            0 :             ++state.dataErrTracking->MatchCounts(Loop);
    1340            0 :             break;
    1341              :         }
    1342              :     }
    1343        10438 :     bool bNewMessageFound = true;
    1344        21244 :     for (int Loop = 1; Loop <= state.dataErrTracking->NumRecurringErrors; ++Loop) {
    1345        21232 :         if (Util::SameString(state.dataErrTracking->RecurringErrors(Loop).Message, " ** Warning ** " + Message)) {
    1346        10426 :             bNewMessageFound = false;
    1347        10426 :             MsgIndex = Loop;
    1348        10426 :             break;
    1349              :         }
    1350              :     }
    1351        10438 :     if (bNewMessageFound) {
    1352           12 :         MsgIndex = 0;
    1353              :     }
    1354              : 
    1355        10438 :     ++state.dataErrTracking->TotalWarningErrors;
    1356        10438 :     StoreRecurringErrorMessage(state, " ** Warning ** " + Message, MsgIndex, val, val, _, units, units, "");
    1357        10438 : }
    1358              : 
    1359           36 : void ShowRecurringContinueErrorAtEnd(EnergyPlusData &state,
    1360              :                                      std::string const &Message, // Message automatically written to "error file" at end of simulation
    1361              :                                      int &MsgIndex,              // Recurring message index, if zero, next available index is assigned
    1362              :                                      ObjexxFCL::Optional<Real64 const> ReportMaxOf, // Track and report the max of the values passed to this argument
    1363              :                                      ObjexxFCL::Optional<Real64 const> ReportMinOf, // Track and report the min of the values passed to this argument
    1364              :                                      ObjexxFCL::Optional<Real64 const> ReportSumOf, // Track and report the sum of the values passed to this argument
    1365              :                                      std::string const &ReportMaxUnits,             // optional char string (<=15 length) of units for max value
    1366              :                                      std::string const &ReportMinUnits,             // optional char string (<=15 length) of units for min value
    1367              :                                      std::string const &ReportSumUnits              // optional char string (<=15 length) of units for sum value
    1368              : )
    1369              : {
    1370              : 
    1371              :     // SUBROUTINE INFORMATION:
    1372              :     //       AUTHOR         Michael J. Witte
    1373              :     //       DATE WRITTEN   August 2004
    1374              : 
    1375              :     // PURPOSE OF THIS SUBROUTINE:
    1376              :     // This subroutine stores a recurring ErrorMessage with a continue designation
    1377              :     // for output at the end of the simulation with automatic tracking of number
    1378              :     // of occurrences and optional tracking of associated min, max, and sum values
    1379              : 
    1380              :     // METHODOLOGY EMPLOYED:
    1381              :     // Calls StoreRecurringErrorMessage utility routine.
    1382              : 
    1383              :     // INTERFACE BLOCK SPECIFICATIONS
    1384              :     //  Use for recurring "continue" error messages shown once at end of simulation
    1385              :     //  with count of occurrences and optional max, min, sum
    1386              : 
    1387          756 :     for (int Loop = 1; Loop <= DataErrorTracking::SearchCounts; ++Loop) {
    1388          720 :         if (has(Message, DataErrorTracking::MessageSearch[Loop])) {
    1389            0 :             ++state.dataErrTracking->MatchCounts(Loop);
    1390            0 :             break;
    1391              :         }
    1392              :     }
    1393           36 :     bool bNewMessageFound = true;
    1394          234 :     for (int Loop = 1; Loop <= state.dataErrTracking->NumRecurringErrors; ++Loop) {
    1395          228 :         if (Util::SameString(state.dataErrTracking->RecurringErrors(Loop).Message, " **   ~~~   ** " + Message)) {
    1396           30 :             bNewMessageFound = false;
    1397           30 :             MsgIndex = Loop;
    1398           30 :             break;
    1399              :         }
    1400              :     }
    1401           36 :     if (bNewMessageFound) {
    1402            6 :         MsgIndex = 0;
    1403              :     }
    1404              : 
    1405          108 :     StoreRecurringErrorMessage(
    1406           72 :         state, " **   ~~~   ** " + Message, MsgIndex, ReportMaxOf, ReportMinOf, ReportSumOf, ReportMaxUnits, ReportMinUnits, ReportSumUnits);
    1407           36 : }
    1408              : 
    1409      4270944 : void StoreRecurringErrorMessage(EnergyPlusData &state,
    1410              :                                 std::string const &ErrorMessage, // Message automatically written to "error file" at end of simulation
    1411              :                                 int &ErrorMsgIndex,              // Recurring message index, if zero, next available index is assigned
    1412              :                                 ObjexxFCL::Optional<Real64 const> ErrorReportMaxOf, // Track and report the max of the values passed to this argument
    1413              :                                 ObjexxFCL::Optional<Real64 const> ErrorReportMinOf, // Track and report the min of the values passed to this argument
    1414              :                                 ObjexxFCL::Optional<Real64 const> ErrorReportSumOf, // Track and report the sum of the values passed to this argument
    1415              :                                 std::string const &ErrorReportMaxUnits,             // Units for "max" reporting
    1416              :                                 std::string const &ErrorReportMinUnits,             // Units for "min" reporting
    1417              :                                 std::string const &ErrorReportSumUnits              // Units for "sum" reporting
    1418              : )
    1419              : {
    1420              : 
    1421              :     // SUBROUTINE INFORMATION:
    1422              :     //       AUTHOR         Michael J. Witte
    1423              :     //       DATE WRITTEN   August 2004
    1424              :     //       MODIFIED       September 2005;LKL;Added Units
    1425              : 
    1426              :     // PURPOSE OF THIS SUBROUTINE:
    1427              :     // This subroutine stores a recurring ErrorMessage with
    1428              :     // for output at the end of the simulation with automatic tracking of number
    1429              :     // of occurrences and optional tracking of associated min, max, and sum values
    1430              : 
    1431              :     // If Index is zero, then assign next available index and reallocate array
    1432      4270944 :     if (ErrorMsgIndex == 0) {
    1433          314 :         state.dataErrTracking->RecurringErrors.redimension(++state.dataErrTracking->NumRecurringErrors);
    1434          314 :         ErrorMsgIndex = state.dataErrTracking->NumRecurringErrors;
    1435              :         // The message string only needs to be stored once when a new recurring message is created
    1436          314 :         state.dataErrTracking->RecurringErrors(ErrorMsgIndex).Message = ErrorMessage;
    1437          314 :         state.dataErrTracking->RecurringErrors(ErrorMsgIndex).Count = 1;
    1438          314 :         if (state.dataGlobal->WarmupFlag) {
    1439          143 :             state.dataErrTracking->RecurringErrors(ErrorMsgIndex).WarmupCount = 1;
    1440              :         }
    1441          314 :         if (state.dataGlobal->DoingSizing) {
    1442            1 :             state.dataErrTracking->RecurringErrors(ErrorMsgIndex).SizingCount = 1;
    1443              :         }
    1444              : 
    1445              :         // For max, min, and sum values, store the current value when a new recurring message is created
    1446          314 :         if (present(ErrorReportMaxOf)) {
    1447          256 :             state.dataErrTracking->RecurringErrors(ErrorMsgIndex).MaxValue = ErrorReportMaxOf;
    1448          256 :             state.dataErrTracking->RecurringErrors(ErrorMsgIndex).ReportMax = true;
    1449          256 :             if (!ErrorReportMaxUnits.empty()) {
    1450           56 :                 state.dataErrTracking->RecurringErrors(ErrorMsgIndex).MaxUnits = ErrorReportMaxUnits;
    1451              :             }
    1452              :         }
    1453          314 :         if (present(ErrorReportMinOf)) {
    1454          254 :             state.dataErrTracking->RecurringErrors(ErrorMsgIndex).MinValue = ErrorReportMinOf;
    1455          254 :             state.dataErrTracking->RecurringErrors(ErrorMsgIndex).ReportMin = true;
    1456          254 :             if (!ErrorReportMinUnits.empty()) {
    1457           56 :                 state.dataErrTracking->RecurringErrors(ErrorMsgIndex).MinUnits = ErrorReportMinUnits;
    1458              :             }
    1459              :         }
    1460          314 :         if (present(ErrorReportSumOf)) {
    1461            0 :             state.dataErrTracking->RecurringErrors(ErrorMsgIndex).SumValue = ErrorReportSumOf;
    1462            0 :             state.dataErrTracking->RecurringErrors(ErrorMsgIndex).ReportSum = true;
    1463            0 :             if (!ErrorReportSumUnits.empty()) {
    1464            0 :                 state.dataErrTracking->RecurringErrors(ErrorMsgIndex).SumUnits = ErrorReportSumUnits;
    1465              :             }
    1466              :         }
    1467              : 
    1468      4270630 :     } else if (ErrorMsgIndex > 0) {
    1469              :         // Do stats and store
    1470      4270630 :         ++state.dataErrTracking->RecurringErrors(ErrorMsgIndex).Count;
    1471      4270630 :         if (state.dataGlobal->WarmupFlag) {
    1472      3107402 :             ++state.dataErrTracking->RecurringErrors(ErrorMsgIndex).WarmupCount;
    1473              :         }
    1474      4270630 :         if (state.dataGlobal->DoingSizing) {
    1475        10109 :             ++state.dataErrTracking->RecurringErrors(ErrorMsgIndex).SizingCount;
    1476              :         }
    1477              : 
    1478      4270630 :         if (present(ErrorReportMaxOf)) {
    1479      4148459 :             state.dataErrTracking->RecurringErrors(ErrorMsgIndex).MaxValue =
    1480      4148459 :                 max(ErrorReportMaxOf, state.dataErrTracking->RecurringErrors(ErrorMsgIndex).MaxValue);
    1481      4148459 :             state.dataErrTracking->RecurringErrors(ErrorMsgIndex).ReportMax = true;
    1482              :         }
    1483      4270630 :         if (present(ErrorReportMinOf)) {
    1484      4140029 :             state.dataErrTracking->RecurringErrors(ErrorMsgIndex).MinValue =
    1485      4140029 :                 min(ErrorReportMinOf, state.dataErrTracking->RecurringErrors(ErrorMsgIndex).MinValue);
    1486      4140029 :             state.dataErrTracking->RecurringErrors(ErrorMsgIndex).ReportMin = true;
    1487              :         }
    1488      4270630 :         if (present(ErrorReportSumOf)) {
    1489            0 :             state.dataErrTracking->RecurringErrors(ErrorMsgIndex).SumValue += ErrorReportSumOf;
    1490            0 :             state.dataErrTracking->RecurringErrors(ErrorMsgIndex).ReportSum = true;
    1491              :         }
    1492              :     } else {
    1493              :         // If ErrorMsgIndex < 0, then do nothing
    1494              :     }
    1495      4270944 : }
    1496              : 
    1497        21474 : void ShowErrorMessage(EnergyPlusData &state, std::string const &ErrorMessage, OptionalOutputFileRef OutUnit1, OptionalOutputFileRef OutUnit2)
    1498              : {
    1499              : 
    1500              :     // SUBROUTINE INFORMATION:
    1501              :     //       AUTHOR         Linda K. Lawrie
    1502              :     //       DATE WRITTEN   December 1997
    1503              : 
    1504              :     // PURPOSE OF THIS SUBROUTINE:
    1505              :     // This subroutine displays the error messages on the indicated
    1506              :     // file unit numbers, in addition to the "standard error output" unit.
    1507              : 
    1508              :     // METHODOLOGY EMPLOYED:
    1509              :     // If arguments OutUnit1 and/or OutUnit2 are present the
    1510              :     // error message is written to these as well and the standard one.
    1511              : 
    1512        21474 :     auto *err_stream = state.files.err_stream.get();
    1513              : 
    1514        21474 :     if (state.dataUtilityRoutines->outputErrorHeader && err_stream) {
    1515          803 :         *err_stream << "Program Version," << state.dataStrGlobals->VerStringVar << ',' << state.dataStrGlobals->IDDVerString << '\n';
    1516          803 :         state.dataUtilityRoutines->outputErrorHeader = false;
    1517              :     }
    1518              : 
    1519        21474 :     if (!state.dataGlobal->DoingInputProcessing) {
    1520        21474 :         if (err_stream) {
    1521        21474 :             *err_stream << "  " << ErrorMessage << '\n';
    1522              :         }
    1523              :     } else {
    1524              :         // CacheIPErrorFile is never opened or closed
    1525              :         // so this output would just go to stdout
    1526              :         // ObjexxFCL::gio::write(CacheIPErrorFile, fmtA) << ErrorMessage;
    1527            0 :         if (state.dataGlobal->printConsoleOutput) {
    1528            0 :             std::cout << ErrorMessage << '\n';
    1529              :         }
    1530              :     }
    1531        21474 :     if (OutUnit1) {
    1532            0 :         print(OutUnit1.value(), "  {}", ErrorMessage);
    1533              :     }
    1534        21474 :     if (OutUnit2) {
    1535            0 :         print(OutUnit2.value(), "  {}", ErrorMessage);
    1536              :     }
    1537              :     // std::string tmp = "  " + ErrorMessage + '\n';
    1538              :     // if (errorCallback) DataGlobals::errorCallback(tmp.c_str());
    1539        21474 : }
    1540              : 
    1541          803 : void SummarizeErrors(EnergyPlusData &state)
    1542              : {
    1543              : 
    1544              :     // SUBROUTINE INFORMATION:
    1545              :     //       AUTHOR         Linda K. Lawrie
    1546              :     //       DATE WRITTEN   March 2003
    1547              : 
    1548              :     // PURPOSE OF THIS SUBROUTINE:
    1549              :     // This subroutine provides a summary of certain errors that might
    1550              :     // otherwise get lost in the shuffle of many similar messages.
    1551              : 
    1552              :     std::string::size_type StartC;
    1553              :     std::string::size_type EndC;
    1554              : 
    1555          803 :     if (any_gt(state.dataErrTracking->MatchCounts, 0)) {
    1556           66 :         ShowMessage(state, "");
    1557           66 :         ShowMessage(state, "===== Final Error Summary =====");
    1558           66 :         ShowMessage(state, "The following error categories occurred.  Consider correcting or noting.");
    1559          693 :         for (int Loop = 1; Loop <= DataErrorTracking::SearchCounts; ++Loop) {
    1560          660 :             if (state.dataErrTracking->MatchCounts(Loop) > 0) {
    1561          108 :                 ShowMessage(state, DataErrorTracking::Summaries[Loop]);
    1562           36 :                 std::string thisMoreDetails = DataErrorTracking::MoreDetails[Loop];
    1563           36 :                 if (!thisMoreDetails.empty()) {
    1564           36 :                     StartC = 0;
    1565           36 :                     EndC = len(thisMoreDetails) - 1;
    1566          131 :                     while (EndC != std::string::npos) {
    1567          131 :                         EndC = index(thisMoreDetails.substr(StartC), "<CR");
    1568          131 :                         ShowMessage(state, format("..{}", thisMoreDetails.substr(StartC, EndC)));
    1569          131 :                         if (thisMoreDetails.substr(StartC + EndC, 5) == "<CRE>") {
    1570           36 :                             break;
    1571              :                         }
    1572           95 :                         StartC += EndC + 4;
    1573           95 :                         EndC = len(thisMoreDetails.substr(StartC)) - 1;
    1574              :                     }
    1575              :                 }
    1576           36 :             }
    1577              :         }
    1578           99 :         ShowMessage(state, "");
    1579              :     }
    1580          803 : }
    1581              : 
    1582          803 : void ShowRecurringErrors(EnergyPlusData &state)
    1583              : {
    1584              : 
    1585              :     // SUBROUTINE INFORMATION:
    1586              :     //       AUTHOR         Linda K. Lawrie
    1587              :     //       DATE WRITTEN   March 2003
    1588              : 
    1589              :     // PURPOSE OF THIS SUBROUTINE:
    1590              :     // This subroutine provides a summary of certain errors that might
    1591              :     // otherwise get lost in the shuffle of many similar messages.
    1592              : 
    1593              :     static constexpr std::string_view StatMessageStart(" **   ~~~   ** ");
    1594              : 
    1595          803 :     if (state.dataErrTracking->NumRecurringErrors > 0) {
    1596          224 :         ShowMessage(state, "");
    1597          224 :         ShowMessage(state, "===== Recurring Error Summary =====");
    1598          224 :         ShowMessage(state, "The following recurring error messages occurred.");
    1599          426 :         for (int Loop = 1; Loop <= state.dataErrTracking->NumRecurringErrors; ++Loop) {
    1600          314 :             auto const &error = state.dataErrTracking->RecurringErrors(Loop);
    1601              :             // Suppress reporting the count if it is a continue error
    1602          314 :             if (has_prefix(error.Message, " **   ~~~   ** ")) {
    1603            6 :                 ShowMessage(state, error.Message);
    1604            6 :                 if (state.dataSQLiteProcedures->sqlite) {
    1605            0 :                     state.dataSQLiteProcedures->sqlite->updateSQLiteErrorRecord(error.Message);
    1606              :                 }
    1607            6 :                 if (state.dataGlobal->errorCallback) {
    1608            0 :                     state.dataGlobal->errorCallback(Error::Continue, error.Message);
    1609              :                 }
    1610              :             } else {
    1611          308 :                 const bool warning = has_prefix(error.Message, " ** Warning ** ");
    1612          308 :                 const bool severe = has_prefix(error.Message, " ** Severe  ** ");
    1613              : 
    1614          616 :                 ShowMessage(state, "");
    1615          308 :                 ShowMessage(state, error.Message);
    1616          308 :                 ShowMessage(state, format("{}  This error occurred {} total times;", StatMessageStart, error.Count));
    1617          308 :                 ShowMessage(state, format("{}  during Warmup {} times;", StatMessageStart, error.WarmupCount));
    1618          308 :                 ShowMessage(state, format("{}  during Sizing {} times.", StatMessageStart, error.SizingCount));
    1619          308 :                 if (state.dataSQLiteProcedures->sqlite) {
    1620            0 :                     if (warning) {
    1621            0 :                         state.dataSQLiteProcedures->sqlite->createSQLiteErrorRecord(1, 0, error.Message.substr(15), error.Count);
    1622            0 :                     } else if (severe) {
    1623            0 :                         state.dataSQLiteProcedures->sqlite->createSQLiteErrorRecord(1, 1, error.Message.substr(15), error.Count);
    1624              :                     }
    1625              :                 }
    1626          308 :                 if (state.dataGlobal->errorCallback) {
    1627            0 :                     Error level = Error::Warning;
    1628            0 :                     if (severe) {
    1629            0 :                         level = Error::Severe;
    1630              :                     }
    1631            0 :                     state.dataGlobal->errorCallback(level, error.Message);
    1632            0 :                     state.dataGlobal->errorCallback(Error::Continue, "");
    1633              :                 }
    1634              :             }
    1635          314 :             std::string StatMessage = "";
    1636          314 :             if (error.ReportMax) {
    1637          256 :                 std::string MaxOut = format("{:.6f}", error.MaxValue);
    1638          256 :                 StatMessage += "  Max=" + MaxOut;
    1639          256 :                 if (!error.MaxUnits.empty()) {
    1640           56 :                     StatMessage += ' ' + error.MaxUnits;
    1641              :                 }
    1642          256 :             }
    1643          314 :             if (error.ReportMin) {
    1644          254 :                 std::string MinOut = format("{:.6f}", error.MinValue);
    1645          254 :                 StatMessage += "  Min=" + MinOut;
    1646          254 :                 if (!error.MinUnits.empty()) {
    1647           56 :                     StatMessage += ' ' + error.MinUnits;
    1648              :                 }
    1649          254 :             }
    1650          314 :             if (error.ReportSum) {
    1651            0 :                 std::string SumOut = format("{:.6f}", error.SumValue);
    1652            0 :                 StatMessage += "  Sum=" + SumOut;
    1653            0 :                 if (!error.SumUnits.empty()) {
    1654            0 :                     StatMessage += ' ' + error.SumUnits;
    1655              :                 }
    1656            0 :             }
    1657          314 :             if (error.ReportMax || error.ReportMin || error.ReportSum) {
    1658          270 :                 ShowMessage(state, format("{}{}", StatMessageStart, StatMessage));
    1659              :             }
    1660          314 :         }
    1661          336 :         ShowMessage(state, "");
    1662              :     }
    1663          803 : }
    1664              : 
    1665            0 : void ShowSevereDuplicateName(EnergyPlusData &state, ErrorObjectHeader const &eoh)
    1666              : {
    1667            0 :     ShowSevereError(state, format("{}: {} = {}, duplicate name.", eoh.routineName, eoh.objectType, eoh.objectName));
    1668            0 : }
    1669              : 
    1670            0 : void ShowSevereEmptyField(
    1671              :     EnergyPlusData &state, ErrorObjectHeader const &eoh, std::string_view fieldName, std::string_view depFieldName, std::string_view depFieldVal)
    1672              : {
    1673            0 :     ShowSevereError(state, format("{}: {} = {}", eoh.routineName, eoh.objectType, eoh.objectName));
    1674            0 :     ShowContinueError(state,
    1675            0 :                       format("{} cannot be empty{}.", fieldName, depFieldName.empty() ? "" : format(" when {} = {}", depFieldName, depFieldVal)));
    1676            0 : }
    1677              : 
    1678            0 : void ShowSevereItemNotFound(EnergyPlusData &state, ErrorObjectHeader const &eoh, std::string_view fieldName, std::string_view fieldVal)
    1679              : {
    1680            0 :     ShowSevereError(state, format("{}: {} = {}", eoh.routineName, eoh.objectType, eoh.objectName));
    1681            0 :     ShowContinueError(state, format("{} = {}, item not found.", fieldName, fieldVal));
    1682            0 : }
    1683              : 
    1684            0 : void ShowSevereItemNotFoundAudit(EnergyPlusData &state, ErrorObjectHeader const &eoh, std::string_view fieldName, std::string_view fieldVal)
    1685              : {
    1686            0 :     ShowSevereError(state, format("{}: {} = {}", eoh.routineName, eoh.objectType, eoh.objectName), OptionalOutputFileRef{state.files.audit});
    1687            0 :     ShowContinueError(state, format("{} = {}, item not found.", fieldName, fieldVal), OptionalOutputFileRef{state.files.audit});
    1688            0 : }
    1689              : 
    1690            0 : void ShowSevereDuplicateAssignment(
    1691              :     EnergyPlusData &state, ErrorObjectHeader const &eoh, std::string_view fieldName, std::string_view fieldVal, std::string_view prevVal)
    1692              : {
    1693            0 :     ShowSevereError(state, format("{}: {} = {}", eoh.routineName, eoh.objectType, eoh.objectName));
    1694            0 :     ShowContinueError(state, format("{} = {}, field previously assigned to {}.", fieldName, fieldVal, prevVal));
    1695            0 : }
    1696              : 
    1697            0 : void ShowSevereInvalidKey(
    1698              :     EnergyPlusData &state, ErrorObjectHeader const &eoh, std::string_view fieldName, std::string_view fieldVal, std::string_view msg)
    1699              : {
    1700            0 :     ShowSevereError(state, format("{}: {} = {}", eoh.routineName, eoh.objectType, eoh.objectName));
    1701            0 :     ShowContinueError(state, format("{} = {}, invalid key.", fieldName, fieldVal));
    1702            0 :     if (!msg.empty()) {
    1703            0 :         ShowContinueError(state, format(msg));
    1704              :     }
    1705            0 : }
    1706              : 
    1707            0 : void ShowSevereInvalidBool(EnergyPlusData &state, ErrorObjectHeader const &eoh, std::string_view fieldName, std::string_view fieldVal)
    1708              : {
    1709            0 :     ShowSevereError(state, format("{}: {} = {}", eoh.routineName, eoh.objectType, eoh.objectName));
    1710            0 :     ShowContinueError(state, format("{} = {}, invalid boolean (\"Yes\"/\"No\").", fieldName, fieldVal));
    1711            0 : }
    1712              : 
    1713            0 : void ShowSevereCustom(EnergyPlusData &state, ErrorObjectHeader const &eoh, std::string_view msg)
    1714              : {
    1715            0 :     ShowSevereError(state, format("{}: {} = {}", eoh.routineName, eoh.objectType, eoh.objectName));
    1716            0 :     ShowContinueError(state, format("{}", msg));
    1717            0 : }
    1718              : 
    1719            0 : void ShowSevereCustomAudit(EnergyPlusData &state, ErrorObjectHeader const &eoh, std::string_view msg)
    1720              : {
    1721            0 :     ShowSevereError(state, format("{}: {} = {}", eoh.routineName, eoh.objectType, eoh.objectName), OptionalOutputFileRef{state.files.audit});
    1722            0 :     ShowContinueError(state, format("{}", msg), OptionalOutputFileRef{state.files.audit});
    1723            0 : }
    1724              : 
    1725            0 : void ShowSevereCustomField(
    1726              :     EnergyPlusData &state, ErrorObjectHeader const &eoh, std::string_view fieldName, std::string_view fieldValue, std::string_view msg)
    1727              : {
    1728            0 :     ShowSevereError(state, format("{}: {} = {}", eoh.routineName, eoh.objectType, eoh.objectName));
    1729            0 :     ShowContinueError(state, format("{} = {}, {}", fieldName, fieldValue, msg));
    1730            0 : }
    1731              : 
    1732            0 : void ShowSevereBadMin(EnergyPlusData &state,
    1733              :                       ErrorObjectHeader const &eoh,
    1734              :                       std::string_view fieldName,
    1735              :                       Real64 fieldVal,
    1736              :                       Clusive cluMin,
    1737              :                       Real64 minVal,
    1738              :                       std::string_view msg)
    1739              : {
    1740            0 :     ShowSevereError(state, format("{}: {} = {}", eoh.routineName, eoh.objectType, eoh.objectName));
    1741            0 :     ShowContinueError(state, format("{} = {}, but must be {} {}", fieldName, fieldVal, cluMin == Clusive::In ? ">=" : ">", minVal));
    1742            0 :     if (!msg.empty()) {
    1743            0 :         ShowContinueError(state, format("{}", msg));
    1744              :     }
    1745            0 : }
    1746              : 
    1747            0 : void ShowSevereBadMax(EnergyPlusData &state,
    1748              :                       ErrorObjectHeader const &eoh,
    1749              :                       std::string_view fieldName,
    1750              :                       Real64 fieldVal,
    1751              :                       Clusive cluMax,
    1752              :                       Real64 maxVal,
    1753              :                       std::string_view msg)
    1754              : {
    1755            0 :     ShowSevereError(state, format("{}: {} = {}", eoh.routineName, eoh.objectType, eoh.objectName));
    1756            0 :     ShowContinueError(state, format("{} = {}, but must be {} {}", fieldName, fieldVal, cluMax == Clusive::In ? "<=" : "<", maxVal));
    1757            0 :     if (!msg.empty()) {
    1758            0 :         ShowContinueError(state, format("{}", msg));
    1759              :     }
    1760            0 : }
    1761              : 
    1762            0 : void ShowSevereBadMinMax(EnergyPlusData &state,
    1763              :                          ErrorObjectHeader const &eoh,
    1764              :                          std::string_view fieldName,
    1765              :                          Real64 fieldVal,
    1766              :                          Clusive cluMin,
    1767              :                          Real64 minVal,
    1768              :                          Clusive cluMax,
    1769              :                          Real64 maxVal,
    1770              :                          std::string_view msg)
    1771              : {
    1772            0 :     ShowSevereError(state, format("{}: {} = {}", eoh.routineName, eoh.objectType, eoh.objectName));
    1773            0 :     ShowContinueError(state,
    1774            0 :                       format("{} = {}, but must be {} {} and {} {}",
    1775              :                              fieldName,
    1776              :                              fieldVal,
    1777            0 :                              cluMin == Clusive::In ? ">=" : ">",
    1778              :                              minVal,
    1779            0 :                              cluMax == Clusive::In ? "<=" : "<",
    1780              :                              maxVal));
    1781            0 :     if (!msg.empty()) {
    1782            0 :         ShowContinueError(state, format("{}", msg));
    1783              :     }
    1784            0 : }
    1785              : 
    1786            0 : void ShowWarningItemNotFound(EnergyPlusData &state, ErrorObjectHeader const &eoh, std::string_view fieldName, std::string_view fieldVal)
    1787              : {
    1788            0 :     ShowWarningError(state, format("{}: {} = {}", eoh.routineName, eoh.objectType, eoh.objectName));
    1789            0 :     ShowContinueError(state, format("{} = {}, item not found", fieldName, fieldVal));
    1790            0 : }
    1791              : 
    1792            0 : void ShowWarningCustom(EnergyPlusData &state, ErrorObjectHeader const &eoh, std::string_view msg)
    1793              : {
    1794            0 :     ShowWarningError(state, format("{}: {} = {}", eoh.routineName, eoh.objectType, eoh.objectName));
    1795            0 :     ShowContinueError(state, format("{}", msg));
    1796            0 : }
    1797              : 
    1798            2 : void ShowWarningCustomField(
    1799              :     EnergyPlusData &state, ErrorObjectHeader const &eoh, std::string_view fieldName, std::string_view fieldValue, std::string_view msg)
    1800              : {
    1801            2 :     ShowWarningError(state, format("{}: {} = {}", eoh.routineName, eoh.objectType, eoh.objectName));
    1802            2 :     ShowContinueError(state, format("{} = {}, {}", fieldName, fieldValue, msg));
    1803            2 : }
    1804              : 
    1805            1 : void ShowWarningInvalidKey(EnergyPlusData &state,
    1806              :                            ErrorObjectHeader const &eoh,
    1807              :                            std::string_view fieldName,
    1808              :                            std::string_view fieldVal,
    1809              :                            std::string_view defaultVal,
    1810              :                            std::string_view msg)
    1811              : {
    1812            1 :     ShowWarningError(state, format("{}: {} = {}", eoh.routineName, eoh.objectType, eoh.objectName));
    1813            1 :     ShowContinueError(state, format("{} = {}, invalid key, {} will be used.", fieldName, fieldVal, defaultVal));
    1814            1 :     if (!msg.empty()) {
    1815            0 :         ShowContinueError(state, format(msg));
    1816              :     }
    1817            1 : }
    1818              : 
    1819            0 : void ShowWarningInvalidBool(
    1820              :     EnergyPlusData &state, ErrorObjectHeader const &eoh, std::string_view fieldName, std::string_view fieldVal, std::string_view defaultVal)
    1821              : {
    1822            0 :     ShowWarningError(state, format("{}: {} = {}", eoh.routineName, eoh.objectType, eoh.objectName));
    1823            0 :     ShowContinueError(state, format("{} = {}, invalid boolean (\"Yes\"/\"No\"), {} will be used.", fieldName, fieldVal, defaultVal));
    1824            0 : }
    1825              : 
    1826           34 : void ShowWarningEmptyField(EnergyPlusData &state,
    1827              :                            ErrorObjectHeader const &eoh,
    1828              :                            std::string_view fieldName,
    1829              :                            std::string_view defaultVal,
    1830              :                            std::string_view depFieldName,
    1831              :                            std::string_view depFieldVal)
    1832              : {
    1833           34 :     ShowWarningError(state, format("{}: {} = {}", eoh.routineName, eoh.objectType, eoh.objectName));
    1834           34 :     ShowContinueError(state, format("{} is empty.", fieldName));
    1835              : 
    1836           34 :     if (!depFieldName.empty()) {
    1837            0 :         ShowContinueError(state, format("Cannot be empty when {} = {}", depFieldName, depFieldVal));
    1838              :     }
    1839           34 :     if (!defaultVal.empty()) {
    1840            0 :         ShowContinueError(state, format("{} will be used.", defaultVal));
    1841              :     }
    1842           34 : }
    1843              : 
    1844            3 : void ShowWarningNonEmptyField(
    1845              :     EnergyPlusData &state, ErrorObjectHeader const &eoh, std::string_view fieldName, std::string_view depFieldName, std::string_view depFieldValue)
    1846              : {
    1847            3 :     ShowWarningError(state, format("{}: {} = {}", eoh.routineName, eoh.objectType, eoh.objectName));
    1848            3 :     ShowContinueError(state, format("{} is not empty.", fieldName));
    1849            3 :     if (!depFieldName.empty()) {
    1850            3 :         ShowContinueError(state, format("{} is ignored when {} = {}.", fieldName, depFieldName, depFieldValue));
    1851              :     }
    1852            3 : }
    1853              : 
    1854           13 : void ShowWarningItemNotFound(
    1855              :     EnergyPlusData &state, ErrorObjectHeader const &eoh, std::string_view fieldName, std::string_view fieldVal, std::string_view defaultVal)
    1856              : {
    1857           13 :     ShowWarningError(state, format("{}: {} = {}", eoh.routineName, eoh.objectType, eoh.objectName));
    1858           13 :     if (defaultVal.empty()) {
    1859           13 :         ShowContinueError(state, format("{} = {}, item not found.", fieldName, fieldVal));
    1860              :     } else {
    1861            0 :         ShowContinueError(state, format("{} = {}, item not found, {} will be used.", fieldName, fieldVal, defaultVal));
    1862              :     }
    1863           13 : }
    1864              : 
    1865            0 : void ShowWarningBadMin(EnergyPlusData &state,
    1866              :                        ErrorObjectHeader const &eoh,
    1867              :                        std::string_view fieldName,
    1868              :                        Real64 fieldVal,
    1869              :                        Clusive cluMin,
    1870              :                        Real64 minVal,
    1871              :                        std::string_view msg)
    1872              : {
    1873            0 :     ShowWarningError(state, format("{}: {} = {}", eoh.routineName, eoh.objectType, eoh.objectName));
    1874            0 :     ShowContinueError(state, format("{} = {}, but must be {} {}", fieldName, fieldVal, cluMin == Clusive::In ? ">=" : ">", minVal));
    1875            0 :     if (!msg.empty()) {
    1876            0 :         ShowContinueError(state, format("{}", msg));
    1877              :     }
    1878            0 : }
    1879              : 
    1880            0 : void ShowWarningBadMax(EnergyPlusData &state,
    1881              :                        ErrorObjectHeader const &eoh,
    1882              :                        std::string_view fieldName,
    1883              :                        Real64 fieldVal,
    1884              :                        Clusive cluMax,
    1885              :                        Real64 maxVal,
    1886              :                        std::string_view msg)
    1887              : {
    1888            0 :     ShowWarningError(state, format("{}: {} = {}", eoh.routineName, eoh.objectType, eoh.objectName));
    1889            0 :     ShowContinueError(state, format("{} = {}, but must be {} {}", fieldName, fieldVal, cluMax == Clusive::In ? "<=" : "<", maxVal));
    1890            0 :     ShowContinueError(state, format("{} = {}, but must be {} {}", fieldName, fieldVal, cluMax == Clusive::In ? "<=" : "<", maxVal));
    1891            0 :     if (!msg.empty()) {
    1892            0 :         ShowContinueError(state, format("{}", msg));
    1893              :     }
    1894            0 : }
    1895              : 
    1896            0 : void ShowWarningBadMinMax(EnergyPlusData &state,
    1897              :                           ErrorObjectHeader const &eoh,
    1898              :                           std::string_view fieldName,
    1899              :                           Real64 fieldVal,
    1900              :                           Clusive cluMin,
    1901              :                           Real64 minVal,
    1902              :                           Clusive cluMax,
    1903              :                           Real64 maxVal,
    1904              :                           std::string_view msg)
    1905              : {
    1906            0 :     ShowWarningError(state, format("{}: {} = {}", eoh.routineName, eoh.objectType, eoh.objectName));
    1907            0 :     ShowContinueError(state,
    1908            0 :                       format("{} = {}, but must be {} {} and {} {}",
    1909              :                              fieldName,
    1910              :                              fieldVal,
    1911            0 :                              cluMin == Clusive::In ? ">=" : ">",
    1912              :                              minVal,
    1913            0 :                              cluMax == Clusive::In ? "<=" : "<",
    1914              :                              maxVal));
    1915            0 :     if (!msg.empty()) {
    1916            0 :         ShowContinueError(state, format("{}", msg));
    1917              :     }
    1918            0 : }
    1919              : 
    1920              : } // namespace EnergyPlus
        

Generated by: LCOV version 2.0-1