Reference documentation for deal.II version GIT 90d86f7ad9 2022-05-28 14:10: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 #ifdef DEAL_II_WITH_TRILINOS
35 # include <Epetra_Comm.h>
36 # include <Epetra_Map.h>
37 # include <Teuchos_Comm.hpp>
38 # include <Teuchos_RCP.hpp>
39 # ifdef DEAL_II_WITH_MPI
40 # include <Epetra_MpiComm.h>
41 # else
42 # include <Epetra_SerialComm.h>
43 # endif
44 #endif
45 
46 #include <boost/archive/binary_iarchive.hpp>
47 #include <boost/archive/binary_oarchive.hpp>
48 #include <boost/core/demangle.hpp>
49 #include <boost/iostreams/device/array.hpp>
50 #include <boost/iostreams/device/back_inserter.hpp>
51 #include <boost/iostreams/filtering_streambuf.hpp>
52 #include <boost/serialization/array.hpp>
53 #include <boost/serialization/complex.hpp>
54 #include <boost/serialization/vector.hpp>
55 
56 #ifdef DEAL_II_WITH_ZLIB
57 # include <boost/iostreams/filter/gzip.hpp>
58 #endif
59 
61 
63 
64 // forward declare Point
65 #ifndef DOXYGEN
66 template <int dim, typename Number>
67 class Point;
68 #endif
69 
77 namespace Utilities
78 {
85  std::string
87 
104  template <int dim, typename Number>
105  std::vector<std::array<std::uint64_t, dim>>
107  const std::vector<Point<dim, Number>> &points,
108  const int bits_per_dim = 64);
109 
113  template <int dim>
114  std::vector<std::array<std::uint64_t, dim>>
116  const std::vector<std::array<std::uint64_t, dim>> &points,
117  const int bits_per_dim = 64);
118 
134  template <int dim>
135  std::uint64_t
136  pack_integers(const std::array<std::uint64_t, dim> &index,
137  const int bits_per_dim);
138 
151  std::string
152  compress(const std::string &input);
153 
167  std::string
168  decompress(const std::string &compressed_input);
169 
183  std::string
184  encode_base64(const std::vector<unsigned char> &binary_input);
185 
194  std::vector<unsigned char>
195  decode_base64(const std::string &base64_input);
196 
218  std::string
219  int_to_string(const unsigned int value,
220  const unsigned int digits = numbers::invalid_unsigned_int);
221 
233  template <typename number>
234  std::string
235  to_string(const number value,
236  const unsigned int digits = numbers::invalid_unsigned_int);
237 
242  unsigned int
243  needed_digits(const unsigned int max_number);
244 
253  template <typename Number>
254  Number
255  truncate_to_n_digits(const Number number, const unsigned int n_digits);
256 
261  int
262  string_to_int(const std::string &s);
263 
275  std::string
276  dim_string(const int dim, const int spacedim);
277 
282  std::vector<int>
283  string_to_int(const std::vector<std::string> &s);
284 
289  double
290  string_to_double(const std::string &s);
291 
292 
297  std::vector<double>
298  string_to_double(const std::vector<std::string> &s);
299 
300 
343  std::vector<std::string>
344  split_string_list(const std::string &s, const std::string &delimiter = ",");
345 
346 
351  std::vector<std::string>
352  split_string_list(const std::string &s, const char delimiter);
353 
354 
364  std::vector<std::string>
365  break_text_into_lines(const std::string &original_text,
366  const unsigned int width,
367  const char delimiter = ' ');
368 
373  bool
374  match_at_string_start(const std::string &name, const std::string &pattern);
375 
384  std::pair<int, unsigned int>
385  get_integer_at_position(const std::string &name, const unsigned int position);
386 
391  std::string
392  replace_in_string(const std::string &input,
393  const std::string &from,
394  const std::string &to);
395 
401  std::string
402  trim(const std::string &input);
403 
429  double
430  generate_normal_random_number(const double a, const double sigma);
431 
439  template <class T>
440  std::string
441  type_to_string(const T &t);
442 
451  template <int N, typename T>
452  T
453  fixed_power(const T t);
454 
460  template <typename T>
461  constexpr T
462  pow(const T base, const int iexp)
463  {
464 #if defined(DEBUG) && !defined(DEAL_II_CXX14_CONSTEXPR_BUG)
465  // Up to __builtin_expect this is the same code as in the 'Assert' macro.
466  // The call to __builtin_expect turns out to be problematic.
467  if (!(iexp >= 0))
470  abort_or_throw_on_exception,
471  __FILE__,
472  __LINE__,
473  __PRETTY_FUNCTION__,
474  "iexp>=0",
475  "ExcMessage(\"The exponent must not be negative!\")",
476  ExcMessage("The exponent must not be negative!"));
477 #endif
478  // The "exponentiation by squaring" algorithm used below has to be
479  // compressed to one statement due to C++11's restrictions on constexpr
480  // functions. A more descriptive version would be:
481  //
482  // <code>
483  // if (iexp <= 0)
484  // return 1;
485  //
486  // // avoid overflow of one additional recursion with pow(base * base, 0)
487  // if (iexp == 1)
488  // return base;
489  //
490  // // if the current exponent is not divisible by two,
491  // // we need to account for that.
492  // const unsigned int prefactor = (iexp % 2 == 1) ? base : 1;
493  //
494  // // a^b = (a*a)^(b/2) for b even
495  // // a^b = a*(a*a)^((b-1)/2 for b odd
496  // return prefactor * ::Utilities::pow(base*base, iexp/2);
497  // </code>
498 
499  static_assert(std::is_integral<T>::value, "Only integral types supported");
500 
501  return iexp <= 0 ?
502  1 :
503  (iexp == 1 ? base :
504  (((iexp % 2 == 1) ? base : 1) *
505  ::Utilities::pow(base * base, iexp / 2)));
506  }
507 
529  template <typename Iterator, typename T>
530  Iterator
531  lower_bound(Iterator first, Iterator last, const T &val);
532 
533 
539  template <typename Iterator, typename T, typename Comp>
540  Iterator
541  lower_bound(Iterator first, Iterator last, const T &val, const Comp comp);
542 
548  template <typename Integer>
549  std::vector<Integer>
550  reverse_permutation(const std::vector<Integer> &permutation);
551 
557  template <typename Integer>
558  std::vector<Integer>
559  invert_permutation(const std::vector<Integer> &permutation);
560 
576  template <typename T>
577  size_t
578  pack(const T & object,
579  std::vector<char> &dest_buffer,
580  const bool allow_compression = true);
581 
590  template <typename T>
591  std::vector<char>
592  pack(const T &object, const bool allow_compression = true);
593 
624  template <typename T>
625  T
626  unpack(const std::vector<char> &buffer, const bool allow_compression = true);
627 
636  template <typename T>
637  T
638  unpack(const std::vector<char>::const_iterator &cbegin,
639  const std::vector<char>::const_iterator &cend,
640  const bool allow_compression = true);
641 
674  template <typename T, int N>
675  void
676  unpack(const std::vector<char> &buffer,
677  T (&unpacked_object)[N],
678  const bool allow_compression = true);
679 
688  template <typename T, int N>
689  void
690  unpack(const std::vector<char>::const_iterator &cbegin,
691  const std::vector<char>::const_iterator &cend,
692  T (&unpacked_object)[N],
693  const bool allow_compression = true);
694 
698  bool
699  get_bit(const unsigned char number, const unsigned int n);
700 
701 
705  void
706  set_bit(unsigned char &number, const unsigned int n, const bool x);
707 
708 
766  template <typename To, typename From>
767  std::unique_ptr<To>
768  dynamic_unique_cast(std::unique_ptr<From> &&p);
769 
773  template <typename T>
774  T &
776 
780  template <typename T>
781  T &
782  get_underlying_value(std::shared_ptr<T> &p);
783 
787  template <typename T>
788  T &
789  get_underlying_value(const std::shared_ptr<T> &p);
790 
794  template <typename T>
795  T &
796  get_underlying_value(std::unique_ptr<T> &p);
797 
801  template <typename T>
802  T &
803  get_underlying_value(const std::unique_ptr<T> &p);
804 
810  namespace System
811  {
819  double
820  get_cpu_load();
821 
855  const std::string
857 
862  struct MemoryStats
863  {
867  unsigned long int VmPeak;
868 
872  unsigned long int VmSize;
873 
877  unsigned long int VmHWM;
878 
883  unsigned long int VmRSS;
884  };
885 
886 
891  void
893 
894 
898  std::string
899  get_hostname();
900 
901 
905  std::string
906  get_time();
907 
912  std::string
913  get_date();
914 
929  void
930  posix_memalign(void **memptr, std::size_t alignment, std::size_t size);
931  } // namespace System
932 
933 
934 #ifdef DEAL_II_WITH_TRILINOS
940  namespace Trilinos
941  {
951  const Epetra_Comm &
952  comm_world();
953 
963  const Epetra_Comm &
964  comm_self();
965 
974  const Teuchos::RCP<const Teuchos::Comm<int>> &
976 
1009  Epetra_Comm *
1010  duplicate_communicator(const Epetra_Comm &communicator);
1011 
1034  void
1035  destroy_communicator(Epetra_Comm &communicator);
1036 
1045  unsigned int
1046  get_n_mpi_processes(const Epetra_Comm &mpi_communicator);
1047 
1054  unsigned int
1055  get_this_mpi_process(const Epetra_Comm &mpi_communicator);
1056 
1067  Epetra_Map
1068  duplicate_map(const Epetra_BlockMap &map, const Epetra_Comm &comm);
1069  } // namespace Trilinos
1070 
1071 #endif
1072 
1073 
1074 } // namespace Utilities
1075 
1076 
1077 // --------------------- inline functions
1078 
1079 namespace Utilities
1080 {
1081  template <int N, typename T>
1082  inline T
1083  fixed_power(const T x)
1084  {
1085  Assert(
1086  !std::is_integral<T>::value || (N >= 0),
1087  ExcMessage(
1088  "The non-type template parameter N must be a non-negative integer for integral type T"));
1089 
1090  if (N == 0)
1091  return T(1.);
1092  else if (N < 0)
1093  return T(1.) / fixed_power<-N>(x);
1094  else
1095  // Use exponentiation by squaring:
1096  return ((N % 2 == 1) ? x * fixed_power<N / 2>(x * x) :
1097  fixed_power<N / 2>(x * x));
1098  }
1099 
1100 
1101 
1102  template <class T>
1103  inline std::string
1104  type_to_string(const T &t)
1105  {
1106  return boost::core::demangle(typeid(t).name());
1107  }
1108 
1109 
1110 
1111  template <typename Iterator, typename T>
1112  inline Iterator
1113  lower_bound(Iterator first, Iterator last, const T &val)
1114  {
1115  return Utilities::lower_bound(first, last, val, std::less<T>());
1116  }
1117 
1118 
1119 
1120  template <typename Iterator, typename T, typename Comp>
1121  inline Iterator
1122  lower_bound(Iterator first, Iterator last, const T &val, const Comp comp)
1123  {
1124  // verify that the two iterators are properly ordered. since
1125  // we need operator- for the iterator type anyway, do the
1126  // test as follows, rather than via 'last >= first'
1127  Assert(last - first >= 0,
1128  ExcMessage(
1129  "The given iterators do not satisfy the proper ordering."));
1130 
1131  unsigned int len = static_cast<unsigned int>(last - first);
1132 
1133  if (len == 0)
1134  return first;
1135 
1136  while (true)
1137  {
1138  // if length equals 8 or less,
1139  // then do a rolled out
1140  // search. use a switch without
1141  // breaks for that and roll-out
1142  // the loop somehow
1143  if (len < 8)
1144  {
1145  switch (len)
1146  {
1147  case 7:
1148  if (!comp(*first, val))
1149  return first;
1150  ++first;
1152  case 6:
1153  if (!comp(*first, val))
1154  return first;
1155  ++first;
1157  case 5:
1158  if (!comp(*first, val))
1159  return first;
1160  ++first;
1162  case 4:
1163  if (!comp(*first, val))
1164  return first;
1165  ++first;
1167  case 3:
1168  if (!comp(*first, val))
1169  return first;
1170  ++first;
1172  case 2:
1173  if (!comp(*first, val))
1174  return first;
1175  ++first;
1177  case 1:
1178  if (!comp(*first, val))
1179  return first;
1180  return first + 1;
1181  default:
1182  // indices seem
1183  // to not be
1184  // sorted
1185  // correctly!? or
1186  // did len
1187  // become==0
1188  // somehow? that
1189  // shouldn't have
1190  // happened
1191  Assert(false, ExcInternalError());
1192  }
1193  }
1194 
1195 
1196 
1197  const unsigned int half = len >> 1;
1198  const Iterator middle = first + half;
1199 
1200  // if the value is larger than
1201  // that pointed to by the
1202  // middle pointer, then the
1203  // insertion point must be
1204  // right of it
1205  if (comp(*middle, val))
1206  {
1207  first = middle + 1;
1208  len -= half + 1;
1209  }
1210  else
1211  len = half;
1212  }
1213  }
1214 
1215 
1216  // --------------------- non-inline functions
1217 
1218  namespace internal
1219  {
1225  template <typename T>
1227  {
1228  static constexpr bool value = false;
1229  };
1230 
1231 
1232 
1233  template <typename T>
1234  struct IsVectorOfTriviallyCopyable<std::vector<T>>
1235  {
1236  static constexpr bool value =
1237  std::is_trivially_copyable<T>::value && !std::is_same<T, bool>::value;
1238  };
1239 
1240 
1241 
1242  template <typename T>
1243  struct IsVectorOfTriviallyCopyable<std::vector<std::vector<T>>>
1244  {
1245  static constexpr bool value =
1246  std::is_trivially_copyable<T>::value && !std::is_same<T, bool>::value;
1247  };
1248 
1249 
1250 
1259  template <typename T>
1260  inline void
1262  std::vector<char> &)
1263  {
1264  // We shouldn't get here:
1265  Assert(false, ExcInternalError());
1266  }
1267 
1268 
1269 
1270  template <typename T,
1271  typename = std::enable_if_t<!std::is_same<T, bool>::value &&
1272  std::is_trivially_copyable<T>::value>>
1273  inline void
1275  const std::vector<T> &object,
1276  std::vector<char> & dest_buffer)
1277  {
1278  const typename std::vector<T>::size_type vector_size = object.size();
1279 
1280  // Reserve for the buffer so that it can store the size of 'object' as
1281  // well as all of its elements.
1282  dest_buffer.reserve(dest_buffer.size() + sizeof(vector_size) +
1283  vector_size * sizeof(T));
1284 
1285  // Copy the size into the vector
1286  dest_buffer.insert(dest_buffer.end(),
1287  reinterpret_cast<const char *>(&vector_size),
1288  reinterpret_cast<const char *>(&vector_size + 1));
1289 
1290  // Insert the elements at the end of the vector:
1291  if (vector_size > 0)
1292  dest_buffer.insert(dest_buffer.end(),
1293  reinterpret_cast<const char *>(object.data()),
1294  reinterpret_cast<const char *>(object.data() +
1295  vector_size));
1296  }
1297 
1298 
1299 
1300  template <typename T,
1301  typename = std::enable_if_t<!std::is_same<T, bool>::value &&
1302  std::is_trivially_copyable<T>::value>>
1303  inline void
1305  const std::vector<std::vector<T>> &object,
1306  std::vector<char> & dest_buffer)
1307  {
1308  using size_type = typename std::vector<T>::size_type;
1309  const size_type vector_size = object.size();
1310 
1311  typename std::vector<T>::size_type aggregated_size = 0;
1312  std::vector<size_type> sizes;
1313  sizes.reserve(vector_size);
1314  for (const auto &a : object)
1315  {
1316  aggregated_size += a.size();
1317  sizes.push_back(a.size());
1318  }
1319 
1320  // Reserve for the buffer so that it can store the size of 'object' as
1321  // well as all of its elements.
1322  dest_buffer.reserve(dest_buffer.size() +
1323  sizeof(vector_size) * (1 + vector_size) +
1324  aggregated_size * sizeof(T));
1325 
1326  // Copy the size into the vector
1327  dest_buffer.insert(dest_buffer.end(),
1328  reinterpret_cast<const char *>(&vector_size),
1329  reinterpret_cast<const char *>(&vector_size + 1));
1330 
1331  // Copy the sizes of the individual chunks into the vector
1332  if (vector_size > 0)
1333  dest_buffer.insert(dest_buffer.end(),
1334  reinterpret_cast<const char *>(sizes.data()),
1335  reinterpret_cast<const char *>(sizes.data() +
1336  vector_size));
1337 
1338  // Insert the elements at the end of the vector:
1339  for (const auto &a : object)
1340  dest_buffer.insert(dest_buffer.end(),
1341  reinterpret_cast<const char *>(a.data()),
1342  reinterpret_cast<const char *>(a.data() + a.size()));
1343  }
1344 
1345 
1346 
1347  template <typename T>
1348  inline void
1350  const std::vector<char>::const_iterator &,
1351  const std::vector<char>::const_iterator &,
1352  T &)
1353  {
1354  // We shouldn't get here:
1355  Assert(false, ExcInternalError());
1356  }
1357 
1358 
1359 
1360  template <typename T,
1361  typename = std::enable_if_t<!std::is_same<T, bool>::value &&
1362  std::is_trivially_copyable<T>::value>>
1363  inline void
1365  const std::vector<char>::const_iterator &cbegin,
1366  const std::vector<char>::const_iterator &cend,
1367  std::vector<T> & object)
1368  {
1369  // First get the size of the vector, and resize the output object
1370  typename std::vector<T>::size_type vector_size;
1371  memcpy(&vector_size, &*cbegin, sizeof(vector_size));
1372 
1373  Assert(static_cast<std::ptrdiff_t>(cend - cbegin) ==
1374  static_cast<std::ptrdiff_t>(sizeof(vector_size) +
1375  vector_size * sizeof(T)),
1376  ExcMessage("The given buffer has the wrong size."));
1377  (void)cend;
1378 
1379  // Then copy the elements:
1380  object.clear();
1381  if (vector_size > 0)
1382  object.insert(object.end(),
1383  reinterpret_cast<const T *>(&*cbegin +
1384  sizeof(vector_size)),
1385  reinterpret_cast<const T *>(&*cend));
1386  }
1387 
1388 
1389 
1390  template <typename T,
1391  typename = std::enable_if_t<!std::is_same<T, bool>::value &&
1392  std::is_trivially_copyable<T>::value>>
1393  inline void
1395  const std::vector<char>::const_iterator &cbegin,
1396  const std::vector<char>::const_iterator &cend,
1397  std::vector<std::vector<T>> & object)
1398  {
1399  // First get the size of the vector, and resize the output object
1400  using size_type = typename std::vector<T>::size_type;
1401  std::vector<char>::const_iterator iterator = cbegin;
1402  size_type vector_size;
1403  memcpy(&vector_size, &*iterator, sizeof(vector_size));
1404  object.clear();
1405  object.resize(vector_size);
1406  std::vector<size_type> sizes(vector_size);
1407  if (vector_size > 0)
1408  memcpy(sizes.data(),
1409  &*iterator + sizeof(vector_size),
1410  vector_size * sizeof(size_type));
1411 
1412  iterator += sizeof(vector_size) * (1 + vector_size);
1413  size_type aggregated_size = 0;
1414  for (const auto a : sizes)
1415  aggregated_size += a;
1416 
1417  Assert(static_cast<std::ptrdiff_t>(cend - iterator) ==
1418  static_cast<std::ptrdiff_t>(aggregated_size * sizeof(T)),
1419  ExcMessage("The given buffer has the wrong size."));
1420  (void)cend;
1421 
1422  // Then copy the elements:
1423  for (unsigned int i = 0; i < vector_size; ++i)
1424  if (sizes[i] > 0)
1425  {
1426  object[i].insert(object[i].end(),
1427  reinterpret_cast<const T *>(&*iterator),
1428  reinterpret_cast<const T *>(&*iterator +
1429  sizeof(T) * sizes[i]));
1430  iterator += sizeof(T) * sizes[i];
1431  }
1432 
1433  Assert(iterator == cend,
1434  ExcMessage("The given buffer has the wrong size."));
1435  }
1436 
1437  } // namespace internal
1438 
1439 
1440 
1441  template <typename T>
1442  size_t
1443  pack(const T & object,
1444  std::vector<char> &dest_buffer,
1445  const bool allow_compression)
1446  {
1447  std::size_t size = 0;
1448 
1449 
1450  // see if the object is small and copyable via memcpy. if so, use
1451  // this fast path. otherwise, we have to go through the BOOST
1452  // serialization machinery
1453 #ifdef DEAL_II_HAVE_CXX17
1454  if constexpr (std::is_trivially_copyable<T>() && sizeof(T) < 256)
1455 #else
1456  if (std::is_trivially_copyable<T>() && sizeof(T) < 256)
1457 #endif
1458  {
1459  (void)allow_compression;
1460  const std::size_t previous_size = dest_buffer.size();
1461  dest_buffer.resize(previous_size + sizeof(T));
1462 
1463  std::memcpy(dest_buffer.data() + previous_size, &object, sizeof(T));
1464 
1465  size = sizeof(T);
1466  }
1467  // Next try if we have a vector of trivially copyable objects.
1468  // If that is the case, we can shortcut the whole BOOST serialization
1469  // machinery and just copy the content of the vector bit for bit
1470  // into the output buffer, assuming that we are not asked to compress
1471  // the data.
1473  (allow_compression == false))
1474  {
1475  const std::size_t previous_size = dest_buffer.size();
1476 
1477  // When we have DEAL_II_HAVE_CXX17 set by default, we can just
1478  // inline the code of the following function here and make the 'if'
1479  // above a 'if constexpr'. Without the 'constexpr', we need to keep
1480  // the general template of the function that throws an exception.
1482  dest_buffer);
1483 
1484  size = dest_buffer.size() - previous_size;
1485  }
1486  else
1487  {
1488  // use buffer as the target of a compressing
1489  // stream into which we serialize the current object
1490  const std::size_t previous_size = dest_buffer.size();
1491  {
1492  boost::iostreams::filtering_ostreambuf fosb;
1493 #ifdef DEAL_II_WITH_ZLIB
1494  if (allow_compression)
1495  fosb.push(boost::iostreams::gzip_compressor());
1496 #else
1497  (void)allow_compression;
1498 #endif
1499  fosb.push(boost::iostreams::back_inserter(dest_buffer));
1500 
1501  boost::archive::binary_oarchive boa(fosb);
1502  boa << object;
1503  // the stream object has to be destroyed before the return statement
1504  // to ensure that all data has been written in the buffer
1505  }
1506  size = dest_buffer.size() - previous_size;
1507  }
1508 
1509  return size;
1510  }
1511 
1512 
1513  template <typename T>
1514  std::vector<char>
1515  pack(const T &object, const bool allow_compression)
1516  {
1517  std::vector<char> buffer;
1518  pack<T>(object, buffer, allow_compression);
1519  return buffer;
1520  }
1521 
1522 
1523 
1524  template <typename T>
1525  T
1526  unpack(const std::vector<char>::const_iterator &cbegin,
1527  const std::vector<char>::const_iterator &cend,
1528  const bool allow_compression)
1529  {
1530  // see if the object is small and copyable via memcpy. if so, use
1531  // this fast path. otherwise, we have to go through the BOOST
1532  // serialization machinery
1533 #ifdef DEAL_II_HAVE_CXX17
1534  if constexpr (std::is_trivially_copyable<T>() && sizeof(T) < 256)
1535 #else
1536  if (std::is_trivially_copyable<T>() && sizeof(T) < 256)
1537 #endif
1538  {
1539  T object;
1540 
1541  (void)allow_compression;
1542  Assert(std::distance(cbegin, cend) == sizeof(T), ExcInternalError());
1543  std::memcpy(&object, &*cbegin, sizeof(T));
1544 
1545  return object;
1546  }
1547  // Next try if we have a vector of trivially copyable objects.
1548  // If that is the case, we can shortcut the whole BOOST serialization
1549  // machinery and just copy the content of the buffer bit for bit
1550  // into an appropriately sized output vector, assuming that we
1551  // are not asked to compress the data.
1553  (allow_compression == false))
1554  {
1555  // When we have DEAL_II_HAVE_CXX17 set by default, we can just
1556  // inline the code of the following function here and make the 'if'
1557  // above a 'if constexpr'. Without the 'constexpr', we need to keep
1558  // the general template of the function that throws an exception.
1559  T object;
1561  cend,
1562  object);
1563  return object;
1564  }
1565  else
1566  {
1567  // decompress the buffer section into the object
1568  boost::iostreams::filtering_istreambuf fisb;
1569 #ifdef DEAL_II_WITH_ZLIB
1570  if (allow_compression)
1571  fisb.push(boost::iostreams::gzip_decompressor());
1572 #else
1573  (void)allow_compression;
1574 #endif
1575  fisb.push(boost::iostreams::array_source(&*cbegin, cend - cbegin));
1576 
1577  boost::archive::binary_iarchive bia(fisb);
1578 
1579  T object;
1580  bia >> object;
1581  return object;
1582  }
1583 
1584  return T();
1585  }
1586 
1587 
1588  template <typename T>
1589  T
1590  unpack(const std::vector<char> &buffer, const bool allow_compression)
1591  {
1592  return unpack<T>(buffer.cbegin(), buffer.cend(), allow_compression);
1593  }
1594 
1595 
1596  template <typename T, int N>
1597  void
1598  unpack(const std::vector<char>::const_iterator &cbegin,
1599  const std::vector<char>::const_iterator &cend,
1600  T (&unpacked_object)[N],
1601  const bool allow_compression)
1602  {
1603  // see if the object is small and copyable via memcpy. if so, use
1604  // this fast path. otherwise, we have to go through the BOOST
1605  // serialization machinery
1606 #ifdef DEAL_II_HAVE_CXX17
1607  if constexpr (std::is_trivially_copyable<T>() && sizeof(T) * N < 256)
1608 #else
1609  if (std::is_trivially_copyable<T>() && sizeof(T) * N < 256)
1610 #endif
1611  {
1612  Assert(std::distance(cbegin, cend) == sizeof(T) * N,
1613  ExcInternalError());
1614  std::memcpy(unpacked_object, &*cbegin, sizeof(T) * N);
1615  }
1616  else
1617  {
1618  // decompress the buffer section into the object
1619  boost::iostreams::filtering_istreambuf fisb;
1620 #ifdef DEAL_II_WITH_ZLIB
1621  if (allow_compression)
1622  fisb.push(boost::iostreams::gzip_decompressor());
1623 #else
1624  (void)allow_compression;
1625 #endif
1626  fisb.push(boost::iostreams::array_source(&*cbegin, cend - cbegin));
1627 
1628  boost::archive::binary_iarchive bia(fisb);
1629  bia >> unpacked_object;
1630  }
1631  }
1632 
1633 
1634  template <typename T, int N>
1635  void
1636  unpack(const std::vector<char> &buffer,
1637  T (&unpacked_object)[N],
1638  const bool allow_compression)
1639  {
1640  unpack<T, N>(buffer.cbegin(),
1641  buffer.cend(),
1642  unpacked_object,
1643  allow_compression);
1644  }
1645 
1646 
1647 
1648  inline bool
1649  get_bit(const unsigned char number, const unsigned int n)
1650  {
1651  AssertIndexRange(n, 8);
1652 
1653  // source:
1654  // https://stackoverflow.com/questions/47981/how-do-you-set-clear-and-toggle-a-single-bit
1655  // "Checking a bit"
1656  return ((number >> n) & 1U) != 0u;
1657  }
1658 
1659 
1660 
1661  inline void
1662  set_bit(unsigned char &number, const unsigned int n, const bool x)
1663  {
1664  AssertIndexRange(n, 8);
1665 
1666  // source:
1667  // https://stackoverflow.com/questions/47981/how-do-you-set-clear-and-toggle-a-single-bit
1668  // "Changing the nth bit to x"
1669  number ^= (-static_cast<unsigned char>(x) ^ number) & (1U << n);
1670  }
1671 
1672 
1673 
1674  template <typename To, typename From>
1675  inline std::unique_ptr<To>
1676  dynamic_unique_cast(std::unique_ptr<From> &&p)
1677  {
1678  // Let's see if we can cast from 'From' to 'To'. If so, do the cast,
1679  // and then release the pointer from the old
1680  // owner
1681  if (To *cast = dynamic_cast<To *>(p.get()))
1682  {
1683  std::unique_ptr<To> result(cast);
1684  p.release();
1685  return result;
1686  }
1687  else
1688  throw std::bad_cast();
1689  }
1690 
1691 
1692 
1693  template <typename T>
1694  inline T &
1696  {
1697  return p;
1698  }
1699 
1700 
1701 
1702  template <typename T>
1703  inline T &
1704  get_underlying_value(std::shared_ptr<T> &p)
1705  {
1706  return *p;
1707  }
1708 
1709 
1710 
1711  template <typename T>
1712  inline T &
1713  get_underlying_value(const std::shared_ptr<T> &p)
1714  {
1715  return *p;
1716  }
1717 
1718 
1719 
1720  template <typename T>
1721  inline T &
1722  get_underlying_value(std::unique_ptr<T> &p)
1723  {
1724  return *p;
1725  }
1726 
1727 
1728 
1729  template <typename T>
1730  inline T &
1731  get_underlying_value(const std::unique_ptr<T> &p)
1732  {
1733  return *p;
1734  }
1735 
1736 
1737 
1738  template <typename Integer>
1739  std::vector<Integer>
1740  reverse_permutation(const std::vector<Integer> &permutation)
1741  {
1742  const std::size_t n = permutation.size();
1743 
1744  std::vector<Integer> out(n);
1745  for (std::size_t i = 0; i < n; ++i)
1746  out[i] = n - 1 - permutation[i];
1747 
1748  return out;
1749  }
1750 
1751 
1752 
1753  template <typename Integer>
1754  std::vector<Integer>
1755  invert_permutation(const std::vector<Integer> &permutation)
1756  {
1757  const std::size_t n = permutation.size();
1758 
1759  std::vector<Integer> out(n, numbers::invalid_unsigned_int);
1760 
1761  for (std::size_t i = 0; i < n; ++i)
1762  {
1763  AssertIndexRange(permutation[i], n);
1764  out[permutation[i]] = i;
1765  }
1766 
1767  // check that we have actually reached
1768  // all indices
1769  for (std::size_t i = 0; i < n; ++i)
1771  ExcMessage("The given input permutation had duplicate entries!"));
1772 
1773  return out;
1774  }
1775 } // namespace Utilities
1776 
1777 
1779 
1780 #ifndef DOXYGEN
1781 namespace boost
1782 {
1783  namespace serialization
1784  {
1785  // Provides boost and c++11 with a way to serialize tuples and pairs
1786  // automatically.
1787  template <int N>
1788  struct Serialize
1789  {
1790  template <class Archive, typename... Args>
1791  static void
1792  serialize(Archive &ar, std::tuple<Args...> &t, const unsigned int version)
1793  {
1794  ar &std::get<N - 1>(t);
1795  Serialize<N - 1>::serialize(ar, t, version);
1796  }
1797  };
1798 
1799  template <>
1800  struct Serialize<0>
1801  {
1802  template <class Archive, typename... Args>
1803  static void
1804  serialize(Archive &ar, std::tuple<Args...> &t, const unsigned int version)
1805  {
1806  (void)ar;
1807  (void)t;
1808  (void)version;
1809  }
1810  };
1811 
1812  template <class Archive, typename... Args>
1813  void
1814  serialize(Archive &ar, std::tuple<Args...> &t, const unsigned int version)
1815  {
1816  Serialize<sizeof...(Args)>::serialize(ar, t, version);
1817  }
1818  } // namespace serialization
1819 } // namespace boost
1820 #endif
1821 
1822 #endif
Definition: point.h:111
#define DEAL_II_NAMESPACE_OPEN
Definition: config.h:433
#define DEAL_II_DISABLE_EXTRA_DIAGNOSTICS
Definition: config.h:447
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:434
#define DEAL_II_FALLTHROUGH
Definition: config.h:176
#define DEAL_II_ENABLE_EXTRA_DIAGNOSTICS
Definition: config.h:486
Point< 2 > first
Definition: grid_out.cc:4603
static ::ExceptionBase & ExcInternalError()
#define Assert(cond, exc)
Definition: exceptions.h:1473
#define AssertIndexRange(index, range)
Definition: exceptions.h:1732
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 destroy_communicator(Epetra_Comm &communicator)
Definition: utilities.cc:1153
Epetra_Map duplicate_map(const Epetra_BlockMap &map, const Epetra_Comm &comm)
Definition: utilities.cc:1187
unsigned int get_this_mpi_process(const Epetra_Comm &mpi_communicator)
Definition: utilities.cc:1179
unsigned int get_n_mpi_processes(const Epetra_Comm &mpi_communicator)
Definition: utilities.cc:1172
const Epetra_Comm & comm_self()
Definition: utilities.cc:1110
const Teuchos::RCP< const Teuchos::Comm< int > > & tpetra_comm_self()
Definition: utilities.cc:1094
Epetra_Comm * duplicate_communicator(const Epetra_Comm &communicator)
Definition: utilities.cc:1126
const Epetra_Comm & comm_world()
Definition: utilities.cc:1078
void create_vector_of_trivially_copyable_from_buffer(const std::vector< char >::const_iterator &, const std::vector< char >::const_iterator &, T &)
Definition: utilities.h:1349
void append_vector_of_trivially_copyable_to_buffer(const T &, std::vector< char > &)
Definition: utilities.h:1261
constexpr T pow(const T base, const int iexp)
Definition: utilities.h:462
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:1695
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:1104
size_t pack(const T &object, std::vector< char > &dest_buffer, const bool allow_compression=true)
Definition: utilities.h:1443
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:1649
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:1676
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:1590
T fixed_power(const T t)
Definition: utilities.h:1083
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:1113
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:1662
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:1740
std::vector< Integer > invert_permutation(const std::vector< Integer > &permutation)
Definition: utilities.h:1755
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:1358
static const unsigned int invalid_unsigned_int
Definition: types.h:201
unsigned long int VmRSS
Definition: utilities.h:883
unsigned long int VmPeak
Definition: utilities.h:867
unsigned long int VmSize
Definition: utilities.h:872
unsigned long int VmHWM
Definition: utilities.h:877
const MPI_Comm & comm