Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2023, 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/UtilityRoutines.hh>
91 :
92 : // Third Party Headers
93 : #include <fast_float/fast_float.h>
94 :
95 : namespace EnergyPlus {
96 :
97 : namespace UtilityRoutines {
98 :
99 1732997 : 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 1732997 : Real64 rProcessNumber = 0.0;
126 1732997 : ErrorFlag = false;
127 :
128 1732997 : if (String.empty()) return rProcessNumber;
129 :
130 1732989 : auto const front_trim(String.find_first_not_of(' '));
131 1732989 : auto const back_trim(String.find_last_not_of(' '));
132 1732989 : if (front_trim == std::string::npos || back_trim == std::string::npos) {
133 0 : return rProcessNumber;
134 : } else {
135 1732989 : String = String.substr(front_trim, back_trim - front_trim + 1);
136 : }
137 :
138 1732989 : auto result = fast_float::from_chars(String.data(), String.data() + String.size(), rProcessNumber);
139 1732989 : size_t remaining_size = result.ptr - String.data();
140 1732989 : if (result.ec == std::errc::result_out_of_range || result.ec == std::errc::invalid_argument) {
141 6346 : rProcessNumber = 0.0;
142 6346 : ErrorFlag = true;
143 1726643 : } else if (remaining_size != String.size()) {
144 32462 : 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 32462 : 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 50 : std::string str{String};
156 25 : std::replace_if(
157 185 : str.begin(), str.end(), [](const char c) { return c == 'D' || c == 'd'; }, 'e');
158 25 : return ProcessNumber(str, ErrorFlag);
159 32437 : } 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 0 : }
169 : } else {
170 32437 : rProcessNumber = 0.0;
171 32437 : ErrorFlag = true;
172 : }
173 1694181 : } else if (!std::isfinite(rProcessNumber)) {
174 0 : rProcessNumber = 0.0;
175 0 : ErrorFlag = true;
176 : }
177 :
178 1732964 : return rProcessNumber;
179 : }
180 :
181 1190286 : 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 4541287 : for (int Count = 1; Count <= NumItems; ++Count) {
198 3421792 : if (String == ListOfItems(Count)) return Count;
199 : }
200 1119495 : return 0; // Not found
201 : }
202 :
203 316199 : 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 34308578 : for (int Count = 1; Count <= NumItems; ++Count) {
220 34244133 : if (String == ListOfItems(Count)) return Count;
221 : }
222 64445 : return 0; // Not found
223 : }
224 :
225 473166 : 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 473166 : int Probe(0);
242 473166 : int LBnd(0);
243 473166 : int UBnd(NumItems + 1);
244 473166 : bool Found(false);
245 7827452 : while ((!Found) || (Probe != 0)) {
246 4150309 : Probe = (UBnd - LBnd) / 2;
247 4150309 : if (Probe == 0) break;
248 3703660 : Probe += LBnd;
249 3703660 : if (equali(String, ListOfItems(Probe))) {
250 26517 : Found = true;
251 26517 : break;
252 3677143 : } else if (lessthani(String, ListOfItems(Probe))) {
253 1360392 : UBnd = Probe;
254 : } else {
255 2316751 : LBnd = Probe;
256 : }
257 : }
258 473166 : return Probe;
259 : }
260 :
261 4003 : 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 4003 : int FindItem = UtilityRoutines::FindItemInList(String, ListOfItems, NumItems);
278 4003 : if (FindItem != 0) return FindItem;
279 :
280 25072 : for (int Count = 1; Count <= NumItems; ++Count) {
281 25072 : 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 = UtilityRoutines::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, StringToDisplay + ", duplicate name=" + NameToVerify);
339 0 : ErrorFound = true;
340 : }
341 : }
342 :
343 0 : if (NameToVerify.empty()) {
344 0 : ShowSevereError(state, StringToDisplay + ", cannot be blank");
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, StringToDisplay + ", duplicate name=" + NameToVerify);
377 0 : ErrorFound = true;
378 : }
379 : }
380 :
381 0 : if (NameToVerify.empty()) {
382 0 : ShowSevereError(state, StringToDisplay + ", cannot be blank");
383 0 : ErrorFound = true;
384 0 : IsBlank = true;
385 : } else {
386 0 : IsBlank = false;
387 : }
388 0 : }
389 :
390 96267 : bool IsNameEmpty(EnergyPlusData &state, std::string &NameToVerify, std::string_view StringToDisplay, bool &ErrorFound)
391 : {
392 96267 : if (NameToVerify.empty()) {
393 0 : ShowSevereError(state, std::string{StringToDisplay} + " Name, cannot be blank");
394 0 : ErrorFound = true;
395 0 : NameToVerify = "xxxxx";
396 0 : return true;
397 : }
398 96267 : 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 = MakeUPPERCase(key);
404 0 : return std::hash<std::string>()(keyCopy);
405 : }
406 :
407 40767328 : bool case_insensitive_comparator::operator()(std::string_view const a, std::string_view const b) const noexcept
408 : {
409 40767328 : return lessthani(a, b); // SameString(a, b);
410 : }
411 :
412 93 : 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 93 : 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 93 : state.dataUtilityRoutines->appendPerfLog_headerRow = state.dataUtilityRoutines->appendPerfLog_headerRow + colHeader + ",";
426 93 : state.dataUtilityRoutines->appendPerfLog_valuesRow = state.dataUtilityRoutines->appendPerfLog_valuesRow + colValue + ",";
427 :
428 93 : if (finalColumn) {
429 6 : 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(state,
435 0 : "appendPerfLog: Could not open file \"" + state.dataStrGlobals->outputPerfLogFilePath.string() +
436 : "\" for output (write).");
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(state,
446 0 : "appendPerfLog: Could not open file \"" + state.dataStrGlobals->outputPerfLogFilePath.string() +
447 : "\" for output (append).");
448 : }
449 0 : fsPerfLog << state.dataUtilityRoutines->appendPerfLog_valuesRow << std::endl;
450 : }
451 : }
452 3 : fsPerfLog.close();
453 : }
454 : }
455 :
456 32 : bool ValidateFuelType([[maybe_unused]] EnergyPlusData &state,
457 : std::string const &FuelTypeInput,
458 : std::string &FuelTypeOutput,
459 : bool &FuelTypeErrorsFound,
460 : bool const AllowSteamAndDistrict)
461 : {
462 : // FUNCTION INFORMATION:
463 : // AUTHOR Dareum Nam
464 : // DATE WRITTEN May 2020
465 :
466 : // PURPOSE OF THIS FUNCTION:
467 : // Validates fuel types and sets output strings
468 :
469 64 : auto const SELECT_CASE_var(UtilityRoutines::MakeUPPERCase(FuelTypeInput));
470 :
471 32 : if (SELECT_CASE_var == "ELECTRICITY") {
472 0 : FuelTypeOutput = "Electricity";
473 :
474 32 : } else if (SELECT_CASE_var == "NATURALGAS") {
475 15 : FuelTypeOutput = "NaturalGas";
476 :
477 17 : } else if (SELECT_CASE_var == "DIESEL") {
478 17 : FuelTypeOutput = "Diesel";
479 :
480 0 : } else if (SELECT_CASE_var == "GASOLINE") {
481 0 : FuelTypeOutput = "Gasoline";
482 :
483 0 : } else if (SELECT_CASE_var == "COAL") {
484 0 : FuelTypeOutput = "Coal";
485 :
486 0 : } else if (SELECT_CASE_var == "FUELOILNO1") {
487 0 : FuelTypeOutput = "FuelOilNo1";
488 :
489 0 : } else if (SELECT_CASE_var == "FUELOILNO2") {
490 0 : FuelTypeOutput = "FuelOilNo2";
491 :
492 0 : } else if (SELECT_CASE_var == "PROPANE") {
493 0 : FuelTypeOutput = "Propane";
494 :
495 0 : } else if (SELECT_CASE_var == "OTHERFUEL1") {
496 0 : FuelTypeOutput = "OtherFuel1";
497 :
498 0 : } else if (SELECT_CASE_var == "OTHERFUEL2") {
499 0 : FuelTypeOutput = "OtherFuel2";
500 :
501 : } else {
502 0 : if (AllowSteamAndDistrict) {
503 0 : if (SELECT_CASE_var == "STEAM") {
504 0 : FuelTypeOutput = "Steam";
505 0 : } else if (SELECT_CASE_var == "DISTRICTHEATING") {
506 0 : FuelTypeOutput = "DistrictHeating";
507 0 : } else if (SELECT_CASE_var == "DISTRICTCOOLING") {
508 0 : FuelTypeOutput = "DistrictCooling";
509 : } else {
510 0 : FuelTypeErrorsFound = true;
511 : }
512 : } else {
513 0 : FuelTypeErrorsFound = true;
514 : }
515 : }
516 :
517 64 : return FuelTypeErrorsFound;
518 : }
519 :
520 333 : bool ValidateFuelTypeWithAssignResourceTypeNum(std::string const &FuelTypeInput,
521 : std::string &FuelTypeOutput,
522 : DataGlobalConstants::ResourceType &FuelTypeNum,
523 : bool &FuelTypeErrorsFound)
524 : {
525 : // FUNCTION INFORMATION:
526 : // AUTHOR Dareum Nam
527 : // DATE WRITTEN May 2020
528 :
529 : // PURPOSE OF THIS FUNCTION:
530 : // Validates fuel types and sets output strings with DataGlobalConstants::AssignResourceTypeNum() (Boilers.cc and boilerSteam.cc)
531 :
532 666 : auto const SELECT_CASE_var(FuelTypeInput);
533 :
534 333 : if (SELECT_CASE_var == "ELECTRICITY") {
535 118 : FuelTypeOutput = "Electricity";
536 118 : FuelTypeNum = DataGlobalConstants::AssignResourceTypeNum("ELECTRICITY");
537 :
538 215 : } else if (SELECT_CASE_var == "NATURALGAS") {
539 214 : FuelTypeOutput = "NaturalGas";
540 214 : FuelTypeNum = DataGlobalConstants::AssignResourceTypeNum("NATURALGAS");
541 :
542 1 : } else if (SELECT_CASE_var == "DIESEL") {
543 0 : FuelTypeOutput = "Diesel";
544 0 : FuelTypeNum = DataGlobalConstants::AssignResourceTypeNum("DIESEL");
545 :
546 1 : } else if (SELECT_CASE_var == "GASOLINE") {
547 0 : FuelTypeOutput = "Gasoline";
548 0 : FuelTypeNum = DataGlobalConstants::AssignResourceTypeNum("GASOLINE");
549 :
550 1 : } else if (SELECT_CASE_var == "COAL") {
551 0 : FuelTypeOutput = "Coal";
552 0 : FuelTypeNum = DataGlobalConstants::AssignResourceTypeNum("COAL");
553 :
554 1 : } else if (SELECT_CASE_var == "FUELOILNO1") {
555 0 : FuelTypeOutput = "FuelOilNo1";
556 0 : FuelTypeNum = DataGlobalConstants::AssignResourceTypeNum("FUELOILNO1");
557 :
558 1 : } else if (SELECT_CASE_var == "FUELOILNO2") {
559 0 : FuelTypeOutput = "FuelOilNo2";
560 0 : FuelTypeNum = DataGlobalConstants::AssignResourceTypeNum("FUELOILNO2");
561 :
562 1 : } else if (SELECT_CASE_var == "PROPANE") {
563 0 : FuelTypeOutput = "Propane";
564 0 : FuelTypeNum = DataGlobalConstants::AssignResourceTypeNum("PROPANE");
565 :
566 1 : } else if (SELECT_CASE_var == "OTHERFUEL1") {
567 1 : FuelTypeOutput = "OtherFuel1";
568 1 : FuelTypeNum = DataGlobalConstants::AssignResourceTypeNum("OTHERFUEL1");
569 :
570 0 : } else if (SELECT_CASE_var == "OTHERFUEL2") {
571 0 : FuelTypeOutput = "OtherFuel2";
572 0 : FuelTypeNum = DataGlobalConstants::AssignResourceTypeNum("OTHERFUEL2");
573 :
574 : } else {
575 0 : FuelTypeErrorsFound = true;
576 : }
577 :
578 666 : return FuelTypeErrorsFound;
579 : }
580 :
581 1542 : Real64 epElapsedTime()
582 : {
583 :
584 : // FUNCTION INFORMATION:
585 : // AUTHOR Linda Lawrie
586 : // DATE WRITTEN February 2012
587 : // MODIFIED na
588 : // RE-ENGINEERED na
589 :
590 : // PURPOSE OF THIS FUNCTION:
591 : // An alternative method for timing elapsed times is to call the standard
592 : // Date_And_Time routine and set the "time".
593 :
594 : // Return value
595 : Real64 calctime; // calculated time based on hrs, minutes, seconds, milliseconds
596 :
597 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
598 3084 : Array1D<Int32> clockvalues(8);
599 : // value(1) Current year
600 : // value(2) Current month
601 : // value(3) Current day
602 : // value(4) Time difference with respect to UTC in minutes (0-59)
603 : // value(5) Hour of the day (0-23)
604 : // value(6) Minutes (0-59)
605 : // value(7) Seconds (0-59)
606 : // value(8) Milliseconds (0-999)
607 :
608 1542 : date_and_time(_, _, _, clockvalues);
609 1542 : calctime = clockvalues(5) * 3600.0 + clockvalues(6) * 60.0 + clockvalues(7) + clockvalues(8) / 1000.0;
610 :
611 3084 : return calctime;
612 : }
613 :
614 : } // namespace UtilityRoutines
615 :
616 2 : int AbortEnergyPlus(EnergyPlusData &state)
617 : {
618 :
619 : // SUBROUTINE INFORMATION:
620 : // AUTHOR Linda K. Lawrie
621 : // DATE WRITTEN December 1997
622 : // MODIFIED na
623 : // RE-ENGINEERED na
624 :
625 : // PURPOSE OF THIS SUBROUTINE:
626 : // This subroutine causes the program to halt due to a fatal error.
627 :
628 : // METHODOLOGY EMPLOYED:
629 : // Puts a message on output files.
630 : // Closes files.
631 : // Stops the program.
632 :
633 : // Using/Aliasing
634 : using namespace DataSystemVariables;
635 : using namespace DataErrorTracking;
636 : using BranchInputManager::TestBranchIntegrity;
637 : using BranchNodeConnections::CheckNodeConnections;
638 : using BranchNodeConnections::TestCompSetInletOutletNodes;
639 : using ExternalInterface::CloseSocket;
640 :
641 : using NodeInputManager::CheckMarkedNodes;
642 : using NodeInputManager::SetupNodeVarsForReporting;
643 : using PlantManager::CheckPlantOnAbort;
644 : using SimulationManager::ReportLoopConnections;
645 : using SolarShading::ReportSurfaceErrors;
646 : using SystemReports::ReportAirLoopConnections;
647 :
648 : // Locals
649 : // SUBROUTINE ARGUMENT DEFINITIONS:
650 :
651 : // SUBROUTINE PARAMETER DEFINITIONS:
652 :
653 4 : std::string NumWarnings;
654 4 : std::string NumSevere;
655 4 : std::string NumWarningsDuringWarmup;
656 4 : std::string NumSevereDuringWarmup;
657 4 : std::string NumWarningsDuringSizing;
658 4 : std::string NumSevereDuringSizing;
659 : int Hours; // Elapsed Time Hour Reporting
660 : int Minutes; // Elapsed Time Minute Reporting
661 : Real64 Seconds; // Elapsed Time Second Reporting
662 : bool ErrFound;
663 : bool TerminalError;
664 :
665 2 : if (state.dataSQLiteProcedures->sqlite) {
666 0 : state.dataSQLiteProcedures->sqlite->updateSQLiteSimulationRecord(true, false);
667 : }
668 :
669 2 : state.dataErrTracking->AbortProcessing = true;
670 2 : if (state.dataErrTracking->AskForConnectionsReport) {
671 0 : state.dataErrTracking->AskForConnectionsReport = false; // Set false here in case any further fatal errors in below processing...
672 :
673 0 : ShowMessage(state, "Fatal error -- final processing. More error messages may appear.");
674 0 : SetupNodeVarsForReporting(state);
675 :
676 0 : ErrFound = false;
677 0 : TerminalError = false;
678 0 : TestBranchIntegrity(state, ErrFound);
679 0 : if (ErrFound) TerminalError = true;
680 0 : TestAirPathIntegrity(state, ErrFound);
681 0 : if (ErrFound) TerminalError = true;
682 0 : CheckMarkedNodes(state, ErrFound);
683 0 : if (ErrFound) TerminalError = true;
684 0 : CheckNodeConnections(state, ErrFound);
685 0 : if (ErrFound) TerminalError = true;
686 0 : TestCompSetInletOutletNodes(state, ErrFound);
687 0 : if (ErrFound) TerminalError = true;
688 :
689 0 : if (!TerminalError) {
690 0 : ReportAirLoopConnections(state);
691 0 : ReportLoopConnections(state);
692 : }
693 :
694 2 : } else if (!state.dataErrTracking->ExitDuringSimulations) {
695 2 : ShowMessage(state, "Warning: Node connection errors not checked - most system input has not been read (see previous warning).");
696 2 : ShowMessage(state, "Fatal error -- final processing. Program exited before simulations began. See previous error messages.");
697 : }
698 :
699 2 : if (state.dataErrTracking->AskForSurfacesReport) {
700 2 : ReportSurfaces(state);
701 : }
702 :
703 2 : ReportSurfaceErrors(state);
704 2 : CheckPlantOnAbort(state);
705 2 : ShowRecurringErrors(state);
706 2 : SummarizeErrors(state);
707 2 : CloseMiscOpenFiles(state);
708 2 : NumWarnings = fmt::to_string(state.dataErrTracking->TotalWarningErrors);
709 2 : NumSevere = fmt::to_string(state.dataErrTracking->TotalSevereErrors);
710 2 : NumWarningsDuringWarmup = fmt::to_string(state.dataErrTracking->TotalWarningErrorsDuringWarmup);
711 2 : NumSevereDuringWarmup = fmt::to_string(state.dataErrTracking->TotalSevereErrorsDuringWarmup);
712 2 : NumWarningsDuringSizing = fmt::to_string(state.dataErrTracking->TotalWarningErrorsDuringSizing);
713 2 : NumSevereDuringSizing = fmt::to_string(state.dataErrTracking->TotalSevereErrorsDuringSizing);
714 :
715 : // catch up with timings if in middle
716 2 : state.dataSysVars->Time_Finish = UtilityRoutines::epElapsedTime();
717 2 : if (state.dataSysVars->Time_Finish < state.dataSysVars->Time_Start) state.dataSysVars->Time_Finish += 24.0 * 3600.0;
718 2 : state.dataSysVars->Elapsed_Time = state.dataSysVars->Time_Finish - state.dataSysVars->Time_Start;
719 2 : if (state.dataSysVars->Elapsed_Time < 0.0) state.dataSysVars->Elapsed_Time = 0.0;
720 2 : Hours = state.dataSysVars->Elapsed_Time / 3600.0;
721 2 : state.dataSysVars->Elapsed_Time -= Hours * 3600.0;
722 2 : Minutes = state.dataSysVars->Elapsed_Time / 60.0;
723 2 : state.dataSysVars->Elapsed_Time -= Minutes * 60.0;
724 2 : Seconds = state.dataSysVars->Elapsed_Time;
725 2 : if (Seconds < 0.0) Seconds = 0.0;
726 4 : const auto Elapsed = format("{:02}hr {:02}min {:5.2F}sec", Hours, Minutes, Seconds);
727 :
728 2 : state.dataResultsFramework->resultsFramework->SimulationInformation.setRunTime(Elapsed);
729 2 : state.dataResultsFramework->resultsFramework->SimulationInformation.setNumErrorsWarmup(NumWarningsDuringWarmup, NumSevereDuringWarmup);
730 2 : state.dataResultsFramework->resultsFramework->SimulationInformation.setNumErrorsSizing(NumWarningsDuringSizing, NumSevereDuringSizing);
731 2 : state.dataResultsFramework->resultsFramework->SimulationInformation.setNumErrorsSummary(NumWarnings, NumSevere);
732 :
733 6 : ShowMessage(state,
734 4 : "EnergyPlus Warmup Error Summary. During Warmup: " + NumWarningsDuringWarmup + " Warning; " + NumSevereDuringWarmup +
735 : " Severe Errors.");
736 6 : ShowMessage(state,
737 4 : "EnergyPlus Sizing Error Summary. During Sizing: " + NumWarningsDuringSizing + " Warning; " + NumSevereDuringSizing +
738 : " Severe Errors.");
739 6 : ShowMessage(state,
740 4 : "EnergyPlus Terminated--Fatal Error Detected. " + NumWarnings + " Warning; " + NumSevere + " Severe Errors; Elapsed Time=" + Elapsed);
741 2 : DisplayString(state, "EnergyPlus Run Time=" + Elapsed);
742 :
743 : {
744 4 : auto tempfl = state.files.endFile.try_open(state.files.outputControl.end);
745 :
746 2 : if (!tempfl.good()) {
747 0 : DisplayString(state, "AbortEnergyPlus: Could not open file " + tempfl.filePath.string() + " for output (write).");
748 : }
749 2 : print(
750 2 : tempfl, "EnergyPlus Terminated--Fatal Error Detected. {} Warning; {} Severe Errors; Elapsed Time={}\n", NumWarnings, NumSevere, Elapsed);
751 : }
752 :
753 2 : state.dataResultsFramework->resultsFramework->writeOutputs(state);
754 :
755 : std::cerr << "Program terminated: "
756 2 : << "EnergyPlus Terminated--Error(s) Detected." << std::endl;
757 : // Close the socket used by ExternalInterface. This call also sends the flag "-1" to the ExternalInterface,
758 : // indicating that E+ terminated with an error.
759 2 : if (state.dataExternalInterface->NumExternalInterfaces > 0) CloseSocket(state, -1);
760 :
761 2 : if (state.dataGlobal->eplusRunningViaAPI) {
762 0 : state.files.flushAll();
763 : }
764 :
765 4 : return EXIT_FAILURE;
766 : }
767 :
768 771 : void CloseMiscOpenFiles(EnergyPlusData &state)
769 : {
770 :
771 : // SUBROUTINE INFORMATION:
772 : // AUTHOR Linda K. Lawrie
773 : // DATE WRITTEN December 1997
774 : // MODIFIED na
775 : // RE-ENGINEERED na
776 :
777 : // PURPOSE OF THIS SUBROUTINE:
778 : // This subroutine scans potential unit numbers and closes
779 : // any that are still open.
780 :
781 : // METHODOLOGY EMPLOYED:
782 : // Use INQUIRE to determine if file is open.
783 :
784 : // Using/Aliasing
785 : using DaylightingManager::CloseDFSFile;
786 : using DaylightingManager::CloseReportIllumMaps;
787 :
788 771 : CloseReportIllumMaps(state);
789 771 : CloseDFSFile(state);
790 :
791 771 : if (state.dataReportFlag->DebugOutput || (state.files.debug.good() && state.files.debug.position() > 0)) {
792 2 : state.files.debug.close();
793 : } else {
794 769 : state.files.debug.del();
795 : }
796 771 : }
797 :
798 769 : int EndEnergyPlus(EnergyPlusData &state)
799 : {
800 :
801 : // SUBROUTINE INFORMATION:
802 : // AUTHOR Linda K. Lawrie
803 : // DATE WRITTEN December 1997
804 : // MODIFIED na
805 : // RE-ENGINEERED na
806 :
807 : // PURPOSE OF THIS SUBROUTINE:
808 : // This subroutine causes the program to terminate when complete (no errors).
809 :
810 : // METHODOLOGY EMPLOYED:
811 : // Puts a message on output files.
812 : // Closes files.
813 : // Stops the program.
814 :
815 : using namespace DataSystemVariables;
816 : using namespace DataErrorTracking;
817 : using ExternalInterface::CloseSocket;
818 :
819 : using SolarShading::ReportSurfaceErrors;
820 :
821 1538 : std::string NumWarnings;
822 1538 : std::string NumSevere;
823 1538 : std::string NumWarningsDuringWarmup;
824 1538 : std::string NumSevereDuringWarmup;
825 1538 : std::string NumWarningsDuringSizing;
826 1538 : std::string NumSevereDuringSizing;
827 : int Hours; // Elapsed Time Hour Reporting
828 : int Minutes; // Elapsed Time Minute Reporting
829 : Real64 Seconds; // Elapsed Time Second Reporting
830 :
831 769 : if (state.dataSQLiteProcedures->sqlite) {
832 0 : state.dataSQLiteProcedures->sqlite->updateSQLiteSimulationRecord(true, true);
833 : }
834 :
835 769 : ReportSurfaceErrors(state);
836 769 : ShowRecurringErrors(state);
837 769 : SummarizeErrors(state);
838 769 : CloseMiscOpenFiles(state);
839 769 : NumWarnings = fmt::to_string(state.dataErrTracking->TotalWarningErrors);
840 769 : strip(NumWarnings);
841 769 : NumSevere = fmt::to_string(state.dataErrTracking->TotalSevereErrors);
842 769 : strip(NumSevere);
843 769 : NumWarningsDuringWarmup = fmt::to_string(state.dataErrTracking->TotalWarningErrorsDuringWarmup);
844 769 : strip(NumWarningsDuringWarmup);
845 769 : NumSevereDuringWarmup = fmt::to_string(state.dataErrTracking->TotalSevereErrorsDuringWarmup);
846 769 : strip(NumSevereDuringWarmup);
847 769 : NumWarningsDuringSizing = fmt::to_string(state.dataErrTracking->TotalWarningErrorsDuringSizing);
848 769 : strip(NumWarningsDuringSizing);
849 769 : NumSevereDuringSizing = fmt::to_string(state.dataErrTracking->TotalSevereErrorsDuringSizing);
850 769 : strip(NumSevereDuringSizing);
851 :
852 769 : state.dataSysVars->Time_Finish = UtilityRoutines::epElapsedTime();
853 769 : if (state.dataSysVars->Time_Finish < state.dataSysVars->Time_Start) state.dataSysVars->Time_Finish += 24.0 * 3600.0;
854 769 : state.dataSysVars->Elapsed_Time = state.dataSysVars->Time_Finish - state.dataSysVars->Time_Start;
855 769 : if (state.dataGlobal->createPerfLog) {
856 3 : UtilityRoutines::appendPerfLog(state, "Run Time [seconds]", format("{:.2R}", state.dataSysVars->Elapsed_Time));
857 : }
858 769 : Hours = state.dataSysVars->Elapsed_Time / 3600.0;
859 769 : state.dataSysVars->Elapsed_Time -= Hours * 3600.0;
860 769 : Minutes = state.dataSysVars->Elapsed_Time / 60.0;
861 769 : state.dataSysVars->Elapsed_Time -= Minutes * 60.0;
862 769 : Seconds = state.dataSysVars->Elapsed_Time;
863 769 : if (Seconds < 0.0) Seconds = 0.0;
864 1538 : const auto Elapsed = format("{:02}hr {:02}min {:5.2F}sec", Hours, Minutes, Seconds);
865 :
866 769 : state.dataResultsFramework->resultsFramework->SimulationInformation.setRunTime(Elapsed);
867 769 : state.dataResultsFramework->resultsFramework->SimulationInformation.setNumErrorsWarmup(NumWarningsDuringWarmup, NumSevereDuringWarmup);
868 769 : state.dataResultsFramework->resultsFramework->SimulationInformation.setNumErrorsSizing(NumWarningsDuringSizing, NumSevereDuringSizing);
869 769 : state.dataResultsFramework->resultsFramework->SimulationInformation.setNumErrorsSummary(NumWarnings, NumSevere);
870 :
871 769 : if (state.dataGlobal->createPerfLog) {
872 3 : UtilityRoutines::appendPerfLog(state, "Run Time [string]", Elapsed);
873 3 : UtilityRoutines::appendPerfLog(state, "Number of Warnings", NumWarnings);
874 3 : UtilityRoutines::appendPerfLog(state, "Number of Severe", NumSevere, true); // last item so write the perfLog file
875 : }
876 2307 : ShowMessage(state,
877 1538 : "EnergyPlus Warmup Error Summary. During Warmup: " + NumWarningsDuringWarmup + " Warning; " + NumSevereDuringWarmup +
878 : " Severe Errors.");
879 2307 : ShowMessage(state,
880 1538 : "EnergyPlus Sizing Error Summary. During Sizing: " + NumWarningsDuringSizing + " Warning; " + NumSevereDuringSizing +
881 : " Severe Errors.");
882 769 : ShowMessage(state, "EnergyPlus Completed Successfully-- " + NumWarnings + " Warning; " + NumSevere + " Severe Errors; Elapsed Time=" + Elapsed);
883 769 : DisplayString(state, "EnergyPlus Run Time=" + Elapsed);
884 :
885 : {
886 1538 : auto tempfl = state.files.endFile.try_open(state.files.outputControl.end);
887 769 : if (!tempfl.good()) {
888 0 : DisplayString(state, "EndEnergyPlus: Could not open file " + tempfl.filePath.string() + " for output (write).");
889 : }
890 769 : print(tempfl, "EnergyPlus Completed Successfully-- {} Warning; {} Severe Errors; Elapsed Time={}\n", NumWarnings, NumSevere, Elapsed);
891 : }
892 :
893 769 : state.dataResultsFramework->resultsFramework->writeOutputs(state);
894 :
895 769 : if (state.dataGlobal->printConsoleOutput) std::cerr << "EnergyPlus Completed Successfully." << std::endl;
896 : // Close the ExternalInterface socket. This call also sends the flag "1" to the ExternalInterface,
897 : // indicating that E+ finished its simulation
898 769 : if ((state.dataExternalInterface->NumExternalInterfaces > 0) && state.dataExternalInterface->haveExternalInterfaceBCVTB) CloseSocket(state, 1);
899 :
900 769 : if (state.dataGlobal->eplusRunningViaAPI) {
901 0 : state.files.flushAll();
902 : }
903 :
904 1538 : return EXIT_SUCCESS;
905 : }
906 :
907 0 : void ConvertCaseToUpper(std::string_view InputString, // Input string
908 : std::string &OutputString // Output string (in UpperCase)
909 : )
910 : {
911 :
912 : // SUBROUTINE INFORMATION:
913 : // AUTHOR Linda K. Lawrie
914 : // DATE WRITTEN September 1997
915 : // MODIFIED na
916 : // RE-ENGINEERED na
917 :
918 : // PURPOSE OF THIS SUBROUTINE:
919 : // Convert a string to upper case
920 :
921 : // METHODOLOGY EMPLOYED:
922 : // This routine is not dependant upon the ASCII
923 : // code. It works by storing the upper and lower case alphabet. It
924 : // scans the whole input string. If it finds a character in the lower
925 : // case alphabet, it makes an appropriate substitution.
926 :
927 : // Using/Aliasing
928 : static constexpr std::string_view UpperCase("ABCDEFGHIJKLMNOPQRSTUVWXYZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝ");
929 : static constexpr std::string_view LowerCase("abcdefghijklmnopqrstuvwxyzàáâãäåæçèéêëìíîïðñòóôõöøùúûüý");
930 :
931 0 : OutputString = InputString;
932 :
933 0 : for (std::string::size_type A = 0; A < len(InputString); ++A) {
934 0 : std::string::size_type const B = index(LowerCase, InputString[A]);
935 0 : if (B != std::string::npos) {
936 0 : OutputString[A] = UpperCase[B];
937 : }
938 : }
939 0 : }
940 :
941 33 : void ConvertCaseToLower(std::string_view InputString, // Input string
942 : std::string &OutputString // Output string (in LowerCase)
943 : )
944 : {
945 :
946 : // SUBROUTINE INFORMATION:
947 : // AUTHOR Linda K. Lawrie
948 : // DATE WRITTEN September 1997
949 : // MODIFIED na
950 : // RE-ENGINEERED na
951 :
952 : // PURPOSE OF THIS SUBROUTINE:
953 : // Convert a string to lower case
954 :
955 : // METHODOLOGY EMPLOYED:
956 : // This routine is not dependant upon the ASCII
957 : // code. It works by storing the upper and lower case alphabet. It
958 : // scans the whole input string. If it finds a character in the lower
959 : // case alphabet, it makes an appropriate substitution.
960 :
961 : // Using/Aliasing
962 : static constexpr std::string_view UpperCase("ABCDEFGHIJKLMNOPQRSTUVWXYZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝ");
963 : static constexpr std::string_view LowerCase("abcdefghijklmnopqrstuvwxyzàáâãäåæçèéêëìíîïðñòóôõöøùúûüý");
964 :
965 33 : OutputString = InputString;
966 :
967 367 : for (std::string::size_type A = 0; A < len(InputString); ++A) {
968 334 : std::string::size_type const B = index(UpperCase, InputString[A]);
969 334 : if (B != std::string::npos) {
970 334 : OutputString[A] = LowerCase[B];
971 : }
972 : }
973 33 : }
974 :
975 6160 : std::string::size_type FindNonSpace(std::string const &String) // String to be scanned
976 : {
977 :
978 : // FUNCTION INFORMATION:
979 : // AUTHOR Linda K. Lawrie
980 : // DATE WRITTEN September 1997
981 : // MODIFIED na
982 : // RE-ENGINEERED na
983 :
984 : // PURPOSE OF THIS FUNCTION:
985 : // This function finds the first non-space character in the passed string
986 : // and returns that position as the result to the calling program.
987 :
988 : // METHODOLOGY EMPLOYED:
989 : // Scan string for character not equal to blank.
990 :
991 : // REFERENCES:
992 : // na
993 :
994 : // USE STATEMENTS:
995 : // na
996 :
997 : // Return value
998 :
999 : // Locals
1000 : // FUNCTION ARGUMENT DEFINITIONS:
1001 :
1002 : // FUNCTION PARAMETER DEFINITIONS:
1003 : // na
1004 :
1005 : // INTERFACE BLOCK SPECIFICATIONS
1006 : // na
1007 :
1008 : // DERIVED TYPE DEFINITIONS
1009 : // na
1010 :
1011 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
1012 :
1013 6160 : return String.find_first_not_of(' ');
1014 : }
1015 :
1016 3855 : bool env_var_on(std::string const &env_var_str)
1017 : {
1018 :
1019 : // FUNCTION INFORMATION:
1020 : // AUTHOR Stuart G. Mentzer
1021 : // DATE WRITTEN April 2014
1022 : // MODIFIED na
1023 : // RE-ENGINEERED na
1024 :
1025 : // PURPOSE OF THIS FUNCTION:
1026 : // Test if a boolean environment variable value is "on" (has value starting with Y or T)
1027 :
1028 3855 : return ((!env_var_str.empty()) && is_any_of(env_var_str[0], "YyTt"));
1029 : }
1030 :
1031 2 : void ShowFatalError(EnergyPlusData &state, std::string const &ErrorMessage, OptionalOutputFileRef OutUnit1, OptionalOutputFileRef OutUnit2)
1032 : {
1033 :
1034 : // SUBROUTINE INFORMATION:
1035 : // AUTHOR Linda K. Lawrie
1036 : // DATE WRITTEN September 1997
1037 : // MODIFIED Kyle Benne
1038 : // August 2010
1039 : // Added sqlite output
1040 : // RE-ENGINEERED na
1041 :
1042 : // PURPOSE OF THIS SUBROUTINE:
1043 : // This subroutine puts ErrorMessage with a Fatal designation on
1044 : // designated output files. Then, the program is aborted.
1045 :
1046 : // METHODOLOGY EMPLOYED:
1047 : // Calls ShowErrorMessage utility routine.
1048 : // Calls AbortEnergyPlus
1049 :
1050 : using namespace DataErrorTracking;
1051 :
1052 2 : ShowErrorMessage(state, " ** Fatal ** " + ErrorMessage, OutUnit1, OutUnit2);
1053 2 : DisplayString(state, "**FATAL:" + ErrorMessage);
1054 :
1055 2 : ShowErrorMessage(state, " ...Summary of Errors that led to program termination:", OutUnit1, OutUnit2);
1056 2 : ShowErrorMessage(state, format(" ..... Reference severe error count={}", state.dataErrTracking->TotalSevereErrors), OutUnit1, OutUnit2);
1057 2 : ShowErrorMessage(state, " ..... Last severe error=" + state.dataErrTracking->LastSevereError, OutUnit1, OutUnit2);
1058 2 : if (state.dataSQLiteProcedures->sqlite) {
1059 0 : state.dataSQLiteProcedures->sqlite->createSQLiteErrorRecord(1, 2, ErrorMessage, 1);
1060 0 : if (state.dataSQLiteProcedures->sqlite->sqliteWithinTransaction()) state.dataSQLiteProcedures->sqlite->sqliteCommit();
1061 : }
1062 2 : if (state.dataGlobal->errorCallback) {
1063 0 : state.dataGlobal->errorCallback(Error::Fatal, ErrorMessage);
1064 : }
1065 2 : throw FatalError(ErrorMessage);
1066 : }
1067 :
1068 78 : void ShowSevereError(EnergyPlusData &state, std::string const &ErrorMessage, OptionalOutputFileRef OutUnit1, OptionalOutputFileRef OutUnit2)
1069 : {
1070 :
1071 : // SUBROUTINE INFORMATION:
1072 : // AUTHOR Linda K. Lawrie
1073 : // DATE WRITTEN September 1997
1074 : // MODIFIED na
1075 : // RE-ENGINEERED na
1076 :
1077 : // PURPOSE OF THIS SUBROUTINE:
1078 : // This subroutine puts ErrorMessage with a Severe designation on
1079 : // designated output files.
1080 :
1081 : // METHODOLOGY EMPLOYED:
1082 : // Calls ShowErrorMessage utility routine.
1083 :
1084 : using namespace DataStringGlobals;
1085 : using namespace DataErrorTracking;
1086 : int Loop;
1087 :
1088 1638 : for (Loop = 1; Loop <= SearchCounts; ++Loop) {
1089 1560 : if (has(ErrorMessage, MessageSearch[Loop])) ++state.dataErrTracking->MatchCounts(Loop);
1090 : }
1091 :
1092 78 : ++state.dataErrTracking->TotalSevereErrors;
1093 101 : if (state.dataGlobal->WarmupFlag && !state.dataGlobal->DoingSizing && !state.dataGlobal->KickOffSimulation &&
1094 23 : !state.dataErrTracking->AbortProcessing)
1095 23 : ++state.dataErrTracking->TotalSevereErrorsDuringWarmup;
1096 78 : if (state.dataGlobal->DoingSizing) ++state.dataErrTracking->TotalSevereErrorsDuringSizing;
1097 78 : ShowErrorMessage(state, " ** Severe ** " + ErrorMessage, OutUnit1, OutUnit2);
1098 78 : state.dataErrTracking->LastSevereError = ErrorMessage;
1099 :
1100 : // Could set a variable here that gets checked at some point?
1101 :
1102 78 : if (state.dataSQLiteProcedures->sqlite) {
1103 6 : state.dataSQLiteProcedures->sqlite->createSQLiteErrorRecord(1, 1, ErrorMessage, 1);
1104 : }
1105 78 : if (state.dataGlobal->errorCallback) {
1106 0 : state.dataGlobal->errorCallback(Error::Severe, ErrorMessage);
1107 : }
1108 78 : }
1109 :
1110 5 : void ShowSevereMessage(EnergyPlusData &state, std::string const &ErrorMessage, OptionalOutputFileRef OutUnit1, OptionalOutputFileRef OutUnit2)
1111 : {
1112 :
1113 : // SUBROUTINE INFORMATION:
1114 : // AUTHOR Linda K. Lawrie
1115 : // DATE WRITTEN September 2009
1116 : // MODIFIED na
1117 : // RE-ENGINEERED na
1118 :
1119 : // PURPOSE OF THIS SUBROUTINE:
1120 : // This subroutine puts ErrorMessage with a Severe designation on
1121 : // designated output files.
1122 : // But does not bump the error count so can be used in conjunction with recurring
1123 : // error calls.
1124 :
1125 : // METHODOLOGY EMPLOYED:
1126 : // Calls ShowErrorMessage utility routine.
1127 :
1128 : using namespace DataStringGlobals;
1129 : using namespace DataErrorTracking;
1130 :
1131 : int Loop;
1132 :
1133 105 : for (Loop = 1; Loop <= SearchCounts; ++Loop) {
1134 100 : if (has(ErrorMessage, MessageSearch[Loop])) ++state.dataErrTracking->MatchCounts(Loop);
1135 : }
1136 :
1137 5 : ShowErrorMessage(state, " ** Severe ** " + ErrorMessage, OutUnit1, OutUnit2);
1138 5 : state.dataErrTracking->LastSevereError = ErrorMessage;
1139 :
1140 : // Could set a variable here that gets checked at some point?
1141 :
1142 5 : if (state.dataSQLiteProcedures->sqlite) {
1143 1 : state.dataSQLiteProcedures->sqlite->createSQLiteErrorRecord(1, 1, ErrorMessage, 0);
1144 : }
1145 5 : if (state.dataGlobal->errorCallback) {
1146 0 : state.dataGlobal->errorCallback(Error::Severe, ErrorMessage);
1147 : }
1148 5 : }
1149 :
1150 3963 : void ShowContinueError(EnergyPlusData &state, std::string const &Message, OptionalOutputFileRef OutUnit1, OptionalOutputFileRef OutUnit2)
1151 : {
1152 :
1153 : // SUBROUTINE INFORMATION:
1154 : // AUTHOR Linda K. Lawrie
1155 : // DATE WRITTEN October 2001
1156 : // MODIFIED na
1157 : // RE-ENGINEERED na
1158 :
1159 : // PURPOSE OF THIS SUBROUTINE:
1160 : // This subroutine displays a 'continued error' message on designated output files.
1161 :
1162 : // METHODOLOGY EMPLOYED:
1163 : // Calls ShowErrorMessage utility routine.
1164 :
1165 3963 : ShowErrorMessage(state, " ** ~~~ ** " + Message, OutUnit1, OutUnit2);
1166 3963 : if (state.dataSQLiteProcedures->sqlite) {
1167 633 : state.dataSQLiteProcedures->sqlite->updateSQLiteErrorRecord(Message);
1168 : }
1169 3963 : if (state.dataGlobal->errorCallback) {
1170 0 : state.dataGlobal->errorCallback(Error::Continue, Message);
1171 : }
1172 3963 : }
1173 :
1174 186 : void ShowContinueErrorTimeStamp(EnergyPlusData &state, std::string const &Message, OptionalOutputFileRef OutUnit1, OptionalOutputFileRef OutUnit2)
1175 : {
1176 :
1177 : // SUBROUTINE INFORMATION:
1178 : // AUTHOR Linda K. Lawrie
1179 : // DATE WRITTEN February 2004
1180 : // MODIFIED na
1181 : // RE-ENGINEERED na
1182 :
1183 : // PURPOSE OF THIS SUBROUTINE:
1184 : // This subroutine displays a 'continued error' timestamp message on designated output files.
1185 :
1186 : // METHODOLOGY EMPLOYED:
1187 : // Calls ShowErrorMessage utility routine.
1188 :
1189 : // Using/Aliasing
1190 : using General::CreateSysTimeIntervalString;
1191 :
1192 372 : std::string cEnvHeader;
1193 :
1194 186 : if (state.dataGlobal->WarmupFlag) {
1195 79 : if (!state.dataGlobal->DoingSizing) {
1196 79 : cEnvHeader = " During Warmup, Environment=";
1197 : } else {
1198 0 : cEnvHeader = " During Warmup & Sizing, Environment=";
1199 : }
1200 : } else {
1201 107 : if (!state.dataGlobal->DoingSizing) {
1202 107 : cEnvHeader = " Environment=";
1203 : } else {
1204 0 : cEnvHeader = " During Sizing, Environment=";
1205 : }
1206 : }
1207 :
1208 186 : if (len(Message) < 50) {
1209 338 : const auto m = Message + cEnvHeader + state.dataEnvrn->EnvironmentName + ", at Simulation time=" + state.dataEnvrn->CurMnDy + ' ' +
1210 676 : CreateSysTimeIntervalString(state);
1211 169 : ShowErrorMessage(state, " ** ~~~ ** " + m, OutUnit1, OutUnit2);
1212 169 : if (state.dataSQLiteProcedures->sqlite) {
1213 28 : state.dataSQLiteProcedures->sqlite->updateSQLiteErrorRecord(m);
1214 : }
1215 169 : if (state.dataGlobal->errorCallback) {
1216 0 : state.dataGlobal->errorCallback(Error::Continue, m);
1217 : }
1218 : } else {
1219 34 : const auto m = " ** ~~~ ** " + Message;
1220 34 : const auto postfix = " ** ~~~ ** " + cEnvHeader + state.dataEnvrn->EnvironmentName + ", at Simulation time=" + state.dataEnvrn->CurMnDy +
1221 68 : ' ' + CreateSysTimeIntervalString(state);
1222 17 : ShowErrorMessage(state, m);
1223 17 : ShowErrorMessage(state, postfix, OutUnit1, OutUnit2);
1224 17 : if (state.dataSQLiteProcedures->sqlite) {
1225 1 : state.dataSQLiteProcedures->sqlite->updateSQLiteErrorRecord(m);
1226 : }
1227 17 : if (state.dataGlobal->errorCallback) {
1228 0 : state.dataGlobal->errorCallback(Error::Continue, m);
1229 0 : state.dataGlobal->errorCallback(Error::Continue, postfix);
1230 : }
1231 : }
1232 186 : }
1233 :
1234 13346 : void ShowMessage(EnergyPlusData &state, std::string const &Message, OptionalOutputFileRef OutUnit1, OptionalOutputFileRef OutUnit2)
1235 : {
1236 :
1237 : // SUBROUTINE INFORMATION:
1238 : // AUTHOR Linda K. Lawrie
1239 : // DATE WRITTEN September 1997
1240 : // MODIFIED na
1241 : // RE-ENGINEERED na
1242 :
1243 : // PURPOSE OF THIS SUBROUTINE:
1244 : // This subroutine displays a simple message on designated output files.
1245 :
1246 : // METHODOLOGY EMPLOYED:
1247 : // Calls ShowErrorMessage utility routine.
1248 :
1249 13346 : if (Message.empty()) {
1250 565 : ShowErrorMessage(state, " *************", OutUnit1, OutUnit2);
1251 : } else {
1252 12781 : ShowErrorMessage(state, " ************* " + Message, OutUnit1, OutUnit2);
1253 12781 : if (state.dataSQLiteProcedures->sqlite) {
1254 1453 : state.dataSQLiteProcedures->sqlite->createSQLiteErrorRecord(1, -1, Message, 0);
1255 : }
1256 12781 : if (state.dataGlobal->errorCallback) {
1257 0 : state.dataGlobal->errorCallback(Error::Info, Message);
1258 : }
1259 : }
1260 13346 : }
1261 :
1262 2098 : void ShowWarningError(EnergyPlusData &state, std::string const &ErrorMessage, OptionalOutputFileRef OutUnit1, OptionalOutputFileRef OutUnit2)
1263 : {
1264 :
1265 : // SUBROUTINE INFORMATION:
1266 : // AUTHOR Linda K. Lawrie
1267 : // DATE WRITTEN September 1997
1268 : // MODIFIED na
1269 : // RE-ENGINEERED na
1270 :
1271 : // PURPOSE OF THIS SUBROUTINE:
1272 : // This subroutine puts ErrorMessage with a Warning designation on
1273 : // designated output files.
1274 :
1275 : // METHODOLOGY EMPLOYED:
1276 : // Calls ShowErrorMessage utility routine.
1277 :
1278 : using namespace DataStringGlobals;
1279 : using namespace DataErrorTracking;
1280 : int Loop;
1281 :
1282 44058 : for (Loop = 1; Loop <= SearchCounts; ++Loop) {
1283 41960 : if (has(ErrorMessage, MessageSearch[Loop])) ++state.dataErrTracking->MatchCounts(Loop);
1284 : }
1285 :
1286 2098 : ++state.dataErrTracking->TotalWarningErrors;
1287 2110 : if (state.dataGlobal->WarmupFlag && !state.dataGlobal->DoingSizing && !state.dataGlobal->KickOffSimulation &&
1288 12 : !state.dataErrTracking->AbortProcessing)
1289 12 : ++state.dataErrTracking->TotalWarningErrorsDuringWarmup;
1290 2098 : if (state.dataGlobal->DoingSizing) ++state.dataErrTracking->TotalWarningErrorsDuringSizing;
1291 2098 : ShowErrorMessage(state, " ** Warning ** " + ErrorMessage, OutUnit1, OutUnit2);
1292 :
1293 2098 : if (state.dataSQLiteProcedures->sqlite) {
1294 427 : state.dataSQLiteProcedures->sqlite->createSQLiteErrorRecord(1, 0, ErrorMessage, 1);
1295 : }
1296 2098 : if (state.dataGlobal->errorCallback) {
1297 0 : state.dataGlobal->errorCallback(Error::Warning, ErrorMessage);
1298 : }
1299 2098 : }
1300 :
1301 163 : void ShowWarningMessage(EnergyPlusData &state, std::string const &ErrorMessage, OptionalOutputFileRef OutUnit1, OptionalOutputFileRef OutUnit2)
1302 : {
1303 :
1304 : // SUBROUTINE INFORMATION:
1305 : // AUTHOR Linda K. Lawrie
1306 : // DATE WRITTEN September 2009
1307 :
1308 : // PURPOSE OF THIS SUBROUTINE:
1309 : // This subroutine puts ErrorMessage with a Warning designation on
1310 : // designated output files.
1311 : // But does not bump the error count so can be used in conjunction with recurring
1312 : // error calls.
1313 :
1314 : // METHODOLOGY EMPLOYED:
1315 : // Calls ShowErrorMessage utility routine.
1316 :
1317 : // Using/Aliasing
1318 : using namespace DataStringGlobals;
1319 : using namespace DataErrorTracking;
1320 :
1321 3423 : for (int Loop = 1; Loop <= SearchCounts; ++Loop) {
1322 3260 : if (has(ErrorMessage, MessageSearch[Loop])) ++state.dataErrTracking->MatchCounts(Loop);
1323 : }
1324 :
1325 163 : ShowErrorMessage(state, " ** Warning ** " + ErrorMessage, OutUnit1, OutUnit2);
1326 163 : if (state.dataSQLiteProcedures->sqlite) {
1327 33 : state.dataSQLiteProcedures->sqlite->createSQLiteErrorRecord(1, 0, ErrorMessage, 0);
1328 : }
1329 163 : if (state.dataGlobal->errorCallback) {
1330 0 : state.dataGlobal->errorCallback(Error::Warning, ErrorMessage);
1331 : }
1332 163 : }
1333 :
1334 29040 : void ShowRecurringSevereErrorAtEnd(EnergyPlusData &state,
1335 : std::string const &Message, // Message automatically written to "error file" at end of simulation
1336 : int &MsgIndex, // Recurring message index, if zero, next available index is assigned
1337 : Optional<Real64 const> ReportMaxOf, // Track and report the max of the values passed to this argument
1338 : Optional<Real64 const> ReportMinOf, // Track and report the min of the values passed to this argument
1339 : Optional<Real64 const> ReportSumOf, // Track and report the sum of the values passed to this argument
1340 : std::string const &ReportMaxUnits, // optional char string (<=15 length) of units for max value
1341 : std::string const &ReportMinUnits, // optional char string (<=15 length) of units for min value
1342 : std::string const &ReportSumUnits // optional char string (<=15 length) of units for sum value
1343 : )
1344 : {
1345 :
1346 : // SUBROUTINE INFORMATION:
1347 : // AUTHOR Michael J. Witte
1348 : // DATE WRITTEN August 2004
1349 :
1350 : // PURPOSE OF THIS SUBROUTINE:
1351 : // This subroutine stores a recurring ErrorMessage with a Severe designation
1352 : // for output at the end of the simulation with automatic tracking of number
1353 : // of occurrences and optional tracking of associated min, max, and sum values
1354 :
1355 : // METHODOLOGY EMPLOYED:
1356 : // Calls StoreRecurringErrorMessage utility routine.
1357 :
1358 : // Using/Aliasing
1359 : using namespace DataStringGlobals;
1360 : using namespace DataErrorTracking;
1361 :
1362 : // INTERFACE BLOCK SPECIFICATIONS
1363 : // Use for recurring "severe" error messages shown once at end of simulation
1364 : // with count of occurrences and optional max, min, sum
1365 :
1366 609840 : for (int Loop = 1; Loop <= SearchCounts; ++Loop) {
1367 580800 : if (has(Message, MessageSearch[Loop])) {
1368 0 : ++state.dataErrTracking->MatchCounts(Loop);
1369 0 : break;
1370 : }
1371 : }
1372 29040 : bool bNewMessageFound = true;
1373 33777 : for (int Loop = 1; Loop <= state.dataErrTracking->NumRecurringErrors; ++Loop) {
1374 33772 : if (UtilityRoutines::SameString(state.dataErrTracking->RecurringErrors(Loop).Message, " ** Severe ** " + Message)) {
1375 29035 : bNewMessageFound = false;
1376 29035 : MsgIndex = Loop;
1377 29035 : break;
1378 : }
1379 : }
1380 29040 : if (bNewMessageFound) {
1381 5 : MsgIndex = 0;
1382 : }
1383 :
1384 29040 : ++state.dataErrTracking->TotalSevereErrors;
1385 87120 : StoreRecurringErrorMessage(
1386 58080 : state, " ** Severe ** " + Message, MsgIndex, ReportMaxOf, ReportMinOf, ReportSumOf, ReportMaxUnits, ReportMinUnits, ReportSumUnits);
1387 29040 : }
1388 :
1389 3377068 : void ShowRecurringWarningErrorAtEnd(EnergyPlusData &state,
1390 : std::string const &Message, // Message automatically written to "error file" at end of simulation
1391 : int &MsgIndex, // Recurring message index, if zero, next available index is assigned
1392 : Optional<Real64 const> ReportMaxOf, // Track and report the max of the values passed to this argument
1393 : Optional<Real64 const> ReportMinOf, // Track and report the min of the values passed to this argument
1394 : Optional<Real64 const> ReportSumOf, // Track and report the sum of the values passed to this argument
1395 : std::string const &ReportMaxUnits, // optional char string (<=15 length) of units for max value
1396 : std::string const &ReportMinUnits, // optional char string (<=15 length) of units for min value
1397 : std::string const &ReportSumUnits // 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 70912478 : for (int Loop = 1; Loop <= SearchCounts; ++Loop) {
1422 67536260 : if (has(Message, MessageSearch[Loop])) {
1423 850 : ++state.dataErrTracking->MatchCounts(Loop);
1424 850 : break;
1425 : }
1426 : }
1427 3377068 : bool bNewMessageFound = true;
1428 9953066 : for (int Loop = 1; Loop <= state.dataErrTracking->NumRecurringErrors; ++Loop) {
1429 9952788 : if (UtilityRoutines::SameString(state.dataErrTracking->RecurringErrors(Loop).Message, " ** Warning ** " + Message)) {
1430 3376790 : bNewMessageFound = false;
1431 3376790 : MsgIndex = Loop;
1432 3376790 : break;
1433 : }
1434 : }
1435 3377068 : if (bNewMessageFound) {
1436 278 : MsgIndex = 0;
1437 : }
1438 :
1439 3377068 : ++state.dataErrTracking->TotalWarningErrors;
1440 10131204 : StoreRecurringErrorMessage(
1441 6754136 : state, " ** Warning ** " + Message, MsgIndex, ReportMaxOf, ReportMinOf, ReportSumOf, ReportMaxUnits, ReportMinUnits, ReportSumUnits);
1442 3377068 : }
1443 :
1444 36 : void ShowRecurringContinueErrorAtEnd(EnergyPlusData &state,
1445 : std::string const &Message, // Message automatically written to "error file" at end of simulation
1446 : int &MsgIndex, // Recurring message index, if zero, next available index is assigned
1447 : Optional<Real64 const> ReportMaxOf, // Track and report the max of the values passed to this argument
1448 : Optional<Real64 const> ReportMinOf, // Track and report the min of the values passed to this argument
1449 : Optional<Real64 const> ReportSumOf, // Track and report the sum of the values passed to this argument
1450 : std::string const &ReportMaxUnits, // optional char string (<=15 length) of units for max value
1451 : std::string const &ReportMinUnits, // optional char string (<=15 length) of units for min value
1452 : std::string const &ReportSumUnits // optional char string (<=15 length) of units for sum value
1453 : )
1454 : {
1455 :
1456 : // SUBROUTINE INFORMATION:
1457 : // AUTHOR Michael J. Witte
1458 : // DATE WRITTEN August 2004
1459 :
1460 : // PURPOSE OF THIS SUBROUTINE:
1461 : // This subroutine stores a recurring ErrorMessage with a continue designation
1462 : // for output at the end of the simulation with automatic tracking of number
1463 : // of occurrences and optional tracking of associated min, max, and sum values
1464 :
1465 : // METHODOLOGY EMPLOYED:
1466 : // Calls StoreRecurringErrorMessage utility routine.
1467 :
1468 : // Using/Aliasing
1469 : using namespace DataStringGlobals;
1470 : using namespace DataErrorTracking;
1471 :
1472 : // INTERFACE BLOCK SPECIFICATIONS
1473 : // Use for recurring "continue" error messages shown once at end of simulation
1474 : // with count of occurrences and optional max, min, sum
1475 :
1476 756 : for (int Loop = 1; Loop <= SearchCounts; ++Loop) {
1477 720 : if (has(Message, MessageSearch[Loop])) {
1478 0 : ++state.dataErrTracking->MatchCounts(Loop);
1479 0 : break;
1480 : }
1481 : }
1482 36 : bool bNewMessageFound = true;
1483 234 : for (int Loop = 1; Loop <= state.dataErrTracking->NumRecurringErrors; ++Loop) {
1484 228 : if (UtilityRoutines::SameString(state.dataErrTracking->RecurringErrors(Loop).Message, " ** ~~~ ** " + Message)) {
1485 30 : bNewMessageFound = false;
1486 30 : MsgIndex = Loop;
1487 30 : break;
1488 : }
1489 : }
1490 36 : if (bNewMessageFound) {
1491 6 : MsgIndex = 0;
1492 : }
1493 :
1494 108 : StoreRecurringErrorMessage(
1495 72 : state, " ** ~~~ ** " + Message, MsgIndex, ReportMaxOf, ReportMinOf, ReportSumOf, ReportMaxUnits, ReportMinUnits, ReportSumUnits);
1496 36 : }
1497 :
1498 3406144 : void StoreRecurringErrorMessage(EnergyPlusData &state,
1499 : std::string const &ErrorMessage, // Message automatically written to "error file" at end of simulation
1500 : int &ErrorMsgIndex, // Recurring message index, if zero, next available index is assigned
1501 : Optional<Real64 const> ErrorReportMaxOf, // Track and report the max of the values passed to this argument
1502 : Optional<Real64 const> ErrorReportMinOf, // Track and report the min of the values passed to this argument
1503 : Optional<Real64 const> ErrorReportSumOf, // Track and report the sum of the values passed to this argument
1504 : std::string const &ErrorReportMaxUnits, // Units for "max" reporting
1505 : std::string const &ErrorReportMinUnits, // Units for "min" reporting
1506 : std::string const &ErrorReportSumUnits // Units for "sum" reporting
1507 : )
1508 : {
1509 :
1510 : // SUBROUTINE INFORMATION:
1511 : // AUTHOR Michael J. Witte
1512 : // DATE WRITTEN August 2004
1513 : // MODIFIED September 2005;LKL;Added Units
1514 :
1515 : // PURPOSE OF THIS SUBROUTINE:
1516 : // This subroutine stores a recurring ErrorMessage with
1517 : // for output at the end of the simulation with automatic tracking of number
1518 : // of occurrences and optional tracking of associated min, max, and sum values
1519 :
1520 : // Using/Aliasing
1521 : using namespace DataStringGlobals;
1522 : using namespace DataErrorTracking;
1523 : // If Index is zero, then assign next available index and reallocate array
1524 3406144 : if (ErrorMsgIndex == 0) {
1525 289 : state.dataErrTracking->RecurringErrors.redimension(++state.dataErrTracking->NumRecurringErrors);
1526 289 : ErrorMsgIndex = state.dataErrTracking->NumRecurringErrors;
1527 : // The message string only needs to be stored once when a new recurring message is created
1528 289 : state.dataErrTracking->RecurringErrors(ErrorMsgIndex).Message = ErrorMessage;
1529 289 : state.dataErrTracking->RecurringErrors(ErrorMsgIndex).Count = 1;
1530 289 : if (state.dataGlobal->WarmupFlag) state.dataErrTracking->RecurringErrors(ErrorMsgIndex).WarmupCount = 1;
1531 289 : if (state.dataGlobal->DoingSizing) state.dataErrTracking->RecurringErrors(ErrorMsgIndex).SizingCount = 1;
1532 :
1533 : // For max, min, and sum values, store the current value when a new recurring message is created
1534 289 : if (present(ErrorReportMaxOf)) {
1535 240 : state.dataErrTracking->RecurringErrors(ErrorMsgIndex).MaxValue = ErrorReportMaxOf;
1536 240 : state.dataErrTracking->RecurringErrors(ErrorMsgIndex).ReportMax = true;
1537 240 : if (!ErrorReportMaxUnits.empty()) {
1538 59 : state.dataErrTracking->RecurringErrors(ErrorMsgIndex).MaxUnits = ErrorReportMaxUnits;
1539 : }
1540 : }
1541 289 : if (present(ErrorReportMinOf)) {
1542 238 : state.dataErrTracking->RecurringErrors(ErrorMsgIndex).MinValue = ErrorReportMinOf;
1543 238 : state.dataErrTracking->RecurringErrors(ErrorMsgIndex).ReportMin = true;
1544 238 : if (!ErrorReportMinUnits.empty()) {
1545 59 : state.dataErrTracking->RecurringErrors(ErrorMsgIndex).MinUnits = ErrorReportMinUnits;
1546 : }
1547 : }
1548 289 : if (present(ErrorReportSumOf)) {
1549 0 : state.dataErrTracking->RecurringErrors(ErrorMsgIndex).SumValue = ErrorReportSumOf;
1550 0 : state.dataErrTracking->RecurringErrors(ErrorMsgIndex).ReportSum = true;
1551 0 : if (!ErrorReportSumUnits.empty()) {
1552 0 : state.dataErrTracking->RecurringErrors(ErrorMsgIndex).SumUnits = ErrorReportSumUnits;
1553 : }
1554 : }
1555 :
1556 3405855 : } else if (ErrorMsgIndex > 0) {
1557 : // Do stats and store
1558 3405855 : ++state.dataErrTracking->RecurringErrors(ErrorMsgIndex).Count;
1559 3405855 : if (state.dataGlobal->WarmupFlag) ++state.dataErrTracking->RecurringErrors(ErrorMsgIndex).WarmupCount;
1560 3405855 : if (state.dataGlobal->DoingSizing) ++state.dataErrTracking->RecurringErrors(ErrorMsgIndex).SizingCount;
1561 :
1562 3405855 : if (present(ErrorReportMaxOf)) {
1563 2950380 : state.dataErrTracking->RecurringErrors(ErrorMsgIndex).MaxValue =
1564 2950380 : max(ErrorReportMaxOf, state.dataErrTracking->RecurringErrors(ErrorMsgIndex).MaxValue);
1565 2950380 : state.dataErrTracking->RecurringErrors(ErrorMsgIndex).ReportMax = true;
1566 : }
1567 3405855 : if (present(ErrorReportMinOf)) {
1568 2942154 : state.dataErrTracking->RecurringErrors(ErrorMsgIndex).MinValue =
1569 2942154 : min(ErrorReportMinOf, state.dataErrTracking->RecurringErrors(ErrorMsgIndex).MinValue);
1570 2942154 : state.dataErrTracking->RecurringErrors(ErrorMsgIndex).ReportMin = true;
1571 : }
1572 3405855 : if (present(ErrorReportSumOf)) {
1573 0 : state.dataErrTracking->RecurringErrors(ErrorMsgIndex).SumValue += ErrorReportSumOf;
1574 0 : state.dataErrTracking->RecurringErrors(ErrorMsgIndex).ReportSum = true;
1575 : }
1576 : } else {
1577 : // If ErrorMsgIndex < 0, then do nothing
1578 : }
1579 3406144 : }
1580 :
1581 19864 : void ShowErrorMessage(EnergyPlusData &state, std::string const &ErrorMessage, OptionalOutputFileRef OutUnit1, OptionalOutputFileRef OutUnit2)
1582 : {
1583 :
1584 : // SUBROUTINE INFORMATION:
1585 : // AUTHOR Linda K. Lawrie
1586 : // DATE WRITTEN December 1997
1587 : // MODIFIED na
1588 : // RE-ENGINEERED na
1589 :
1590 : // PURPOSE OF THIS SUBROUTINE:
1591 : // This subroutine displays the error messages on the indicated
1592 : // file unit numbers, in addition to the "standard error output"
1593 : // unit.
1594 :
1595 : // METHODOLOGY EMPLOYED:
1596 : // If arguments OutUnit1 and/or OutUnit2 are present the
1597 : // error message is written to these as well and the standard one.
1598 :
1599 19864 : auto *err_stream = state.files.err_stream.get();
1600 :
1601 19864 : if (state.dataUtilityRoutines->outputErrorHeader && err_stream) {
1602 771 : *err_stream << "Program Version," << state.dataStrGlobals->VerStringVar << ',' << state.dataStrGlobals->IDDVerString << '\n';
1603 771 : state.dataUtilityRoutines->outputErrorHeader = false;
1604 : }
1605 :
1606 19864 : if (!state.dataGlobal->DoingInputProcessing) {
1607 19864 : if (err_stream) *err_stream << " " << ErrorMessage << '\n';
1608 : } else {
1609 : // CacheIPErrorFile is never opened or closed
1610 : // so this output would just go to stdout
1611 : // ObjexxFCL::gio::write(CacheIPErrorFile, fmtA) << ErrorMessage;
1612 0 : if (state.dataGlobal->printConsoleOutput) std::cout << ErrorMessage << '\n';
1613 : }
1614 19864 : if (present(OutUnit1)) {
1615 0 : print(OutUnit1(), " {}", ErrorMessage);
1616 : }
1617 19864 : if (present(OutUnit2)) {
1618 0 : print(OutUnit2(), " {}", ErrorMessage);
1619 : }
1620 : // std::string tmp = " " + ErrorMessage + '\n';
1621 : // if (errorCallback) DataGlobals::errorCallback(tmp.c_str());
1622 19864 : }
1623 :
1624 771 : void SummarizeErrors(EnergyPlusData &state)
1625 : {
1626 :
1627 : // SUBROUTINE INFORMATION:
1628 : // AUTHOR Linda K. Lawrie
1629 : // DATE WRITTEN March 2003
1630 : // MODIFIED na
1631 : // RE-ENGINEERED na
1632 :
1633 : // PURPOSE OF THIS SUBROUTINE:
1634 : // This subroutine provides a summary of certain errors that might
1635 : // otherwise get lost in the shuffle of many similar messages.
1636 :
1637 : using namespace DataErrorTracking;
1638 :
1639 : std::string::size_type StartC;
1640 : std::string::size_type EndC;
1641 :
1642 771 : if (any_gt(state.dataErrTracking->MatchCounts, 0)) {
1643 38 : ShowMessage(state, "");
1644 38 : ShowMessage(state, "===== Final Error Summary =====");
1645 38 : ShowMessage(state, "The following error categories occurred. Consider correcting or noting.");
1646 798 : for (int Loop = 1; Loop <= SearchCounts; ++Loop) {
1647 760 : if (state.dataErrTracking->MatchCounts(Loop) > 0) {
1648 45 : ShowMessage(state, Summaries[Loop]);
1649 90 : std::string thisMoreDetails = MoreDetails[Loop];
1650 45 : if (!thisMoreDetails.empty()) {
1651 45 : StartC = 0;
1652 45 : EndC = len(thisMoreDetails) - 1;
1653 391 : while (EndC != std::string::npos) {
1654 218 : EndC = index(thisMoreDetails.substr(StartC), "<CR");
1655 218 : ShowMessage(state, ".." + thisMoreDetails.substr(StartC, EndC));
1656 218 : if (thisMoreDetails.substr(StartC + EndC, 5) == "<CRE>") break;
1657 173 : StartC += EndC + 4;
1658 173 : EndC = len(thisMoreDetails.substr(StartC)) - 1;
1659 : }
1660 : }
1661 : }
1662 : }
1663 38 : ShowMessage(state, "");
1664 : }
1665 771 : }
1666 :
1667 771 : void ShowRecurringErrors(EnergyPlusData &state)
1668 : {
1669 :
1670 : // SUBROUTINE INFORMATION:
1671 : // AUTHOR Linda K. Lawrie
1672 : // DATE WRITTEN March 2003
1673 : // MODIFIED na
1674 : // RE-ENGINEERED na
1675 :
1676 : // PURPOSE OF THIS SUBROUTINE:
1677 : // This subroutine provides a summary of certain errors that might
1678 : // otherwise get lost in the shuffle of many similar messages.
1679 :
1680 : // Using/Aliasing
1681 : using namespace DataErrorTracking;
1682 :
1683 : using General::strip_trailing_zeros;
1684 :
1685 : static constexpr std::string_view StatMessageStart(" ** ~~~ ** ");
1686 :
1687 : int Loop;
1688 1542 : std::string StatMessage;
1689 1542 : std::string MaxOut;
1690 1542 : std::string MinOut;
1691 1542 : std::string SumOut;
1692 :
1693 771 : if (state.dataErrTracking->NumRecurringErrors > 0) {
1694 103 : ShowMessage(state, "");
1695 103 : ShowMessage(state, "===== Recurring Error Summary =====");
1696 103 : ShowMessage(state, "The following recurring error messages occurred.");
1697 392 : for (Loop = 1; Loop <= state.dataErrTracking->NumRecurringErrors; ++Loop) {
1698 289 : auto const &error(state.dataErrTracking->RecurringErrors(Loop));
1699 : // Suppress reporting the count if it is a continue error
1700 289 : if (has_prefix(error.Message, " ** ~~~ ** ")) {
1701 6 : ShowMessage(state, error.Message);
1702 6 : if (state.dataSQLiteProcedures->sqlite) {
1703 0 : state.dataSQLiteProcedures->sqlite->updateSQLiteErrorRecord(error.Message);
1704 : }
1705 6 : if (state.dataGlobal->errorCallback) {
1706 0 : state.dataGlobal->errorCallback(Error::Continue, error.Message);
1707 : }
1708 : } else {
1709 283 : const auto warning = has_prefix(error.Message, " ** Warning ** ");
1710 283 : const auto severe = has_prefix(error.Message, " ** Severe ** ");
1711 :
1712 283 : ShowMessage(state, "");
1713 283 : ShowMessage(state, error.Message);
1714 283 : ShowMessage(state, format("{} This error occurred {} total times;", StatMessageStart, error.Count));
1715 283 : ShowMessage(state, format("{} during Warmup {} times;", StatMessageStart, error.WarmupCount));
1716 283 : ShowMessage(state, format("{} during Sizing {} times.", StatMessageStart, error.SizingCount));
1717 283 : if (state.dataSQLiteProcedures->sqlite) {
1718 0 : if (warning) {
1719 0 : state.dataSQLiteProcedures->sqlite->createSQLiteErrorRecord(1, 0, error.Message.substr(15), error.Count);
1720 0 : } else if (severe) {
1721 0 : state.dataSQLiteProcedures->sqlite->createSQLiteErrorRecord(1, 1, error.Message.substr(15), error.Count);
1722 : }
1723 : }
1724 283 : if (state.dataGlobal->errorCallback) {
1725 0 : Error level = Error::Warning;
1726 0 : if (severe) {
1727 0 : level = Error::Severe;
1728 : }
1729 0 : state.dataGlobal->errorCallback(level, error.Message);
1730 0 : state.dataGlobal->errorCallback(Error::Continue, "");
1731 : }
1732 : }
1733 289 : StatMessage = "";
1734 289 : if (error.ReportMax) {
1735 240 : MaxOut = format("{:.6R}", error.MaxValue);
1736 240 : strip_trailing_zeros(MaxOut);
1737 240 : StatMessage += " Max=" + MaxOut;
1738 240 : if (!error.MaxUnits.empty()) StatMessage += ' ' + error.MaxUnits;
1739 : }
1740 289 : if (error.ReportMin) {
1741 238 : MinOut = format("{:.6R}", error.MinValue);
1742 238 : strip_trailing_zeros(MinOut);
1743 238 : StatMessage += " Min=" + MinOut;
1744 238 : if (!error.MinUnits.empty()) StatMessage += ' ' + error.MinUnits;
1745 : }
1746 289 : if (error.ReportSum) {
1747 0 : SumOut = format("{:.6R}", error.SumValue);
1748 0 : strip_trailing_zeros(SumOut);
1749 0 : StatMessage += " Sum=" + SumOut;
1750 0 : if (!error.SumUnits.empty()) StatMessage += ' ' + error.SumUnits;
1751 : }
1752 289 : if (error.ReportMax || error.ReportMin || error.ReportSum) {
1753 254 : ShowMessage(state, std::string{StatMessageStart} + StatMessage);
1754 : }
1755 : }
1756 103 : ShowMessage(state, "");
1757 : }
1758 771 : }
1759 :
1760 2313 : } // namespace EnergyPlus
|