16 #ifndef dealii_utilities_h
17 #define dealii_utilities_h
23 #include <boost/archive/binary_iarchive.hpp>
24 #include <boost/archive/binary_oarchive.hpp>
25 #include <boost/core/demangle.hpp>
26 #include <boost/iostreams/device/array.hpp>
27 #include <boost/iostreams/device/back_inserter.hpp>
28 #include <boost/iostreams/filtering_streambuf.hpp>
29 #include <boost/serialization/array.hpp>
30 #include <boost/serialization/complex.hpp>
31 #include <boost/serialization/vector.hpp>
37 #include <type_traits>
42 #ifdef DEAL_II_WITH_ZLIB
43 # include <boost/iostreams/filter/gzip.hpp>
50 template <
int dim,
typename Number>
89 template <
int dim,
typename Number>
90 std::vector<std::array<std::uint64_t, dim>>
93 const int bits_per_dim = 64);
99 std::vector<std::array<std::uint64_t, dim>>
101 const std::vector<std::array<std::uint64_t, dim>> &points,
102 const int bits_per_dim = 64);
122 const int bits_per_dim);
153 decompress(
const std::string &compressed_input);
169 encode_base64(
const std::vector<unsigned char> &binary_input);
179 std::vector<unsigned char>
218 template <
typename number>
238 template <
typename Number>
261 dim_string(
const int dim,
const int spacedim);
328 std::vector<std::string>
336 std::vector<std::string>
349 std::vector<std::string>
351 const unsigned int width,
352 const char delimiter =
' ');
369 std::pair<int, unsigned int>
378 const std::string &from,
379 const std::string &to);
387 trim(
const std::string &input);
436 template <
int N,
typename T>
445 template <
typename T>
447 pow(
const T base,
const int iexp)
449 #if defined(DEBUG) && !defined(DEAL_II_CXX14_CONSTEXPR_BUG)
452 # if KOKKOS_VERSION >= 30600
457 abort_or_throw_on_exception,
462 "ExcMessage(\"The exponent must not be negative!\")",
463 ExcMessage(
"The exponent must not be negative!"));
466 # ifdef KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST
470 abort_or_throw_on_exception,
475 "ExcMessage(\"The exponent must not be negative!\")",
476 ExcMessage(
"The exponent must not be negative!"));
480 static_assert(std::is_integral_v<T>,
"Only integral types supported");
523 template <
typename Iterator,
typename T>
533 template <
typename Iterator,
typename T,
typename Comp>
542 template <
typename Integer>
551 template <
typename Integer>
609 template <
typename T>
611 pack(
const T &
object,
612 std::vector<char> &dest_buffer,
613 const bool allow_compression =
true);
623 template <
typename T>
625 pack(
const T &
object,
const bool allow_compression =
true);
658 template <
typename T>
660 unpack(
const std::vector<char> &buffer,
const bool allow_compression =
true);
670 template <
typename T>
672 unpack(
const std::vector<char>::const_iterator &cbegin,
673 const std::vector<char>::const_iterator &cend,
674 const bool allow_compression =
true);
708 template <
typename T,
int N>
710 unpack(
const std::vector<char> &buffer,
711 T (&unpacked_object)[
N],
712 const bool allow_compression =
true);
722 template <
typename T,
int N>
724 unpack(
const std::vector<char>::const_iterator &cbegin,
725 const std::vector<char>::const_iterator &cend,
726 T (&unpacked_object)[
N],
727 const bool allow_compression =
true);
733 get_bit(
const unsigned char number,
const unsigned int n);
740 set_bit(
unsigned char &number,
const unsigned int n,
const bool x);
800 template <
typename To,
typename From>
807 template <
typename T>
814 template <
typename T>
821 template <
typename T>
828 template <
typename T>
835 template <
typename T>
964 posix_memalign(
void **memptr, std::size_t alignment, std::size_t size);
973 template <
int N,
typename T>
977 Assert(((std::is_integral_v<T> ==
true) && (
N >= 0)) ||
978 (std::is_integral_v<T> ==
false),
979 ExcMessage(
"If the type of the argument, T, is an integer type, "
980 "then the exponent N must be a non-negative integer "
981 "because the result would otherwise not be an integer."));
992 fixed_power<N / 2>(x * x));
1001 return boost::core::demangle(
typeid(t).name());
1006 template <
typename Iterator,
typename T>
1015 template <
typename Iterator,
typename T,
typename Comp>
1024 "The given iterators do not satisfy the proper ordering."));
1026 unsigned int len =
static_cast<unsigned int>(last -
first);
1043 if (!comp(*
first, val))
1048 if (!comp(*
first, val))
1053 if (!comp(*
first, val))
1058 if (!comp(*
first, val))
1063 if (!comp(*
first, val))
1068 if (!comp(*
first, val))
1073 if (!comp(*
first, val))
1092 const unsigned int half = len >> 1;
1093 const Iterator middle =
first + half;
1100 if (comp(*middle, val))
1120 template <
typename T>
1128 template <
typename T>
1132 std::is_trivially_copyable_v<T> && !std::is_same_v<T, bool>;
1137 template <
typename T>
1141 std::is_trivially_copyable_v<T> && !std::is_same_v<T, bool>;
1154 template <
typename T>
1157 std::vector<char> &)
1165 template <
typename T,
1166 typename = std::enable_if_t<!std::is_same_v<T, bool> &&
1167 std::is_trivially_copyable_v<T>>>
1170 const std::vector<T> &
object,
1171 std::vector<char> &dest_buffer)
1177 dest_buffer.reserve(dest_buffer.size() +
sizeof(vector_size) +
1178 vector_size *
sizeof(
T));
1181 dest_buffer.insert(dest_buffer.end(),
1182 reinterpret_cast<const char *
>(&vector_size),
1183 reinterpret_cast<const char *
>(&vector_size + 1));
1186 if (vector_size > 0)
1187 dest_buffer.insert(dest_buffer.end(),
1188 reinterpret_cast<const char *
>(
object.data()),
1189 reinterpret_cast<const char *
>(
object.data() +
1195 template <
typename T,
1196 typename = std::enable_if_t<!std::is_same_v<T, bool> &&
1197 std::is_trivially_copyable_v<T>>>
1200 const std::vector<std::vector<T>> &
object,
1201 std::vector<char> &dest_buffer)
1204 const size_type vector_size =
object.size();
1207 std::vector<size_type> sizes;
1208 sizes.reserve(vector_size);
1209 for (
const auto &a :
object)
1211 aggregated_size += a.size();
1212 sizes.push_back(a.size());
1217 dest_buffer.reserve(dest_buffer.size() +
1218 sizeof(vector_size) * (1 + vector_size) +
1219 aggregated_size *
sizeof(
T));
1222 dest_buffer.insert(dest_buffer.end(),
1223 reinterpret_cast<const char *
>(&vector_size),
1224 reinterpret_cast<const char *
>(&vector_size + 1));
1227 if (vector_size > 0)
1228 dest_buffer.insert(dest_buffer.end(),
1229 reinterpret_cast<const char *
>(sizes.data()),
1230 reinterpret_cast<const char *
>(sizes.data() +
1234 for (
const auto &a :
object)
1235 dest_buffer.insert(dest_buffer.end(),
1236 reinterpret_cast<const char *
>(a.data()),
1237 reinterpret_cast<const char *
>(a.data() + a.size()));
1242 template <
typename T>
1245 const std::vector<char>::const_iterator &,
1246 const std::vector<char>::const_iterator &,
1255 template <
typename T,
1256 typename = std::enable_if_t<!std::is_same_v<T, bool> &&
1257 std::is_trivially_copyable_v<T>>>
1260 const std::vector<char>::const_iterator &cbegin,
1261 const std::vector<char>::const_iterator &cend,
1262 std::vector<T> &
object)
1269 memcpy(&vector_size, &*cbegin,
sizeof(vector_size));
1271 Assert(
static_cast<std::ptrdiff_t
>(cend - cbegin) ==
1272 static_cast<std::ptrdiff_t
>(
sizeof(vector_size) +
1273 vector_size *
sizeof(
T)),
1274 ExcMessage(
"The given buffer has the wrong size."));
1279 if (vector_size > 0)
1281 const T *
const buffer_data_begin =
1282 reinterpret_cast<const T *
>(&*cbegin +
sizeof(vector_size));
1283 const T *
const buffer_data_end = buffer_data_begin + vector_size;
1284 object.insert(
object.
end(), buffer_data_begin, buffer_data_end);
1290 template <
typename T,
1291 typename = std::enable_if_t<!std::is_same_v<T, bool> &&
1292 std::is_trivially_copyable_v<T>>>
1295 const std::vector<char>::const_iterator &cbegin,
1296 const std::vector<char>::const_iterator &cend,
1297 std::vector<std::vector<T>> &
object)
1301 std::vector<char>::const_iterator iterator = cbegin;
1303 memcpy(&vector_size, &*iterator,
sizeof(vector_size));
1305 object.resize(vector_size);
1306 std::vector<size_type> sizes(vector_size);
1307 if (vector_size > 0)
1308 memcpy(sizes.data(),
1309 &*iterator +
sizeof(vector_size),
1312 iterator +=
sizeof(vector_size) * (1 + vector_size);
1314 for (
const auto a : sizes)
1315 aggregated_size += a;
1317 Assert(
static_cast<std::ptrdiff_t
>(cend - iterator) ==
1318 static_cast<std::ptrdiff_t
>(aggregated_size *
sizeof(
T)),
1319 ExcMessage(
"The given buffer has the wrong size."));
1323 for (
unsigned int i = 0; i < vector_size; ++i)
1326 object[i].insert(
object[i].
end(),
1327 reinterpret_cast<const T *
>(&*iterator),
1328 reinterpret_cast<const T *
>(&*iterator +
1329 sizeof(
T) * sizes[i]));
1330 iterator +=
sizeof(
T) * sizes[i];
1334 ExcMessage(
"The given buffer has the wrong size."));
1341 template <
typename T>
1344 std::vector<char> &dest_buffer,
1345 const bool allow_compression)
1347 std::size_t size = 0;
1353 if constexpr (std::is_trivially_copyable<T>() &&
sizeof(
T) < 256)
1361 size = (std::is_same_v<T, std::tuple<>> ? 0 :
sizeof(
T));
1363 (void)allow_compression;
1364 const std::size_t previous_size = dest_buffer.size();
1365 dest_buffer.resize(previous_size + size);
1368 std::memcpy(dest_buffer.data() + previous_size, &
object, size);
1376 (allow_compression ==
false))
1378 const std::size_t previous_size = dest_buffer.size();
1387 size = dest_buffer.size() - previous_size;
1393 const std::size_t previous_size = dest_buffer.size();
1395 boost::iostreams::filtering_ostreambuf fosb;
1396 #ifdef DEAL_II_WITH_ZLIB
1397 if (allow_compression)
1398 fosb.push(boost::iostreams::gzip_compressor());
1400 (void)allow_compression;
1402 fosb.push(boost::iostreams::back_inserter(dest_buffer));
1404 boost::archive::binary_oarchive boa(fosb);
1409 size = dest_buffer.size() - previous_size;
1416 template <
typename T>
1418 pack(
const T &
object,
const bool allow_compression)
1420 std::vector<char> buffer;
1421 pack<T>(
object, buffer, allow_compression);
1427 template <
typename T>
1429 unpack(
const std::vector<char>::const_iterator &cbegin,
1430 const std::vector<char>::const_iterator &cend,
1431 const bool allow_compression)
1436 if constexpr (std::is_trivially_copyable<T>() &&
sizeof(
T) < 256)
1444 const std::size_t size =
1445 (std::is_same_v<T, std::tuple<>> ? 0 :
sizeof(
T));
1449 (void)allow_compression;
1453 std::memcpy(&
object, &*cbegin, size);
1463 (allow_compression ==
false))
1478 boost::iostreams::filtering_istreambuf fisb;
1479 #ifdef DEAL_II_WITH_ZLIB
1480 if (allow_compression)
1481 fisb.push(boost::iostreams::gzip_decompressor());
1483 (void)allow_compression;
1485 fisb.push(boost::iostreams::array_source(&*cbegin, cend - cbegin));
1487 boost::archive::binary_iarchive bia(fisb);
1498 template <
typename T>
1500 unpack(
const std::vector<char> &buffer,
const bool allow_compression)
1502 return unpack<T>(buffer.cbegin(), buffer.cend(), allow_compression);
1506 template <
typename T,
int N>
1508 unpack(
const std::vector<char>::const_iterator &cbegin,
1509 const std::vector<char>::const_iterator &cend,
1510 T (&unpacked_object)[
N],
1511 const bool allow_compression)
1516 if constexpr (std::is_trivially_copyable<T>() &&
sizeof(
T) *
N < 256)
1518 Assert(std::distance(cbegin, cend) ==
sizeof(
T) *
N,
1520 std::memcpy(unpacked_object, &*cbegin,
sizeof(
T) *
N);
1525 boost::iostreams::filtering_istreambuf fisb;
1526 #ifdef DEAL_II_WITH_ZLIB
1527 if (allow_compression)
1528 fisb.push(boost::iostreams::gzip_decompressor());
1530 (void)allow_compression;
1532 fisb.push(boost::iostreams::array_source(&*cbegin, cend - cbegin));
1534 boost::archive::binary_iarchive bia(fisb);
1535 bia >> unpacked_object;
1540 template <
typename T,
int N>
1543 T (&unpacked_object)[
N],
1544 const bool allow_compression)
1546 unpack<T, N>(buffer.cbegin(),
1555 get_bit(
const unsigned char number,
const unsigned int n)
1562 return ((number >> n) & 1U) != 0u;
1568 set_bit(
unsigned char &number,
const unsigned int n,
const bool x)
1575 number ^= (-
static_cast<unsigned char>(x) ^ number) & (1U << n);
1580 template <
typename To,
typename From>
1581 inline std::unique_ptr<To>
1587 if (To *cast =
dynamic_cast<To *
>(p.get()))
1589 std::unique_ptr<To> result(cast);
1594 throw std::bad_cast();
1599 template <
typename T>
1608 template <
typename T>
1617 template <
typename T>
1626 template <
typename T>
1635 template <
typename T>
1644 template <
typename Integer>
1645 std::vector<Integer>
1648 const std::size_t n = permutation.size();
1650 std::vector<Integer> out(n);
1651 for (std::size_t i = 0; i < n; ++i)
1652 out[i] = n - 1 - permutation[i];
1659 template <
typename Integer>
1660 std::vector<Integer>
1663 const std::size_t n = permutation.size();
1667 for (std::size_t i = 0; i < n; ++i)
1670 out[permutation[i]] = i;
1675 for (std::size_t i = 0; i < n; ++i)
1677 ExcMessage(
"The given input permutation had duplicate entries!"));
1689 namespace serialization
1696 template <
class Archive,
typename... Args>
1698 serialize(Archive &ar, std::tuple<Args...> &t,
const unsigned int version)
1700 ar &std::get<
N - 1>(t);
1701 Serialize<N - 1>::serialize(ar, t, version);
1708 template <
class Archive,
typename... Args>
1710 serialize(Archive &ar, std::tuple<Args...> &t,
const unsigned int version)
1718 template <
class Archive,
typename... Args>
1720 serialize(Archive &ar, std::tuple<Args...> &t,
const unsigned int version)
1722 Serialize<
sizeof...(Args)>::serialize(ar, t, version);
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_CXX20_REQUIRES(condition)
#define DEAL_II_NAMESPACE_CLOSE
#define DEAL_II_FALLTHROUGH
static ::ExceptionBase & ExcInternalError()
#define Assert(cond, exc)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcMessage(std::string arg1)
types::global_dof_index size_type
VectorType::value_type * end(VectorType &V)
void get_memory_stats(MemoryStats &stats)
std::string get_hostname()
void posix_memalign(void **memptr, std::size_t alignment, std::size_t size)
std::string get_current_vectorization_level()
void create_vector_of_trivially_copyable_from_buffer(const std::vector< char >::const_iterator &, const std::vector< char >::const_iterator &, T &)
void append_vector_of_trivially_copyable_to_buffer(const T &, std::vector< char > &)
constexpr T pow(const T base, const int iexp)
std::vector< std::string > split_string_list(const std::string &s, const std::string &delimiter=",")
T & get_underlying_value(T &p)
Number truncate_to_n_digits(const Number number, const unsigned int n_digits)
std::string type_to_string(const T &t)
size_t pack(const T &object, std::vector< char > &dest_buffer, const bool allow_compression=true)
std::string dim_string(const int dim, const int spacedim)
std::uint64_t pack_integers(const std::array< std::uint64_t, dim > &index, const int bits_per_dim)
bool get_bit(const unsigned char number, const unsigned int n)
std::pair< int, unsigned int > get_integer_at_position(const std::string &name, const unsigned int position)
std::string encode_base64(const std::vector< unsigned char > &binary_input)
std::vector< std::array< std::uint64_t, dim > > inverse_Hilbert_space_filling_curve(const std::vector< Point< dim, Number >> &points, const int bits_per_dim=64)
std::unique_ptr< To > dynamic_unique_cast(std::unique_ptr< From > &&p)
std::string replace_in_string(const std::string &input, const std::string &from, const std::string &to)
std::vector< unsigned char > decode_base64(const std::string &base64_input)
std::vector< std::string > break_text_into_lines(const std::string &original_text, const unsigned int width, const char delimiter=' ')
std::string to_string(const number value, const unsigned int digits=numbers::invalid_unsigned_int)
std::string compress(const std::string &input)
std::string int_to_string(const unsigned int value, const unsigned int digits=numbers::invalid_unsigned_int)
bool match_at_string_start(const std::string &name, const std::string &pattern)
T unpack(const std::vector< char > &buffer, const bool allow_compression=true)
std::string decompress(const std::string &compressed_input)
unsigned int needed_digits(const unsigned int max_number)
Iterator lower_bound(Iterator first, Iterator last, const T &val)
double string_to_double(const std::string &s)
std::string dealii_version_string()
void set_bit(unsigned char &number, const unsigned int n, const bool x)
std::string trim(const std::string &input)
double generate_normal_random_number(const double a, const double sigma)
std::vector< Integer > reverse_permutation(const std::vector< Integer > &permutation)
std::vector< Integer > invert_permutation(const std::vector< Integer > &permutation)
int string_to_int(const std::string &s)
void issue_error_noreturn(ExceptionHandling handling, const char *file, int line, const char *function, const char *cond, const char *exc_name, ExceptionType e)
static const unsigned int invalid_unsigned_int
#define DEAL_II_HOST_DEVICE
static constexpr bool value