Reference documentation for deal.II version 9.4.0
\(\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 
615  template <typename T>
616  size_t
617  pack(const T & object,
618  std::vector<char> &dest_buffer,
619  const bool allow_compression = true);
620 
629  template <typename T>
630  std::vector<char>
631  pack(const T &object, const bool allow_compression = true);
632 
664  template <typename T>
665  T
666  unpack(const std::vector<char> &buffer, const bool allow_compression = true);
667 
676  template <typename T>
677  T
678  unpack(const std::vector<char>::const_iterator &cbegin,
679  const std::vector<char>::const_iterator &cend,
680  const bool allow_compression = true);
681 
714  template <typename T, int N>
715  void
716  unpack(const std::vector<char> &buffer,
717  T (&unpacked_object)[N],
718  const bool allow_compression = true);
719 
728  template <typename T, int N>
729  void
730  unpack(const std::vector<char>::const_iterator &cbegin,
731  const std::vector<char>::const_iterator &cend,
732  T (&unpacked_object)[N],
733  const bool allow_compression = true);
734 
738  bool
739  get_bit(const unsigned char number, const unsigned int n);
740 
741 
745  void
746  set_bit(unsigned char &number, const unsigned int n, const bool x);
747 
748 
806  template <typename To, typename From>
807  std::unique_ptr<To>
808  dynamic_unique_cast(std::unique_ptr<From> &&p);
809 
813  template <typename T>
814  T &
816 
820  template <typename T>
821  T &
822  get_underlying_value(std::shared_ptr<T> &p);
823 
827  template <typename T>
828  T &
829  get_underlying_value(const std::shared_ptr<T> &p);
830 
834  template <typename T>
835  T &
836  get_underlying_value(std::unique_ptr<T> &p);
837 
841  template <typename T>
842  T &
843  get_underlying_value(const std::unique_ptr<T> &p);
844 
850  namespace System
851  {
859  double
860  get_cpu_load();
861 
895  const std::string
897 
902  struct MemoryStats
903  {
907  unsigned long int VmPeak;
908 
912  unsigned long int VmSize;
913 
917  unsigned long int VmHWM;
918 
923  unsigned long int VmRSS;
924  };
925 
926 
931  void
933 
934 
938  std::string
939  get_hostname();
940 
941 
945  std::string
946  get_time();
947 
952  std::string
953  get_date();
954 
969  void
970  posix_memalign(void **memptr, std::size_t alignment, std::size_t size);
971  } // namespace System
972 
973 
974 #ifdef DEAL_II_WITH_TRILINOS
980  namespace Trilinos
981  {
991  const Epetra_Comm &
992  comm_world();
993 
1003  const Epetra_Comm &
1004  comm_self();
1005 
1014  const Teuchos::RCP<const Teuchos::Comm<int>> &
1015  tpetra_comm_self();
1016 
1049  Epetra_Comm *
1050  duplicate_communicator(const Epetra_Comm &communicator);
1051 
1074  void
1075  destroy_communicator(Epetra_Comm &communicator);
1076 
1085  unsigned int
1086  get_n_mpi_processes(const Epetra_Comm &mpi_communicator);
1087 
1094  unsigned int
1095  get_this_mpi_process(const Epetra_Comm &mpi_communicator);
1096 
1107  Epetra_Map
1108  duplicate_map(const Epetra_BlockMap &map, const Epetra_Comm &comm);
1109  } // namespace Trilinos
1110 
1111 #endif
1112 
1113 
1114 } // namespace Utilities
1115 
1116 
1117 // --------------------- inline functions
1118 
1119 namespace Utilities
1120 {
1121  template <int N, typename T>
1122  inline T
1123  fixed_power(const T x)
1124  {
1125  Assert(
1126  !std::is_integral<T>::value || (N >= 0),
1127  ExcMessage(
1128  "The non-type template parameter N must be a non-negative integer for integral type T"));
1129 
1130  if (N == 0)
1131  return T(1.);
1132  else if (N < 0)
1133  return T(1.) / fixed_power<-N>(x);
1134  else
1135  // Use exponentiation by squaring:
1136  return ((N % 2 == 1) ? x * fixed_power<N / 2>(x * x) :
1137  fixed_power<N / 2>(x * x));
1138  }
1139 
1140 
1141 
1142  template <class T>
1143  inline std::string
1144  type_to_string(const T &t)
1145  {
1146  return boost::core::demangle(typeid(t).name());
1147  }
1148 
1149 
1150 
1151  template <typename Iterator, typename T>
1152  inline Iterator
1153  lower_bound(Iterator first, Iterator last, const T &val)
1154  {
1155  return Utilities::lower_bound(first, last, val, std::less<T>());
1156  }
1157 
1158 
1159 
1160  template <typename Iterator, typename T, typename Comp>
1161  inline Iterator
1162  lower_bound(Iterator first, Iterator last, const T &val, const Comp comp)
1163  {
1164  // verify that the two iterators are properly ordered. since
1165  // we need operator- for the iterator type anyway, do the
1166  // test as follows, rather than via 'last >= first'
1167  Assert(last - first >= 0,
1168  ExcMessage(
1169  "The given iterators do not satisfy the proper ordering."));
1170 
1171  unsigned int len = static_cast<unsigned int>(last - first);
1172 
1173  if (len == 0)
1174  return first;
1175 
1176  while (true)
1177  {
1178  // if length equals 8 or less,
1179  // then do a rolled out
1180  // search. use a switch without
1181  // breaks for that and roll-out
1182  // the loop somehow
1183  if (len < 8)
1184  {
1185  switch (len)
1186  {
1187  case 7:
1188  if (!comp(*first, val))
1189  return first;
1190  ++first;
1192  case 6:
1193  if (!comp(*first, val))
1194  return first;
1195  ++first;
1197  case 5:
1198  if (!comp(*first, val))
1199  return first;
1200  ++first;
1202  case 4:
1203  if (!comp(*first, val))
1204  return first;
1205  ++first;
1207  case 3:
1208  if (!comp(*first, val))
1209  return first;
1210  ++first;
1212  case 2:
1213  if (!comp(*first, val))
1214  return first;
1215  ++first;
1217  case 1:
1218  if (!comp(*first, val))
1219  return first;
1220  return first + 1;
1221  default:
1222  // indices seem
1223  // to not be
1224  // sorted
1225  // correctly!? or
1226  // did len
1227  // become==0
1228  // somehow? that
1229  // shouldn't have
1230  // happened
1231  Assert(false, ExcInternalError());
1232  }
1233  }
1234 
1235 
1236 
1237  const unsigned int half = len >> 1;
1238  const Iterator middle = first + half;
1239 
1240  // if the value is larger than
1241  // that pointed to by the
1242  // middle pointer, then the
1243  // insertion point must be
1244  // right of it
1245  if (comp(*middle, val))
1246  {
1247  first = middle + 1;
1248  len -= half + 1;
1249  }
1250  else
1251  len = half;
1252  }
1253  }
1254 
1255 
1256  // --------------------- non-inline functions
1257 
1258  namespace internal
1259  {
1265  template <typename T>
1267  {
1268  static constexpr bool value = false;
1269  };
1270 
1271 
1272 
1273  template <typename T>
1274  struct IsVectorOfTriviallyCopyable<std::vector<T>>
1275  {
1276  static constexpr bool value =
1277  std::is_trivially_copyable<T>::value && !std::is_same<T, bool>::value;
1278  };
1279 
1280 
1281 
1282  template <typename T>
1283  struct IsVectorOfTriviallyCopyable<std::vector<std::vector<T>>>
1284  {
1285  static constexpr bool value =
1286  std::is_trivially_copyable<T>::value && !std::is_same<T, bool>::value;
1287  };
1288 
1289 
1290 
1299  template <typename T>
1300  inline void
1302  std::vector<char> &)
1303  {
1304  // We shouldn't get here:
1305  Assert(false, ExcInternalError());
1306  }
1307 
1308 
1309 
1310  template <typename T,
1311  typename = std::enable_if_t<!std::is_same<T, bool>::value &&
1312  std::is_trivially_copyable<T>::value>>
1313  inline void
1315  const std::vector<T> &object,
1316  std::vector<char> & dest_buffer)
1317  {
1318  const typename std::vector<T>::size_type vector_size = object.size();
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() + sizeof(vector_size) +
1323  vector_size * sizeof(T));
1324 
1325  // Copy the size into the vector
1326  dest_buffer.insert(dest_buffer.end(),
1327  reinterpret_cast<const char *>(&vector_size),
1328  reinterpret_cast<const char *>(&vector_size + 1));
1329 
1330  // Insert the elements at the end of the vector:
1331  if (vector_size > 0)
1332  dest_buffer.insert(dest_buffer.end(),
1333  reinterpret_cast<const char *>(object.data()),
1334  reinterpret_cast<const char *>(object.data() +
1335  vector_size));
1336  }
1337 
1338 
1339 
1340  template <typename T,
1341  typename = std::enable_if_t<!std::is_same<T, bool>::value &&
1342  std::is_trivially_copyable<T>::value>>
1343  inline void
1345  const std::vector<std::vector<T>> &object,
1346  std::vector<char> & dest_buffer)
1347  {
1348  using size_type = typename std::vector<T>::size_type;
1349  const size_type vector_size = object.size();
1350 
1351  typename std::vector<T>::size_type aggregated_size = 0;
1352  std::vector<size_type> sizes;
1353  sizes.reserve(vector_size);
1354  for (const auto &a : object)
1355  {
1356  aggregated_size += a.size();
1357  sizes.push_back(a.size());
1358  }
1359 
1360  // Reserve for the buffer so that it can store the size of 'object' as
1361  // well as all of its elements.
1362  dest_buffer.reserve(dest_buffer.size() +
1363  sizeof(vector_size) * (1 + vector_size) +
1364  aggregated_size * sizeof(T));
1365 
1366  // Copy the size into the vector
1367  dest_buffer.insert(dest_buffer.end(),
1368  reinterpret_cast<const char *>(&vector_size),
1369  reinterpret_cast<const char *>(&vector_size + 1));
1370 
1371  // Copy the sizes of the individual chunks into the vector
1372  if (vector_size > 0)
1373  dest_buffer.insert(dest_buffer.end(),
1374  reinterpret_cast<const char *>(sizes.data()),
1375  reinterpret_cast<const char *>(sizes.data() +
1376  vector_size));
1377 
1378  // Insert the elements at the end of the vector:
1379  for (const auto &a : object)
1380  dest_buffer.insert(dest_buffer.end(),
1381  reinterpret_cast<const char *>(a.data()),
1382  reinterpret_cast<const char *>(a.data() + a.size()));
1383  }
1384 
1385 
1386 
1387  template <typename T>
1388  inline void
1390  const std::vector<char>::const_iterator &,
1391  const std::vector<char>::const_iterator &,
1392  T &)
1393  {
1394  // We shouldn't get here:
1395  Assert(false, ExcInternalError());
1396  }
1397 
1398 
1399 
1400  template <typename T,
1401  typename = std::enable_if_t<!std::is_same<T, bool>::value &&
1402  std::is_trivially_copyable<T>::value>>
1403  inline void
1405  const std::vector<char>::const_iterator &cbegin,
1406  const std::vector<char>::const_iterator &cend,
1407  std::vector<T> & object)
1408  {
1409  // First get the size of the vector, and resize the output object
1410  typename std::vector<T>::size_type vector_size;
1411  memcpy(&vector_size, &*cbegin, sizeof(vector_size));
1412 
1413  Assert(static_cast<std::ptrdiff_t>(cend - cbegin) ==
1414  static_cast<std::ptrdiff_t>(sizeof(vector_size) +
1415  vector_size * sizeof(T)),
1416  ExcMessage("The given buffer has the wrong size."));
1417  (void)cend;
1418 
1419  // Then copy the elements:
1420  object.clear();
1421  if (vector_size > 0)
1422  object.insert(object.end(),
1423  reinterpret_cast<const T *>(&*cbegin +
1424  sizeof(vector_size)),
1425  reinterpret_cast<const T *>(&*cend));
1426  }
1427 
1428 
1429 
1430  template <typename T,
1431  typename = std::enable_if_t<!std::is_same<T, bool>::value &&
1432  std::is_trivially_copyable<T>::value>>
1433  inline void
1435  const std::vector<char>::const_iterator &cbegin,
1436  const std::vector<char>::const_iterator &cend,
1437  std::vector<std::vector<T>> & object)
1438  {
1439  // First get the size of the vector, and resize the output object
1440  using size_type = typename std::vector<T>::size_type;
1441  std::vector<char>::const_iterator iterator = cbegin;
1442  size_type vector_size;
1443  memcpy(&vector_size, &*iterator, sizeof(vector_size));
1444  object.clear();
1445  object.resize(vector_size);
1446  std::vector<size_type> sizes(vector_size);
1447  if (vector_size > 0)
1448  memcpy(sizes.data(),
1449  &*iterator + sizeof(vector_size),
1450  vector_size * sizeof(size_type));
1451 
1452  iterator += sizeof(vector_size) * (1 + vector_size);
1453  size_type aggregated_size = 0;
1454  for (const auto a : sizes)
1455  aggregated_size += a;
1456 
1457  Assert(static_cast<std::ptrdiff_t>(cend - iterator) ==
1458  static_cast<std::ptrdiff_t>(aggregated_size * sizeof(T)),
1459  ExcMessage("The given buffer has the wrong size."));
1460  (void)cend;
1461 
1462  // Then copy the elements:
1463  for (unsigned int i = 0; i < vector_size; ++i)
1464  if (sizes[i] > 0)
1465  {
1466  object[i].insert(object[i].end(),
1467  reinterpret_cast<const T *>(&*iterator),
1468  reinterpret_cast<const T *>(&*iterator +
1469  sizeof(T) * sizes[i]));
1470  iterator += sizeof(T) * sizes[i];
1471  }
1472 
1473  Assert(iterator == cend,
1474  ExcMessage("The given buffer has the wrong size."));
1475  }
1476 
1477  } // namespace internal
1478 
1479 
1480 
1481  template <typename T>
1482  size_t
1483  pack(const T & object,
1484  std::vector<char> &dest_buffer,
1485  const bool allow_compression)
1486  {
1487  std::size_t size = 0;
1488 
1489 
1490  // see if the object is small and copyable via memcpy. if so, use
1491  // this fast path. otherwise, we have to go through the BOOST
1492  // serialization machinery
1493 #ifdef DEAL_II_HAVE_CXX17
1494  if constexpr (std::is_trivially_copyable<T>() && sizeof(T) < 256)
1495 #else
1496  if (std::is_trivially_copyable<T>() && sizeof(T) < 256)
1497 #endif
1498  {
1499  // Determine the size. There are places where we would like to use a
1500  // truly empty type, for which we use std::tuple<> (i.e., a tuple
1501  // of zero elements). For this class, the compiler reports a nonzero
1502  // sizeof(...) because that is the minimum possible for objects --
1503  // objects need to have distinct addresses, so they need to have a size
1504  // of at least one. But we can special case this situation.
1505  size = (std::is_same<T, std::tuple<>>::value ? 0 : sizeof(T));
1506 
1507  (void)allow_compression;
1508  const std::size_t previous_size = dest_buffer.size();
1509  dest_buffer.resize(previous_size + size);
1510 
1511  if (size > 0)
1512  std::memcpy(dest_buffer.data() + previous_size, &object, size);
1513  }
1514  // Next try if we have a vector of trivially copyable objects.
1515  // If that is the case, we can shortcut the whole BOOST serialization
1516  // machinery and just copy the content of the vector bit for bit
1517  // into the output buffer, assuming that we are not asked to compress
1518  // the data.
1520  (allow_compression == false))
1521  {
1522  const std::size_t previous_size = dest_buffer.size();
1523 
1524  // When we have DEAL_II_HAVE_CXX17 set by default, we can just
1525  // inline the code of the following function here and make the 'if'
1526  // above a 'if constexpr'. Without the 'constexpr', we need to keep
1527  // the general template of the function that throws an exception.
1529  dest_buffer);
1530 
1531  size = dest_buffer.size() - previous_size;
1532  }
1533  else
1534  {
1535  // use buffer as the target of a compressing
1536  // stream into which we serialize the current object
1537  const std::size_t previous_size = dest_buffer.size();
1538  {
1539  boost::iostreams::filtering_ostreambuf fosb;
1540 #ifdef DEAL_II_WITH_ZLIB
1541  if (allow_compression)
1542  fosb.push(boost::iostreams::gzip_compressor());
1543 #else
1544  (void)allow_compression;
1545 #endif
1546  fosb.push(boost::iostreams::back_inserter(dest_buffer));
1547 
1548  boost::archive::binary_oarchive boa(fosb);
1549  boa << object;
1550  // the stream object has to be destroyed before the return statement
1551  // to ensure that all data has been written in the buffer
1552  }
1553  size = dest_buffer.size() - previous_size;
1554  }
1555 
1556  return size;
1557  }
1558 
1559 
1560  template <typename T>
1561  std::vector<char>
1562  pack(const T &object, const bool allow_compression)
1563  {
1564  std::vector<char> buffer;
1565  pack<T>(object, buffer, allow_compression);
1566  return buffer;
1567  }
1568 
1569 
1570 
1571  template <typename T>
1572  T
1573  unpack(const std::vector<char>::const_iterator &cbegin,
1574  const std::vector<char>::const_iterator &cend,
1575  const bool allow_compression)
1576  {
1577  // see if the object is small and copyable via memcpy. if so, use
1578  // this fast path. otherwise, we have to go through the BOOST
1579  // serialization machinery
1580 #ifdef DEAL_II_HAVE_CXX17
1581  if constexpr (std::is_trivially_copyable<T>() && sizeof(T) < 256)
1582 #else
1583  if (std::is_trivially_copyable<T>() && sizeof(T) < 256)
1584 #endif
1585  {
1586  // Determine the size. There are places where we would like to use a
1587  // truly empty type, for which we use std::tuple<> (i.e., a tuple
1588  // of zero elements). For this class, the compiler reports a nonzero
1589  // sizeof(...) because that is the minimum possible for objects --
1590  // objects need to have distinct addresses, so they need to have a size
1591  // of at least one. But we can special case this situation.
1592  const std::size_t size =
1593  (std::is_same<T, std::tuple<>>::value ? 0 : sizeof(T));
1594 
1595  T object;
1596 
1597  (void)allow_compression;
1598  Assert(std::distance(cbegin, cend) == size, ExcInternalError());
1599 
1600  if (size > 0)
1601  std::memcpy(&object, &*cbegin, size);
1602 
1603  return object;
1604  }
1605  // Next try if we have a vector of trivially copyable objects.
1606  // If that is the case, we can shortcut the whole BOOST serialization
1607  // machinery and just copy the content of the buffer bit for bit
1608  // into an appropriately sized output vector, assuming that we
1609  // are not asked to compress the data.
1611  (allow_compression == false))
1612  {
1613  // When we have DEAL_II_HAVE_CXX17 set by default, we can just
1614  // inline the code of the following function here and make the 'if'
1615  // above a 'if constexpr'. Without the 'constexpr', we need to keep
1616  // the general template of the function that throws an exception.
1617  T object;
1619  cend,
1620  object);
1621  return object;
1622  }
1623  else
1624  {
1625  // decompress the buffer section into the object
1626  boost::iostreams::filtering_istreambuf fisb;
1627 #ifdef DEAL_II_WITH_ZLIB
1628  if (allow_compression)
1629  fisb.push(boost::iostreams::gzip_decompressor());
1630 #else
1631  (void)allow_compression;
1632 #endif
1633  fisb.push(boost::iostreams::array_source(&*cbegin, cend - cbegin));
1634 
1635  boost::archive::binary_iarchive bia(fisb);
1636 
1637  T object;
1638  bia >> object;
1639  return object;
1640  }
1641 
1642  return T();
1643  }
1644 
1645 
1646  template <typename T>
1647  T
1648  unpack(const std::vector<char> &buffer, const bool allow_compression)
1649  {
1650  return unpack<T>(buffer.cbegin(), buffer.cend(), allow_compression);
1651  }
1652 
1653 
1654  template <typename T, int N>
1655  void
1656  unpack(const std::vector<char>::const_iterator &cbegin,
1657  const std::vector<char>::const_iterator &cend,
1658  T (&unpacked_object)[N],
1659  const bool allow_compression)
1660  {
1661  // see if the object is small and copyable via memcpy. if so, use
1662  // this fast path. otherwise, we have to go through the BOOST
1663  // serialization machinery
1664 #ifdef DEAL_II_HAVE_CXX17
1665  if constexpr (std::is_trivially_copyable<T>() && sizeof(T) * N < 256)
1666 #else
1667  if (std::is_trivially_copyable<T>() && sizeof(T) * N < 256)
1668 #endif
1669  {
1670  Assert(std::distance(cbegin, cend) == sizeof(T) * N,
1671  ExcInternalError());
1672  std::memcpy(unpacked_object, &*cbegin, sizeof(T) * N);
1673  }
1674  else
1675  {
1676  // decompress the buffer section into the object
1677  boost::iostreams::filtering_istreambuf fisb;
1678 #ifdef DEAL_II_WITH_ZLIB
1679  if (allow_compression)
1680  fisb.push(boost::iostreams::gzip_decompressor());
1681 #else
1682  (void)allow_compression;
1683 #endif
1684  fisb.push(boost::iostreams::array_source(&*cbegin, cend - cbegin));
1685 
1686  boost::archive::binary_iarchive bia(fisb);
1687  bia >> unpacked_object;
1688  }
1689  }
1690 
1691 
1692  template <typename T, int N>
1693  void
1694  unpack(const std::vector<char> &buffer,
1695  T (&unpacked_object)[N],
1696  const bool allow_compression)
1697  {
1698  unpack<T, N>(buffer.cbegin(),
1699  buffer.cend(),
1700  unpacked_object,
1701  allow_compression);
1702  }
1703 
1704 
1705 
1706  inline bool
1707  get_bit(const unsigned char number, const unsigned int n)
1708  {
1709  AssertIndexRange(n, 8);
1710 
1711  // source:
1712  // https://stackoverflow.com/questions/47981/how-do-you-set-clear-and-toggle-a-single-bit
1713  // "Checking a bit"
1714  return ((number >> n) & 1U) != 0u;
1715  }
1716 
1717 
1718 
1719  inline void
1720  set_bit(unsigned char &number, const unsigned int n, const bool x)
1721  {
1722  AssertIndexRange(n, 8);
1723 
1724  // source:
1725  // https://stackoverflow.com/questions/47981/how-do-you-set-clear-and-toggle-a-single-bit
1726  // "Changing the nth bit to x"
1727  number ^= (-static_cast<unsigned char>(x) ^ number) & (1U << n);
1728  }
1729 
1730 
1731 
1732  template <typename To, typename From>
1733  inline std::unique_ptr<To>
1734  dynamic_unique_cast(std::unique_ptr<From> &&p)
1735  {
1736  // Let's see if we can cast from 'From' to 'To'. If so, do the cast,
1737  // and then release the pointer from the old
1738  // owner
1739  if (To *cast = dynamic_cast<To *>(p.get()))
1740  {
1741  std::unique_ptr<To> result(cast);
1742  p.release();
1743  return result;
1744  }
1745  else
1746  throw std::bad_cast();
1747  }
1748 
1749 
1750 
1751  template <typename T>
1752  inline T &
1754  {
1755  return p;
1756  }
1757 
1758 
1759 
1760  template <typename T>
1761  inline T &
1762  get_underlying_value(std::shared_ptr<T> &p)
1763  {
1764  return *p;
1765  }
1766 
1767 
1768 
1769  template <typename T>
1770  inline T &
1771  get_underlying_value(const std::shared_ptr<T> &p)
1772  {
1773  return *p;
1774  }
1775 
1776 
1777 
1778  template <typename T>
1779  inline T &
1780  get_underlying_value(std::unique_ptr<T> &p)
1781  {
1782  return *p;
1783  }
1784 
1785 
1786 
1787  template <typename T>
1788  inline T &
1789  get_underlying_value(const std::unique_ptr<T> &p)
1790  {
1791  return *p;
1792  }
1793 
1794 
1795 
1796  template <typename Integer>
1797  std::vector<Integer>
1798  reverse_permutation(const std::vector<Integer> &permutation)
1799  {
1800  const std::size_t n = permutation.size();
1801 
1802  std::vector<Integer> out(n);
1803  for (std::size_t i = 0; i < n; ++i)
1804  out[i] = n - 1 - permutation[i];
1805 
1806  return out;
1807  }
1808 
1809 
1810 
1811  template <typename Integer>
1812  std::vector<Integer>
1813  invert_permutation(const std::vector<Integer> &permutation)
1814  {
1815  const std::size_t n = permutation.size();
1816 
1817  std::vector<Integer> out(n, numbers::invalid_unsigned_int);
1818 
1819  for (std::size_t i = 0; i < n; ++i)
1820  {
1821  AssertIndexRange(permutation[i], n);
1822  out[permutation[i]] = i;
1823  }
1824 
1825  // check that we have actually reached
1826  // all indices
1827  for (std::size_t i = 0; i < n; ++i)
1829  ExcMessage("The given input permutation had duplicate entries!"));
1830 
1831  return out;
1832  }
1833 } // namespace Utilities
1834 
1835 
1837 
1838 #ifndef DOXYGEN
1839 namespace boost
1840 {
1841  namespace serialization
1842  {
1843  // Provides boost and c++11 with a way to serialize tuples and pairs
1844  // automatically.
1845  template <int N>
1846  struct Serialize
1847  {
1848  template <class Archive, typename... Args>
1849  static void
1850  serialize(Archive &ar, std::tuple<Args...> &t, const unsigned int version)
1851  {
1852  ar &std::get<N - 1>(t);
1853  Serialize<N - 1>::serialize(ar, t, version);
1854  }
1855  };
1856 
1857  template <>
1858  struct Serialize<0>
1859  {
1860  template <class Archive, typename... Args>
1861  static void
1862  serialize(Archive &ar, std::tuple<Args...> &t, const unsigned int version)
1863  {
1864  (void)ar;
1865  (void)t;
1866  (void)version;
1867  }
1868  };
1869 
1870  template <class Archive, typename... Args>
1871  void
1872  serialize(Archive &ar, std::tuple<Args...> &t, const unsigned int version)
1873  {
1874  Serialize<sizeof...(Args)>::serialize(ar, t, version);
1875  }
1876  } // namespace serialization
1877 } // namespace boost
1878 #endif
1879 
1880 #endif
Definition: point.h:111
#define DEAL_II_NAMESPACE_OPEN
Definition: config.h:442
#define DEAL_II_DISABLE_EXTRA_DIAGNOSTICS
Definition: config.h:456
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:443
#define DEAL_II_FALLTHROUGH
Definition: config.h:176
#define DEAL_II_ENABLE_EXTRA_DIAGNOSTICS
Definition: config.h:495
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:1389
void append_vector_of_trivially_copyable_to_buffer(const T &, std::vector< char > &)
Definition: utilities.h:1301
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:1753
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:1144
size_t pack(const T &object, std::vector< char > &dest_buffer, const bool allow_compression=true)
Definition: utilities.h:1483
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:1707
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:1734
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:1648
T fixed_power(const T t)
Definition: utilities.h:1123
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:1153
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:1720
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:1798
std::vector< Integer > invert_permutation(const std::vector< Integer > &permutation)
Definition: utilities.h:1813
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:923
unsigned long int VmPeak
Definition: utilities.h:907
unsigned long int VmSize
Definition: utilities.h:912
unsigned long int VmHWM
Definition: utilities.h:917
const MPI_Comm & comm