Reference documentation for deal.II version GIT relicensing-245-g36f19064f7 2024-03-29 07:20: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\}}\)
Loading...
Searching...
No Matches
utilities.h
Go to the documentation of this file.
1// ------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: LGPL-2.1-or-later
4// Copyright (C) 2005 - 2024 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Part of the source code is dual licensed under Apache-2.0 WITH
9// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
10// governing the source code and code contributions can be found in
11// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
12//
13// ------------------------------------------------------------------------
14
15#ifndef dealii_utilities_h
16#define dealii_utilities_h
17
18#include <deal.II/base/config.h>
19
21
22#include <boost/archive/binary_iarchive.hpp>
23#include <boost/archive/binary_oarchive.hpp>
24#include <boost/core/demangle.hpp>
25#include <boost/iostreams/device/array.hpp>
26#include <boost/iostreams/device/back_inserter.hpp>
27#include <boost/iostreams/filtering_streambuf.hpp>
28#include <boost/serialization/array.hpp>
29#include <boost/serialization/complex.hpp>
30#include <boost/serialization/vector.hpp>
31
32#include <cstddef>
33#include <functional>
34#include <string>
35#include <tuple>
36#include <type_traits>
37#include <typeinfo>
38#include <utility>
39#include <vector>
40
41#ifdef DEAL_II_WITH_ZLIB
42# include <boost/iostreams/filter/gzip.hpp>
43#endif
44
46
47// forward declare Point
48#ifndef DOXYGEN
49template <int dim, typename Number>
51class Point;
52#endif
53
61namespace Utilities
62{
69 std::string
71
88 template <int dim, typename Number>
89 std::vector<std::array<std::uint64_t, dim>>
91 const std::vector<Point<dim, Number>> &points,
92 const int bits_per_dim = 64);
93
97 template <int dim>
98 std::vector<std::array<std::uint64_t, dim>>
100 const std::vector<std::array<std::uint64_t, dim>> &points,
101 const int bits_per_dim = 64);
102
118 template <int dim>
119 std::uint64_t
120 pack_integers(const std::array<std::uint64_t, dim> &index,
121 const int bits_per_dim);
122
135 std::string
136 compress(const std::string &input);
137
151 std::string
152 decompress(const std::string &compressed_input);
153
167 std::string
168 encode_base64(const std::vector<unsigned char> &binary_input);
169
178 std::vector<unsigned char>
179 decode_base64(const std::string &base64_input);
180
202 std::string
203 int_to_string(const unsigned int value,
204 const unsigned int digits = numbers::invalid_unsigned_int);
205
217 template <typename number>
218 std::string
219 to_string(const number value,
220 const unsigned int digits = numbers::invalid_unsigned_int);
221
226 unsigned int
227 needed_digits(const unsigned int max_number);
228
237 template <typename Number>
238 Number
239 truncate_to_n_digits(const Number number, const unsigned int n_digits);
240
245 int
246 string_to_int(const std::string &s);
247
259 std::string
260 dim_string(const int dim, const int spacedim);
261
266 std::vector<int>
267 string_to_int(const std::vector<std::string> &s);
268
273 double
274 string_to_double(const std::string &s);
275
276
281 std::vector<double>
282 string_to_double(const std::vector<std::string> &s);
283
284
327 std::vector<std::string>
328 split_string_list(const std::string &s, const std::string &delimiter = ",");
329
330
335 std::vector<std::string>
336 split_string_list(const std::string &s, const char delimiter);
337
338
348 std::vector<std::string>
349 break_text_into_lines(const std::string &original_text,
350 const unsigned int width,
351 const char delimiter = ' ');
352
357 bool
358 match_at_string_start(const std::string &name, const std::string &pattern);
359
368 std::pair<int, unsigned int>
369 get_integer_at_position(const std::string &name, const unsigned int position);
370
375 std::string
376 replace_in_string(const std::string &input,
377 const std::string &from,
378 const std::string &to);
379
385 std::string
386 trim(const std::string &input);
387
413 double
414 generate_normal_random_number(const double a, const double sigma);
415
423 template <class T>
424 std::string
425 type_to_string(const T &t);
426
452 template <int N, typename T>
453 constexpr T
454 fixed_power(const T t);
455
463 template <typename T, typename = std::enable_if_t<std::is_arithmetic_v<T>>>
464 constexpr DEAL_II_HOST_DEVICE T
465 pow(const T base, const int iexp);
466
488 template <typename Iterator, typename T>
489 Iterator
490 lower_bound(Iterator first, Iterator last, const T &val);
491
497 template <typename Iterator, typename T, typename Comp>
498 Iterator
499 lower_bound(Iterator first, Iterator last, const T &val, const Comp comp);
500
506 template <typename Integer>
507 std::vector<Integer>
508 reverse_permutation(const std::vector<Integer> &permutation);
509
515 template <typename Integer>
516 std::vector<Integer>
517 invert_permutation(const std::vector<Integer> &permutation);
518
573 template <typename T>
574 size_t
575 pack(const T &object,
576 std::vector<char> &dest_buffer,
577 const bool allow_compression = true);
578
587 template <typename T>
588 std::vector<char>
589 pack(const T &object, const bool allow_compression = true);
590
622 template <typename T>
623 T
624 unpack(const std::vector<char> &buffer, const bool allow_compression = true);
625
634 template <typename T>
635 T
636 unpack(const std::vector<char>::const_iterator &cbegin,
637 const std::vector<char>::const_iterator &cend,
638 const bool allow_compression = true);
639
672 template <typename T, int N>
673 void
674 unpack(const std::vector<char> &buffer,
675 T (&unpacked_object)[N],
676 const bool allow_compression = true);
677
686 template <typename T, int N>
687 void
688 unpack(const std::vector<char>::const_iterator &cbegin,
689 const std::vector<char>::const_iterator &cend,
690 T (&unpacked_object)[N],
691 const bool allow_compression = true);
692
696 bool
697 get_bit(const unsigned char number, const unsigned int n);
698
699
703 void
704 set_bit(unsigned char &number, const unsigned int n, const bool x);
705
706
764 template <typename To, typename From>
765 std::unique_ptr<To>
766 dynamic_unique_cast(std::unique_ptr<From> &&p);
767
771 template <typename T>
772 T &
774
778 template <typename T>
779 T &
780 get_underlying_value(std::shared_ptr<T> &p);
781
785 template <typename T>
786 T &
787 get_underlying_value(const std::shared_ptr<T> &p);
788
792 template <typename T>
793 T &
794 get_underlying_value(std::unique_ptr<T> &p);
795
799 template <typename T>
800 T &
801 get_underlying_value(const std::unique_ptr<T> &p);
802
808 namespace System
809 {
817 double
818 get_cpu_load();
819
853 std::string
855
861 {
865 unsigned long int VmPeak;
866
870 unsigned long int VmSize;
871
875 unsigned long int VmHWM;
876
881 unsigned long int VmRSS;
882 };
883
884
889 void
891
892
896 std::string
897 get_hostname();
898
899
903 std::string
904 get_time();
905
910 std::string
911 get_date();
912
927 void
928 posix_memalign(void **memptr, std::size_t alignment, std::size_t size);
929 } // namespace System
930} // namespace Utilities
931
932
933// --------------------- inline functions
934
935namespace Utilities
936{
937 template <int N, typename T>
938 inline constexpr T
939 fixed_power(const T x)
940 {
941 Assert(((std::is_integral_v<T> == true) && (N >= 0)) ||
942 (std::is_integral_v<T> == false),
943 ExcMessage("If the type of the argument, T, is an integer type, "
944 "then the exponent N must be a non-negative integer "
945 "because the result would otherwise not be an integer."));
946
947 if (N == 0)
948 return T(1.);
949 else if (N < 0)
950 // For negative exponents, turn things into a positive exponent
951 return T(1.) / fixed_power<-N>(x);
952 else
953 // If we get here, we have a positive exponent. Compute the result
954 // by repeated squaring:
955 return ((N % 2 == 1) ? x * fixed_power<N / 2>(x * x) :
956 fixed_power<N / 2>(x * x));
957 }
958
959
960
961 template <typename T, typename>
962 constexpr DEAL_II_HOST_DEVICE T
963 pow(const T base, const int iexp)
964 {
965#if defined(DEBUG) && !defined(DEAL_II_CXX14_CONSTEXPR_BUG)
966 // Up to __builtin_expect this is the same code as in the 'Assert' macro.
967 // The call to __builtin_expect turns out to be problematic.
968# if KOKKOS_VERSION >= 30600
969 KOKKOS_IF_ON_HOST(({
970 if (!(iexp >= 0))
973 abort_or_throw_on_exception,
974 __FILE__,
975 __LINE__,
976 __PRETTY_FUNCTION__,
977 "iexp>=0",
978 "ExcMessage(\"The exponent must not be negative!\")",
979 ExcMessage("The exponent must not be negative!"));
980 }))
981# else
982# ifdef KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST
983 if (!(iexp >= 0))
986 abort_or_throw_on_exception,
987 __FILE__,
988 __LINE__,
989 __PRETTY_FUNCTION__,
990 "iexp>=0",
991 "ExcMessage(\"The exponent must not be negative!\")",
992 ExcMessage("The exponent must not be negative!"));
993# endif
994# endif
995#endif
996 // The "exponentiation by squaring" algorithm used below has to be expressed
997 // in an iterative version since SYCL doesn't allow recursive functions used
998 // in device code.
999
1000 if (iexp <= 0)
1001 return 1;
1002
1003 int exp = iexp;
1004 T x = base;
1005 T y = 1;
1006 while (exp > 1)
1007 {
1008 if (exp % 2 == 1)
1009 y *= x;
1010 x *= x;
1011 exp /= 2;
1012 }
1013 return x * y;
1014 }
1015
1016
1017
1018 template <class T>
1019 inline std::string
1020 type_to_string(const T &t)
1021 {
1022 return boost::core::demangle(typeid(t).name());
1023 }
1024
1025
1026
1027 template <typename Iterator, typename T>
1028 inline Iterator
1029 lower_bound(Iterator first, Iterator last, const T &val)
1030 {
1031 return Utilities::lower_bound(first, last, val, std::less<T>());
1032 }
1033
1034
1035
1036 template <typename Iterator, typename T, typename Comp>
1037 inline Iterator
1038 lower_bound(Iterator first, Iterator last, const T &val, const Comp comp)
1039 {
1040 // verify that the two iterators are properly ordered. since
1041 // we need operator- for the iterator type anyway, do the
1042 // test as follows, rather than via 'last >= first'
1043 Assert(last - first >= 0,
1044 ExcMessage(
1045 "The given iterators do not satisfy the proper ordering."));
1046
1047 unsigned int len = static_cast<unsigned int>(last - first);
1048
1049 if (len == 0)
1050 return first;
1051
1052 while (true)
1053 {
1054 // if length equals 8 or less,
1055 // then do a rolled out
1056 // search. use a switch without
1057 // breaks for that and roll-out
1058 // the loop somehow
1059 if (len < 8)
1060 {
1061 switch (len)
1062 {
1063 case 7:
1064 if (!comp(*first, val))
1065 return first;
1066 ++first;
1068 case 6:
1069 if (!comp(*first, val))
1070 return first;
1071 ++first;
1073 case 5:
1074 if (!comp(*first, val))
1075 return first;
1076 ++first;
1078 case 4:
1079 if (!comp(*first, val))
1080 return first;
1081 ++first;
1083 case 3:
1084 if (!comp(*first, val))
1085 return first;
1086 ++first;
1088 case 2:
1089 if (!comp(*first, val))
1090 return first;
1091 ++first;
1093 case 1:
1094 if (!comp(*first, val))
1095 return first;
1096 return first + 1;
1097 default:
1098 // indices seem
1099 // to not be
1100 // sorted
1101 // correctly!? or
1102 // did len
1103 // become==0
1104 // somehow? that
1105 // shouldn't have
1106 // happened
1108 }
1109 }
1110
1111
1112
1113 const unsigned int half = len >> 1;
1114 const Iterator middle = first + half;
1115
1116 // if the value is larger than
1117 // that pointed to by the
1118 // middle pointer, then the
1119 // insertion point must be
1120 // right of it
1121 if (comp(*middle, val))
1122 {
1123 first = middle + 1;
1124 len -= half + 1;
1125 }
1126 else
1127 len = half;
1128 }
1129 }
1130
1131
1132 // --------------------- non-inline functions
1133
1134 namespace internal
1135 {
1141 template <typename T>
1143 {
1144 static constexpr bool value = false;
1145 };
1146
1147
1148
1149 template <typename T>
1151 {
1152 static constexpr bool value =
1153 std::is_trivially_copyable_v<T> && !std::is_same_v<T, bool>;
1154 };
1155
1156
1157
1158 template <typename T>
1159 struct IsVectorOfTriviallyCopyable<std::vector<std::vector<T>>>
1160 {
1161 static constexpr bool value =
1162 std::is_trivially_copyable_v<T> && !std::is_same_v<T, bool>;
1163 };
1164
1165
1166
1175 template <typename T>
1176 inline void
1178 std::vector<char> &)
1179 {
1180 // We shouldn't get here:
1182 }
1183
1184
1185
1186 template <typename T,
1187 typename = std::enable_if_t<!std::is_same_v<T, bool> &&
1188 std::is_trivially_copyable_v<T>>>
1189 inline void
1191 const std::vector<T> &object,
1192 std::vector<char> &dest_buffer)
1193 {
1194 const typename std::vector<T>::size_type vector_size = object.size();
1195
1196 // Reserve for the buffer so that it can store the size of 'object' as
1197 // well as all of its elements.
1198 dest_buffer.reserve(dest_buffer.size() + sizeof(vector_size) +
1199 vector_size * sizeof(T));
1200
1201 // Copy the size into the vector
1202 dest_buffer.insert(dest_buffer.end(),
1203 reinterpret_cast<const char *>(&vector_size),
1204 reinterpret_cast<const char *>(&vector_size + 1));
1205
1206 // Insert the elements at the end of the vector:
1207 if (vector_size > 0)
1208 dest_buffer.insert(dest_buffer.end(),
1209 reinterpret_cast<const char *>(object.data()),
1210 reinterpret_cast<const char *>(object.data() +
1211 vector_size));
1212 }
1213
1214
1215
1216 template <typename T,
1217 typename = std::enable_if_t<!std::is_same_v<T, bool> &&
1218 std::is_trivially_copyable_v<T>>>
1219 inline void
1221 const std::vector<std::vector<T>> &object,
1222 std::vector<char> &dest_buffer)
1223 {
1224 using size_type = typename std::vector<T>::size_type;
1225 const size_type vector_size = object.size();
1226
1227 typename std::vector<T>::size_type aggregated_size = 0;
1228 std::vector<size_type> sizes;
1229 sizes.reserve(vector_size);
1230 for (const auto &a : object)
1231 {
1232 aggregated_size += a.size();
1233 sizes.push_back(a.size());
1234 }
1235
1236 // Reserve for the buffer so that it can store the size of 'object' as
1237 // well as all of its elements.
1238 dest_buffer.reserve(dest_buffer.size() +
1239 sizeof(vector_size) * (1 + vector_size) +
1240 aggregated_size * sizeof(T));
1241
1242 // Copy the size into the vector
1243 dest_buffer.insert(dest_buffer.end(),
1244 reinterpret_cast<const char *>(&vector_size),
1245 reinterpret_cast<const char *>(&vector_size + 1));
1246
1247 // Copy the sizes of the individual chunks into the vector
1248 if (vector_size > 0)
1249 dest_buffer.insert(dest_buffer.end(),
1250 reinterpret_cast<const char *>(sizes.data()),
1251 reinterpret_cast<const char *>(sizes.data() +
1252 vector_size));
1253
1254 // Insert the elements at the end of the vector:
1255 for (const auto &a : object)
1256 dest_buffer.insert(dest_buffer.end(),
1257 reinterpret_cast<const char *>(a.data()),
1258 reinterpret_cast<const char *>(a.data() + a.size()));
1259 }
1260
1261
1262
1263 template <typename T>
1264 inline void
1266 const std::vector<char>::const_iterator &,
1267 const std::vector<char>::const_iterator &,
1268 T &)
1269 {
1270 // We shouldn't get here:
1272 }
1273
1274
1275
1276 template <typename T,
1277 typename = std::enable_if_t<!std::is_same_v<T, bool> &&
1278 std::is_trivially_copyable_v<T>>>
1279 inline void
1281 const std::vector<char>::const_iterator &cbegin,
1282 const std::vector<char>::const_iterator &cend,
1283 std::vector<T> &object)
1284 {
1285 // The size of the object vector can be found in cbegin of the buffer.
1286 // The data starts at cbegin + sizeof(vector_size).
1287
1288 // Get the size of the vector
1289 typename std::vector<T>::size_type vector_size;
1290 memcpy(&vector_size, &*cbegin, sizeof(vector_size));
1291
1292 Assert(static_cast<std::ptrdiff_t>(cend - cbegin) ==
1293 static_cast<std::ptrdiff_t>(sizeof(vector_size) +
1294 vector_size * sizeof(T)),
1295 ExcMessage("The given buffer has the wrong size."));
1296 (void)cend;
1297
1298 // Resize the output array and copy the elements into it. We need
1299 // to make sure that we don't access the buffer via a
1300 // reinterpret_cast<T*> because the T objects in the buffer may
1301 // not be aligned properly. Rather, use memcpy, which doesn't care
1302 // about alignment and is correct in this situation because we
1303 // are dealing with trivially copyable objects.
1304 //
1305 // (Strictly speaking, this writes into the output object twice, once
1306 // for the resize() operation and once during memcpy. This could be
1307 // avoided by (i) checking whether the point is aligned, using for
1308 // example boost::alignment::is_aligned(), and (ii) if the data
1309 // is aligned, re-create the output vector using
1310 // object.clear();
1311 // object.insert (object.end(),
1312 // (T*)(&*cbegin + sizeof(vector_size)),
1313 // (T*)(&*cbegin + sizeof(vector_size)) + vector_size);
1314 // In practice, the difference is likely rather small, assuming the
1315 // compiler does not already optimize away the first initialization.
1316 object.resize(vector_size);
1317 if (vector_size > 0)
1318 std::memcpy(object.data(),
1319 &*cbegin + sizeof(vector_size),
1320 vector_size * sizeof(T));
1321 }
1322
1323
1324
1325 template <typename T,
1326 typename = std::enable_if_t<!std::is_same_v<T, bool> &&
1327 std::is_trivially_copyable_v<T>>>
1328 inline void
1330 const std::vector<char>::const_iterator &cbegin,
1331 const std::vector<char>::const_iterator &cend,
1332 std::vector<std::vector<T>> &object)
1333 {
1334 // First get the size of the vector, and resize the output object
1335 using size_type = typename std::vector<T>::size_type;
1336 std::vector<char>::const_iterator iterator = cbegin;
1337 size_type vector_size;
1338 memcpy(&vector_size, &*iterator, sizeof(vector_size));
1339 object.clear();
1340 object.resize(vector_size);
1341 std::vector<size_type> sizes(vector_size);
1342 if (vector_size > 0)
1343 std::memcpy(sizes.data(),
1344 &*iterator + sizeof(vector_size),
1345 vector_size * sizeof(size_type));
1346
1347 iterator += sizeof(vector_size) * (1 + vector_size);
1348 size_type aggregated_size = 0;
1349 for (const auto a : sizes)
1350 aggregated_size += a;
1351
1352 Assert(static_cast<std::ptrdiff_t>(cend - iterator) ==
1353 static_cast<std::ptrdiff_t>(aggregated_size * sizeof(T)),
1354 ExcMessage("The given buffer has the wrong size."));
1355 (void)cend;
1356
1357 // Then copy the elements. As for the previous function, use memcpy
1358 // rather than accessing the data via reinterpret_cast<T*> to
1359 // avoid alignment issues.
1360 for (unsigned int i = 0; i < vector_size; ++i)
1361 if (sizes[i] > 0)
1362 {
1363 object[i].resize(sizes[i]);
1364 std::memcpy(object[i].data(), &*iterator, sizes[i] * sizeof(T));
1365 iterator += sizes[i] * sizeof(T);
1366 }
1367
1368 Assert(iterator == cend,
1369 ExcMessage("The given buffer has the wrong size."));
1370 }
1371
1372 } // namespace internal
1373
1374
1375
1376 template <typename T>
1377 size_t
1378 pack(const T &object,
1379 std::vector<char> &dest_buffer,
1380 const bool allow_compression)
1381 {
1382 std::size_t size = 0;
1383
1384
1385 // see if the object is small and copyable via memcpy. if so, use
1386 // this fast path. otherwise, we have to go through the BOOST
1387 // serialization machinery
1388 if constexpr (std::is_trivially_copyable<T>() && sizeof(T) < 256)
1389 {
1390 // Determine the size. There are places where we would like to use a
1391 // truly empty type, for which we use std::tuple<> (i.e., a tuple
1392 // of zero elements). For this class, the compiler reports a nonzero
1393 // sizeof(...) because that is the minimum possible for objects --
1394 // objects need to have distinct addresses, so they need to have a size
1395 // of at least one. But we can special case this situation.
1396 size = (std::is_same_v<T, std::tuple<>> ? 0 : sizeof(T));
1397
1398 (void)allow_compression;
1399 const std::size_t previous_size = dest_buffer.size();
1400 dest_buffer.resize(previous_size + size);
1401
1402 if (size > 0)
1403 std::memcpy(dest_buffer.data() + previous_size, &object, size);
1404 }
1405 // Next try if we have a vector of trivially copyable objects.
1406 // If that is the case, we can shortcut the whole BOOST serialization
1407 // machinery and just copy the content of the vector bit for bit
1408 // into the output buffer, assuming that we are not asked to compress
1409 // the data.
1411 (allow_compression == false))
1412 {
1413 const std::size_t previous_size = dest_buffer.size();
1414
1415 // When we have DEAL_II_HAVE_CXX17 set by default, we can just
1416 // inline the code of the following function here and make the 'if'
1417 // above a 'if constexpr'. Without the 'constexpr', we need to keep
1418 // the general template of the function that throws an exception.
1420 dest_buffer);
1421
1422 size = dest_buffer.size() - previous_size;
1423 }
1424 else
1425 {
1426 // use buffer as the target of a compressing
1427 // stream into which we serialize the current object
1428 const std::size_t previous_size = dest_buffer.size();
1429 {
1430 boost::iostreams::filtering_ostreambuf fosb;
1431#ifdef DEAL_II_WITH_ZLIB
1432 if (allow_compression)
1433 fosb.push(boost::iostreams::gzip_compressor());
1434#else
1435 (void)allow_compression;
1436#endif
1437 fosb.push(boost::iostreams::back_inserter(dest_buffer));
1438
1439 boost::archive::binary_oarchive boa(fosb);
1440 boa << object;
1441 // the stream object has to be destroyed before the return statement
1442 // to ensure that all data has been written in the buffer
1443 }
1444 size = dest_buffer.size() - previous_size;
1445 }
1446
1447 return size;
1448 }
1449
1450
1451 template <typename T>
1452 std::vector<char>
1453 pack(const T &object, const bool allow_compression)
1454 {
1455 std::vector<char> buffer;
1456 pack<T>(object, buffer, allow_compression);
1457 return buffer;
1458 }
1459
1460
1461
1462 template <typename T>
1463 T
1464 unpack(const std::vector<char>::const_iterator &cbegin,
1465 const std::vector<char>::const_iterator &cend,
1466 const bool allow_compression)
1467 {
1468 // see if the object is small and copyable via memcpy. if so, use
1469 // this fast path. otherwise, we have to go through the BOOST
1470 // serialization machinery
1471 if constexpr (std::is_trivially_copyable<T>() && sizeof(T) < 256)
1472 {
1473 // Determine the size. There are places where we would like to use a
1474 // truly empty type, for which we use std::tuple<> (i.e., a tuple
1475 // of zero elements). For this class, the compiler reports a nonzero
1476 // sizeof(...) because that is the minimum possible for objects --
1477 // objects need to have distinct addresses, so they need to have a size
1478 // of at least one. But we can special case this situation.
1479 const std::size_t size =
1480 (std::is_same_v<T, std::tuple<>> ? 0 : sizeof(T));
1481
1482 T object;
1483
1484 (void)allow_compression;
1485 Assert(std::distance(cbegin, cend) == size, ExcInternalError());
1486
1487 if (size > 0)
1488 std::memcpy(&object, &*cbegin, size);
1489
1490 return object;
1491 }
1492 // Next try if we have a vector of trivially copyable objects.
1493 // If that is the case, we can shortcut the whole BOOST serialization
1494 // machinery and just copy the content of the buffer bit for bit
1495 // into an appropriately sized output vector, assuming that we
1496 // are not asked to compress the data.
1498 (allow_compression == false))
1499 {
1500 // When we have DEAL_II_HAVE_CXX17 set by default, we can just
1501 // inline the code of the following function here and make the 'if'
1502 // above a 'if constexpr'. Without the 'constexpr', we need to keep
1503 // the general template of the function that throws an exception.
1504 T object;
1506 cend,
1507 object);
1508 return object;
1509 }
1510 else
1511 {
1512 // decompress the buffer section into the object
1513 boost::iostreams::filtering_istreambuf fisb;
1514#ifdef DEAL_II_WITH_ZLIB
1515 if (allow_compression)
1516 fisb.push(boost::iostreams::gzip_decompressor());
1517#else
1518 (void)allow_compression;
1519#endif
1520 fisb.push(boost::iostreams::array_source(&*cbegin, cend - cbegin));
1521
1522 boost::archive::binary_iarchive bia(fisb);
1523
1524 T object;
1525 bia >> object;
1526 return object;
1527 }
1528
1529 return T();
1530 }
1531
1532
1533 template <typename T>
1534 T
1535 unpack(const std::vector<char> &buffer, const bool allow_compression)
1536 {
1537 return unpack<T>(buffer.cbegin(), buffer.cend(), allow_compression);
1538 }
1539
1540
1541 template <typename T, int N>
1542 void
1543 unpack(const std::vector<char>::const_iterator &cbegin,
1544 const std::vector<char>::const_iterator &cend,
1545 T (&unpacked_object)[N],
1546 const bool allow_compression)
1547 {
1548 // see if the object is small and copyable via memcpy. if so, use
1549 // this fast path. otherwise, we have to go through the BOOST
1550 // serialization machinery
1551 if constexpr (std::is_trivially_copyable<T>() && sizeof(T) * N < 256)
1552 {
1553 Assert(std::distance(cbegin, cend) == sizeof(T) * N,
1555 std::memcpy(unpacked_object, &*cbegin, sizeof(T) * N);
1556 }
1557 else
1558 {
1559 // decompress the buffer section into the object
1560 boost::iostreams::filtering_istreambuf fisb;
1561#ifdef DEAL_II_WITH_ZLIB
1562 if (allow_compression)
1563 fisb.push(boost::iostreams::gzip_decompressor());
1564#else
1565 (void)allow_compression;
1566#endif
1567 fisb.push(boost::iostreams::array_source(&*cbegin, cend - cbegin));
1568
1569 boost::archive::binary_iarchive bia(fisb);
1570 bia >> unpacked_object;
1571 }
1572 }
1573
1574
1575 template <typename T, int N>
1576 void
1577 unpack(const std::vector<char> &buffer,
1578 T (&unpacked_object)[N],
1579 const bool allow_compression)
1580 {
1581 unpack<T, N>(buffer.cbegin(),
1582 buffer.cend(),
1583 unpacked_object,
1584 allow_compression);
1585 }
1586
1587
1588
1589 inline bool
1590 get_bit(const unsigned char number, const unsigned int n)
1591 {
1592 AssertIndexRange(n, 8);
1593
1594 // source:
1595 // https://stackoverflow.com/questions/47981/how-do-you-set-clear-and-toggle-a-single-bit
1596 // "Checking a bit"
1597 return ((number >> n) & 1U) != 0u;
1598 }
1599
1600
1601
1602 inline void
1603 set_bit(unsigned char &number, const unsigned int n, const bool x)
1604 {
1605 AssertIndexRange(n, 8);
1606
1607 // source:
1608 // https://stackoverflow.com/questions/47981/how-do-you-set-clear-and-toggle-a-single-bit
1609 // "Changing the nth bit to x"
1610 number ^= (-static_cast<unsigned char>(x) ^ number) & (1U << n);
1611 }
1612
1613
1614
1615 template <typename To, typename From>
1616 inline std::unique_ptr<To>
1617 dynamic_unique_cast(std::unique_ptr<From> &&p)
1618 {
1619 // Let's see if we can cast from 'From' to 'To'. If so, do the cast,
1620 // and then release the pointer from the old
1621 // owner
1622 if (To *cast = dynamic_cast<To *>(p.get()))
1623 {
1624 std::unique_ptr<To> result(cast);
1625 p.release();
1626 return result;
1627 }
1628 else
1629 throw std::bad_cast();
1630 }
1631
1632
1633
1634 template <typename T>
1635 inline T &
1637 {
1638 return p;
1639 }
1640
1641
1642
1643 template <typename T>
1644 inline T &
1645 get_underlying_value(std::shared_ptr<T> &p)
1646 {
1647 return *p;
1648 }
1649
1650
1651
1652 template <typename T>
1653 inline T &
1654 get_underlying_value(const std::shared_ptr<T> &p)
1655 {
1656 return *p;
1657 }
1658
1659
1660
1661 template <typename T>
1662 inline T &
1663 get_underlying_value(std::unique_ptr<T> &p)
1664 {
1665 return *p;
1666 }
1667
1668
1669
1670 template <typename T>
1671 inline T &
1672 get_underlying_value(const std::unique_ptr<T> &p)
1673 {
1674 return *p;
1675 }
1676
1677
1678
1679 template <typename Integer>
1680 std::vector<Integer>
1681 reverse_permutation(const std::vector<Integer> &permutation)
1682 {
1683 const std::size_t n = permutation.size();
1684
1685 std::vector<Integer> out(n);
1686 for (std::size_t i = 0; i < n; ++i)
1687 out[i] = n - 1 - permutation[i];
1688
1689 return out;
1690 }
1691
1692
1693
1694 template <typename Integer>
1695 std::vector<Integer>
1696 invert_permutation(const std::vector<Integer> &permutation)
1697 {
1698 const std::size_t n = permutation.size();
1699
1700 std::vector<Integer> out(n, numbers::invalid_unsigned_int);
1701
1702 for (std::size_t i = 0; i < n; ++i)
1703 {
1704 AssertIndexRange(permutation[i], n);
1705 out[permutation[i]] = i;
1706 }
1707
1708 // check that we have actually reached
1709 // all indices
1710 for (std::size_t i = 0; i < n; ++i)
1712 ExcMessage("The given input permutation had duplicate entries!"));
1713
1714 return out;
1715 }
1716} // namespace Utilities
1717
1718
1720
1721#ifndef DOXYGEN
1722namespace boost
1723{
1724 namespace serialization
1725 {
1726 // Provides boost and c++11 with a way to serialize tuples and pairs
1727 // automatically.
1728 template <int N>
1729 struct Serialize
1730 {
1731 template <class Archive, typename... Args>
1732 static void
1733 serialize(Archive &ar, std::tuple<Args...> &t, const unsigned int version)
1734 {
1735 ar &std::get<N - 1>(t);
1736 Serialize<N - 1>::serialize(ar, t, version);
1737 }
1738 };
1739
1740 template <>
1741 struct Serialize<0>
1742 {
1743 template <class Archive, typename... Args>
1744 static void
1745 serialize(Archive &ar, std::tuple<Args...> &t, const unsigned int version)
1746 {
1747 (void)ar;
1748 (void)t;
1749 (void)version;
1750 }
1751 };
1752
1753 template <class Archive, typename... Args>
1754 void
1755 serialize(Archive &ar, std::tuple<Args...> &t, const unsigned int version)
1756 {
1757 Serialize<sizeof...(Args)>::serialize(ar, t, version);
1758 }
1759 } // namespace serialization
1760} // namespace boost
1761#endif
1762
1763#endif
Definition point.h:111
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:502
#define DEAL_II_CXX20_REQUIRES(condition)
Definition config.h:177
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:503
#define DEAL_II_FALLTHROUGH
Definition config.h:235
Point< 2 > first
Definition grid_out.cc:4613
#define Assert(cond, exc)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcMessage(std::string arg1)
#define DEAL_II_ASSERT_UNREACHABLE()
void get_memory_stats(MemoryStats &stats)
Definition utilities.cc:964
std::string get_hostname()
Definition utilities.cc:998
std::string get_time()
void posix_memalign(void **memptr, std::size_t alignment, std::size_t size)
double get_cpu_load()
Definition utilities.cc:930
std::string get_current_vectorization_level()
Definition utilities.cc:938
std::string get_date()
void create_vector_of_trivially_copyable_from_buffer(const std::vector< char >::const_iterator &, const std::vector< char >::const_iterator &, T &)
Definition utilities.h:1265
void append_vector_of_trivially_copyable_to_buffer(const T &, std::vector< char > &)
Definition utilities.h:1177
std::vector< std::string > split_string_list(const std::string &s, const std::string &delimiter=",")
Definition utilities.cc:701
T & get_underlying_value(T &p)
Definition utilities.h:1636
Number truncate_to_n_digits(const Number number, const unsigned int n_digits)
Definition utilities.cc:578
std::string type_to_string(const T &t)
Definition utilities.h:1020
size_t pack(const T &object, std::vector< char > &dest_buffer, const bool allow_compression=true)
Definition utilities.h:1378
std::string dim_string(const int dim, const int spacedim)
Definition utilities.cc:555
std::uint64_t pack_integers(const std::array< std::uint64_t, dim > &index, const int bits_per_dim)
Definition utilities.cc:366
bool get_bit(const unsigned char number, const unsigned int n)
Definition utilities.h:1590
std::pair< int, unsigned int > get_integer_at_position(const std::string &name, const unsigned int position)
Definition utilities.cc:847
std::string encode_base64(const std::vector< unsigned char > &binary_input)
Definition utilities.cc:433
std::unique_ptr< To > dynamic_unique_cast(std::unique_ptr< From > &&p)
Definition utilities.h:1617
constexpr T fixed_power(const T t)
Definition utilities.h:939
std::string replace_in_string(const std::string &input, const std::string &from, const std::string &to)
Definition utilities.cc:509
std::vector< unsigned char > decode_base64(const std::string &base64_input)
Definition utilities.cc:446
std::vector< std::string > break_text_into_lines(const std::string &original_text, const unsigned int width, const char delimiter=' ')
Definition utilities.cc:755
std::string to_string(const number value, const unsigned int digits=numbers::invalid_unsigned_int)
Definition utilities.cc:479
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:145
std::string compress(const std::string &input)
Definition utilities.cc:389
std::string int_to_string(const unsigned int value, const unsigned int digits=numbers::invalid_unsigned_int)
Definition utilities.cc:470
bool match_at_string_start(const std::string &name, const std::string &pattern)
Definition utilities.cc:832
T unpack(const std::vector< char > &buffer, const bool allow_compression=true)
Definition utilities.h:1535
std::string decompress(const std::string &compressed_input)
Definition utilities.cc:411
unsigned int needed_digits(const unsigned int max_number)
Definition utilities.cc:565
Iterator lower_bound(Iterator first, Iterator last, const T &val)
Definition utilities.h:1029
double string_to_double(const std::string &s)
Definition utilities.cc:653
std::string dealii_version_string()
Definition utilities.cc:94
void set_bit(unsigned char &number, const unsigned int n, const bool x)
Definition utilities.h:1603
constexpr T pow(const T base, const int iexp)
Definition utilities.h:963
std::string trim(const std::string &input)
Definition utilities.cc:528
double generate_normal_random_number(const double a, const double sigma)
Definition utilities.cc:889
std::vector< Integer > reverse_permutation(const std::vector< Integer > &permutation)
Definition utilities.h:1681
std::vector< Integer > invert_permutation(const std::vector< Integer > &permutation)
Definition utilities.h:1696
int string_to_int(const std::string &s)
Definition utilities.cc:605
void issue_error_noreturn(ExceptionHandling handling, const char *file, int line, const char *function, const char *cond, const char *exc_name, ExceptionType e)
static const unsigned int invalid_unsigned_int
Definition types.h:220
STL namespace.
#define DEAL_II_HOST_DEVICE
Definition numbers.h:34