Block-Structured AMR Software Framework
Loading...
Searching...
No Matches
AMReX_Utility.H
Go to the documentation of this file.
1#ifndef BL_UTILITY_H
2#define BL_UTILITY_H
3#include <AMReX_Config.H>
4
5#include <AMReX_BLassert.H>
6#include <AMReX_REAL.H>
7#include <AMReX_INT.H>
8#include <AMReX_Array.H>
9#include <AMReX_Vector.H>
10#include <AMReX_Box.H>
11#include <AMReX_BoxArray.H>
12#include <AMReX_Demangle.H>
15#include <AMReX_Random.H>
16#include <AMReX_GpuQualifiers.H>
17#include <AMReX_FileSystem.H>
18#include <AMReX_String.H>
19#include <AMReX_TypeTraits.H>
20
21#include <cfloat>
22#include <chrono>
23#include <climits>
24#include <cstdlib>
25#include <iostream>
26#include <limits>
27#include <map>
28#include <ostream>
29#include <sstream>
30#include <string>
31#include <string_view>
32#include <tuple>
33#include <typeinfo>
34#include <type_traits>
35#include <utility>
36
37namespace amrex
38{
44 template <typename T> bool is_it (std::string const& s, T& v);
45
47 const std::vector<std::string>& Tokenize (const std::string& instr,
48 const std::string& separators);
49
74 bool UtilCreateDirectory (const std::string& path,
75 mode_t mode,
76 bool verbose = false);
78 void CreateDirectoryFailed (const std::string& dir);
80 void FileOpenFailed (const std::string& file);
87 bool FileExists(const std::string &filename);
89 std::string UniqueString();
91 void UtilCreateCleanDirectory (const std::string &path,
92 bool callbarrier = true);
93
95 void UtilCreateDirectoryDestructive(const std::string &path,
96 bool callbarrier = true);
97
99 void UtilRenameDirectoryToOld (const std::string &path,
100 bool callbarrier = true);
106 void OutOfMemory ();
124 double InvNormDist (double p);
147 double InvNormDistBest (double p);
148
149 /* \brief cumulative refinement ratio between levels */
150 int CRRBetweenLevels(int fromlevel, int tolevel,
151 const Vector<int> &refratios);
152
153 class expect;
154 std::istream& operator>>(std::istream&, const expect& exp);
155
156 class expect
157 {
158 friend std::istream& operator>>(std::istream&, const expect& exp);
159 public:
160 explicit expect (std::string str_);
161 explicit expect (const char* istr_);
162 explicit expect (char c);
163 [[nodiscard]] const std::string& the_string( ) const;
164 private:
165 std::string istr;
166 };
167
169 {
170 public:
171 StreamRetry(std::ostream &os, std::string suffix, int maxtries);
172 StreamRetry(std::string filename, bool abortonretryfailure, int maxtries);
173 bool TryOutput();
174 bool TryFileOutput();
175 static int NStreamErrors() { return nStreamErrors; }
176 static void ClearStreamErrors() { nStreamErrors = 0; }
177
178 private:
179 int tries, maxTries;
180 bool abortOnRetryFailure = true;
181 std::string fileName;
182 std::ostream *sros;
183 std::ostream::pos_type spos;
184 std::string suffix;
185
186 static int nStreamErrors;
187 };
188
189 Vector<char> SerializeStringArray(const Vector<std::string> &stringArray);
190 Vector<std::string> UnSerializeStringArray(const Vector<char> &charArray);
191 void SyncStrings(const Vector<std::string> &localStrings,
192 Vector<std::string> &syncedStrings, bool &alreadySynced);
193
194 //
195 // Memory Usage Counting
196 //
197 // For gcc, there are extra 32 bytes for each map node.
198 // For others, this number may be different.
200 static const Long gcc_map_node_extra_bytes = 32L;
202 template <typename T> amrex::Long bytesOf (const std::vector<T>& v);
203 template <typename Key, typename T, class Compare> amrex::Long bytesOf (const std::map<Key,T,Compare>& m);
204
205 void BroadcastBool(bool &bBool, int myLocalId, int rootId, const MPI_Comm &localComm);
206
207 void BroadcastString(std::string &bStr, int myLocalId, int rootId, const MPI_Comm &localComm);
208 void BroadcastStringArray(Vector<std::string> &bSA, int myLocalId, int rootId, const MPI_Comm &localComm);
209
210 template<class T> void BroadcastArray(Vector<T> &aT, int myLocalId, int rootId, const MPI_Comm &localComm);
211
212 void Sleep (double sleepsec); // Sleep for sleepsec seconds
213
214
215 using MaxResSteadyClock = std::conditional_t<std::chrono::high_resolution_clock::is_steady,
216 std::chrono::high_resolution_clock,
217 std::chrono::steady_clock>;
218 double second () noexcept;
219
220 template<typename T> void hash_combine (uint64_t & seed, const T & val) noexcept;
221 template<typename T> uint64_t hash_vector (const Vector<T> & vec, uint64_t seed = 0xDEADBEEFDEADBEEF) noexcept;
222
223 template <class T>
224 std::ostream& ToString(std::ostream& os,
225 const T& t,
226 const char* symbol_begin = "[",
227 const char* symbol_delim = ", ",
228 const char* symbol_end = "]",
229 const char* symbol_str = "\"",
230 int limit = 100);
231
232 template <class T>
233 std::string ToString(const T& t,
234 const char* symbol_begin = "[",
235 const char* symbol_delim = ", ",
236 const char* symbol_end = "]",
237 const char* symbol_str = "\"",
238 int limit = 100,
239 std::ostringstream ss = std::ostringstream{});
240
250 template <typename F, typename... T>
252 auto callNoinline (F const& f, T&&... arg)
253 -> decltype(std::declval<F>()(std::declval<T>()...)); // needed for nvcc
254}
255
256template <typename T>
257bool amrex::is_it (std::string const& s, T& v)
258{
259 std::istringstream ss(s);
260 if (ss >> v) {
261 std::string left;
262 std::getline(ss, left);
263 return left.empty();
264 } else {
265 return false;
266 }
267}
268
269template<class T> void amrex::BroadcastArray(Vector<T> &aT, int myLocalId, int rootId, const MPI_Comm &localComm)
270{
271 int aT_Size(-2);
272 if(myLocalId == rootId) {
273 aT_Size = aT.size();
274 }
275 ParallelDescriptor::Bcast(&aT_Size, 1, rootId, localComm);
276 BL_ASSERT(aT_Size >= 0);
277 if(myLocalId != rootId) {
278 aT.resize(aT_Size);
279 }
280 if(aT_Size > 0) {
281 ParallelDescriptor::Bcast(aT.dataPtr(), aT.size(), rootId, localComm);
282 }
283}
284
285
286//
287// I'm going to document right here all the BL macros that aren't documented
288// anywhere else. Note that all these #ifdef ... #endif blocks are necessary
289// to get doc++ to properly document the macros.
290//
291
292#ifdef BL_LANG_FORT
293#undef BL_LANG_FORT
294/*
295 The macro BL_LANG_FORT indicates that Fortran code is being compiled.
296*/
297#define BL_LANG_FORT 1
298#endif /*BL_LANG_FORT*/
299
300#ifdef BL_FORT_USE_UNDERSCORE
301#undef BL_FORT_USE_UNDERSCORE
302/*
303 The macro BL_FORT_USE_UNDERSCORE indicates that C++ code should call
304 Fortran routines by appending an underscore to the name of the Fortran
305 routine. This is set automatically by the make subsystem.
306
307 For example, if the Fortran routine is named abcxyx, then it will
308 be called in C++ code as abcxyz_.
309*/
310#define BL_FORT_USE_UNDERSCORE 1
311#endif /*BL_FORT_USE_UNDERSCORE*/
312
313#ifdef BL_FORT_USE_UPPERCASE
314#undef BL_FORT_USE_UPPERCASE
315/*
316 The macro BL_FORT_USE_UPPERCASE indicates that C++ code should call
317 Fortran routines using uppercase letters for all the letters in the
318 routine. This is set automatically by the make subsystem.
319
320 For example, if the Fortran routine is named abcxyx, then it will
321 be called in C++ code as ABCXYZ.
322*/
323#define BL_FORT_USE_UPPERCASE 1
324#endif /*BL_FORT_USE_UPPERCASE*/
325
326#ifdef BL_FORT_USE_LOWERCASE
327#undef BL_FORT_USE_LOWERCASE
328/*
329 The macro BL_FORT_USE_LOWERCASE indicates that C++ code should call
330 Fortran routines using lowercase letters for all the letters in the
331 routine. This is set automatically by the make subsystem.
332
333 For example, if the Fortran routine is named abcxyx, then it will
334 be called in C++ code as abcxyx.
335*/
336#define BL_FORT_USE_LOWERCASE 1
337#endif /*BL_FORT_USE_LOWERCASE*/
338
339/*
340 BL_IGNORE_MAX is a macro that expands to the literal value 100000. It is
341 defined when compiling either Fortran or C++ code; i.e. when either
342 BL_LANG_CC or BL_LANG_FORT is defined. It is used in calls to
343 istream::ignore() in the AMReX code when reading in characters from an
344 istream. We use this macro instead of the more proper INT_MAX from
345 <limits> since at least one compiler didn't work properly when
346 istream::ignore() was passed INT_MAX.
347*/
348#define BL_IGNORE_MAX 100000
349
350template <typename T>
352amrex::bytesOf (const std::vector<T>& v)
353{
354 return sizeof(v) + v.capacity()*sizeof(T);
355}
356
357template <typename Key, typename T, class Compare>
359amrex::bytesOf (const std::map<Key,T,Compare>& m)
360{
361 return sizeof(m) + m.size()*(sizeof(Key)+sizeof(T)+gcc_map_node_extra_bytes);
362}
363
364extern "C" {
365 void* amrex_malloc (std::size_t size);
366 void amrex_free (void* p);
367}
368
369// hash combiner borrowed from Boost
370/*
371Boost Software License - Version 1.0 - August 17th, 2003
372
373Permission is hereby granted, free of charge, to any person or organization
374obtaining a copy of the software and accompanying documentation covered by
375this license (the "Software") to use, reproduce, display, distribute,
376execute, and transmit the Software, and to prepare derivative works of the
377Software, and to permit third-parties to whom the Software is furnished to
378do so, all subject to the following:
379
380The copyright notices in the Software and this entire statement, including
381the above license grant, this restriction and the following disclaimer,
382must be included in all copies of the Software, in whole or in part, and
383all derivative works of the Software, unless such copies or derivative
384works are solely in the form of machine-executable object code generated by
385a source language processor.
386
387THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
388IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
389FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
390SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
391FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
392ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
393DEALINGS IN THE SOFTWARE.
394*/
395template<typename T>
396void
397amrex::hash_combine (uint64_t & seed, const T & val) noexcept
398{
399 seed ^= std::hash<T>()(val) + 0x9e3779b9 + (seed<<6) + (seed>>2);
400}
401
402template<typename T>
403uint64_t
404amrex::hash_vector (const Vector<T> & vec, uint64_t seed) noexcept
405{
406 for (const auto & x: vec) {
407 hash_combine(seed, x);
408 }
409 return seed;
410}
411
413namespace amrex::detail {
414
415 // Determine if type has .begin() and .end() member functions
416 template <class T>
417 constexpr decltype((std::declval<T>().begin(), std::declval<T>().end(), true)) HasBeginEnd() {
418 return true;
419 }
420 template <class T, class... Args>
421 constexpr bool HasBeginEnd(Args...) {
422 return false;
423 }
424
425 // Determine if type has a specialization for std::tuple_size
426 template <class T>
427 constexpr decltype((std::tuple_size<T>::value, true)) HasTupleSize() { // NOLINT(modernize-type-traits)
428 return true;
429 }
430 template <class T, class... Args>
431 constexpr bool HasTupleSize(Args...) {
432 return false;
433 }
434
435 // Helper for tuple unpacking
436 template <class T, std::size_t... idx>
437 void ToStringTupleImp(std::index_sequence<idx...>, std::ostream& os, const T& t,
438 const char* symbol_begin, const char* symbol_delim,
439 const char* symbol_end, const char* symbol_str, int limit) {
440 os << symbol_begin;
441 Long count = 0;
442 auto op = [&](auto& value) {
443 if (count > 0 && (count <= limit || limit < 0)) {
444 os << symbol_delim;
445 }
446 if (count < limit || limit < 0) {
447 ToString(os, value, symbol_begin, symbol_delim, symbol_end,
448 symbol_str, limit);
449 } else if (count == limit) {
450 os << "...";
451 }
452 ++count;
453 };
454 (op(std::get<idx>(t)), ...);
455 os << symbol_end;
456 }
457}
459
460template <class T>
461std::ostream& amrex::ToString(std::ostream& os, const T& t, const char* symbol_begin,
462 const char* symbol_delim, const char* symbol_end,
463 const char* symbol_str, int limit)
464{
465 if constexpr (std::is_same_v<std::string, T> ||
466 std::is_same_v<std::string_view, T> ||
467 std::is_same_v<char*, std::decay_t<T>> ||
468 std::is_same_v<const char*, T>) {
469 // String-like types
470 os << symbol_str << t << symbol_str;
471 } else if constexpr (std::is_same_v<signed char, T> ||
472 std::is_same_v<unsigned char, T>) {
473 // Buffer-like types, don't print as char
474 os << static_cast<int>(t);
475 } else if constexpr (std::is_pointer_v<T>) {
476 // Pointer types, don't print char* as string
477 os << static_cast<const void*>(t);
478 } else if constexpr (detail::HasBeginEnd<T>() || std::is_array_v<T>) {
479 // Array-like types
480 os << symbol_begin;
481 Long count = 0;
482 for (auto& value : t) {
483 if (count > 0) {
484 os << symbol_delim;
485 }
486 if (count < limit || limit < 0) {
487 ToString(os, value, symbol_begin, symbol_delim, symbol_end,
488 symbol_str, limit);
489 } else if (count == limit) {
490 os << "...";
491 break;
492 }
493 ++count;
494 }
495 os << symbol_end;
496 } else if constexpr (detail::HasTupleSize<T>()) {
497 // Tuple-like types
498 detail::ToStringTupleImp(std::make_index_sequence<std::tuple_size_v<T>>{},
499 os, t, symbol_begin, symbol_delim, symbol_end,
500 symbol_str, limit);
501 } else {
502 // Scalar types
503 os << t;
504 }
505 return os;
506}
507
508template <class T>
509std::string amrex::ToString(const T& t, const char* symbol_begin, const char* symbol_delim,
510 const char* symbol_end, const char* symbol_str,
511 int limit, std::ostringstream ss)
512{
513 ToString(ss, t, symbol_begin, symbol_delim, symbol_end, symbol_str, limit);
514 return ss.str();
515}
516
517template <typename F, typename... T>
519auto amrex::callNoinline (F const& f, T&&... arg)
520 -> decltype(std::declval<F>()(std::declval<T>()...)) // needed for nvcc
521{
524 return f(std::forward<T>(arg)...);
525 }
526 ))
527 AMREX_IF_ON_DEVICE(( return f(std::forward<T>(arg)...); ))
528}
529
530#endif /*BL_UTILITY_H*/
Fixed-size array types for use on GPU and CPU.
Assertion macros used across AMReX for runtime consistency checks.
#define BL_ASSERT(EX)
Definition AMReX_BLassert.H:39
Container and helper utilities for sets of boxes on integer index space.
Integer-lattice boxes and helpers for defining index-space regions.
Helper for converting compiler-mangled type names to readable strings.
Maps FABs in a FabArray to MPI processes.
#define AMREX_NO_INLINE
Definition AMReX_Extension.H:141
#define AMREX_IF_ON_DEVICE(CODE)
Definition AMReX_GpuQualifiers.H:56
#define AMREX_IF_ON_HOST(CODE)
Definition AMReX_GpuQualifiers.H:58
#define AMREX_GPU_HOST_DEVICE
Definition AMReX_GpuQualifiers.H:20
void amrex_free(void *p)
Definition AMReX_Utility.cpp:933
void * amrex_malloc(std::size_t size)
Definition AMReX_Utility.cpp:927
Definition AMReX_Utility.H:169
bool TryFileOutput()
Definition AMReX_Utility.cpp:626
static void ClearStreamErrors()
Definition AMReX_Utility.H:176
bool TryOutput()
Definition AMReX_Utility.cpp:575
static int NStreamErrors()
Definition AMReX_Utility.H:175
This class is a thin wrapper around std::vector. Unlike vector, Vector::operator[] provides bound che...
Definition AMReX_Vector.H:29
T * dataPtr() noexcept
get access to the underlying data pointer
Definition AMReX_Vector.H:50
Long size() const noexcept
Definition AMReX_Vector.H:54
Definition AMReX_Utility.H:157
friend std::istream & operator>>(std::istream &, const expect &exp)
const std::string & the_string() const
Definition AMReX_Utility.cpp:547
amrex_long Long
Definition AMReX_INT.H:30
int MPI_Comm
Definition AMReX_ccse-mpi.H:51
Definition AMReX_Amr.cpp:50
std::ostream & ToString(std::ostream &os, const T &t, const char *symbol_begin="[", const char *symbol_delim=", ", const char *symbol_end="]", const char *symbol_str="\"", int limit=100)
Definition AMReX_Utility.H:461
void SyncStrings(const Vector< std::string > &localStrings, Vector< std::string > &syncedStrings, bool &alreadySynced)
Definition AMReX_Utility.cpp:674
double InvNormDistBest(double p)
This function returns an approximation of the inverse cumulative standard normal distribution functio...
Definition AMReX_Utility.cpp:387
void FileOpenFailed(const std::string &file)
Output a message and abort when couldn't open the file.
Definition AMReX_Utility.cpp:116
int CRRBetweenLevels(int fromlevel, int tolevel, const Vector< int > &refratios)
Definition AMReX_Utility.cpp:232
void BroadcastStringArray(Vector< std::string > &bSA, int myLocalId, int rootId, const MPI_Comm &localComm)
Definition AMReX_Utility.cpp:896
__host__ __device__ T arg(const GpuComplex< T > &a_z) noexcept
Return the angle of a complex number's polar representation.
Definition AMReX_GpuComplex.H:403
Vector< std::string > UnSerializeStringArray(const Vector< char > &charArray)
Definition AMReX_Utility.cpp:850
std::conditional_t< std::chrono::high_resolution_clock::is_steady, std::chrono::high_resolution_clock, std::chrono::steady_clock > MaxResSteadyClock
Definition AMReX_Utility.H:217
amrex::Long bytesOf(const std::vector< T > &v)
Definition AMReX_Utility.H:352
bool FileExists(const std::string &filename)
Check if a file already exists. Return true if the filename is an existing file, directory,...
Definition AMReX_Utility.cpp:124
bool is_it(std::string const &s, T &v)
Useful C++ Utility Functions.
Definition AMReX_Utility.H:257
const std::vector< std::string > & Tokenize(const std::string &instr, const std::string &separators)
Splits "instr" into separate pieces based on "separators".
Definition AMReX_Utility.cpp:40
double second() noexcept
Definition AMReX_Utility.cpp:919
uint64_t hash_vector(const Vector< T > &vec, uint64_t seed=0xDEADBEEFDEADBEEF) noexcept
Definition AMReX_Utility.H:404
void UtilCreateCleanDirectory(const std::string &path, bool callbarrier=true)
Create a new directory, renaming the old one if it exists.
Definition AMReX_Utility.cpp:146
void CreateDirectoryFailed(const std::string &dir)
Output a message and abort when couldn't create the directory.
Definition AMReX_Utility.cpp:108
void BroadcastArray(Vector< T > &aT, int myLocalId, int rootId, const MPI_Comm &localComm)
Definition AMReX_Utility.H:269
bool UtilCreateDirectory(const std::string &path, mode_t mode, bool verbose=false)
Creates the specified directories. path may be either a full pathname or a relative pathname....
Definition AMReX_Utility.cpp:95
__host__ __device__ auto callNoinline(F const &f, T &&... arg) -> decltype(std::declval< F >()(std::declval< T >()...))
Call given function without inline.
Definition AMReX_Utility.H:519
void BroadcastString(std::string &bStr, int myLocalId, int rootId, const MPI_Comm &localComm)
Definition AMReX_Utility.cpp:880
__host__ __device__ GpuComplex< T > exp(const GpuComplex< T > &a_z) noexcept
Complex expotential function.
Definition AMReX_GpuComplex.H:339
Vector< char > SerializeStringArray(const Vector< std::string > &stringArray)
Definition AMReX_Utility.cpp:836
std::istream & operator>>(std::istream &is, BoxND< dim > &bx)
Read a BoxND from is.
Definition AMReX_Box.H:1965
void hash_combine(uint64_t &seed, const T &val) noexcept
Definition AMReX_Utility.H:397
void Sleep(double sleepsec)
Definition AMReX_Utility.cpp:910
void UtilRenameDirectoryToOld(const std::string &path, bool callbarrier=true)
Rename a current directory if it exists.
Definition AMReX_Utility.cpp:201
double InvNormDist(double p)
This function returns an approximation of the inverse cumulative standard normal distribution functio...
Definition AMReX_Utility.cpp:266
void UtilCreateDirectoryDestructive(const std::string &path, bool callbarrier=true)
Create a new directory, removing old one if it exists.
Definition AMReX_Utility.cpp:175
std::string UniqueString()
Create a (probably) unique string.
Definition AMReX_Utility.cpp:130
void BroadcastBool(bool &bBool, int myLocalId, int rootId, const MPI_Comm &localComm)
Definition AMReX_Utility.cpp:865
void OutOfMemory()
Aborts after printing message indicating out-of-memory; i.e. operator new has failed....
Definition AMReX_Utility.cpp:226
Definition AMReX_TypeTraits.H:94