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 : #ifndef UtilityRoutines_hh_INCLUDED
49 : #define UtilityRoutines_hh_INCLUDED
50 :
51 : // C++ Headers
52 : #include <functional>
53 : #include <optional>
54 :
55 : // ObjexxFCL Headers
56 : #include <ObjexxFCL/Array1D.hh>
57 : #include <ObjexxFCL/Array1S.fwd.hh>
58 : #include <ObjexxFCL/MArray1.fwd.hh>
59 : #include <ObjexxFCL/string.functions.hh>
60 :
61 : #include <GSL/span.h>
62 :
63 : // EnergyPlus Headers
64 : #include <EnergyPlus/Data/BaseData.hh>
65 : #include <EnergyPlus/DataGlobalConstants.hh>
66 : #include <EnergyPlus/DataGlobals.hh>
67 : #include <EnergyPlus/EnergyPlus.hh>
68 :
69 : namespace EnergyPlus {
70 :
71 : // Forward declarations
72 : class InputOutputFile;
73 : struct EnergyPlusData;
74 :
75 : int AbortEnergyPlus(EnergyPlusData &state);
76 :
77 : void CloseMiscOpenFiles(EnergyPlusData &state);
78 :
79 : void CloseOutOpenFiles();
80 :
81 : int EndEnergyPlus(EnergyPlusData &state);
82 :
83 : void ConvertCaseToUpper(std::string_view InputString, // Input string
84 : std::string &OutputString // Output string (in UpperCase)
85 : );
86 :
87 : void ConvertCaseToLower(std::string_view InputString, // Input string
88 : std::string &OutputString // Output string (in LowerCase)
89 : );
90 :
91 : std::string::size_type FindNonSpace(std::string const &String); // String to be scanned
92 :
93 0 : template <typename T, typename = std::enable_if_t<std::is_arithmetic_v<T>>> inline constexpr T pow2(T x)
94 : {
95 0 : return x * x;
96 : }
97 :
98 : template <typename T, typename = std::enable_if_t<std::is_arithmetic_v<T>>> inline constexpr T pow3(T x)
99 : {
100 : return x * x * x;
101 : }
102 :
103 0 : template <typename T, typename = std::enable_if_t<std::is_arithmetic_v<T>>> inline constexpr T pow4(T x)
104 : {
105 0 : T y(x * x);
106 0 : return y * y;
107 : }
108 :
109 : template <typename T, typename = std::enable_if_t<std::is_arithmetic_v<T>>> inline constexpr T pow5(T x)
110 : {
111 : T y(x * x);
112 : y *= y;
113 : return y * x;
114 : }
115 :
116 : template <typename T, typename = std::enable_if_t<std::is_arithmetic_v<T>>> inline constexpr T pow6(T x)
117 : {
118 : T y(x * x);
119 : y *= y;
120 : return y * y;
121 : }
122 :
123 : template <typename T, typename = std::enable_if_t<std::is_arithmetic_v<T>>> inline constexpr T pow7(T x)
124 : {
125 : T y(x * x);
126 : y *= y;
127 : y *= y;
128 : return y * x;
129 : }
130 :
131 : bool env_var_on(std::string const &env_var_str);
132 :
133 : using OptionalOutputFileRef = std::optional<std::reference_wrapper<EnergyPlus::InputOutputFile>>;
134 :
135 : enum class ErrorMessageCategory
136 : {
137 : Invalid = -1,
138 : Unclassified,
139 : Input_invalid,
140 : Input_field_not_found,
141 : Input_field_blank,
142 : Input_object_not_found,
143 : Input_cannot_find_object,
144 : Input_topology_problem,
145 : Input_unused,
146 : Input_fatal,
147 : Runtime_general,
148 : Runtime_flow_out_of_range,
149 : Runtime_temp_out_of_range,
150 : Runtime_airflow_network,
151 : Fatal_general,
152 : Developer_general,
153 : Developer_invalid_index,
154 : Num
155 : };
156 : void emitErrorMessage(EnergyPlusData &state, ErrorMessageCategory category, std::string const &msg, bool shouldFatal);
157 : void emitErrorMessages(EnergyPlusData &state,
158 : ErrorMessageCategory category,
159 : std::initializer_list<std::string> const &msgs,
160 : bool shouldFatal,
161 : int zeroBasedTimeStampIndex = -1);
162 : void emitWarningMessage(EnergyPlusData &state, ErrorMessageCategory category, std::string const &msg, bool countAsError = false);
163 : void emitWarningMessages(EnergyPlusData &state,
164 : ErrorMessageCategory category,
165 : std::initializer_list<std::string> const &msgs,
166 : bool countAsError = false);
167 :
168 : void ShowFatalError(EnergyPlusData &state, std::string const &ErrorMessage, OptionalOutputFileRef OutUnit1 = {}, OptionalOutputFileRef OutUnit2 = {});
169 :
170 : void ShowSevereError(EnergyPlusData &state,
171 : std::string const &ErrorMessage,
172 : OptionalOutputFileRef OutUnit1 = {},
173 : OptionalOutputFileRef OutUnit2 = {});
174 :
175 : void ShowSevereMessage(EnergyPlusData &state,
176 : std::string const &ErrorMessage,
177 : OptionalOutputFileRef OutUnit1 = {},
178 : OptionalOutputFileRef OutUnit2 = {});
179 :
180 : void ShowContinueError(EnergyPlusData &state, std::string const &Message, OptionalOutputFileRef OutUnit1 = {}, OptionalOutputFileRef OutUnit2 = {});
181 :
182 : void ShowContinueErrorTimeStamp(EnergyPlusData &state,
183 : std::string const &Message,
184 : OptionalOutputFileRef OutUnit1 = {},
185 : OptionalOutputFileRef OutUnit2 = {});
186 :
187 : void ShowMessage(EnergyPlusData &state, std::string const &Message, OptionalOutputFileRef OutUnit1 = {}, OptionalOutputFileRef OutUnit2 = {});
188 :
189 : void ShowWarningError(EnergyPlusData &state,
190 : std::string const &ErrorMessage,
191 : OptionalOutputFileRef OutUnit1 = {},
192 : OptionalOutputFileRef OutUnit2 = {});
193 :
194 : void ShowWarningMessage(EnergyPlusData &state,
195 : std::string const &ErrorMessage,
196 : OptionalOutputFileRef OutUnit1 = {},
197 : OptionalOutputFileRef OutUnit2 = {});
198 :
199 : void ShowRecurringSevereErrorAtEnd(EnergyPlusData &state,
200 : std::string const &Message, // Message automatically written to "error file" at end of simulation
201 : int &MsgIndex, // Recurring message index, if zero, next available index is assigned
202 : Real64 const val, // Track and report the max of the values passed to this argument
203 : std::string const &units);
204 :
205 : void ShowRecurringSevereErrorAtEnd(
206 : EnergyPlusData &state,
207 : std::string const &Message, // Message automatically written to "error file" at end of simulation
208 : int &MsgIndex, // Recurring message index, if zero, next available index is assigned
209 : ObjexxFCL::Optional<Real64 const> ReportMaxOf = _, // Track and report the max of the values passed to this argument
210 : ObjexxFCL::Optional<Real64 const> ReportMinOf = _, // Track and report the min of the values passed to this argument
211 : ObjexxFCL::Optional<Real64 const> ReportSumOf = _, // Track and report the sum of the values passed to this argument
212 : std::string const &ReportMaxUnits = "", // optional char string (<=15 length) of units for max value
213 : std::string const &ReportMinUnits = "", // optional char string (<=15 length) of units for min value
214 : std::string const &ReportSumUnits = "" // optional char string (<=15 length) of units for sum value
215 : );
216 :
217 : void ShowRecurringWarningErrorAtEnd(EnergyPlusData &state,
218 : std::string const &Message, // Message automatically written to "error file" at end of simulation
219 : int &MsgIndex, // Recurring message index, if zero, next available index is assigned
220 : Real64 const val,
221 : std::string const &units // optional char string (<=15 length) of units for sum value
222 : );
223 :
224 : void ShowRecurringWarningErrorAtEnd(
225 : EnergyPlusData &state,
226 : std::string const &Message, // Message automatically written to "error file" at end of simulation
227 : int &MsgIndex, // Recurring message index, if zero, next available index is assigned
228 : ObjexxFCL::Optional<Real64 const> ReportMaxOf = _, // Track and report the max of the values passed to this argument
229 : ObjexxFCL::Optional<Real64 const> ReportMinOf = _, // Track and report the min of the values passed to this argument
230 : ObjexxFCL::Optional<Real64 const> ReportSumOf = _, // Track and report the sum of the values passed to this argument
231 : std::string const &ReportMaxUnits = "", // optional char string (<=15 length) of units for max value
232 : std::string const &ReportMinUnits = "", // optional char string (<=15 length) of units for min value
233 : std::string const &ReportSumUnits = "" // optional char string (<=15 length) of units for sum value
234 : );
235 :
236 : void ShowRecurringContinueErrorAtEnd(
237 : EnergyPlusData &state,
238 : std::string const &Message, // Message automatically written to "error file" at end of simulation
239 : int &MsgIndex, // Recurring message index, if zero, next available index is assigned
240 : ObjexxFCL::Optional<Real64 const> ReportMaxOf = _, // Track and report the max of the values passed to this argument
241 : ObjexxFCL::Optional<Real64 const> ReportMinOf = _, // Track and report the min of the values passed to this argument
242 : ObjexxFCL::Optional<Real64 const> ReportSumOf = _, // Track and report the sum of the values passed to this argument
243 : std::string const &ReportMaxUnits = "", // optional char string (<=15 length) of units for max value
244 : std::string const &ReportMinUnits = "", // optional char string (<=15 length) of units for min value
245 : std::string const &ReportSumUnits = "" // optional char string (<=15 length) of units for sum value
246 : );
247 :
248 : void StoreRecurringErrorMessage(
249 : EnergyPlusData &state,
250 : std::string const &ErrorMessage, // Message automatically written to "error file" at end of simulation
251 : int &ErrorMsgIndex, // Recurring message index, if zero, next available index is assigned
252 : ObjexxFCL::Optional<Real64 const> ErrorReportMaxOf = _, // Track and report the max of the values passed to this argument
253 : ObjexxFCL::Optional<Real64 const> ErrorReportMinOf = _, // Track and report the min of the values passed to this argument
254 : ObjexxFCL::Optional<Real64 const> ErrorReportSumOf = _, // Track and report the sum of the values passed to this argument
255 : std::string const &ErrorReportMaxUnits = "", // Units for "max" reporting
256 : std::string const &ErrorReportMinUnits = "", // Units for "min" reporting
257 : std::string const &ErrorReportSumUnits = "" // Units for "sum" reporting
258 : );
259 :
260 : void ShowErrorMessage(EnergyPlusData &state,
261 : std::string const &ErrorMessage,
262 : OptionalOutputFileRef OutUnit1 = {},
263 : OptionalOutputFileRef OutUnit2 = {});
264 :
265 : void SummarizeErrors(EnergyPlusData &state);
266 :
267 : void ShowRecurringErrors(EnergyPlusData &state);
268 :
269 : struct ErrorCountIndex
270 : {
271 : int index = 0;
272 : int count = 0;
273 : };
274 :
275 : struct ErrorObjectHeader
276 : {
277 : std::string_view routineName;
278 : std::string_view objectType;
279 : std::string_view objectName;
280 : };
281 :
282 : void ShowSevereDuplicateName(EnergyPlusData &state, ErrorObjectHeader const &eoh);
283 : void ShowSevereEmptyField(EnergyPlusData &state,
284 : ErrorObjectHeader const &eoh,
285 : std::string_view fieldName,
286 : std::string_view depFieldName = {},
287 : std::string_view depFieldValue = {});
288 : void ShowSevereItemNotFound(EnergyPlusData &state, ErrorObjectHeader const &eoh, std::string_view fieldName, std::string_view fieldValue);
289 : void ShowSevereItemNotFoundAudit(EnergyPlusData &state, ErrorObjectHeader const &eoh, std::string_view fieldName, std::string_view fieldValue);
290 :
291 : void ShowSevereDuplicateAssignment(
292 : EnergyPlusData &state, ErrorObjectHeader const &eoh, std::string_view fieldName, std::string_view fieldValue, std::string_view prevValue);
293 :
294 : void ShowSevereInvalidKey(
295 : EnergyPlusData &state, ErrorObjectHeader const &eoh, std::string_view fieldName, std::string_view fieldValue, std::string_view msg = {});
296 : void ShowSevereInvalidBool(EnergyPlusData &state, ErrorObjectHeader const &eoh, std::string_view fieldName, std::string_view fieldValue);
297 :
298 : void ShowSevereCustom(EnergyPlusData &state, ErrorObjectHeader const &eoh, std::string_view msg);
299 : void ShowSevereCustomField(
300 : EnergyPlusData &state, ErrorObjectHeader const &eoh, std::string_view fieldName, std::string_view fieldValue, std::string_view msg);
301 :
302 : void ShowSevereCustomAudit(EnergyPlusData &state, ErrorObjectHeader const &eoh, std::string_view msg);
303 :
304 : enum class Clusive
305 : {
306 : Invalid = -1,
307 : In,
308 : Ex,
309 : Num
310 : };
311 :
312 : void ShowSevereBadMin(EnergyPlusData &state,
313 : ErrorObjectHeader const &eoh,
314 : std::string_view fieldName,
315 : Real64 fieldVal,
316 : Clusive cluMin,
317 : Real64 minVal,
318 : std::string_view msg = {});
319 : void ShowSevereBadMax(EnergyPlusData &state,
320 : ErrorObjectHeader const &eoh,
321 : std::string_view fieldName,
322 : Real64 fieldVal,
323 : Clusive cluMin,
324 : Real64 maxVal,
325 : std::string_view msg = {});
326 : void ShowSevereBadMinMax(EnergyPlusData &state,
327 : ErrorObjectHeader const &eoh,
328 : std::string_view fieldName,
329 : Real64 fieldVal,
330 : Clusive cluMin,
331 : Real64 minVal,
332 : Clusive cluMax,
333 : Real64 maxVal,
334 : std::string_view msg = {});
335 :
336 : void ShowWarningDuplicateName(EnergyPlusData &state, ErrorObjectHeader const &eoh);
337 : void ShowWarningEmptyField(EnergyPlusData &state,
338 : ErrorObjectHeader const &eoh,
339 : std::string_view fieldName,
340 : std::string_view defaultValue = {},
341 : std::string_view depFieldName = {},
342 : std::string_view depFieldValue = {});
343 :
344 : void ShowWarningNonEmptyField(EnergyPlusData &state,
345 : ErrorObjectHeader const &eoh,
346 : std::string_view fieldName,
347 : std::string_view depFieldName = {},
348 : std::string_view depFieldValue = {});
349 :
350 : void ShowWarningItemNotFound(
351 : EnergyPlusData &state, ErrorObjectHeader const &eoh, std::string_view fieldName, std::string_view fieldValue, std::string_view defaultValue = {});
352 : void ShowWarningInvalidKey(EnergyPlusData &state,
353 : ErrorObjectHeader const &eoh,
354 : std::string_view fieldName,
355 : std::string_view fieldValue,
356 : std::string_view defaultValue,
357 : std::string_view msg = {});
358 : void ShowWarningInvalidBool(
359 : EnergyPlusData &state, ErrorObjectHeader const &eoh, std::string_view fieldName, std::string_view fieldValue, std::string_view defaultValue);
360 : void ShowWarningCustom(EnergyPlusData &state, ErrorObjectHeader const &eoh, std::string_view msg);
361 : void ShowWarningCustomField(
362 : EnergyPlusData &state, ErrorObjectHeader const &eoh, std::string_view fieldName, std::string_view fieldValue, std::string_view msg);
363 :
364 : namespace Util {
365 :
366 : static constexpr std::array<std::string_view, 12> MonthNamesCC{
367 : "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
368 :
369 : static constexpr std::array<std::string_view, 12> MonthNamesUC{
370 : "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE", "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER"};
371 :
372 : template <class T> struct is_shared_ptr : std::false_type
373 : {
374 : };
375 : template <class T> struct is_shared_ptr<std::shared_ptr<T>> : std::true_type
376 : {
377 : };
378 :
379 : Real64 ProcessNumber(std::string_view String, bool &ErrorFlag);
380 :
381 : int FindItemInList(std::string_view const String, Array1_string const &ListOfItems, int NumItems);
382 :
383 242 : inline int FindItemInList(std::string_view const String, Array1_string const &ListOfItems)
384 : {
385 242 : return Util::FindItemInList(String, ListOfItems, ListOfItems.isize());
386 : }
387 :
388 : inline int FindIntInList(Array1_int &list, int item)
389 : {
390 : auto it = std::find(list.begin(), list.end(), item);
391 : return (it == list.end()) ? -1 : (it - list.begin());
392 : }
393 :
394 : inline int FindIntInList(std::vector<int> &list, int item)
395 : {
396 : auto it = std::find(list.begin(), list.end(), item);
397 : return (it == list.end()) ? -1 : (it - list.begin());
398 : }
399 :
400 : int FindItemInList(std::string_view const String, Array1S_string const ListOfItems, int NumItems);
401 :
402 6 : template <typename InputIterator> int FindItemInList(std::string_view const str, InputIterator first, InputIterator last)
403 : {
404 6 : auto it = std::find(first, last, str);
405 6 : if (it != last) {
406 6 : return std::distance(first, it) + 1;
407 : } else {
408 0 : return 0;
409 : }
410 : }
411 :
412 : inline int FindItemInList(std::string_view const String, Array1S_string const ListOfItems)
413 : {
414 : return Util::FindItemInList(String, ListOfItems, ListOfItems.isize());
415 : }
416 :
417 : template <typename A> inline int FindItemInList(std::string_view const String, MArray1<A, std::string> const &ListOfItems, int const NumItems)
418 : {
419 : for (int Count = 1; Count <= NumItems; ++Count) {
420 : if (String == ListOfItems(Count)) return Count;
421 : }
422 : return 0; // Not found
423 : }
424 :
425 : template <typename A> inline int FindItemInList(std::string_view const String, MArray1<A, std::string> const &ListOfItems)
426 : {
427 : return Util::FindItemInList(String, ListOfItems, ListOfItems.isize());
428 : }
429 :
430 : template <typename Container, class = typename std::enable_if<!std::is_same<typename Container::value_type, std::string>::value>::type>
431 : // Container needs and operator[i] and elements need Name
432 108497 : inline int FindItemInList(std::string_view const String, Container const &ListOfItems, int const NumItems)
433 : {
434 237621 : for (typename Container::size_type i = 0, e = NumItems; i < e; ++i) {
435 227508 : if (String == ListOfItems[i].Name) return int(i + 1); // 1-based return index
436 : }
437 10113 : return 0; // Not found
438 : }
439 :
440 : template <typename Container, class = typename std::enable_if<!std::is_same<typename Container::value_type, std::string>::value>::type>
441 : // Container needs isize() and operator[i] and elements need Name
442 102885 : inline int FindItemInList(std::string_view const String, Container const &ListOfItems)
443 : {
444 102885 : return Util::FindItemInList(String, ListOfItems, ListOfItems.isize());
445 : }
446 :
447 : template <typename Container, class = typename std::enable_if<!std::is_same<typename Container::value_type, std::string>::value>::type>
448 : // Container needs operator[i] and value_type
449 : inline int
450 205537 : FindItemInList(std::string_view const String, Container const &ListOfItems, std::string Container::value_type::*name_p, int const NumItems)
451 : {
452 208025 : for (typename Container::size_type i = 0, e = NumItems; i < e; ++i) {
453 207213 : if (String == ListOfItems[i].*name_p) return int(i + 1); // 1-based return index
454 : }
455 812 : return 0; // Not found
456 : }
457 :
458 : template <typename Container, class = typename std::enable_if<!std::is_same<typename Container::value_type, std::string>::value>::type>
459 : // Container needs isize() and operator[i] and value_type
460 204746 : inline int FindItemInList(std::string_view const String, Container const &ListOfItems, std::string Container::value_type::*name_p)
461 : {
462 204746 : return Util::FindItemInList(String, ListOfItems, name_p, ListOfItems.isize());
463 : }
464 :
465 : int FindItemInSortedList(std::string_view const string, Array1S_string const ListOfItems, int NumItems);
466 :
467 : inline int FindItemInSortedList(std::string_view const String, Array1S_string const ListOfItems)
468 : {
469 : return FindItemInSortedList(String, ListOfItems, ListOfItems.isize());
470 : }
471 :
472 : template <typename A>
473 : inline int FindItemInSortedList(std::string_view const String, MArray1<A, std::string> const &ListOfItems, int const NumItems)
474 : {
475 : int Probe(0);
476 : int LBnd(0);
477 : int UBnd(NumItems + 1);
478 : bool Found(false);
479 : while ((!Found) || (Probe != 0)) {
480 : Probe = (UBnd - LBnd) / 2;
481 : if (Probe == 0) break;
482 : Probe += LBnd;
483 : if (equali(String, ListOfItems(Probe))) {
484 : Found = true;
485 : break;
486 : } else if (lessthani(String, ListOfItems(Probe))) {
487 : UBnd = Probe;
488 : } else {
489 : LBnd = Probe;
490 : }
491 : }
492 : return Probe;
493 : }
494 :
495 : template <typename A> inline int FindItemInSortedList(std::string_view const String, MArray1<A, std::string> const &ListOfItems)
496 : {
497 : return FindItemInSortedList(String, ListOfItems, ListOfItems.isize());
498 : }
499 :
500 : template <typename InputIterator> inline int FindItem(InputIterator first, InputIterator last, std::string_view const str, std::false_type)
501 : {
502 : using valueType = typename std::iterator_traits<InputIterator>::value_type;
503 : // static_assert( std::is_convertible< decltype( std::declval< valueType >() ), Named >::value, "Iterator value must inherit from class Named"
504 : // );
505 :
506 : auto const it = std::find_if(first, last, [&str](const valueType &s) { return s.name == str; });
507 : if (it != last) return it - first + 1; // 1-based return index
508 :
509 : auto const it2 = std::find_if(first, last, [&str](const valueType &s) { return equali(s.name, str); });
510 : if (it2 != last) return it2 - first + 1; // 1-based return index
511 :
512 : return 0; // Not found
513 : }
514 :
515 : template <typename InputIterator> inline int FindItem(InputIterator first, InputIterator last, std::string_view const str, std::true_type)
516 : {
517 : using valueType = typename std::iterator_traits<InputIterator>::value_type;
518 : // static_assert( std::is_convertible< decltype( *std::declval< valueType >() ), Named >::value, "Iterator value must inherit from class
519 : // Named" );
520 :
521 : auto const it = std::find_if(first, last, [&str](const valueType &s) { return s->name == str; });
522 : if (it != last) return it - first + 1; // 1-based return index
523 :
524 : auto const it2 = std::find_if(first, last, [&str](const valueType &s) { return equali(s->name, str); });
525 : if (it2 != last) return it2 - first + 1; // 1-based return index
526 :
527 : return 0; // Not found
528 : }
529 :
530 : template <typename InputIterator> inline int FindItem(InputIterator first, InputIterator last, std::string_view str)
531 : {
532 : return FindItem(first, last, str, is_shared_ptr<typename std::iterator_traits<InputIterator>::value_type>{});
533 : }
534 :
535 : int FindItem(std::string_view const String, Array1D_string const &ListOfItems, int const NumItems);
536 :
537 : inline int FindItem(std::string_view const String, Array1D_string const &ListOfItems)
538 : {
539 : return FindItem(String, ListOfItems, ListOfItems.isize());
540 : }
541 :
542 : int FindItem(std::string_view const String, Array1S_string const ListOfItems, int const NumItems);
543 :
544 : inline int FindItem(std::string_view const String, Array1S_string const ListOfItems)
545 : {
546 : return FindItem(String, ListOfItems, ListOfItems.isize());
547 : }
548 :
549 : template <typename A> inline int FindItem(std::string_view const String, MArray1<A, std::string> const &ListOfItems, int const NumItems)
550 : {
551 : int const item_number(Util::FindItemInList(String, ListOfItems, NumItems));
552 : if (item_number != 0) return item_number;
553 : for (int Count = 1; Count <= NumItems; ++Count) {
554 : if (equali(String, ListOfItems(Count))) return Count;
555 : }
556 : return 0; // Not found
557 : }
558 :
559 : template <typename A> inline int FindItem(std::string_view const String, MArray1<A, std::string> const &ListOfItems)
560 : {
561 : return FindItem(String, ListOfItems, ListOfItems.isize());
562 : }
563 :
564 : template <typename Container, class = typename std::enable_if<!std::is_same<typename Container::value_type, std::string>::value>::type>
565 : // Container needs size() and operator[i] and elements need Name
566 611 : inline int FindItem(std::string_view const String, Container const &ListOfItems, int const NumItems)
567 : {
568 611 : int const item_number(Util::FindItemInList(String, ListOfItems, NumItems));
569 611 : if (item_number != 0) return item_number;
570 24 : for (typename Container::size_type i = 0, e = NumItems; i < e; ++i) {
571 23 : if (equali(String, ListOfItems[i].Name)) return i + 1; // 1-based return index
572 : }
573 1 : return 0; // Not found
574 : }
575 :
576 : template <typename Container, class = typename std::enable_if<!std::is_same<typename Container::value_type, std::string>::value>::type>
577 : // Container needs size() and operator[i] and elements need Name
578 610 : inline int FindItem(std::string_view const String, Container const &ListOfItems)
579 : {
580 610 : return FindItem(String, ListOfItems, ListOfItems.isize());
581 : }
582 :
583 : template <typename Container, class = typename std::enable_if<!std::is_same<typename Container::value_type, std::string>::value>::type>
584 : // Container needs size() and operator[i] and value_type
585 29 : inline int FindItem(std::string_view const String, Container const &ListOfItems, std::string Container::value_type::*name_p, int const NumItems)
586 : {
587 29 : int const item_number(Util::FindItemInList(String, ListOfItems, name_p, NumItems));
588 29 : if (item_number != 0) return item_number;
589 153 : for (typename Container::size_type i = 0, e = NumItems; i < e; ++i) {
590 153 : if (equali(String, ListOfItems[i].*name_p)) return i + 1; // 1-based return index
591 : }
592 0 : return 0; // Not found
593 : }
594 :
595 : template <typename Container, class = typename std::enable_if<!std::is_same<typename Container::value_type, std::string>::value>::type>
596 : // Container needs size() and operator[i] and value_type
597 29 : inline int FindItem(std::string_view const String, Container const &ListOfItems, std::string Container::value_type::*name_p)
598 : {
599 29 : return FindItem(String, ListOfItems, name_p, ListOfItems.isize());
600 : }
601 :
602 513303 : inline std::string makeUPPER(std::string_view const InputString) // Input String
603 : {
604 :
605 : // FUNCTION INFORMATION:
606 : // AUTHOR Linda K. Lawrie
607 : // DATE WRITTEN September 1997
608 : // MODIFIED na
609 : // RE-ENGINEERED na
610 :
611 : // PURPOSE OF THIS SUBROUTINE:
612 : // This function returns the Upper Case representation of the InputString.
613 :
614 : // METHODOLOGY EMPLOYED:
615 : // Uses the Intrinsic SCAN function to scan the lowercase representation of
616 : // characters (DataStringGlobals) for each character in the given string.
617 :
618 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
619 :
620 513303 : std::string ResultString(InputString);
621 :
622 15407203 : for (std::string::size_type i = 0, e = len(InputString); i < e; ++i) {
623 14893900 : int const curCharVal = int(InputString[i]);
624 14893900 : if ((97 <= curCharVal && curCharVal <= 122) || (224 <= curCharVal && curCharVal <= 255)) { // lowercase ASCII and accented characters
625 9814278 : ResultString[i] = char(curCharVal - 32);
626 : }
627 : }
628 :
629 513303 : return ResultString;
630 0 : }
631 :
632 989287 : constexpr bool SameString(std::string_view const s, std::string_view const t)
633 : {
634 : // case insensitive comparison
635 989287 : return equali(s, t);
636 : }
637 :
638 : template <typename InputIterator>
639 : inline void VerifyName(EnergyPlusData &state,
640 : InputIterator first,
641 : InputIterator last,
642 : std::string const &NameToVerify,
643 : bool &ErrorFound,
644 : bool &IsBlank,
645 : std::string const &StringToDisplay)
646 : {
647 : IsBlank = false;
648 : ErrorFound = false;
649 : if (NameToVerify.empty()) {
650 : ShowSevereError(state, StringToDisplay + ", cannot be blank");
651 : ErrorFound = true;
652 : IsBlank = true;
653 : return;
654 : }
655 : int Found = FindItem(first, last, NameToVerify);
656 : if (Found != 0) {
657 : ShowSevereError(state, StringToDisplay + ", duplicate name=" + NameToVerify);
658 : ErrorFound = true;
659 : }
660 : }
661 :
662 : void VerifyName(EnergyPlusData &state,
663 : std::string const &NameToVerify,
664 : Array1D_string const &NamesList,
665 : int const NumOfNames,
666 : bool &ErrorFound,
667 : bool &IsBlank,
668 : std::string const &StringToDisplay);
669 :
670 : void VerifyName(EnergyPlusData &state,
671 : std::string const &NameToVerify,
672 : Array1S_string const NamesList,
673 : int const NumOfNames,
674 : bool &ErrorFound,
675 : bool &IsBlank,
676 : std::string const &StringToDisplay);
677 :
678 : template <typename A>
679 : inline void VerifyName(EnergyPlusData &state,
680 : std::string const &NameToVerify,
681 : MArray1<A, std::string> const &NamesList,
682 : int const NumOfNames,
683 : bool &ErrorFound,
684 : bool &IsBlank,
685 : std::string const &StringToDisplay)
686 : { // Overload for member arrays: Implemented here to avoid copy to Array_string to forward to other VerifyName
687 : ErrorFound = false;
688 : if (NumOfNames > 0) {
689 : int const Found = FindItem(NameToVerify, NamesList,
690 : NumOfNames); // Calls FindItem overload that accepts member arrays
691 : if (Found != 0) {
692 : ShowSevereError(state, StringToDisplay + ", duplicate name=" + NameToVerify);
693 : ErrorFound = true;
694 : }
695 : }
696 :
697 : if (NameToVerify.empty()) {
698 : ShowSevereError(state, StringToDisplay + ", cannot be blank");
699 : ErrorFound = true;
700 : IsBlank = true;
701 : } else {
702 : IsBlank = false;
703 : }
704 : }
705 :
706 : template <typename Container, class = typename std::enable_if<!std::is_same<typename Container::value_type, std::string>::value>::type>
707 : // Container needs size() and operator[i] and elements need Name
708 44 : inline void VerifyName(EnergyPlusData &state,
709 : std::string const &NameToVerify,
710 : Container const &NamesList,
711 : int const NumOfNames,
712 : bool &ErrorFound,
713 : bool &IsBlank,
714 : std::string const &StringToDisplay)
715 : {
716 44 : ErrorFound = false;
717 44 : if (NumOfNames > 0) {
718 1 : int const Found = FindItem(NameToVerify, NamesList,
719 : NumOfNames); // Calls FindItem overload that accepts member arrays
720 1 : if (Found != 0) {
721 0 : ShowSevereError(state, StringToDisplay + ", duplicate name=" + NameToVerify);
722 0 : ErrorFound = true;
723 : }
724 : }
725 :
726 44 : if (NameToVerify.empty()) {
727 0 : ShowSevereError(state, StringToDisplay + ", cannot be blank");
728 0 : ErrorFound = true;
729 0 : IsBlank = true;
730 : } else {
731 44 : IsBlank = false;
732 : }
733 44 : }
734 :
735 : template <typename Container, class = typename std::enable_if<!std::is_same<typename Container::value_type, std::string>::value>::type>
736 : // Container needs size() and operator[i] and value_type
737 : inline void VerifyName(EnergyPlusData &state,
738 : std::string const &NameToVerify,
739 : Container const &NamesList,
740 : std::string Container::value_type::*name_p,
741 : int const NumOfNames,
742 : bool &ErrorFound,
743 : bool &IsBlank,
744 : std::string const &StringToDisplay)
745 : {
746 : ErrorFound = false;
747 : if (NumOfNames > 0) {
748 : int const Found = FindItem(NameToVerify, NamesList, name_p, NumOfNames);
749 : if (Found != 0) {
750 : ShowSevereError(state, StringToDisplay + ", duplicate name=" + NameToVerify);
751 : ErrorFound = true;
752 : }
753 : }
754 :
755 : if (NameToVerify.empty()) {
756 : ShowSevereError(state, StringToDisplay + ", cannot be blank");
757 : ErrorFound = true;
758 : IsBlank = true;
759 : } else {
760 : IsBlank = false;
761 : }
762 : }
763 :
764 : bool IsNameEmpty(EnergyPlusData &state, std::string &NameToVerify, std::string_view StringToDisplay, bool &ErrorFound);
765 :
766 : // Two structs for case insensitive containers.
767 : // Eg: for unordered_map, we need to have a case insenstive hasher and a case insensitive comparator
768 : // (The default allocator for unordered_map is fine)
769 : // For map, you'd only need the comparator
770 : struct case_insensitive_hasher
771 : {
772 : using is_transparent = void;
773 : size_t operator()(std::string_view key) const noexcept;
774 : };
775 :
776 : struct case_insensitive_comparator
777 : {
778 : using is_transparent = void;
779 : bool operator()(std::string_view a, std::string_view b) const noexcept;
780 : };
781 :
782 : void appendPerfLog(EnergyPlusData &state, std::string const &colHeader, std::string const &colValue, bool finalColumn = false);
783 :
784 : } // namespace Util
785 :
786 26096 : constexpr int getEnumValue(const gsl::span<const std::string_view> sList, const std::string_view s)
787 : {
788 972205 : for (unsigned int i = 0; i < sList.size(); ++i) {
789 972071 : if (sList[i] == s) return i;
790 : }
791 134 : return -1;
792 : }
793 :
794 : constexpr std::array<std::string_view, 2> yesNoNames = {"No", "Yes"};
795 : constexpr std::array<std::string_view, 2> yesNoNamesUC = {"NO", "YES"};
796 :
797 1227 : constexpr BooleanSwitch getYesNoValue(const std::string_view s)
798 : {
799 1227 : return static_cast<BooleanSwitch>(getEnumValue(yesNoNamesUC, s));
800 : }
801 :
802 : constexpr Real64 fclamp(Real64 v, Real64 min, Real64 max)
803 : {
804 : return (v < min) ? min : ((v > max) ? max : v);
805 : }
806 :
807 : struct UtilityRoutinesData : BaseGlobalStruct
808 : {
809 :
810 : bool outputErrorHeader = true;
811 : std::string appendPerfLog_headerRow;
812 : std::string appendPerfLog_valuesRow;
813 : bool GetMatrixInputFlag = true;
814 :
815 2126 : void init_constant_state([[maybe_unused]] EnergyPlusData &state) override
816 : {
817 2126 : }
818 :
819 1152 : void init_state([[maybe_unused]] EnergyPlusData &state) override
820 : {
821 1152 : }
822 :
823 2100 : void clear_state() override
824 : {
825 2100 : outputErrorHeader = true;
826 2100 : appendPerfLog_headerRow.clear();
827 2100 : appendPerfLog_valuesRow.clear();
828 2100 : GetMatrixInputFlag = true;
829 2100 : }
830 :
831 : // Default Constructor
832 2129 : UtilityRoutinesData() = default;
833 : };
834 : } // namespace EnergyPlus
835 :
836 : #endif
|