Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2024, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : #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 4032 : template <typename T, typename = std::enable_if_t<std::is_arithmetic_v<T>>> inline constexpr T pow4(T x)
104 : {
105 4032 : T y(x * x);
106 4032 : 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 ShowSevereInvalidKey(
290 : EnergyPlusData &state, ErrorObjectHeader const &eoh, std::string_view fieldName, std::string_view fieldValue, std::string_view msg = {});
291 : void ShowSevereInvalidBool(EnergyPlusData &state, ErrorObjectHeader const &eoh, std::string_view fieldName, std::string_view fieldValue);
292 :
293 : void ShowSevereCustomMessage(EnergyPlusData &state, ErrorObjectHeader const &eoh, std::string_view msg);
294 : void ShowWarningDuplicateName(EnergyPlusData &state, ErrorObjectHeader const &eoh);
295 : void ShowWarningEmptyField(EnergyPlusData &state,
296 : ErrorObjectHeader const &eoh,
297 : std::string_view fieldName,
298 : std::string_view defaultValue,
299 : std::string_view depFieldName = {},
300 : std::string_view depFieldValue = {});
301 : void ShowWarningItemNotFound(
302 : EnergyPlusData &state, ErrorObjectHeader const &eoh, std::string_view fieldName, std::string_view fieldValue, std::string_view defaultValue);
303 : void ShowWarningInvalidKey(EnergyPlusData &state,
304 : ErrorObjectHeader const &eoh,
305 : std::string_view fieldName,
306 : std::string_view fieldValue,
307 : std::string_view defaultValue,
308 : std::string_view msg = {});
309 : void ShowWarningInvalidBool(
310 : EnergyPlusData &state, ErrorObjectHeader const &eoh, std::string_view fieldName, std::string_view fieldValue, std::string_view defaultValue);
311 : void ShowWarningCustomMessage(EnergyPlusData &state, ErrorObjectHeader const &eoh, std::string_view msg);
312 :
313 : namespace Util {
314 :
315 : static constexpr std::array<std::string_view, 12> MonthNamesCC{
316 : "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
317 :
318 : static constexpr std::array<std::string_view, 12> MonthNamesUC{
319 : "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE", "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER"};
320 :
321 : template <class T> struct is_shared_ptr : std::false_type
322 : {
323 : };
324 : template <class T> struct is_shared_ptr<std::shared_ptr<T>> : std::true_type
325 : {
326 : };
327 :
328 : Real64 ProcessNumber(std::string_view String, bool &ErrorFlag);
329 :
330 : int FindItemInList(std::string_view const String, Array1_string const &ListOfItems, int NumItems);
331 :
332 1336 : inline int FindItemInList(std::string_view const String, Array1_string const &ListOfItems)
333 : {
334 1336 : return Util::FindItemInList(String, ListOfItems, ListOfItems.isize());
335 : }
336 :
337 : int FindItemInList(std::string_view const String, Array1S_string const ListOfItems, int NumItems);
338 :
339 2780 : template <typename InputIterator> int FindItemInList(std::string_view const str, InputIterator first, InputIterator last)
340 : {
341 2780 : auto it = std::find(first, last, str);
342 2780 : if (it != last) {
343 2780 : return std::distance(first, it) + 1;
344 : } else {
345 0 : return 0;
346 : }
347 : }
348 :
349 : inline int FindItemInList(std::string_view const String, Array1S_string const ListOfItems)
350 : {
351 : return Util::FindItemInList(String, ListOfItems, ListOfItems.isize());
352 : }
353 :
354 : template <typename A> inline int FindItemInList(std::string_view const String, MArray1<A, std::string> const &ListOfItems, int const NumItems)
355 : {
356 : for (int Count = 1; Count <= NumItems; ++Count) {
357 : if (String == ListOfItems(Count)) return Count;
358 : }
359 : return 0; // Not found
360 : }
361 :
362 : template <typename A> inline int FindItemInList(std::string_view const String, MArray1<A, std::string> const &ListOfItems)
363 : {
364 : return Util::FindItemInList(String, ListOfItems, ListOfItems.isize());
365 : }
366 :
367 : template <typename Container, class = typename std::enable_if<!std::is_same<typename Container::value_type, std::string>::value>::type>
368 : // Container needs and operator[i] and elements need Name
369 10398350 : inline int FindItemInList(std::string_view const String, Container const &ListOfItems, int const NumItems)
370 : {
371 151772886 : for (typename Container::size_type i = 0, e = NumItems; i < e; ++i) {
372 151437254 : if (String == ListOfItems[i].Name) return int(i + 1); // 1-based return index
373 : }
374 335632 : return 0; // Not found
375 : }
376 :
377 : template <typename Container, class = typename std::enable_if<!std::is_same<typename Container::value_type, std::string>::value>::type>
378 : // Container needs and operator[i] and elements need Name
379 14079 : inline int FindItemInPtrList(std::string_view const String, Container const &ListOfItems, int const NumItems)
380 : {
381 166834 : for (typename Container::size_type i = 0, e = NumItems; i < e; ++i) {
382 166772 : if (String == ListOfItems[i]->Name) return int(i + 1); // 1-based return index
383 : }
384 62 : return 0; // Not found
385 : }
386 :
387 : template <typename Container, class = typename std::enable_if<!std::is_same<typename Container::value_type, std::string>::value>::type>
388 : // Container needs and operator[i] and elements need Name
389 13984 : inline int FindItemInPtrList(std::string_view const String, Container const &ListOfItems)
390 : {
391 13984 : return Util::FindItemInPtrList(String, ListOfItems, ListOfItems.isize());
392 : }
393 :
394 : template <typename Container, class = typename std::enable_if<!std::is_same<typename Container::value_type, std::string>::value>::type>
395 : // Container needs isize() and operator[i] and elements need Name
396 10243133 : inline int FindItemInList(std::string_view const String, Container const &ListOfItems)
397 : {
398 10243133 : return Util::FindItemInList(String, ListOfItems, ListOfItems.isize());
399 : }
400 :
401 : template <typename Container, class = typename std::enable_if<!std::is_same<typename Container::value_type, std::string>::value>::type>
402 : // Container needs operator[i] and value_type
403 : inline int
404 496311 : FindItemInList(std::string_view const String, Container const &ListOfItems, std::string Container::value_type::*name_p, int const NumItems)
405 : {
406 1700721 : for (typename Container::size_type i = 0, e = NumItems; i < e; ++i) {
407 1680542 : if (String == ListOfItems[i].*name_p) return int(i + 1); // 1-based return index
408 : }
409 20179 : return 0; // Not found
410 : }
411 :
412 : template <typename Container, class = typename std::enable_if<!std::is_same<typename Container::value_type, std::string>::value>::type>
413 : // Container needs isize() and operator[i] and value_type
414 476981 : inline int FindItemInList(std::string_view const String, Container const &ListOfItems, std::string Container::value_type::*name_p)
415 : {
416 476981 : return Util::FindItemInList(String, ListOfItems, name_p, ListOfItems.isize());
417 : }
418 :
419 : int FindItemInSortedList(std::string_view const string, Array1S_string const ListOfItems, int NumItems);
420 :
421 : inline int FindItemInSortedList(std::string_view const String, Array1S_string const ListOfItems)
422 : {
423 : return FindItemInSortedList(String, ListOfItems, ListOfItems.isize());
424 : }
425 :
426 : template <typename A>
427 : inline int FindItemInSortedList(std::string_view const String, MArray1<A, std::string> const &ListOfItems, int const NumItems)
428 : {
429 : int Probe(0);
430 : int LBnd(0);
431 : int UBnd(NumItems + 1);
432 : bool Found(false);
433 : while ((!Found) || (Probe != 0)) {
434 : Probe = (UBnd - LBnd) / 2;
435 : if (Probe == 0) break;
436 : Probe += LBnd;
437 : if (equali(String, ListOfItems(Probe))) {
438 : Found = true;
439 : break;
440 : } else if (lessthani(String, ListOfItems(Probe))) {
441 : UBnd = Probe;
442 : } else {
443 : LBnd = Probe;
444 : }
445 : }
446 : return Probe;
447 : }
448 :
449 : template <typename A> inline int FindItemInSortedList(std::string_view const String, MArray1<A, std::string> const &ListOfItems)
450 : {
451 : return FindItemInSortedList(String, ListOfItems, ListOfItems.isize());
452 : }
453 :
454 : template <typename InputIterator> inline int FindItem(InputIterator first, InputIterator last, std::string_view const str, std::false_type)
455 : {
456 : using valueType = typename std::iterator_traits<InputIterator>::value_type;
457 : // static_assert( std::is_convertible< decltype( std::declval< valueType >() ), Named >::value, "Iterator value must inherit from class Named"
458 : // );
459 :
460 : auto const it = std::find_if(first, last, [&str](const valueType &s) { return s.name == str; });
461 : if (it != last) return it - first + 1; // 1-based return index
462 :
463 : auto const it2 = std::find_if(first, last, [&str](const valueType &s) { return equali(s.name, str); });
464 : if (it2 != last) return it2 - first + 1; // 1-based return index
465 :
466 : return 0; // Not found
467 : }
468 :
469 : template <typename InputIterator> inline int FindItem(InputIterator first, InputIterator last, std::string_view const str, std::true_type)
470 : {
471 : using valueType = typename std::iterator_traits<InputIterator>::value_type;
472 : // static_assert( std::is_convertible< decltype( *std::declval< valueType >() ), Named >::value, "Iterator value must inherit from class
473 : // Named" );
474 :
475 : auto const it = std::find_if(first, last, [&str](const valueType &s) { return s->name == str; });
476 : if (it != last) return it - first + 1; // 1-based return index
477 :
478 : auto const it2 = std::find_if(first, last, [&str](const valueType &s) { return equali(s->name, str); });
479 : if (it2 != last) return it2 - first + 1; // 1-based return index
480 :
481 : return 0; // Not found
482 : }
483 :
484 : template <typename InputIterator> inline int FindItem(InputIterator first, InputIterator last, std::string_view str)
485 : {
486 : return FindItem(first, last, str, is_shared_ptr<typename std::iterator_traits<InputIterator>::value_type>{});
487 : }
488 :
489 : int FindItem(std::string_view const String, Array1D_string const &ListOfItems, int const NumItems);
490 :
491 : inline int FindItem(std::string_view const String, Array1D_string const &ListOfItems)
492 : {
493 : return FindItem(String, ListOfItems, ListOfItems.isize());
494 : }
495 :
496 : int FindItem(std::string_view const String, Array1S_string const ListOfItems, int const NumItems);
497 :
498 : inline int FindItem(std::string_view const String, Array1S_string const ListOfItems)
499 : {
500 : return FindItem(String, ListOfItems, ListOfItems.isize());
501 : }
502 :
503 : template <typename A> inline int FindItem(std::string_view const String, MArray1<A, std::string> const &ListOfItems, int const NumItems)
504 : {
505 : int const item_number(Util::FindItemInList(String, ListOfItems, NumItems));
506 : if (item_number != 0) return item_number;
507 : for (int Count = 1; Count <= NumItems; ++Count) {
508 : if (equali(String, ListOfItems(Count))) return Count;
509 : }
510 : return 0; // Not found
511 : }
512 :
513 : template <typename A> inline int FindItem(std::string_view const String, MArray1<A, std::string> const &ListOfItems)
514 : {
515 : return FindItem(String, ListOfItems, ListOfItems.isize());
516 : }
517 :
518 : template <typename Container, class = typename std::enable_if<!std::is_same<typename Container::value_type, std::string>::value>::type>
519 : // Container needs size() and operator[i] and elements need Name
520 29126 : inline int FindItem(std::string_view const String, Container const &ListOfItems, int const NumItems)
521 : {
522 29126 : int const item_number(Util::FindItemInList(String, ListOfItems, NumItems));
523 29126 : if (item_number != 0) return item_number;
524 234 : for (typename Container::size_type i = 0, e = NumItems; i < e; ++i) {
525 170 : if (equali(String, ListOfItems[i].Name)) return i + 1; // 1-based return index
526 : }
527 64 : return 0; // Not found
528 : }
529 :
530 : template <typename Container, class = typename std::enable_if<!std::is_same<typename Container::value_type, std::string>::value>::type>
531 : // Container needs size() and operator[i] and elements need Name
532 29064 : inline int FindItem(std::string_view const String, Container const &ListOfItems)
533 : {
534 29064 : return FindItem(String, ListOfItems, ListOfItems.isize());
535 : }
536 :
537 : template <typename Container, class = typename std::enable_if<!std::is_same<typename Container::value_type, std::string>::value>::type>
538 : // Container needs size() and operator[i] and value_type
539 48 : inline int FindItem(std::string_view const String, Container const &ListOfItems, std::string Container::value_type::*name_p, int const NumItems)
540 : {
541 48 : int const item_number(Util::FindItemInList(String, ListOfItems, name_p, NumItems));
542 48 : if (item_number != 0) return item_number;
543 256 : for (typename Container::size_type i = 0, e = NumItems; i < e; ++i) {
544 256 : if (equali(String, ListOfItems[i].*name_p)) return i + 1; // 1-based return index
545 : }
546 0 : return 0; // Not found
547 : }
548 :
549 : template <typename Container, class = typename std::enable_if<!std::is_same<typename Container::value_type, std::string>::value>::type>
550 : // Container needs size() and operator[i] and value_type
551 48 : inline int FindItem(std::string_view const String, Container const &ListOfItems, std::string Container::value_type::*name_p)
552 : {
553 48 : return FindItem(String, ListOfItems, name_p, ListOfItems.isize());
554 : }
555 :
556 16200266 : inline std::string makeUPPER(std::string_view const InputString) // Input String
557 : {
558 :
559 : // FUNCTION INFORMATION:
560 : // AUTHOR Linda K. Lawrie
561 : // DATE WRITTEN September 1997
562 : // MODIFIED na
563 : // RE-ENGINEERED na
564 :
565 : // PURPOSE OF THIS SUBROUTINE:
566 : // This function returns the Upper Case representation of the InputString.
567 :
568 : // METHODOLOGY EMPLOYED:
569 : // Uses the Intrinsic SCAN function to scan the lowercase representation of
570 : // characters (DataStringGlobals) for each character in the given string.
571 :
572 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
573 :
574 16200266 : std::string ResultString(InputString);
575 :
576 551018715 : for (std::string::size_type i = 0, e = len(InputString); i < e; ++i) {
577 534818449 : int const curCharVal = int(InputString[i]);
578 534818449 : if ((97 <= curCharVal && curCharVal <= 122) || (224 <= curCharVal && curCharVal <= 255)) { // lowercase ASCII and accented characters
579 356962641 : ResultString[i] = char(curCharVal - 32);
580 : }
581 : }
582 :
583 16200266 : return ResultString;
584 0 : }
585 :
586 707535555 : constexpr bool SameString(std::string_view const s, std::string_view const t)
587 : {
588 : // case insensitive comparison
589 707535555 : return equali(s, t);
590 : }
591 :
592 : template <typename InputIterator>
593 : inline void VerifyName(EnergyPlusData &state,
594 : InputIterator first,
595 : InputIterator last,
596 : std::string const &NameToVerify,
597 : bool &ErrorFound,
598 : bool &IsBlank,
599 : std::string const &StringToDisplay)
600 : {
601 : IsBlank = false;
602 : ErrorFound = false;
603 : if (NameToVerify.empty()) {
604 : ShowSevereError(state, StringToDisplay + ", cannot be blank");
605 : ErrorFound = true;
606 : IsBlank = true;
607 : return;
608 : }
609 : int Found = FindItem(first, last, NameToVerify);
610 : if (Found != 0) {
611 : ShowSevereError(state, StringToDisplay + ", duplicate name=" + NameToVerify);
612 : ErrorFound = true;
613 : }
614 : }
615 :
616 : void VerifyName(EnergyPlusData &state,
617 : std::string const &NameToVerify,
618 : Array1D_string const &NamesList,
619 : int const NumOfNames,
620 : bool &ErrorFound,
621 : bool &IsBlank,
622 : std::string const &StringToDisplay);
623 :
624 : void VerifyName(EnergyPlusData &state,
625 : std::string const &NameToVerify,
626 : Array1S_string const NamesList,
627 : int const NumOfNames,
628 : bool &ErrorFound,
629 : bool &IsBlank,
630 : std::string const &StringToDisplay);
631 :
632 : template <typename A>
633 : inline void VerifyName(EnergyPlusData &state,
634 : std::string const &NameToVerify,
635 : MArray1<A, std::string> const &NamesList,
636 : int const NumOfNames,
637 : bool &ErrorFound,
638 : bool &IsBlank,
639 : std::string const &StringToDisplay)
640 : { // Overload for member arrays: Implemented here to avoid copy to Array_string to forward to other VerifyName
641 : ErrorFound = false;
642 : if (NumOfNames > 0) {
643 : int const Found = FindItem(NameToVerify, NamesList,
644 : NumOfNames); // Calls FindItem overload that accepts member arrays
645 : if (Found != 0) {
646 : ShowSevereError(state, StringToDisplay + ", duplicate name=" + NameToVerify);
647 : ErrorFound = true;
648 : }
649 : }
650 :
651 : if (NameToVerify.empty()) {
652 : ShowSevereError(state, StringToDisplay + ", cannot be blank");
653 : ErrorFound = true;
654 : IsBlank = true;
655 : } else {
656 : IsBlank = false;
657 : }
658 : }
659 :
660 : template <typename Container, class = typename std::enable_if<!std::is_same<typename Container::value_type, std::string>::value>::type>
661 : // Container needs size() and operator[i] and elements need Name
662 125 : inline void VerifyName(EnergyPlusData &state,
663 : std::string const &NameToVerify,
664 : Container const &NamesList,
665 : int const NumOfNames,
666 : bool &ErrorFound,
667 : bool &IsBlank,
668 : std::string const &StringToDisplay)
669 : {
670 125 : ErrorFound = false;
671 125 : if (NumOfNames > 0) {
672 58 : int const Found = FindItem(NameToVerify, NamesList,
673 : NumOfNames); // Calls FindItem overload that accepts member arrays
674 58 : if (Found != 0) {
675 0 : ShowSevereError(state, StringToDisplay + ", duplicate name=" + NameToVerify);
676 0 : ErrorFound = true;
677 : }
678 : }
679 :
680 125 : if (NameToVerify.empty()) {
681 0 : ShowSevereError(state, StringToDisplay + ", cannot be blank");
682 0 : ErrorFound = true;
683 0 : IsBlank = true;
684 : } else {
685 125 : IsBlank = false;
686 : }
687 125 : }
688 :
689 : template <typename Container, class = typename std::enable_if<!std::is_same<typename Container::value_type, std::string>::value>::type>
690 : // Container needs size() and operator[i] and value_type
691 : inline void VerifyName(EnergyPlusData &state,
692 : std::string const &NameToVerify,
693 : Container const &NamesList,
694 : std::string Container::value_type::*name_p,
695 : int const NumOfNames,
696 : bool &ErrorFound,
697 : bool &IsBlank,
698 : std::string const &StringToDisplay)
699 : {
700 : ErrorFound = false;
701 : if (NumOfNames > 0) {
702 : int const Found = FindItem(NameToVerify, NamesList, name_p, NumOfNames);
703 : if (Found != 0) {
704 : ShowSevereError(state, StringToDisplay + ", duplicate name=" + NameToVerify);
705 : ErrorFound = true;
706 : }
707 : }
708 :
709 : if (NameToVerify.empty()) {
710 : ShowSevereError(state, StringToDisplay + ", cannot be blank");
711 : ErrorFound = true;
712 : IsBlank = true;
713 : } else {
714 : IsBlank = false;
715 : }
716 : }
717 :
718 : bool IsNameEmpty(EnergyPlusData &state, std::string &NameToVerify, std::string_view StringToDisplay, bool &ErrorFound);
719 :
720 : // Two structs for case insensitive containers.
721 : // Eg: for unordered_map, we need to have a case insenstive hasher and a case insensitive comparator
722 : // (The default allocator for unordered_map is fine)
723 : // For map, you'd only need the comparator
724 : struct case_insensitive_hasher
725 : {
726 : using is_transparent = void;
727 : size_t operator()(std::string_view key) const noexcept;
728 : };
729 :
730 : struct case_insensitive_comparator
731 : {
732 : using is_transparent = void;
733 : bool operator()(std::string_view a, std::string_view b) const noexcept;
734 : };
735 :
736 : void appendPerfLog(EnergyPlusData &state, std::string const &colHeader, std::string const &colValue, bool finalColumn = false);
737 :
738 : } // namespace Util
739 :
740 4225926 : constexpr int getEnumValue(const gsl::span<const std::string_view> sList, const std::string_view s)
741 : {
742 342219215 : for (unsigned int i = 0; i < sList.size(); ++i) {
743 342218738 : if (sList[i] == s) return i;
744 : }
745 477 : return -1;
746 : }
747 :
748 : constexpr std::array<std::string_view, 2> yesNoNamesUC = {"NO", "YES"};
749 :
750 18261 : constexpr BooleanSwitch getYesNoValue(const std::string_view s)
751 : {
752 18261 : return static_cast<BooleanSwitch>(getEnumValue(yesNoNamesUC, s));
753 : }
754 :
755 : constexpr Real64 fclamp(Real64 v, Real64 min, Real64 max)
756 : {
757 : return (v < min) ? min : ((v > max) ? max : v);
758 : }
759 :
760 : struct UtilityRoutinesData : BaseGlobalStruct
761 : {
762 :
763 : bool outputErrorHeader = true;
764 : std::string appendPerfLog_headerRow;
765 : std::string appendPerfLog_valuesRow;
766 : bool GetMatrixInputFlag = true;
767 :
768 796 : void init_state([[maybe_unused]] EnergyPlusData &state) override
769 : {
770 796 : }
771 :
772 0 : void clear_state() override
773 : {
774 0 : outputErrorHeader = true;
775 0 : appendPerfLog_headerRow.clear();
776 0 : appendPerfLog_valuesRow.clear();
777 0 : GetMatrixInputFlag = true;
778 0 : }
779 :
780 : // Default Constructor
781 796 : UtilityRoutinesData() = default;
782 : };
783 : } // namespace EnergyPlus
784 :
785 : #endif
|