Reference documentation for deal.II version GIT b206511199 2023-01-31 13:40:02+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
utilities.h
Go to the documentation of this file.
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2005 - 2022 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15 
16 #ifndef dealii_utilities_h
17 #define dealii_utilities_h
18 
19 #include <deal.II/base/config.h>
20 
22 
23 #include <cstddef>
24 #include <functional>
25 #include <string>
26 #include <tuple>
27 #include <type_traits>
28 #include <typeinfo>
29 #include <utility>
30 #include <vector>
31 
33 
34 #include <boost/archive/binary_iarchive.hpp>
35 #include <boost/archive/binary_oarchive.hpp>
36 #include <boost/core/demangle.hpp>
37 #include <boost/iostreams/device/array.hpp>
38 #include <boost/iostreams/device/back_inserter.hpp>
39 #include <boost/iostreams/filtering_streambuf.hpp>
40 #include <boost/serialization/array.hpp>
41 #include <boost/serialization/complex.hpp>
42 #include <boost/serialization/vector.hpp>
43 
44 #ifdef DEAL_II_WITH_ZLIB
45 # include <boost/iostreams/filter/gzip.hpp>
46 #endif
47 
49 
51 
52 // forward declare Point
53 #ifndef DOXYGEN
54 template <int dim, typename Number>
55 class Point;
56 #endif
57 
65 namespace Utilities
66 {
73  std::string
75 
92  template <int dim, typename Number>
93  std::vector<std::array<std::uint64_t, dim>>
95  const std::vector<Point<dim, Number>> &points,
96  const int bits_per_dim = 64);
97 
101  template <int dim>
102  std::vector<std::array<std::uint64_t, dim>>
104  const std::vector<std::array<std::uint64_t, dim>> &points,
105  const int bits_per_dim = 64);
106 
122  template <int dim>
123  std::uint64_t
124  pack_integers(const std::array<std::uint64_t, dim> &index,
125  const int bits_per_dim);
126 
139  std::string
140  compress(const std::string &input);
141 
155  std::string
156  decompress(const std::string &compressed_input);
157 
171  std::string
172  encode_base64(const std::vector<unsigned char> &binary_input);
173 
182  std::vector<unsigned char>
183  decode_base64(const std::string &base64_input);
184 
206  std::string
207  int_to_string(const unsigned int value,
208  const unsigned int digits = numbers::invalid_unsigned_int);
209 
221  template <typename number>
222  std::string
223  to_string(const number value,
224  const unsigned int digits = numbers::invalid_unsigned_int);
225 
230  unsigned int
231  needed_digits(const unsigned int max_number);
232 
241  template <typename Number>
242  Number
243  truncate_to_n_digits(const Number number, const unsigned int n_digits);
244 
249  int
250  string_to_int(const std::string &s);
251 
263  std::string
264  dim_string(const int dim, const int spacedim);
265 
270  std::vector<int>
271  string_to_int(const std::vector<std::string> &s);
272 
277  double
278  string_to_double(const std::string &s);
279 
280 
285  std::vector<double>
286  string_to_double(const std::vector<std::string> &s);
287 
288 
331  std::vector<std::string>
332  split_string_list(const std::string &s, const std::string &delimiter = ",");
333 
334 
339  std::vector<std::string>
340  split_string_list(const std::string &s, const char delimiter);
341 
342 
352  std::vector<std::string>
353  break_text_into_lines(const std::string &original_text,
354  const unsigned int width,
355  const char delimiter = ' ');
356 
361  bool
362  match_at_string_start(const std::string &name, const std::string &pattern);
363 
372  std::pair<int, unsigned int>
373  get_integer_at_position(const std::string &name, const unsigned int position);
374 
379  std::string
380  replace_in_string(const std::string &input,
381  const std::string &from,
382  const std::string &to);
383 
389  std::string
390  trim(const std::string &input);
391 
417  double
418  generate_normal_random_number(const double a, const double sigma);
419 
427  template <class T>
428  std::string
429  type_to_string(const T &t);
430 
439  template <int N, typename T>
440  T
441  fixed_power(const T t);
442 
448  template <typename T>
449  constexpr T
450  pow(const T base, const int iexp)
451  {
452 #if defined(DEBUG) && !defined(DEAL_II_CXX14_CONSTEXPR_BUG)
453  // Up to __builtin_expect this is the same code as in the 'Assert' macro.
454  // The call to __builtin_expect turns out to be problematic.
455  if (!(iexp >= 0))
458  abort_or_throw_on_exception,
459  __FILE__,
460  __LINE__,
461  __PRETTY_FUNCTION__,
462  "iexp>=0",
463  "ExcMessage(\"The exponent must not be negative!\")",
464  ExcMessage("The exponent must not be negative!"));
465 #endif
466  // The "exponentiation by squaring" algorithm used below has to be
467  // compressed to one statement due to C++11's restrictions on constexpr
468  // functions. A more descriptive version would be:
469  //
470  // <code>
471  // if (iexp <= 0)
472  // return 1;
473  //
474  // // avoid overflow of one additional recursion with pow(base * base, 0)
475  // if (iexp == 1)
476  // return base;
477  //
478  // // if the current exponent is not divisible by two,
479  // // we need to account for that.
480  // const unsigned int prefactor = (iexp % 2 == 1) ? base : 1;
481  //
482  // // a^b = (a*a)^(b/2) for b even
483  // // a^b = a*(a*a)^((b-1)/2 for b odd
484  // return prefactor * ::Utilities::pow(base*base, iexp/2);
485  // </code>
486 
487  static_assert(std::is_integral<T>::value, "Only integral types supported");
488 
489  return iexp <= 0 ?
490  1 :
491  (iexp == 1 ? base :
492  (((iexp % 2 == 1) ? base : 1) *
493  ::Utilities::pow(base * base, iexp / 2)));
494  }
495 
517  template <typename Iterator, typename T>
518  Iterator
519  lower_bound(Iterator first, Iterator last, const T &val);
520 
521 
527  template <typename Iterator, typename T, typename Comp>
528  Iterator
529  lower_bound(Iterator first, Iterator last, const T &val, const Comp comp);
530 
536  template <typename Integer>
537  std::vector<Integer>
538  reverse_permutation(const std::vector<Integer> &permutation);
539 
545  template <typename Integer>
546  std::vector<Integer>
547  invert_permutation(const std::vector<Integer> &permutation);
548 
603  template <typename T>
604  size_t
605  pack(const T & object,
606  std::vector<char> &dest_buffer,
607  const bool allow_compression = true);
608 
617  template <typename T>
618  std::vector<char>
619  pack(const T &object, const bool allow_compression = true);
620 
652  template <typename T>
653  T
654  unpack(const std::vector<char> &buffer, const bool allow_compression = true);
655 
664  template <typename T>
665  T
666  unpack(const std::vector<char>::const_iterator &cbegin,
667  const std::vector<char>::const_iterator &cend,
668  const bool allow_compression = true);
669 
702  template <typename T, int N>
703  void
704  unpack(const std::vector<char> &buffer,
705  T (&unpacked_object)[N],
706  const bool allow_compression = true);
707 
716  template <typename T, int N>
717  void
718  unpack(const std::vector<char>::const_iterator &cbegin,
719  const std::vector<char>::const_iterator &cend,
720  T (&unpacked_object)[N],
721  const bool allow_compression = true);
722 
726  bool
727  get_bit(const unsigned char number, const unsigned int n);
728 
729 
733  void
734  set_bit(unsigned char &number, const unsigned int n, const bool x);
735 
736 
794  template <typename To, typename From>
795  std::unique_ptr<To>
796  dynamic_unique_cast(std::unique_ptr<From> &&p);
797 
801  template <typename T>
802  T &
804 
808  template <typename T>
809  T &
810  get_underlying_value(std::shared_ptr<T> &p);
811 
815  template <typename T>
816  T &
817  get_underlying_value(const std::shared_ptr<T> &p);
818 
822  template <typename T>
823  T &
824  get_underlying_value(std::unique_ptr<T> &p);
825 
829  template <typename T>
830  T &
831  get_underlying_value(const std::unique_ptr<T> &p);
832 
838  namespace System
839  {
847  double
848  get_cpu_load();
849 
883  const std::string
885 
890  struct MemoryStats
891  {
895  unsigned long int VmPeak;
896 
900  unsigned long int VmSize;
901 
905  unsigned long int VmHWM;
906 
911  unsigned long int VmRSS;
912  };
913 
914 
919  void
921 
922 
926  std::string
927  get_hostname();
928 
929 
933  std::string
934  get_time();
935 
940  std::string
941  get_date();
942 
957  void
958  posix_memalign(void **memptr, std::size_t alignment, std::size_t size);
959  } // namespace System
960 } // namespace Utilities
961 
962 
963 // --------------------- inline functions
964 
965 namespace Utilities
966 {
967  template <int N, typename T>
968  inline T
969  fixed_power(const T x)
970  {
971  Assert(
972  !std::is_integral<T>::value || (N >= 0),
973  ExcMessage(
974  "The non-type template parameter N must be a non-negative integer for integral type T"));
975 
976  if (N == 0)
977  return T(1.);
978  else if (N < 0)
979  return T(1.) / fixed_power<-N>(x);
980  else
981  // Use exponentiation by squaring:
982  return ((N % 2 == 1) ? x * fixed_power<N / 2>(x * x) :
983  fixed_power<N / 2>(x * x));
984  }
985 
986 
987 
988  template <class T>
989  inline std::string
990  type_to_string(const T &t)
991  {
992  return boost::core::demangle(typeid(t).name());
993  }
994 
995 
996 
997  template <typename Iterator, typename T>
998  inline Iterator
999  lower_bound(Iterator first, Iterator last, const T &val)
1000  {
1001  return Utilities::lower_bound(first, last, val, std::less<T>());
1002  }
1003 
1004 
1005 
1006  template <typename Iterator, typename T, typename Comp>
1007  inline Iterator
1008  lower_bound(Iterator first, Iterator last, const T &val, const Comp comp)
1009  {
1010  // verify that the two iterators are properly ordered. since
1011  // we need operator- for the iterator type anyway, do the
1012  // test as follows, rather than via 'last >= first'
1013  Assert(last - first >= 0,
1014  ExcMessage(
1015  "The given iterators do not satisfy the proper ordering."));
1016 
1017  unsigned int len = static_cast<unsigned int>(last - first);
1018 
1019  if (len == 0)
1020  return first;
1021 
1022  while (true)
1023  {
1024  // if length equals 8 or less,
1025  // then do a rolled out
1026  // search. use a switch without
1027  // breaks for that and roll-out
1028  // the loop somehow
1029  if (len < 8)
1030  {
1031  switch (len)
1032  {
1033  case 7:
1034  if (!comp(*first, val))
1035  return first;
1036  ++first;
1038  case 6:
1039  if (!comp(*first, val))
1040  return first;
1041  ++first;
1043  case 5:
1044  if (!comp(*first, val))
1045  return first;
1046  ++first;
1048  case 4:
1049  if (!comp(*first, val))
1050  return first;
1051  ++first;
1053  case 3:
1054  if (!comp(*first, val))
1055  return first;
1056  ++first;
1058  case 2:
1059  if (!comp(*first, val))
1060  return first;
1061  ++first;
1063  case 1:
1064  if (!comp(*first, val))
1065  return first;
1066  return first + 1;
1067  default:
1068  // indices seem
1069  // to not be
1070  // sorted
1071  // correctly!? or
1072  // did len
1073  // become==0
1074  // somehow? that
1075  // shouldn't have
1076  // happened
1077  Assert(false, ExcInternalError());
1078  }
1079  }
1080 
1081 
1082 
1083  const unsigned int half = len >> 1;
1084  const Iterator middle = first + half;
1085 
1086  // if the value is larger than
1087  // that pointed to by the
1088  // middle pointer, then the
1089  // insertion point must be
1090  // right of it
1091  if (comp(*middle, val))
1092  {
1093  first = middle + 1;
1094  len -= half + 1;
1095  }
1096  else
1097  len = half;
1098  }
1099  }
1100 
1101 
1102  // --------------------- non-inline functions
1103 
1104  namespace internal
1105  {
1111  template <typename T>
1113  {
1114  static constexpr bool value = false;
1115  };
1116 
1117 
1118 
1119  template <typename T>
1120  struct IsVectorOfTriviallyCopyable<std::vector<T>>
1121  {
1122  static constexpr bool value =
1123  std::is_trivially_copyable<T>::value && !std::is_same<T, bool>::value;
1124  };
1125 
1126 
1127 
1128  template <typename T>
1129  struct IsVectorOfTriviallyCopyable<std::vector<std::vector<T>>>
1130  {
1131  static constexpr bool value =
1132  std::is_trivially_copyable<T>::value && !std::is_same<T, bool>::value;
1133  };
1134 
1135 
1136 
1145  template <typename T>
1146  inline void
1148  std::vector<char> &)
1149  {
1150  // We shouldn't get here:
1151  Assert(false, ExcInternalError());
1152  }
1153 
1154 
1155 
1156  template <typename T,
1157  typename = std::enable_if_t<!std::is_same<T, bool>::value &&
1158  std::is_trivially_copyable<T>::value>>
1159  inline void
1161  const std::vector<T> &object,
1162  std::vector<char> & dest_buffer)
1163  {
1164  const typename std::vector<T>::size_type vector_size = object.size();
1165 
1166  // Reserve for the buffer so that it can store the size of 'object' as
1167  // well as all of its elements.
1168  dest_buffer.reserve(dest_buffer.size() + sizeof(vector_size) +
1169  vector_size * sizeof(T));
1170 
1171  // Copy the size into the vector
1172  dest_buffer.insert(dest_buffer.end(),
1173  reinterpret_cast<const char *>(&vector_size),
1174  reinterpret_cast<const char *>(&vector_size + 1));
1175 
1176  // Insert the elements at the end of the vector:
1177  if (vector_size > 0)
1178  dest_buffer.insert(dest_buffer.end(),
1179  reinterpret_cast<const char *>(object.data()),
1180  reinterpret_cast<const char *>(object.data() +
1181  vector_size));
1182  }
1183 
1184 
1185 
1186  template <typename T,
1187  typename = std::enable_if_t<!std::is_same<T, bool>::value &&
1188  std::is_trivially_copyable<T>::value>>
1189  inline void
1191  const std::vector<std::vector<T>> &object,
1192  std::vector<char> & dest_buffer)
1193  {
1194  using size_type = typename std::vector<T>::size_type;
1195  const size_type vector_size = object.size();
1196 
1197  typename std::vector<T>::size_type aggregated_size = 0;
1198  std::vector<size_type> sizes;
1199  sizes.reserve(vector_size);
1200  for (const auto &a : object)
1201  {
1202  aggregated_size += a.size();
1203  sizes.push_back(a.size());
1204  }
1205 
1206  // Reserve for the buffer so that it can store the size of 'object' as
1207  // well as all of its elements.
1208  dest_buffer.reserve(dest_buffer.size() +
1209  sizeof(vector_size) * (1 + vector_size) +
1210  aggregated_size * sizeof(T));
1211 
1212  // Copy the size into the vector
1213  dest_buffer.insert(dest_buffer.end(),
1214  reinterpret_cast<const char *>(&vector_size),
1215  reinterpret_cast<const char *>(&vector_size + 1));
1216 
1217  // Copy the sizes of the individual chunks into the vector
1218  if (vector_size > 0)
1219  dest_buffer.insert(dest_buffer.end(),
1220  reinterpret_cast<const char *>(sizes.data()),
1221  reinterpret_cast<const char *>(sizes.data() +
1222  vector_size));
1223 
1224  // Insert the elements at the end of the vector:
1225  for (const auto &a : object)
1226  dest_buffer.insert(dest_buffer.end(),
1227  reinterpret_cast<const char *>(a.data()),
1228  reinterpret_cast<const char *>(a.data() + a.size()));
1229  }
1230 
1231 
1232 
1233  template <typename T>
1234  inline void
1236  const std::vector<char>::const_iterator &,
1237  const std::vector<char>::const_iterator &,
1238  T &)
1239  {
1240  // We shouldn't get here:
1241  Assert(false, ExcInternalError());
1242  }
1243 
1244 
1245 
1246  template <typename T,
1247  typename = std::enable_if_t<!std::is_same<T, bool>::value &&
1248  std::is_trivially_copyable<T>::value>>
1249  inline void
1251  const std::vector<char>::const_iterator &cbegin,
1252  const std::vector<char>::const_iterator &cend,
1253  std::vector<T> & object)
1254  {
1255  // The size of the object vector can be found in cbegin of the buffer.
1256  // The data starts at cbegin + sizeof(vector_size).
1257 
1258  // Get the size of the vector
1259  typename std::vector<T>::size_type vector_size;
1260  memcpy(&vector_size, &*cbegin, sizeof(vector_size));
1261 
1262  Assert(static_cast<std::ptrdiff_t>(cend - cbegin) ==
1263  static_cast<std::ptrdiff_t>(sizeof(vector_size) +
1264  vector_size * sizeof(T)),
1265  ExcMessage("The given buffer has the wrong size."));
1266  (void)cend;
1267 
1268  // Copy the elements:
1269  object.clear();
1270  if (vector_size > 0)
1271  {
1272  const auto buffer_data_begin =
1273  reinterpret_cast<const T *>(&*cbegin + sizeof(vector_size));
1274  const auto buffer_data_end = buffer_data_begin + vector_size;
1275  object.insert(object.end(), buffer_data_begin, buffer_data_end);
1276  }
1277  }
1278 
1279 
1280 
1281  template <typename T,
1282  typename = std::enable_if_t<!std::is_same<T, bool>::value &&
1283  std::is_trivially_copyable<T>::value>>
1284  inline void
1286  const std::vector<char>::const_iterator &cbegin,
1287  const std::vector<char>::const_iterator &cend,
1288  std::vector<std::vector<T>> & object)
1289  {
1290  // First get the size of the vector, and resize the output object
1291  using size_type = typename std::vector<T>::size_type;
1292  std::vector<char>::const_iterator iterator = cbegin;
1293  size_type vector_size;
1294  memcpy(&vector_size, &*iterator, sizeof(vector_size));
1295  object.clear();
1296  object.resize(vector_size);
1297  std::vector<size_type> sizes(vector_size);
1298  if (vector_size > 0)
1299  memcpy(sizes.data(),
1300  &*iterator + sizeof(vector_size),
1301  vector_size * sizeof(size_type));
1302 
1303  iterator += sizeof(vector_size) * (1 + vector_size);
1304  size_type aggregated_size = 0;
1305  for (const auto a : sizes)
1306  aggregated_size += a;
1307 
1308  Assert(static_cast<std::ptrdiff_t>(cend - iterator) ==
1309  static_cast<std::ptrdiff_t>(aggregated_size * sizeof(T)),
1310  ExcMessage("The given buffer has the wrong size."));
1311  (void)cend;
1312 
1313  // Then copy the elements:
1314  for (unsigned int i = 0; i < vector_size; ++i)
1315  if (sizes[i] > 0)
1316  {
1317  object[i].insert(object[i].end(),
1318  reinterpret_cast<const T *>(&*iterator),
1319  reinterpret_cast<const T *>(&*iterator +
1320  sizeof(T) * sizes[i]));
1321  iterator += sizeof(T) * sizes[i];
1322  }
1323 
1324  Assert(iterator == cend,
1325  ExcMessage("The given buffer has the wrong size."));
1326  }
1327 
1328  } // namespace internal
1329 
1330 
1331 
1332  template <typename T>
1333  size_t
1334  pack(const T & object,
1335  std::vector<char> &dest_buffer,
1336  const bool allow_compression)
1337  {
1338  std::size_t size = 0;
1339 
1340 
1341  // see if the object is small and copyable via memcpy. if so, use
1342  // this fast path. otherwise, we have to go through the BOOST
1343  // serialization machinery
1344  if DEAL_II_CONSTEXPR_IN_CONDITIONAL (std::is_trivially_copyable<T>() &&
1345  sizeof(T) < 256)
1346  {
1347  // Determine the size. There are places where we would like to use a
1348  // truly empty type, for which we use std::tuple<> (i.e., a tuple
1349  // of zero elements). For this class, the compiler reports a nonzero
1350  // sizeof(...) because that is the minimum possible for objects --
1351  // objects need to have distinct addresses, so they need to have a size
1352  // of at least one. But we can special case this situation.
1353  size = (std::is_same<T, std::tuple<>>::value ? 0 : sizeof(T));
1354 
1355  (void)allow_compression;
1356  const std::size_t previous_size = dest_buffer.size();
1357  dest_buffer.resize(previous_size + size);
1358 
1359  if (size > 0)
1360  std::memcpy(dest_buffer.data() + previous_size, &object, size);
1361  }
1362  // Next try if we have a vector of trivially copyable objects.
1363  // If that is the case, we can shortcut the whole BOOST serialization
1364  // machinery and just copy the content of the vector bit for bit
1365  // into the output buffer, assuming that we are not asked to compress
1366  // the data.
1368  (allow_compression == false))
1369  {
1370  const std::size_t previous_size = dest_buffer.size();
1371 
1372  // When we have DEAL_II_HAVE_CXX17 set by default, we can just
1373  // inline the code of the following function here and make the 'if'
1374  // above a 'if constexpr'. Without the 'constexpr', we need to keep
1375  // the general template of the function that throws an exception.
1377  dest_buffer);
1378 
1379  size = dest_buffer.size() - previous_size;
1380  }
1381  else
1382  {
1383  // use buffer as the target of a compressing
1384  // stream into which we serialize the current object
1385  const std::size_t previous_size = dest_buffer.size();
1386  {
1387  boost::iostreams::filtering_ostreambuf fosb;
1388 #ifdef DEAL_II_WITH_ZLIB
1389  if (allow_compression)
1390  fosb.push(boost::iostreams::gzip_compressor());
1391 #else
1392  (void)allow_compression;
1393 #endif
1394  fosb.push(boost::iostreams::back_inserter(dest_buffer));
1395 
1396  boost::archive::binary_oarchive boa(fosb);
1397  boa << object;
1398  // the stream object has to be destroyed before the return statement
1399  // to ensure that all data has been written in the buffer
1400  }
1401  size = dest_buffer.size() - previous_size;
1402  }
1403 
1404  return size;
1405  }
1406 
1407 
1408  template <typename T>
1409  std::vector<char>
1410  pack(const T &object, const bool allow_compression)
1411  {
1412  std::vector<char> buffer;
1413  pack<T>(object, buffer, allow_compression);
1414  return buffer;
1415  }
1416 
1417 
1418 
1419  template <typename T>
1420  T
1421  unpack(const std::vector<char>::const_iterator &cbegin,
1422  const std::vector<char>::const_iterator &cend,
1423  const bool allow_compression)
1424  {
1425  // see if the object is small and copyable via memcpy. if so, use
1426  // this fast path. otherwise, we have to go through the BOOST
1427  // serialization machinery
1428  if DEAL_II_CONSTEXPR_IN_CONDITIONAL (std::is_trivially_copyable<T>() &&
1429  sizeof(T) < 256)
1430  {
1431  // Determine the size. There are places where we would like to use a
1432  // truly empty type, for which we use std::tuple<> (i.e., a tuple
1433  // of zero elements). For this class, the compiler reports a nonzero
1434  // sizeof(...) because that is the minimum possible for objects --
1435  // objects need to have distinct addresses, so they need to have a size
1436  // of at least one. But we can special case this situation.
1437  const std::size_t size =
1438  (std::is_same<T, std::tuple<>>::value ? 0 : sizeof(T));
1439 
1440  T object;
1441 
1442  (void)allow_compression;
1443  Assert(std::distance(cbegin, cend) == size, ExcInternalError());
1444 
1445  if (size > 0)
1446  std::memcpy(&object, &*cbegin, size);
1447 
1448  return object;
1449  }
1450  // Next try if we have a vector of trivially copyable objects.
1451  // If that is the case, we can shortcut the whole BOOST serialization
1452  // machinery and just copy the content of the buffer bit for bit
1453  // into an appropriately sized output vector, assuming that we
1454  // are not asked to compress the data.
1456  (allow_compression == false))
1457  {
1458  // When we have DEAL_II_HAVE_CXX17 set by default, we can just
1459  // inline the code of the following function here and make the 'if'
1460  // above a 'if constexpr'. Without the 'constexpr', we need to keep
1461  // the general template of the function that throws an exception.
1462  T object;
1464  cend,
1465  object);
1466  return object;
1467  }
1468  else
1469  {
1470  // decompress the buffer section into the object
1471  boost::iostreams::filtering_istreambuf fisb;
1472 #ifdef DEAL_II_WITH_ZLIB
1473  if (allow_compression)
1474  fisb.push(boost::iostreams::gzip_decompressor());
1475 #else
1476  (void)allow_compression;
1477 #endif
1478  fisb.push(boost::iostreams::array_source(&*cbegin, cend - cbegin));
1479 
1480  boost::archive::binary_iarchive bia(fisb);
1481 
1482  T object;
1483  bia >> object;
1484  return object;
1485  }
1486 
1487  return T();
1488  }
1489 
1490 
1491  template <typename T>
1492  T
1493  unpack(const std::vector<char> &buffer, const bool allow_compression)
1494  {
1495  return unpack<T>(buffer.cbegin(), buffer.cend(), allow_compression);
1496  }
1497 
1498 
1499  template <typename T, int N>
1500  void
1501  unpack(const std::vector<char>::const_iterator &cbegin,
1502  const std::vector<char>::const_iterator &cend,
1503  T (&unpacked_object)[N],
1504  const bool allow_compression)
1505  {
1506  // see if the object is small and copyable via memcpy. if so, use
1507  // this fast path. otherwise, we have to go through the BOOST
1508  // serialization machinery
1509  if DEAL_II_CONSTEXPR_IN_CONDITIONAL (std::is_trivially_copyable<T>() &&
1510  sizeof(T) * N < 256)
1511  {
1512  Assert(std::distance(cbegin, cend) == sizeof(T) * N,
1513  ExcInternalError());
1514  std::memcpy(unpacked_object, &*cbegin, sizeof(T) * N);
1515  }
1516  else
1517  {
1518  // decompress the buffer section into the object
1519  boost::iostreams::filtering_istreambuf fisb;
1520 #ifdef DEAL_II_WITH_ZLIB
1521  if (allow_compression)
1522  fisb.push(boost::iostreams::gzip_decompressor());
1523 #else
1524  (void)allow_compression;
1525 #endif
1526  fisb.push(boost::iostreams::array_source(&*cbegin, cend - cbegin));
1527 
1528  boost::archive::binary_iarchive bia(fisb);
1529  bia >> unpacked_object;
1530  }
1531  }
1532 
1533 
1534  template <typename T, int N>
1535  void
1536  unpack(const std::vector<char> &buffer,
1537  T (&unpacked_object)[N],
1538  const bool allow_compression)
1539  {
1540  unpack<T, N>(buffer.cbegin(),
1541  buffer.cend(),
1542  unpacked_object,
1543  allow_compression);
1544  }
1545 
1546 
1547 
1548  inline bool
1549  get_bit(const unsigned char number, const unsigned int n)
1550  {
1551  AssertIndexRange(n, 8);
1552 
1553  // source:
1554  // https://stackoverflow.com/questions/47981/how-do-you-set-clear-and-toggle-a-single-bit
1555  // "Checking a bit"
1556  return ((number >> n) & 1U) != 0u;
1557  }
1558 
1559 
1560 
1561  inline void
1562  set_bit(unsigned char &number, const unsigned int n, const bool x)
1563  {
1564  AssertIndexRange(n, 8);
1565 
1566  // source:
1567  // https://stackoverflow.com/questions/47981/how-do-you-set-clear-and-toggle-a-single-bit
1568  // "Changing the nth bit to x"
1569  number ^= (-static_cast<unsigned char>(x) ^ number) & (1U << n);
1570  }
1571 
1572 
1573 
1574  template <typename To, typename From>
1575  inline std::unique_ptr<To>
1576  dynamic_unique_cast(std::unique_ptr<From> &&p)
1577  {
1578  // Let's see if we can cast from 'From' to 'To'. If so, do the cast,
1579  // and then release the pointer from the old
1580  // owner
1581  if (To *cast = dynamic_cast<To *>(p.get()))
1582  {
1583  std::unique_ptr<To> result(cast);
1584  p.release();
1585  return result;
1586  }
1587  else
1588  throw std::bad_cast();
1589  }
1590 
1591 
1592 
1593  template <typename T>
1594  inline T &
1596  {
1597  return p;
1598  }
1599 
1600 
1601 
1602  template <typename T>
1603  inline T &
1604  get_underlying_value(std::shared_ptr<T> &p)
1605  {
1606  return *p;
1607  }
1608 
1609 
1610 
1611  template <typename T>
1612  inline T &
1613  get_underlying_value(const std::shared_ptr<T> &p)
1614  {
1615  return *p;
1616  }
1617 
1618 
1619 
1620  template <typename T>
1621  inline T &
1622  get_underlying_value(std::unique_ptr<T> &p)
1623  {
1624  return *p;
1625  }
1626 
1627 
1628 
1629  template <typename T>
1630  inline T &
1631  get_underlying_value(const std::unique_ptr<T> &p)
1632  {
1633  return *p;
1634  }
1635 
1636 
1637 
1638  template <typename Integer>
1639  std::vector<Integer>
1640  reverse_permutation(const std::vector<Integer> &permutation)
1641  {
1642  const std::size_t n = permutation.size();
1643 
1644  std::vector<Integer> out(n);
1645  for (std::size_t i = 0; i < n; ++i)
1646  out[i] = n - 1 - permutation[i];
1647 
1648  return out;
1649  }
1650 
1651 
1652 
1653  template <typename Integer>
1654  std::vector<Integer>
1655  invert_permutation(const std::vector<Integer> &permutation)
1656  {
1657  const std::size_t n = permutation.size();
1658 
1659  std::vector<Integer> out(n, numbers::invalid_unsigned_int);
1660 
1661  for (std::size_t i = 0; i < n; ++i)
1662  {
1663  AssertIndexRange(permutation[i], n);
1664  out[permutation[i]] = i;
1665  }
1666 
1667  // check that we have actually reached
1668  // all indices
1669  for (std::size_t i = 0; i < n; ++i)
1671  ExcMessage("The given input permutation had duplicate entries!"));
1672 
1673  return out;
1674  }
1675 } // namespace Utilities
1676 
1677 
1679 
1680 #ifndef DOXYGEN
1681 namespace boost
1682 {
1683  namespace serialization
1684  {
1685  // Provides boost and c++11 with a way to serialize tuples and pairs
1686  // automatically.
1687  template <int N>
1688  struct Serialize
1689  {
1690  template <class Archive, typename... Args>
1691  static void
1692  serialize(Archive &ar, std::tuple<Args...> &t, const unsigned int version)
1693  {
1694  ar &std::get<N - 1>(t);
1695  Serialize<N - 1>::serialize(ar, t, version);
1696  }
1697  };
1698 
1699  template <>
1700  struct Serialize<0>
1701  {
1702  template <class Archive, typename... Args>
1703  static void
1704  serialize(Archive &ar, std::tuple<Args...> &t, const unsigned int version)
1705  {
1706  (void)ar;
1707  (void)t;
1708  (void)version;
1709  }
1710  };
1711 
1712  template <class Archive, typename... Args>
1713  void
1714  serialize(Archive &ar, std::tuple<Args...> &t, const unsigned int version)
1715  {
1716  Serialize<sizeof...(Args)>::serialize(ar, t, version);
1717  }
1718  } // namespace serialization
1719 } // namespace boost
1720 #endif
1721 
1722 #endif
Definition: point.h:111
#define DEAL_II_CONSTEXPR_IN_CONDITIONAL
Definition: config.h:561
#define DEAL_II_NAMESPACE_OPEN
Definition: config.h:461
#define DEAL_II_DISABLE_EXTRA_DIAGNOSTICS
Definition: config.h:475
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:462
#define DEAL_II_FALLTHROUGH
Definition: config.h:174
#define DEAL_II_ENABLE_EXTRA_DIAGNOSTICS
Definition: config.h:516
Point< 2 > first
Definition: grid_out.cc:4605
static ::ExceptionBase & ExcInternalError()
#define Assert(cond, exc)
Definition: exceptions.h:1509
#define AssertIndexRange(index, range)
Definition: exceptions.h:1768
static ::ExceptionBase & ExcMessage(std::string arg1)
static const char T
static const char N
types::global_dof_index size_type
Definition: cuda_kernels.h:45
VectorType::value_type * end(VectorType &V)
void get_memory_stats(MemoryStats &stats)
Definition: utilities.cc:967
std::string get_hostname()
Definition: utilities.cc:1001
std::string get_time()
Definition: utilities.cc:1016
void posix_memalign(void **memptr, std::size_t alignment, std::size_t size)
Definition: utilities.cc:1047
double get_cpu_load()
Definition: utilities.cc:933
const std::string get_current_vectorization_level()
Definition: utilities.cc:941
std::string get_date()
Definition: utilities.cc:1032
void create_vector_of_trivially_copyable_from_buffer(const std::vector< char >::const_iterator &, const std::vector< char >::const_iterator &, T &)
Definition: utilities.h:1235
void append_vector_of_trivially_copyable_to_buffer(const T &, std::vector< char > &)
Definition: utilities.h:1147
constexpr T pow(const T base, const int iexp)
Definition: utilities.h:450
std::vector< std::string > split_string_list(const std::string &s, const std::string &delimiter=",")
Definition: utilities.cc:704
T & get_underlying_value(T &p)
Definition: utilities.h:1595
Number truncate_to_n_digits(const Number number, const unsigned int n_digits)
Definition: utilities.cc:581
std::string type_to_string(const T &t)
Definition: utilities.h:990
size_t pack(const T &object, std::vector< char > &dest_buffer, const bool allow_compression=true)
Definition: utilities.h:1334
std::string dim_string(const int dim, const int spacedim)
Definition: utilities.cc:558
std::uint64_t pack_integers(const std::array< std::uint64_t, dim > &index, const int bits_per_dim)
Definition: utilities.cc:369
bool get_bit(const unsigned char number, const unsigned int n)
Definition: utilities.h:1549
std::pair< int, unsigned int > get_integer_at_position(const std::string &name, const unsigned int position)
Definition: utilities.cc:850
std::string encode_base64(const std::vector< unsigned char > &binary_input)
Definition: utilities.cc:436
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)
Definition: utilities.cc:148
std::unique_ptr< To > dynamic_unique_cast(std::unique_ptr< From > &&p)
Definition: utilities.h:1576
std::string replace_in_string(const std::string &input, const std::string &from, const std::string &to)
Definition: utilities.cc:512
std::vector< unsigned char > decode_base64(const std::string &base64_input)
Definition: utilities.cc:449
std::vector< std::string > break_text_into_lines(const std::string &original_text, const unsigned int width, const char delimiter=' ')
Definition: utilities.cc:758
std::string to_string(const number value, const unsigned int digits=numbers::invalid_unsigned_int)
Definition: utilities.cc:482
std::string compress(const std::string &input)
Definition: utilities.cc:392
std::string int_to_string(const unsigned int value, const unsigned int digits=numbers::invalid_unsigned_int)
Definition: utilities.cc:473
bool match_at_string_start(const std::string &name, const std::string &pattern)
Definition: utilities.cc:835
T unpack(const std::vector< char > &buffer, const bool allow_compression=true)
Definition: utilities.h:1493
T fixed_power(const T t)
Definition: utilities.h:969
std::string decompress(const std::string &compressed_input)
Definition: utilities.cc:414
unsigned int needed_digits(const unsigned int max_number)
Definition: utilities.cc:568
Iterator lower_bound(Iterator first, Iterator last, const T &val)
Definition: utilities.h:999
double string_to_double(const std::string &s)
Definition: utilities.cc:656
std::string dealii_version_string()
Definition: utilities.cc:97
void set_bit(unsigned char &number, const unsigned int n, const bool x)
Definition: utilities.h:1562
std::string trim(const std::string &input)
Definition: utilities.cc:531
double generate_normal_random_number(const double a, const double sigma)
Definition: utilities.cc:892
std::vector< Integer > reverse_permutation(const std::vector< Integer > &permutation)
Definition: utilities.h:1640
std::vector< Integer > invert_permutation(const std::vector< Integer > &permutation)
Definition: utilities.h:1655
int string_to_int(const std::string &s)
Definition: utilities.cc:608
void issue_error_noreturn(ExceptionHandling handling, const char *file, int line, const char *function, const char *cond, const char *exc_name, ExceptionType e)
Definition: exceptions.h:1394
static const unsigned int invalid_unsigned_int
Definition: types.h:206
unsigned long int VmRSS
Definition: utilities.h:911
unsigned long int VmPeak
Definition: utilities.h:895
unsigned long int VmSize
Definition: utilities.h:900
unsigned long int VmHWM
Definition: utilities.h:905