LCOV - code coverage report
Current view: top level - EnergyPlus - UtilityRoutines.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 61.9 % 801 496
Test Date: 2025-06-02 07:23:51 Functions: 55.4 % 65 36

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

Generated by: LCOV version 2.0-1