LCOV - code coverage report
Current view: top level - EnergyPlus - UtilityRoutines.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 453 694 65.3 %
Date: 2024-08-24 18:31:18 Functions: 31 53 58.5 %

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

Generated by: LCOV version 1.14