Reference documentation for deal.II version 9.4.1
\(\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\}}\)
Loading...
Searching...
No Matches
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
66template <int dim, typename Number>
67class Point;
68#endif
69
77namespace 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
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>> &
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
1119namespace 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>
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,
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
1839namespace 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
#define Assert(cond, exc)
Definition: exceptions.h:1473
#define AssertIndexRange(index, range)
Definition: exceptions.h:1732
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcMessage(std::string arg1)
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::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::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::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
STL namespace.
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