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 12692 : template <typename T, typename = std::enable_if_t<std::is_arithmetic_v<T>>> inline constexpr T pow2(T x)
94 : {
95 12692 : 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 21552 : template <typename T, typename = std::enable_if_t<std::is_arithmetic_v<T>>> inline constexpr T pow4(T x)
104 : {
105 21552 : T y(x * x);
106 21552 : 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 1618 : inline int FindItemInList(std::string_view const String, Array1_string const &ListOfItems)
384 : {
385 1618 : 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 2824 : template <typename InputIterator> int FindItemInList(std::string_view const str, InputIterator first, InputIterator last)
403 : {
404 2824 : auto it = std::find(first, last, str);
405 2824 : if (it != last) {
406 2824 : 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)) {
421 : return Count;
422 : }
423 : }
424 : return 0; // Not found
425 : }
426 :
427 : template <typename A> inline int FindItemInList(std::string_view const String, MArray1<A, std::string> const &ListOfItems)
428 : {
429 : return Util::FindItemInList(String, ListOfItems, ListOfItems.isize());
430 : }
431 :
432 : template <typename Container, class = typename std::enable_if<!std::is_same<typename Container::value_type, std::string>::value>::type>
433 : // Container needs and operator[i] and elements need Name
434 6163256 : inline int FindItemInList(std::string_view const String, Container const &ListOfItems, int const NumItems)
435 : {
436 67365711 : for (typename Container::size_type i = 0, e = NumItems; i < e; ++i) {
437 67087757 : if (String == ListOfItems[i].Name) {
438 5885302 : return int(i + 1); // 1-based return index
439 : }
440 : }
441 277954 : return 0; // Not found
442 : }
443 :
444 : template <typename Container, class = typename std::enable_if<!std::is_same<typename Container::value_type, std::string>::value>::type>
445 : // Container needs isize() and operator[i] and elements need Name
446 6021945 : inline int FindItemInList(std::string_view const String, Container const &ListOfItems)
447 : {
448 6021945 : return Util::FindItemInList(String, ListOfItems, ListOfItems.isize());
449 : }
450 :
451 : template <typename Container, class = typename std::enable_if<!std::is_same<typename Container::value_type, std::string>::value>::type>
452 : // Container needs operator[i] and value_type
453 : inline int
454 498807 : FindItemInList(std::string_view const String, Container const &ListOfItems, std::string Container::value_type::*name_p, int const NumItems)
455 : {
456 1802997 : for (typename Container::size_type i = 0, e = NumItems; i < e; ++i) {
457 1782326 : if (String == ListOfItems[i].*name_p) {
458 478136 : return int(i + 1); // 1-based return index
459 : }
460 : }
461 20671 : return 0; // Not found
462 : }
463 :
464 : template <typename Container, class = typename std::enable_if<!std::is_same<typename Container::value_type, std::string>::value>::type>
465 : // Container needs isize() and operator[i] and value_type
466 478992 : inline int FindItemInList(std::string_view const String, Container const &ListOfItems, std::string Container::value_type::*name_p)
467 : {
468 478992 : return Util::FindItemInList(String, ListOfItems, name_p, ListOfItems.isize());
469 : }
470 :
471 : int FindItemInSortedList(std::string_view const string, Array1S_string const ListOfItems, int NumItems);
472 :
473 : inline int FindItemInSortedList(std::string_view const String, Array1S_string const ListOfItems)
474 : {
475 : return FindItemInSortedList(String, ListOfItems, ListOfItems.isize());
476 : }
477 :
478 : template <typename A>
479 : inline int FindItemInSortedList(std::string_view const String, MArray1<A, std::string> const &ListOfItems, int const NumItems)
480 : {
481 : int Probe(0);
482 : int LBnd(0);
483 : int UBnd(NumItems + 1);
484 : bool Found(false);
485 : while ((!Found) || (Probe != 0)) {
486 : Probe = (UBnd - LBnd) / 2;
487 : if (Probe == 0) {
488 : break;
489 : }
490 : Probe += LBnd;
491 : if (equali(String, ListOfItems(Probe))) {
492 : Found = true;
493 : break;
494 : } else if (lessthani(String, ListOfItems(Probe))) {
495 : UBnd = Probe;
496 : } else {
497 : LBnd = Probe;
498 : }
499 : }
500 : return Probe;
501 : }
502 :
503 : template <typename A> inline int FindItemInSortedList(std::string_view const String, MArray1<A, std::string> const &ListOfItems)
504 : {
505 : return FindItemInSortedList(String, ListOfItems, ListOfItems.isize());
506 : }
507 :
508 : template <typename InputIterator> inline int FindItem(InputIterator first, InputIterator last, std::string_view const str, std::false_type)
509 : {
510 : using valueType = typename std::iterator_traits<InputIterator>::value_type;
511 : // static_assert( std::is_convertible< decltype( std::declval< valueType >() ), Named >::value, "Iterator value must inherit from class Named"
512 : // );
513 :
514 : auto const it = std::find_if(first, last, [&str](const valueType &s) { return s.name == str; });
515 : if (it != last) {
516 : return it - first + 1; // 1-based return index
517 : }
518 :
519 : auto const it2 = std::find_if(first, last, [&str](const valueType &s) { return equali(s.name, str); });
520 : if (it2 != last) {
521 : return it2 - first + 1; // 1-based return index
522 : }
523 :
524 : return 0; // Not found
525 : }
526 :
527 : template <typename InputIterator> inline int FindItem(InputIterator first, InputIterator last, std::string_view const str, std::true_type)
528 : {
529 : using valueType = typename std::iterator_traits<InputIterator>::value_type;
530 : // static_assert( std::is_convertible< decltype( *std::declval< valueType >() ), Named >::value, "Iterator value must inherit from class
531 : // Named" );
532 :
533 : auto const it = std::find_if(first, last, [&str](const valueType &s) { return s->name == str; });
534 : if (it != last) {
535 : return it - first + 1; // 1-based return index
536 : }
537 :
538 : auto const it2 = std::find_if(first, last, [&str](const valueType &s) { return equali(s->name, str); });
539 : if (it2 != last) {
540 : return it2 - first + 1; // 1-based return index
541 : }
542 :
543 : return 0; // Not found
544 : }
545 :
546 : template <typename InputIterator> inline int FindItem(InputIterator first, InputIterator last, std::string_view str)
547 : {
548 : return FindItem(first, last, str, is_shared_ptr<typename std::iterator_traits<InputIterator>::value_type>{});
549 : }
550 :
551 : int FindItem(std::string_view const String, Array1D_string const &ListOfItems, int const NumItems);
552 :
553 : inline int FindItem(std::string_view const String, Array1D_string const &ListOfItems)
554 : {
555 : return FindItem(String, ListOfItems, ListOfItems.isize());
556 : }
557 :
558 : int FindItem(std::string_view const String, Array1S_string const ListOfItems, int const NumItems);
559 :
560 : inline int FindItem(std::string_view const String, Array1S_string const ListOfItems)
561 : {
562 : return FindItem(String, ListOfItems, ListOfItems.isize());
563 : }
564 :
565 : template <typename A> inline int FindItem(std::string_view const String, MArray1<A, std::string> const &ListOfItems, int const NumItems)
566 : {
567 : int const item_number(Util::FindItemInList(String, ListOfItems, NumItems));
568 : if (item_number != 0) {
569 : return item_number;
570 : }
571 : for (int Count = 1; Count <= NumItems; ++Count) {
572 : if (equali(String, ListOfItems(Count))) {
573 : return Count;
574 : }
575 : }
576 : return 0; // Not found
577 : }
578 :
579 : template <typename A> inline int FindItem(std::string_view const String, MArray1<A, std::string> const &ListOfItems)
580 : {
581 : return FindItem(String, ListOfItems, ListOfItems.isize());
582 : }
583 :
584 : template <typename Container, class = typename std::enable_if<!std::is_same<typename Container::value_type, std::string>::value>::type>
585 : // Container needs size() and operator[i] and elements need Name
586 30555 : inline int FindItem(std::string_view const String, Container const &ListOfItems, int const NumItems)
587 : {
588 30555 : int const item_number(Util::FindItemInList(String, ListOfItems, NumItems));
589 30555 : if (item_number != 0) {
590 30491 : return item_number;
591 : }
592 234 : for (typename Container::size_type i = 0, e = NumItems; i < e; ++i) {
593 170 : if (equali(String, ListOfItems[i].Name)) {
594 0 : return i + 1; // 1-based return index
595 : }
596 : }
597 64 : return 0; // Not found
598 : }
599 :
600 : template <typename Container, class = typename std::enable_if<!std::is_same<typename Container::value_type, std::string>::value>::type>
601 : // Container needs size() and operator[i] and elements need Name
602 30493 : inline int FindItem(std::string_view const String, Container const &ListOfItems)
603 : {
604 30493 : return FindItem(String, ListOfItems, ListOfItems.isize());
605 : }
606 :
607 : template <typename Container, class = typename std::enable_if<!std::is_same<typename Container::value_type, std::string>::value>::type>
608 : // Container needs size() and operator[i] and value_type
609 48 : inline int FindItem(std::string_view const String, Container const &ListOfItems, std::string Container::value_type::*name_p, int const NumItems)
610 : {
611 48 : int const item_number(Util::FindItemInList(String, ListOfItems, name_p, NumItems));
612 48 : if (item_number != 0) {
613 2 : return item_number;
614 : }
615 256 : for (typename Container::size_type i = 0, e = NumItems; i < e; ++i) {
616 256 : if (equali(String, ListOfItems[i].*name_p)) {
617 46 : return i + 1; // 1-based return index
618 : }
619 : }
620 0 : return 0; // Not found
621 : }
622 :
623 : template <typename Container, class = typename std::enable_if<!std::is_same<typename Container::value_type, std::string>::value>::type>
624 : // Container needs size() and operator[i] and value_type
625 48 : inline int FindItem(std::string_view const String, Container const &ListOfItems, std::string Container::value_type::*name_p)
626 : {
627 48 : return FindItem(String, ListOfItems, name_p, ListOfItems.isize());
628 : }
629 :
630 17042579 : inline std::string makeUPPER(std::string_view const InputString) // Input String
631 : {
632 :
633 : // FUNCTION INFORMATION:
634 : // AUTHOR Linda K. Lawrie
635 : // DATE WRITTEN September 1997
636 : // MODIFIED na
637 : // RE-ENGINEERED na
638 :
639 : // PURPOSE OF THIS SUBROUTINE:
640 : // This function returns the Upper Case representation of the InputString.
641 :
642 : // METHODOLOGY EMPLOYED:
643 : // Uses the Intrinsic SCAN function to scan the lowercase representation of
644 : // characters (DataStringGlobals) for each character in the given string.
645 :
646 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
647 :
648 17042579 : std::string ResultString(InputString);
649 :
650 579214697 : for (std::string::size_type i = 0, e = len(InputString); i < e; ++i) {
651 562172118 : int const curCharVal = int(InputString[i]);
652 562172118 : if ((97 <= curCharVal && curCharVal <= 122) || (224 <= curCharVal && curCharVal <= 255)) { // lowercase ASCII and accented characters
653 370420691 : ResultString[i] = char(curCharVal - 32);
654 : }
655 : }
656 :
657 17042579 : return ResultString;
658 0 : }
659 :
660 724585920 : constexpr bool SameString(std::string_view const s, std::string_view const t)
661 : {
662 : // case insensitive comparison
663 724585920 : return equali(s, t);
664 : }
665 :
666 : template <typename InputIterator>
667 : inline void VerifyName(EnergyPlusData &state,
668 : InputIterator first,
669 : InputIterator last,
670 : std::string const &NameToVerify,
671 : bool &ErrorFound,
672 : bool &IsBlank,
673 : std::string const &StringToDisplay)
674 : {
675 : IsBlank = false;
676 : ErrorFound = false;
677 : if (NameToVerify.empty()) {
678 : ShowSevereError(state, StringToDisplay + ", cannot be blank");
679 : ErrorFound = true;
680 : IsBlank = true;
681 : return;
682 : }
683 : int Found = FindItem(first, last, NameToVerify);
684 : if (Found != 0) {
685 : ShowSevereError(state, StringToDisplay + ", duplicate name=" + NameToVerify);
686 : ErrorFound = true;
687 : }
688 : }
689 :
690 : void VerifyName(EnergyPlusData &state,
691 : std::string const &NameToVerify,
692 : Array1D_string const &NamesList,
693 : int const NumOfNames,
694 : bool &ErrorFound,
695 : bool &IsBlank,
696 : std::string const &StringToDisplay);
697 :
698 : void VerifyName(EnergyPlusData &state,
699 : std::string const &NameToVerify,
700 : Array1S_string const NamesList,
701 : int const NumOfNames,
702 : bool &ErrorFound,
703 : bool &IsBlank,
704 : std::string const &StringToDisplay);
705 :
706 : template <typename A>
707 : inline void VerifyName(EnergyPlusData &state,
708 : std::string const &NameToVerify,
709 : MArray1<A, std::string> const &NamesList,
710 : int const NumOfNames,
711 : bool &ErrorFound,
712 : bool &IsBlank,
713 : std::string const &StringToDisplay)
714 : { // Overload for member arrays: Implemented here to avoid copy to Array_string to forward to other VerifyName
715 : ErrorFound = false;
716 : if (NumOfNames > 0) {
717 : int const Found = FindItem(NameToVerify, NamesList,
718 : NumOfNames); // Calls FindItem overload that accepts member arrays
719 : if (Found != 0) {
720 : ShowSevereError(state, StringToDisplay + ", duplicate name=" + NameToVerify);
721 : ErrorFound = true;
722 : }
723 : }
724 :
725 : if (NameToVerify.empty()) {
726 : ShowSevereError(state, StringToDisplay + ", cannot be blank");
727 : ErrorFound = true;
728 : IsBlank = true;
729 : } else {
730 : IsBlank = false;
731 : }
732 : }
733 :
734 : template <typename Container, class = typename std::enable_if<!std::is_same<typename Container::value_type, std::string>::value>::type>
735 : // Container needs size() and operator[i] and elements need Name
736 125 : inline void VerifyName(EnergyPlusData &state,
737 : std::string const &NameToVerify,
738 : Container const &NamesList,
739 : int const NumOfNames,
740 : bool &ErrorFound,
741 : bool &IsBlank,
742 : std::string const &StringToDisplay)
743 : {
744 125 : ErrorFound = false;
745 125 : if (NumOfNames > 0) {
746 58 : int const Found = FindItem(NameToVerify, NamesList,
747 : NumOfNames); // Calls FindItem overload that accepts member arrays
748 58 : if (Found != 0) {
749 0 : ShowSevereError(state, StringToDisplay + ", duplicate name=" + NameToVerify);
750 0 : ErrorFound = true;
751 : }
752 : }
753 :
754 125 : if (NameToVerify.empty()) {
755 0 : ShowSevereError(state, StringToDisplay + ", cannot be blank");
756 0 : ErrorFound = true;
757 0 : IsBlank = true;
758 : } else {
759 125 : IsBlank = false;
760 : }
761 125 : }
762 :
763 : template <typename Container, class = typename std::enable_if<!std::is_same<typename Container::value_type, std::string>::value>::type>
764 : // Container needs size() and operator[i] and value_type
765 : inline void VerifyName(EnergyPlusData &state,
766 : std::string const &NameToVerify,
767 : Container const &NamesList,
768 : std::string Container::value_type::*name_p,
769 : int const NumOfNames,
770 : bool &ErrorFound,
771 : bool &IsBlank,
772 : std::string const &StringToDisplay)
773 : {
774 : ErrorFound = false;
775 : if (NumOfNames > 0) {
776 : int const Found = FindItem(NameToVerify, NamesList, name_p, NumOfNames);
777 : if (Found != 0) {
778 : ShowSevereError(state, StringToDisplay + ", duplicate name=" + NameToVerify);
779 : ErrorFound = true;
780 : }
781 : }
782 :
783 : if (NameToVerify.empty()) {
784 : ShowSevereError(state, StringToDisplay + ", cannot be blank");
785 : ErrorFound = true;
786 : IsBlank = true;
787 : } else {
788 : IsBlank = false;
789 : }
790 : }
791 :
792 : bool IsNameEmpty(EnergyPlusData &state, std::string &NameToVerify, std::string_view StringToDisplay, bool &ErrorFound);
793 :
794 : // Two structs for case insensitive containers.
795 : // Eg: for unordered_map, we need to have a case insenstive hasher and a case insensitive comparator
796 : // (The default allocator for unordered_map is fine)
797 : // For map, you'd only need the comparator
798 : struct case_insensitive_hasher
799 : {
800 : using is_transparent = void;
801 : size_t operator()(std::string_view key) const noexcept;
802 : };
803 :
804 : struct case_insensitive_comparator
805 : {
806 : using is_transparent = void;
807 : bool operator()(std::string_view a, std::string_view b) const noexcept;
808 : };
809 :
810 : void appendPerfLog(EnergyPlusData &state, std::string const &colHeader, std::string const &colValue, bool finalColumn = false);
811 :
812 : } // namespace Util
813 :
814 4248645 : constexpr int getEnumValue(const gsl::span<const std::string_view> sList, const std::string_view s)
815 : {
816 342680832 : for (unsigned int i = 0; i < sList.size(); ++i) {
817 342675926 : if (sList[i] == s) {
818 4243739 : return i;
819 : }
820 : }
821 4906 : return -1;
822 : }
823 :
824 : constexpr std::array<std::string_view, 2> yesNoNames = {"No", "Yes"};
825 : constexpr std::array<std::string_view, 2> yesNoNamesUC = {"NO", "YES"};
826 :
827 21613 : constexpr BooleanSwitch getYesNoValue(const std::string_view s)
828 : {
829 21613 : return static_cast<BooleanSwitch>(getEnumValue(yesNoNamesUC, s));
830 : }
831 :
832 : constexpr Real64 fclamp(Real64 v, Real64 min, Real64 max)
833 : {
834 : return (v < min) ? min : ((v > max) ? max : v);
835 : }
836 :
837 : struct UtilityRoutinesData : BaseGlobalStruct
838 : {
839 :
840 : bool outputErrorHeader = true;
841 : std::string appendPerfLog_headerRow;
842 : std::string appendPerfLog_valuesRow;
843 : bool GetMatrixInputFlag = true;
844 :
845 801 : void init_constant_state([[maybe_unused]] EnergyPlusData &state) override
846 : {
847 801 : }
848 :
849 801 : void init_state([[maybe_unused]] EnergyPlusData &state) override
850 : {
851 801 : }
852 :
853 0 : void clear_state() override
854 : {
855 0 : outputErrorHeader = true;
856 0 : appendPerfLog_headerRow.clear();
857 0 : appendPerfLog_valuesRow.clear();
858 0 : GetMatrixInputFlag = true;
859 0 : }
860 :
861 : // Default Constructor
862 801 : UtilityRoutinesData() = default;
863 : };
864 : } // namespace EnergyPlus
865 :
866 : #endif
|