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