Reference documentation for deal.II version GIT relicensing-31-gf283a0fc39 2024-02-29 06:50: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 // Copy the elements:
1299 object.clear();
1300 if (vector_size > 0)
1301 {
1302 const T *const buffer_data_begin =
1303 reinterpret_cast<const T *>(&*cbegin + sizeof(vector_size));
1304 const T *const buffer_data_end = buffer_data_begin + vector_size;
1305 object.insert(object.end(), buffer_data_begin, buffer_data_end);
1306 }
1307 }
1308
1309
1310
1311 template <typename T,
1312 typename = std::enable_if_t<!std::is_same_v<T, bool> &&
1313 std::is_trivially_copyable_v<T>>>
1314 inline void
1316 const std::vector<char>::const_iterator &cbegin,
1317 const std::vector<char>::const_iterator &cend,
1318 std::vector<std::vector<T>> &object)
1319 {
1320 // First get the size of the vector, and resize the output object
1321 using size_type = typename std::vector<T>::size_type;
1322 std::vector<char>::const_iterator iterator = cbegin;
1323 size_type vector_size;
1324 memcpy(&vector_size, &*iterator, sizeof(vector_size));
1325 object.clear();
1326 object.resize(vector_size);
1327 std::vector<size_type> sizes(vector_size);
1328 if (vector_size > 0)
1329 memcpy(sizes.data(),
1330 &*iterator + sizeof(vector_size),
1331 vector_size * sizeof(size_type));
1332
1333 iterator += sizeof(vector_size) * (1 + vector_size);
1334 size_type aggregated_size = 0;
1335 for (const auto a : sizes)
1336 aggregated_size += a;
1337
1338 Assert(static_cast<std::ptrdiff_t>(cend - iterator) ==
1339 static_cast<std::ptrdiff_t>(aggregated_size * sizeof(T)),
1340 ExcMessage("The given buffer has the wrong size."));
1341 (void)cend;
1342
1343 // Then copy the elements:
1344 for (unsigned int i = 0; i < vector_size; ++i)
1345 if (sizes[i] > 0)
1346 {
1347 object[i].insert(object[i].end(),
1348 reinterpret_cast<const T *>(&*iterator),
1349 reinterpret_cast<const T *>(&*iterator +
1350 sizeof(T) * sizes[i]));
1351 iterator += sizeof(T) * sizes[i];
1352 }
1353
1354 Assert(iterator == cend,
1355 ExcMessage("The given buffer has the wrong size."));
1356 }
1357
1358 } // namespace internal
1359
1360
1361
1362 template <typename T>
1363 size_t
1364 pack(const T &object,
1365 std::vector<char> &dest_buffer,
1366 const bool allow_compression)
1367 {
1368 std::size_t size = 0;
1369
1370
1371 // see if the object is small and copyable via memcpy. if so, use
1372 // this fast path. otherwise, we have to go through the BOOST
1373 // serialization machinery
1374 if constexpr (std::is_trivially_copyable<T>() && sizeof(T) < 256)
1375 {
1376 // Determine the size. There are places where we would like to use a
1377 // truly empty type, for which we use std::tuple<> (i.e., a tuple
1378 // of zero elements). For this class, the compiler reports a nonzero
1379 // sizeof(...) because that is the minimum possible for objects --
1380 // objects need to have distinct addresses, so they need to have a size
1381 // of at least one. But we can special case this situation.
1382 size = (std::is_same_v<T, std::tuple<>> ? 0 : sizeof(T));
1383
1384 (void)allow_compression;
1385 const std::size_t previous_size = dest_buffer.size();
1386 dest_buffer.resize(previous_size + size);
1387
1388 if (size > 0)
1389 std::memcpy(dest_buffer.data() + previous_size, &object, size);
1390 }
1391 // Next try if we have a vector of trivially copyable objects.
1392 // If that is the case, we can shortcut the whole BOOST serialization
1393 // machinery and just copy the content of the vector bit for bit
1394 // into the output buffer, assuming that we are not asked to compress
1395 // the data.
1397 (allow_compression == false))
1398 {
1399 const std::size_t previous_size = dest_buffer.size();
1400
1401 // When we have DEAL_II_HAVE_CXX17 set by default, we can just
1402 // inline the code of the following function here and make the 'if'
1403 // above a 'if constexpr'. Without the 'constexpr', we need to keep
1404 // the general template of the function that throws an exception.
1406 dest_buffer);
1407
1408 size = dest_buffer.size() - previous_size;
1409 }
1410 else
1411 {
1412 // use buffer as the target of a compressing
1413 // stream into which we serialize the current object
1414 const std::size_t previous_size = dest_buffer.size();
1415 {
1416 boost::iostreams::filtering_ostreambuf fosb;
1417#ifdef DEAL_II_WITH_ZLIB
1418 if (allow_compression)
1419 fosb.push(boost::iostreams::gzip_compressor());
1420#else
1421 (void)allow_compression;
1422#endif
1423 fosb.push(boost::iostreams::back_inserter(dest_buffer));
1424
1425 boost::archive::binary_oarchive boa(fosb);
1426 boa << object;
1427 // the stream object has to be destroyed before the return statement
1428 // to ensure that all data has been written in the buffer
1429 }
1430 size = dest_buffer.size() - previous_size;
1431 }
1432
1433 return size;
1434 }
1435
1436
1437 template <typename T>
1438 std::vector<char>
1439 pack(const T &object, const bool allow_compression)
1440 {
1441 std::vector<char> buffer;
1442 pack<T>(object, buffer, allow_compression);
1443 return buffer;
1444 }
1445
1446
1447
1448 template <typename T>
1449 T
1450 unpack(const std::vector<char>::const_iterator &cbegin,
1451 const std::vector<char>::const_iterator &cend,
1452 const bool allow_compression)
1453 {
1454 // see if the object is small and copyable via memcpy. if so, use
1455 // this fast path. otherwise, we have to go through the BOOST
1456 // serialization machinery
1457 if constexpr (std::is_trivially_copyable<T>() && sizeof(T) < 256)
1458 {
1459 // Determine the size. There are places where we would like to use a
1460 // truly empty type, for which we use std::tuple<> (i.e., a tuple
1461 // of zero elements). For this class, the compiler reports a nonzero
1462 // sizeof(...) because that is the minimum possible for objects --
1463 // objects need to have distinct addresses, so they need to have a size
1464 // of at least one. But we can special case this situation.
1465 const std::size_t size =
1466 (std::is_same_v<T, std::tuple<>> ? 0 : sizeof(T));
1467
1468 T object;
1469
1470 (void)allow_compression;
1471 Assert(std::distance(cbegin, cend) == size, ExcInternalError());
1472
1473 if (size > 0)
1474 std::memcpy(&object, &*cbegin, size);
1475
1476 return object;
1477 }
1478 // Next try if we have a vector of trivially copyable objects.
1479 // If that is the case, we can shortcut the whole BOOST serialization
1480 // machinery and just copy the content of the buffer bit for bit
1481 // into an appropriately sized output vector, assuming that we
1482 // are not asked to compress the data.
1484 (allow_compression == false))
1485 {
1486 // When we have DEAL_II_HAVE_CXX17 set by default, we can just
1487 // inline the code of the following function here and make the 'if'
1488 // above a 'if constexpr'. Without the 'constexpr', we need to keep
1489 // the general template of the function that throws an exception.
1490 T object;
1492 cend,
1493 object);
1494 return object;
1495 }
1496 else
1497 {
1498 // decompress the buffer section into the object
1499 boost::iostreams::filtering_istreambuf fisb;
1500#ifdef DEAL_II_WITH_ZLIB
1501 if (allow_compression)
1502 fisb.push(boost::iostreams::gzip_decompressor());
1503#else
1504 (void)allow_compression;
1505#endif
1506 fisb.push(boost::iostreams::array_source(&*cbegin, cend - cbegin));
1507
1508 boost::archive::binary_iarchive bia(fisb);
1509
1510 T object;
1511 bia >> object;
1512 return object;
1513 }
1514
1515 return T();
1516 }
1517
1518
1519 template <typename T>
1520 T
1521 unpack(const std::vector<char> &buffer, const bool allow_compression)
1522 {
1523 return unpack<T>(buffer.cbegin(), buffer.cend(), allow_compression);
1524 }
1525
1526
1527 template <typename T, int N>
1528 void
1529 unpack(const std::vector<char>::const_iterator &cbegin,
1530 const std::vector<char>::const_iterator &cend,
1531 T (&unpacked_object)[N],
1532 const bool allow_compression)
1533 {
1534 // see if the object is small and copyable via memcpy. if so, use
1535 // this fast path. otherwise, we have to go through the BOOST
1536 // serialization machinery
1537 if constexpr (std::is_trivially_copyable<T>() && sizeof(T) * N < 256)
1538 {
1539 Assert(std::distance(cbegin, cend) == sizeof(T) * N,
1541 std::memcpy(unpacked_object, &*cbegin, sizeof(T) * N);
1542 }
1543 else
1544 {
1545 // decompress the buffer section into the object
1546 boost::iostreams::filtering_istreambuf fisb;
1547#ifdef DEAL_II_WITH_ZLIB
1548 if (allow_compression)
1549 fisb.push(boost::iostreams::gzip_decompressor());
1550#else
1551 (void)allow_compression;
1552#endif
1553 fisb.push(boost::iostreams::array_source(&*cbegin, cend - cbegin));
1554
1555 boost::archive::binary_iarchive bia(fisb);
1556 bia >> unpacked_object;
1557 }
1558 }
1559
1560
1561 template <typename T, int N>
1562 void
1563 unpack(const std::vector<char> &buffer,
1564 T (&unpacked_object)[N],
1565 const bool allow_compression)
1566 {
1567 unpack<T, N>(buffer.cbegin(),
1568 buffer.cend(),
1569 unpacked_object,
1570 allow_compression);
1571 }
1572
1573
1574
1575 inline bool
1576 get_bit(const unsigned char number, const unsigned int n)
1577 {
1578 AssertIndexRange(n, 8);
1579
1580 // source:
1581 // https://stackoverflow.com/questions/47981/how-do-you-set-clear-and-toggle-a-single-bit
1582 // "Checking a bit"
1583 return ((number >> n) & 1U) != 0u;
1584 }
1585
1586
1587
1588 inline void
1589 set_bit(unsigned char &number, const unsigned int n, const bool x)
1590 {
1591 AssertIndexRange(n, 8);
1592
1593 // source:
1594 // https://stackoverflow.com/questions/47981/how-do-you-set-clear-and-toggle-a-single-bit
1595 // "Changing the nth bit to x"
1596 number ^= (-static_cast<unsigned char>(x) ^ number) & (1U << n);
1597 }
1598
1599
1600
1601 template <typename To, typename From>
1602 inline std::unique_ptr<To>
1603 dynamic_unique_cast(std::unique_ptr<From> &&p)
1604 {
1605 // Let's see if we can cast from 'From' to 'To'. If so, do the cast,
1606 // and then release the pointer from the old
1607 // owner
1608 if (To *cast = dynamic_cast<To *>(p.get()))
1609 {
1610 std::unique_ptr<To> result(cast);
1611 p.release();
1612 return result;
1613 }
1614 else
1615 throw std::bad_cast();
1616 }
1617
1618
1619
1620 template <typename T>
1621 inline T &
1623 {
1624 return p;
1625 }
1626
1627
1628
1629 template <typename T>
1630 inline T &
1631 get_underlying_value(std::shared_ptr<T> &p)
1632 {
1633 return *p;
1634 }
1635
1636
1637
1638 template <typename T>
1639 inline T &
1640 get_underlying_value(const std::shared_ptr<T> &p)
1641 {
1642 return *p;
1643 }
1644
1645
1646
1647 template <typename T>
1648 inline T &
1649 get_underlying_value(std::unique_ptr<T> &p)
1650 {
1651 return *p;
1652 }
1653
1654
1655
1656 template <typename T>
1657 inline T &
1658 get_underlying_value(const std::unique_ptr<T> &p)
1659 {
1660 return *p;
1661 }
1662
1663
1664
1665 template <typename Integer>
1666 std::vector<Integer>
1667 reverse_permutation(const std::vector<Integer> &permutation)
1668 {
1669 const std::size_t n = permutation.size();
1670
1671 std::vector<Integer> out(n);
1672 for (std::size_t i = 0; i < n; ++i)
1673 out[i] = n - 1 - permutation[i];
1674
1675 return out;
1676 }
1677
1678
1679
1680 template <typename Integer>
1681 std::vector<Integer>
1682 invert_permutation(const std::vector<Integer> &permutation)
1683 {
1684 const std::size_t n = permutation.size();
1685
1686 std::vector<Integer> out(n, numbers::invalid_unsigned_int);
1687
1688 for (std::size_t i = 0; i < n; ++i)
1689 {
1690 AssertIndexRange(permutation[i], n);
1691 out[permutation[i]] = i;
1692 }
1693
1694 // check that we have actually reached
1695 // all indices
1696 for (std::size_t i = 0; i < n; ++i)
1698 ExcMessage("The given input permutation had duplicate entries!"));
1699
1700 return out;
1701 }
1702} // namespace Utilities
1703
1704
1706
1707#ifndef DOXYGEN
1708namespace boost
1709{
1710 namespace serialization
1711 {
1712 // Provides boost and c++11 with a way to serialize tuples and pairs
1713 // automatically.
1714 template <int N>
1715 struct Serialize
1716 {
1717 template <class Archive, typename... Args>
1718 static void
1719 serialize(Archive &ar, std::tuple<Args...> &t, const unsigned int version)
1720 {
1721 ar &std::get<N - 1>(t);
1722 Serialize<N - 1>::serialize(ar, t, version);
1723 }
1724 };
1725
1726 template <>
1727 struct Serialize<0>
1728 {
1729 template <class Archive, typename... Args>
1730 static void
1731 serialize(Archive &ar, std::tuple<Args...> &t, const unsigned int version)
1732 {
1733 (void)ar;
1734 (void)t;
1735 (void)version;
1736 }
1737 };
1738
1739 template <class Archive, typename... Args>
1740 void
1741 serialize(Archive &ar, std::tuple<Args...> &t, const unsigned int version)
1742 {
1743 Serialize<sizeof...(Args)>::serialize(ar, t, version);
1744 }
1745 } // namespace serialization
1746} // namespace boost
1747#endif
1748
1749#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:1622
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:1364
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:1576
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:1603
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:1521
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:1589
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:1667
std::vector< Integer > invert_permutation(const std::vector< Integer > &permutation)
Definition utilities.h:1682
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