deal.II version GIT relicensing-6809-ge913b9bb34 2026-09-25 17:20:01+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: Apache-2.0 WITH LLVM-exception OR LGPL-2.1-or-later
4// Copyright (C) 2005 - 2025 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Detailed license information governing the source code and contributions
9// can be found in LICENSE.md and CONTRIBUTING.md at the top level directory.
10//
11// -----------------------------------------------------------------------------
12
13#ifndef dealii_utilities_h
14#define dealii_utilities_h
15
16#include <deal.II/base/config.h>
17
19#include <deal.II/base/types.h>
20
21#include <boost/archive/binary_iarchive.hpp>
22#include <boost/archive/binary_oarchive.hpp>
23#include <boost/core/demangle.hpp>
24#include <boost/iostreams/device/array.hpp>
25#include <boost/iostreams/device/back_inserter.hpp>
26#include <boost/iostreams/filtering_streambuf.hpp>
27#include <boost/serialization/array.hpp>
28#include <boost/serialization/complex.hpp>
29#include <boost/serialization/set.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
426 template <class T>
427 std::string
428 type_to_string(const T &t);
429
455 template <int N, typename T>
456 constexpr T
457 fixed_power(const T t);
458
466 template <typename T, typename = std::enable_if_t<std::is_arithmetic_v<T>>>
467 constexpr DEAL_II_HOST_DEVICE T
468 pow(const T base, const int iexp);
469
491 template <typename Iterator, typename T>
492 Iterator
493 lower_bound(Iterator first, Iterator last, const T &val);
494
500 template <typename Iterator, typename T, typename Comp>
501 Iterator
502 lower_bound(Iterator first, Iterator last, const T &val, const Comp comp);
503
509 template <typename Integer>
510 std::vector<Integer>
511 reverse_permutation(const std::vector<Integer> &permutation);
512
518 template <typename Integer>
519 std::vector<Integer>
520 invert_permutation(const std::vector<Integer> &permutation);
521
576 template <typename T>
577 std::size_t
578 pack(const T &object,
579 std::vector<char> &dest_buffer,
580 const bool allow_compression = true);
581
590 template <typename T>
591 std::vector<char>
592 pack(const T &object, const bool allow_compression = true);
593
625 template <typename T>
626 T
627 unpack(const std::vector<char> &buffer, const bool allow_compression = true);
628
637 template <typename T>
638 T
639 unpack(const std::vector<char>::const_iterator &cbegin,
640 const std::vector<char>::const_iterator &cend,
641 const bool allow_compression = true);
642
675 template <typename T, int N>
676 void
677 unpack(const std::vector<char> &buffer,
678 T (&unpacked_object)[N],
679 const bool allow_compression = true);
680
689 template <typename T, int N>
690 void
691 unpack(const std::vector<char>::const_iterator &cbegin,
692 const std::vector<char>::const_iterator &cend,
693 T (&unpacked_object)[N],
694 const bool allow_compression = true);
695
699 bool
700 get_bit(const unsigned char number, const unsigned int n);
701
702
706 void
707 set_bit(unsigned char &number, const unsigned int n, const bool x);
708
709
767 template <typename To, typename From>
768 std::unique_ptr<To>
769 dynamic_unique_cast(std::unique_ptr<From> &&p);
770
774 template <typename T>
775 T &
777
781 template <typename T>
782 T &
783 get_underlying_value(std::shared_ptr<T> &p);
784
788 template <typename T>
789 T &
790 get_underlying_value(const std::shared_ptr<T> &p);
791
795 template <typename T>
796 T &
797 get_underlying_value(std::unique_ptr<T> &p);
798
802 template <typename T>
803 T &
804 get_underlying_value(const std::unique_ptr<T> &p);
805
811 namespace System
812 {
820 double
821 get_cpu_load();
822
856 std::string
858
864 {
868 unsigned long int VmPeak;
869
873 unsigned long int VmSize;
874
878 unsigned long int VmHWM;
879
884 unsigned long int VmRSS;
885 };
886
887
892 void
894
895
899 std::string
900 get_hostname();
901
902
906 std::string
907 get_time();
908
913 std::string
914 get_date();
915
930 void
931 posix_memalign(void **memptr, std::size_t alignment, std::size_t size);
932 } // namespace System
933} // namespace Utilities
934
935
936// --------------------- inline functions
937
938namespace Utilities
939{
940 template <int N, typename T>
941 inline constexpr T
942 fixed_power(const T x)
943 {
944 Assert(((std::is_integral_v<T> == true) && (N >= 0)) ||
945 (std::is_integral_v<T> == false),
946 ExcMessage("If the type of the argument, T, is an integer type, "
947 "then the exponent N must be a non-negative integer "
948 "because the result would otherwise not be an integer."));
949
950 if (N == 0)
951 return T(1.);
952 else if (N < 0)
953 // For negative exponents, turn things into a positive exponent
954 return T(1.) / fixed_power<-N, T>(x);
955 else
956 // If we get here, we have a positive exponent. Compute the result
957 // by repeated squaring:
958 return ((N % 2 == 1) ? x * fixed_power<N / 2, T>(x * x) :
959 fixed_power<N / 2, T>(x * x));
960 }
961
962
963
964 template <typename T, typename>
965 constexpr DEAL_II_HOST_DEVICE T
966 pow(const T base, const int iexp)
967 {
968 Assert(iexp >= 0, ExcMessage("The exponent must not be negative!"));
969
970 // The "exponentiation by squaring" algorithm used below has to be expressed
971 // in an iterative version since SYCL doesn't allow recursive functions used
972 // in device code.
973
974 if (iexp <= 0)
975 return 1;
976
977 int exp = iexp;
978 T x = base;
979 T y = 1;
980 while (exp > 1)
981 {
982 if (exp % 2 == 1)
983 y *= x;
984 x *= x;
985 exp /= 2;
986 }
987 return x * y;
988 }
989
990
991
992 template <class T>
993 inline std::string
994 type_to_string(const T &t)
995 {
996 return boost::core::demangle(typeid(t).name());
997 }
998
999
1000
1001 template <typename Iterator, typename T>
1002 inline Iterator
1003 lower_bound(Iterator first, Iterator last, const T &val)
1004 {
1005 return Utilities::lower_bound(first, last, val, std::less<T>());
1006 }
1007
1008
1009
1010 template <typename Iterator, typename T, typename Comp>
1011 inline Iterator
1012 lower_bound(Iterator first, Iterator last, const T &val, const Comp comp)
1013 {
1014 // verify that the two iterators are properly ordered. since
1015 // we need operator- for the iterator type anyway, do the
1016 // test as follows, rather than via 'last >= first'
1017 Assert(last - first >= 0,
1018 ExcMessage(
1019 "The given iterators do not satisfy the proper ordering."));
1020
1021 unsigned int len = static_cast<unsigned int>(last - first);
1022
1023 if (len == 0)
1024 return first;
1025
1026 while (true)
1027 {
1028 // if length equals 8 or less,
1029 // then do a rolled out
1030 // search. use a switch without
1031 // breaks for that and roll-out
1032 // the loop somehow
1033 if (len < 8)
1034 {
1035 switch (len)
1036 {
1037 case 7:
1038 if (!comp(*first, val))
1039 return first;
1040 ++first;
1041 [[fallthrough]];
1042 case 6:
1043 if (!comp(*first, val))
1044 return first;
1045 ++first;
1046 [[fallthrough]];
1047 case 5:
1048 if (!comp(*first, val))
1049 return first;
1050 ++first;
1051 [[fallthrough]];
1052 case 4:
1053 if (!comp(*first, val))
1054 return first;
1055 ++first;
1056 [[fallthrough]];
1057 case 3:
1058 if (!comp(*first, val))
1059 return first;
1060 ++first;
1061 [[fallthrough]];
1062 case 2:
1063 if (!comp(*first, val))
1064 return first;
1065 ++first;
1066 [[fallthrough]];
1067 case 1:
1068 if (!comp(*first, val))
1069 return first;
1070 return first + 1;
1071 default:
1072 // indices seem
1073 // to not be
1074 // sorted
1075 // correctly!? or
1076 // did len
1077 // become==0
1078 // somehow? that
1079 // shouldn't have
1080 // happened
1082 }
1083 }
1084
1085
1086
1087 const unsigned int half = len >> 1;
1088 const Iterator middle = first + half;
1089
1090 // if the value is larger than
1091 // that pointed to by the
1092 // middle pointer, then the
1093 // insertion point must be
1094 // right of it
1095 if (comp(*middle, val))
1096 {
1097 first = middle + 1;
1098 len -= half + 1;
1099 }
1100 else
1101 len = half;
1102 }
1103 }
1104
1105
1106 // --------------------- non-inline functions
1107
1108 namespace internal
1109 {
1115 template <typename T>
1117 {
1118 static constexpr bool value = false;
1119 };
1120
1121
1122
1123 template <typename T>
1125 {
1126 static constexpr bool value =
1127 std::is_trivially_copyable_v<T> && !std::is_same_v<T, bool>;
1128 };
1129
1130
1131
1132 template <typename T>
1133 struct IsVectorOfTriviallyCopyable<std::vector<std::vector<T>>>
1134 {
1135 static constexpr bool value =
1136 std::is_trivially_copyable_v<T> && !std::is_same_v<T, bool>;
1137 };
1138
1139
1140
1149 template <typename T>
1150 inline void
1152 std::vector<char> &)
1153 {
1154 // We shouldn't get here:
1156 }
1157
1158
1159
1160 template <typename T,
1161 typename = std::enable_if_t<!std::is_same_v<T, bool> &&
1162 std::is_trivially_copyable_v<T>>>
1163 inline void
1165 const std::vector<T> &object,
1166 std::vector<char> &dest_buffer)
1167 {
1168 const typename std::vector<T>::size_type vector_size = object.size();
1169
1170 // Reserve for the buffer so that it can store the size of 'object' as
1171 // well as all of its elements.
1172 dest_buffer.reserve(dest_buffer.size() + sizeof(vector_size) +
1173 vector_size * sizeof(T));
1174
1175 // Copy the size into the vector
1176 dest_buffer.insert(dest_buffer.end(),
1177 reinterpret_cast<const char *>(&vector_size),
1178 reinterpret_cast<const char *>(&vector_size + 1));
1179
1180 // Insert the elements at the end of the vector:
1181 if (vector_size > 0)
1182 dest_buffer.insert(dest_buffer.end(),
1183 reinterpret_cast<const char *>(object.data()),
1184 reinterpret_cast<const char *>(object.data() +
1185 vector_size));
1186 }
1187
1188
1189
1190 template <typename T,
1191 typename = std::enable_if_t<!std::is_same_v<T, bool> &&
1192 std::is_trivially_copyable_v<T>>>
1193 inline void
1195 const std::vector<std::vector<T>> &object,
1196 std::vector<char> &dest_buffer)
1197 {
1198 using size_type = typename std::vector<T>::size_type;
1199 const size_type vector_size = object.size();
1200
1201 typename std::vector<T>::size_type aggregated_size = 0;
1202 std::vector<size_type> sizes;
1203 sizes.reserve(vector_size);
1204 for (const auto &a : object)
1205 {
1206 aggregated_size += a.size();
1207 sizes.push_back(a.size());
1208 }
1209
1210 // Reserve for the buffer so that it can store the size of 'object' as
1211 // well as all of its elements.
1212 dest_buffer.reserve(dest_buffer.size() +
1213 sizeof(vector_size) * (1 + vector_size) +
1214 aggregated_size * sizeof(T));
1215
1216 // Copy the size into the vector
1217 dest_buffer.insert(dest_buffer.end(),
1218 reinterpret_cast<const char *>(&vector_size),
1219 reinterpret_cast<const char *>(&vector_size + 1));
1220
1221 // Copy the sizes of the individual chunks into the vector
1222 if (vector_size > 0)
1223 dest_buffer.insert(dest_buffer.end(),
1224 reinterpret_cast<const char *>(sizes.data()),
1225 reinterpret_cast<const char *>(sizes.data() +
1226 vector_size));
1227
1228 // Insert the elements at the end of the vector:
1229 for (const auto &a : object)
1230 dest_buffer.insert(dest_buffer.end(),
1231 reinterpret_cast<const char *>(a.data()),
1232 reinterpret_cast<const char *>(a.data() + a.size()));
1233 }
1234
1235
1236
1237 template <typename T>
1238 inline void
1240 const std::vector<char>::const_iterator &,
1241 const std::vector<char>::const_iterator &,
1242 T &)
1243 {
1244 // We shouldn't get here:
1246 }
1247
1248
1249
1250 template <typename T,
1251 typename = std::enable_if_t<!std::is_same_v<T, bool> &&
1252 std::is_trivially_copyable_v<T>>>
1253 inline void
1255 const std::vector<char>::const_iterator &cbegin,
1256 const std::vector<char>::const_iterator &cend,
1257 std::vector<T> &object)
1258 {
1259 // The size of the object vector can be found in cbegin of the buffer.
1260 // The data starts at cbegin + sizeof(vector_size).
1261
1262 // Get the size of the vector
1263 typename std::vector<T>::size_type vector_size;
1264 std::memcpy(&vector_size, &*cbegin, sizeof(vector_size));
1265
1266 Assert(static_cast<std::ptrdiff_t>(cend - cbegin) ==
1267 static_cast<std::ptrdiff_t>(sizeof(vector_size) +
1268 vector_size * sizeof(T)),
1269 ExcMessage("The given buffer has the wrong size."));
1270 (void)cend;
1271
1272 // Resize the output array and copy the elements into it. We need
1273 // to make sure that we don't access the buffer via a
1274 // reinterpret_cast<T*> because the T objects in the buffer may
1275 // not be aligned properly. Rather, use memcpy, which doesn't care
1276 // about alignment and is correct in this situation because we
1277 // are dealing with trivially copyable objects.
1278 //
1279 // (Strictly speaking, this writes into the output object twice, once
1280 // for the resize() operation and once during memcpy. This could be
1281 // avoided by (i) checking whether the point is aligned, using for
1282 // example boost::alignment::is_aligned(), and (ii) if the data
1283 // is aligned, re-create the output vector using
1284 // object.clear();
1285 // object.insert (object.end(),
1286 // (T*)(&*cbegin + sizeof(vector_size)),
1287 // (T*)(&*cbegin + sizeof(vector_size)) + vector_size);
1288 // In practice, the difference is likely rather small, assuming the
1289 // compiler does not already optimize away the first initialization.
1290 object.resize(vector_size);
1291 if (vector_size > 0)
1292 std::memcpy(object.data(),
1293 &*cbegin + sizeof(vector_size),
1294 vector_size * sizeof(T));
1295 }
1296
1297
1298
1299 template <typename T,
1300 typename = std::enable_if_t<!std::is_same_v<T, bool> &&
1301 std::is_trivially_copyable_v<T>>>
1302 inline void
1304 const std::vector<char>::const_iterator &cbegin,
1305 const std::vector<char>::const_iterator &cend,
1306 std::vector<std::vector<T>> &object)
1307 {
1308 // First get the size of the vector, and resize the output object
1309 using size_type = typename std::vector<T>::size_type;
1310 std::vector<char>::const_iterator iterator = cbegin;
1311 size_type vector_size;
1312 std::memcpy(&vector_size, &*iterator, sizeof(vector_size));
1313 object.clear();
1314 object.resize(vector_size);
1315 std::vector<size_type> sizes(vector_size);
1316 if (vector_size > 0)
1317 std::memcpy(sizes.data(),
1318 &*iterator + sizeof(vector_size),
1319 vector_size * sizeof(size_type));
1320
1321 iterator += sizeof(vector_size) * (1 + vector_size);
1322 size_type aggregated_size = 0;
1323 for (const auto a : sizes)
1324 aggregated_size += a;
1325
1326 Assert(static_cast<std::ptrdiff_t>(cend - iterator) ==
1327 static_cast<std::ptrdiff_t>(aggregated_size * sizeof(T)),
1328 ExcMessage("The given buffer has the wrong size."));
1329 (void)cend;
1330
1331 // Then copy the elements. As for the previous function, use memcpy
1332 // rather than accessing the data via reinterpret_cast<T*> to
1333 // avoid alignment issues.
1334 for (unsigned int i = 0; i < vector_size; ++i)
1335 if (sizes[i] > 0)
1336 {
1337 object[i].resize(sizes[i]);
1338 std::memcpy(object[i].data(), &*iterator, sizes[i] * sizeof(T));
1339 iterator += sizes[i] * sizeof(T);
1340 }
1341
1342 Assert(iterator == cend,
1343 ExcMessage("The given buffer has the wrong size."));
1344 }
1345
1346 } // namespace internal
1347
1348
1349
1350 template <typename T>
1351 std::size_t
1352 pack(const T &object,
1353 std::vector<char> &dest_buffer,
1354 const bool allow_compression)
1355 {
1356 std::size_t size = 0;
1357
1358
1359 // see if the object is small and copyable via memcpy. if so, use
1360 // this fast path. otherwise, we have to go through the BOOST
1361 // serialization machinery
1362 if constexpr (std::is_trivially_copyable<T>() && sizeof(T) < 256)
1363 {
1364 // Determine the size. There are places where we would like to use a
1365 // truly empty type, for which we use std::tuple<> (i.e., a tuple
1366 // of zero elements). For this class, the compiler reports a nonzero
1367 // sizeof(...) because that is the minimum possible for objects --
1368 // objects need to have distinct addresses, so they need to have a size
1369 // of at least one. But we can special case this situation.
1370 size = (std::is_same_v<T, std::tuple<>> ? 0 : sizeof(T));
1371
1372 (void)allow_compression;
1373 const std::size_t previous_size = dest_buffer.size();
1374 dest_buffer.resize(previous_size + size);
1375
1376 if (size > 0)
1377 std::memcpy(dest_buffer.data() + previous_size, &object, size);
1378 }
1379 // Next try if we have a vector of trivially copyable objects.
1380 // If that is the case, we can shortcut the whole BOOST serialization
1381 // machinery and just copy the content of the vector bit for bit
1382 // into the output buffer, assuming that we are not asked to compress
1383 // the data.
1385 (allow_compression == false))
1386 {
1387 const std::size_t previous_size = dest_buffer.size();
1388
1389 // When we have DEAL_II_HAVE_CXX17 set by default, we can just
1390 // inline the code of the following function here and make the 'if'
1391 // above a 'if constexpr'. Without the 'constexpr', we need to keep
1392 // the general template of the function that throws an exception.
1394 dest_buffer);
1395
1396 size = dest_buffer.size() - previous_size;
1397 }
1398 else
1399 {
1400 // use buffer as the target of a compressing
1401 // stream into which we serialize the current object
1402 const std::size_t previous_size = dest_buffer.size();
1403 {
1404 boost::iostreams::filtering_ostreambuf fosb;
1405#ifdef DEAL_II_WITH_ZLIB
1406 if (allow_compression)
1407 fosb.push(boost::iostreams::gzip_compressor());
1408#else
1409 (void)allow_compression;
1410#endif
1411 fosb.push(boost::iostreams::back_inserter(dest_buffer));
1412
1413 boost::archive::binary_oarchive boa(fosb);
1414 boa << object;
1415 // the stream object has to be destroyed before the return statement
1416 // to ensure that all data has been written in the buffer
1417 }
1418 size = dest_buffer.size() - previous_size;
1419 }
1420
1421 return size;
1422 }
1423
1424
1425 template <typename T>
1426 std::vector<char>
1427 pack(const T &object, const bool allow_compression)
1428 {
1429 std::vector<char> buffer;
1430 pack<T>(object, buffer, allow_compression);
1431 return buffer;
1432 }
1433
1434
1435
1436 template <typename T>
1437 T
1438 unpack(const std::vector<char>::const_iterator &cbegin,
1439 const std::vector<char>::const_iterator &cend,
1440 const bool allow_compression)
1441 {
1442 // see if the object is small and copyable via memcpy. if so, use
1443 // this fast path. otherwise, we have to go through the BOOST
1444 // serialization machinery
1445 if constexpr (std::is_trivially_copyable<T>() && sizeof(T) < 256)
1446 {
1447 // Determine the size. There are places where we would like to use a
1448 // truly empty type, for which we use std::tuple<> (i.e., a tuple
1449 // of zero elements). For this class, the compiler reports a nonzero
1450 // sizeof(...) because that is the minimum possible for objects --
1451 // objects need to have distinct addresses, so they need to have a size
1452 // of at least one. But we can special case this situation.
1453 const std::size_t size =
1454 (std::is_same_v<T, std::tuple<>> ? 0 : sizeof(T));
1455
1456 T object;
1457
1458 (void)allow_compression;
1459 Assert(std::distance(cbegin, cend) == size, ExcInternalError());
1460
1461 if (size > 0)
1462 std::memcpy(&object, &*cbegin, size);
1463
1464 return object;
1465 }
1466 // Next try if we have a vector of trivially copyable objects.
1467 // If that is the case, we can shortcut the whole BOOST serialization
1468 // machinery and just copy the content of the buffer bit for bit
1469 // into an appropriately sized output vector, assuming that we
1470 // are not asked to compress the data.
1472 (allow_compression == false))
1473 {
1474 // When we have DEAL_II_HAVE_CXX17 set by default, we can just
1475 // inline the code of the following function here and make the 'if'
1476 // above a 'if constexpr'. Without the 'constexpr', we need to keep
1477 // the general template of the function that throws an exception.
1478 T object;
1480 cend,
1481 object);
1482 return object;
1483 }
1484 else
1485 {
1486 // decompress the buffer section into the object
1487 boost::iostreams::filtering_istreambuf fisb;
1488#ifdef DEAL_II_WITH_ZLIB
1489 if (allow_compression)
1490 fisb.push(boost::iostreams::gzip_decompressor());
1491#else
1492 (void)allow_compression;
1493#endif
1494 fisb.push(boost::iostreams::array_source(&*cbegin, cend - cbegin));
1495
1496 boost::archive::binary_iarchive bia(fisb);
1497
1498 T object;
1499 bia >> object;
1500 return object;
1501 }
1502
1503 return T();
1504 }
1505
1506
1507 template <typename T>
1508 T
1509 unpack(const std::vector<char> &buffer, const bool allow_compression)
1510 {
1511 return unpack<T>(buffer.cbegin(), buffer.cend(), allow_compression);
1512 }
1513
1514
1515 template <typename T, int N>
1516 void
1517 unpack(const std::vector<char>::const_iterator &cbegin,
1518 const std::vector<char>::const_iterator &cend,
1519 T (&unpacked_object)[N],
1520 const bool allow_compression)
1521 {
1522 // see if the object is small and copyable via memcpy. if so, use
1523 // this fast path. otherwise, we have to go through the BOOST
1524 // serialization machinery
1525 if constexpr (std::is_trivially_copyable<T>() && sizeof(T) * N < 256)
1526 {
1527 Assert(std::distance(cbegin, cend) == sizeof(T) * N,
1529 std::memcpy(unpacked_object, &*cbegin, sizeof(T) * N);
1530 }
1531 else
1532 {
1533 // decompress the buffer section into the object
1534 boost::iostreams::filtering_istreambuf fisb;
1535#ifdef DEAL_II_WITH_ZLIB
1536 if (allow_compression)
1537 fisb.push(boost::iostreams::gzip_decompressor());
1538#else
1539 (void)allow_compression;
1540#endif
1541 fisb.push(boost::iostreams::array_source(&*cbegin, cend - cbegin));
1542
1543 boost::archive::binary_iarchive bia(fisb);
1544 bia >> unpacked_object;
1545 }
1546 }
1547
1548
1549 template <typename T, int N>
1550 void
1551 unpack(const std::vector<char> &buffer,
1552 T (&unpacked_object)[N],
1553 const bool allow_compression)
1554 {
1555 unpack<T, N>(buffer.cbegin(),
1556 buffer.cend(),
1557 unpacked_object,
1558 allow_compression);
1559 }
1560
1561
1562
1563 inline bool
1564 get_bit(const unsigned char number, const unsigned int n)
1565 {
1566 AssertIndexRange(n, 8);
1567
1568 // source:
1569 // https://stackoverflow.com/questions/47981/how-do-you-set-clear-and-toggle-a-single-bit
1570 // "Checking a bit"
1571 return ((number >> n) & 1U) != 0u;
1572 }
1573
1574
1575
1576 inline void
1577 set_bit(unsigned char &number, const unsigned int n, const bool x)
1578 {
1579 AssertIndexRange(n, 8);
1580
1581 // source:
1582 // https://stackoverflow.com/questions/47981/how-do-you-set-clear-and-toggle-a-single-bit
1583 // "Changing the nth bit to x"
1584 number ^= (-static_cast<unsigned char>(x) ^ number) & (1U << n);
1585 }
1586
1587
1588
1589 template <typename To, typename From>
1590 inline std::unique_ptr<To>
1591 dynamic_unique_cast(std::unique_ptr<From> &&p)
1592 {
1593 // Let's see if we can cast from 'From' to 'To'. If so, do the cast,
1594 // and then release the pointer from the old
1595 // owner
1596 if (To *cast = dynamic_cast<To *>(p.get()))
1597 {
1598 std::unique_ptr<To> result(cast);
1599 p.release();
1600 return result;
1601 }
1602 else
1603 throw std::bad_cast();
1604 }
1605
1606
1607
1608 template <typename T>
1609 inline T &
1611 {
1612 return p;
1613 }
1614
1615
1616
1617 template <typename T>
1618 inline T &
1619 get_underlying_value(std::shared_ptr<T> &p)
1620 {
1621 return *p;
1622 }
1623
1624
1625
1626 template <typename T>
1627 inline T &
1628 get_underlying_value(const std::shared_ptr<T> &p)
1629 {
1630 return *p;
1631 }
1632
1633
1634
1635 template <typename T>
1636 inline T &
1637 get_underlying_value(std::unique_ptr<T> &p)
1638 {
1639 return *p;
1640 }
1641
1642
1643
1644 template <typename T>
1645 inline T &
1646 get_underlying_value(const std::unique_ptr<T> &p)
1647 {
1648 return *p;
1649 }
1650
1651
1652
1653 template <typename Integer>
1654 std::vector<Integer>
1655 reverse_permutation(const std::vector<Integer> &permutation)
1656 {
1657 const std::size_t n = permutation.size();
1658
1659 std::vector<Integer> out(n);
1660 for (std::size_t i = 0; i < n; ++i)
1661 out[i] = n - 1 - permutation[i];
1662
1663 return out;
1664 }
1665
1666
1667
1668 template <typename Integer>
1669 std::vector<Integer>
1670 invert_permutation(const std::vector<Integer> &permutation)
1671 {
1672 const std::size_t n = permutation.size();
1673
1674 std::vector<Integer> out(n, numbers::invalid_unsigned_int);
1675
1676 for (std::size_t i = 0; i < n; ++i)
1677 {
1678 AssertIndexRange(permutation[i], n);
1679 out[permutation[i]] = i;
1680 }
1681
1682 // check that we have actually reached
1683 // all indices
1684 for (std::size_t i = 0; i < n; ++i)
1686 ExcMessage("The given input permutation had duplicate entries!"));
1687
1688 return out;
1689 }
1690} // namespace Utilities
1691
1692
1694
1695#ifndef DOXYGEN
1696namespace boost
1697{
1698 namespace serialization
1699 {
1700 // Provides boost and c++11 with a way to serialize tuples and pairs
1701 // automatically.
1702 template <int N>
1703 struct Serialize
1704 {
1705 template <class Archive, typename... Args>
1706 static void
1707 serialize(Archive &ar, std::tuple<Args...> &t, const unsigned int version)
1708 {
1709 ar &std::get<N - 1>(t);
1710 Serialize<N - 1>::serialize(ar, t, version);
1711 }
1712 };
1713
1714 template <>
1715 struct Serialize<0>
1716 {
1717 template <class Archive, typename... Args>
1718 static void
1719 serialize(Archive &ar, std::tuple<Args...> &t, const unsigned int version)
1720 {
1721 (void)ar;
1722 (void)t;
1723 (void)version;
1724 }
1725 };
1726
1727 template <class Archive, typename... Args>
1728 void
1729 serialize(Archive &ar, std::tuple<Args...> &t, const unsigned int version)
1730 {
1731 Serialize<sizeof...(Args)>::serialize(ar, t, version);
1732 }
1733 } // namespace serialization
1734} // namespace boost
1735#endif
1736
1737#endif
*  const_iterator cbegin() const
*  const_iterator cend() const
*  *  iterator()=default
Definition point.h:111
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_CXX20_REQUIRES(condition)
Definition config.h:249
#define DEAL_II_HOST_DEVICE
Definition config.h:171
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#define DEAL_II_ASSERT_UNREACHABLE()
Point< 2 > first
Definition grid_out.cc:4639
#define Assert(cond, exc)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcMessage(std::string arg1)
std::vector< index_type > data
Definition mpi.cc:734
std::size_t size
Definition mpi.cc:733
constexpr char N
constexpr char T
*  *  *  RotationFunction< dim, Number >::RotationFunction Number(dim)
void get_memory_stats(MemoryStats &stats)
Definition utilities.cc:948
std::string get_hostname()
Definition utilities.cc:982
std::string get_time()
Definition utilities.cc:997
void posix_memalign(void **memptr, std::size_t alignment, std::size_t size)
double get_cpu_load()
Definition utilities.cc:914
std::string get_current_vectorization_level()
Definition utilities.cc:922
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:1239
void append_vector_of_trivially_copyable_to_buffer(const T &, std::vector< char > &)
Definition utilities.h:1151
std::size_t pack(const T &object, std::vector< char > &dest_buffer, const bool allow_compression=true)
Definition utilities.h:1352
std::vector< std::string > split_string_list(const std::string &s, const std::string &delimiter=",")
Definition utilities.cc:695
T & get_underlying_value(T &p)
Definition utilities.h:1610
Number truncate_to_n_digits(const Number number, const unsigned int n_digits)
Definition utilities.cc:570
std::string type_to_string(const T &t)
Definition utilities.h:994
std::string dim_string(const int dim, const int spacedim)
Definition utilities.cc:547
std::uint64_t pack_integers(const std::array< std::uint64_t, dim > &index, const int bits_per_dim)
Definition utilities.cc:358
bool get_bit(const unsigned char number, const unsigned int n)
Definition utilities.h:1564
std::pair< int, unsigned int > get_integer_at_position(const std::string &name, const unsigned int position)
Definition utilities.cc:831
std::string encode_base64(const std::vector< unsigned char > &binary_input)
Definition utilities.cc:425
std::unique_ptr< To > dynamic_unique_cast(std::unique_ptr< From > &&p)
Definition utilities.h:1591
constexpr T fixed_power(const T t)
Definition utilities.h:942
std::string replace_in_string(const std::string &input, const std::string &from, const std::string &to)
Definition utilities.cc:501
std::vector< unsigned char > decode_base64(const std::string &base64_input)
Definition utilities.cc:438
std::vector< std::string > break_text_into_lines(const std::string &original_text, const unsigned int width, const char delimiter=' ')
Definition utilities.cc:749
std::string to_string(const number value, const unsigned int digits=numbers::invalid_unsigned_int)
Definition utilities.cc:473
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:138
std::string compress(const std::string &input)
Definition utilities.cc:381
std::string int_to_string(const unsigned int value, const unsigned int digits=numbers::invalid_unsigned_int)
Definition utilities.cc:464
bool match_at_string_start(const std::string &name, const std::string &pattern)
Definition utilities.cc:816
T unpack(const std::vector< char > &buffer, const bool allow_compression=true)
Definition utilities.h:1509
std::string decompress(const std::string &compressed_input)
Definition utilities.cc:403
unsigned int needed_digits(const unsigned int max_number)
Definition utilities.cc:557
Iterator lower_bound(Iterator first, Iterator last, const T &val)
Definition utilities.h:1003
double string_to_double(const std::string &s)
Definition utilities.cc:646
std::string dealii_version_string()
Definition utilities.cc:87
void set_bit(unsigned char &number, const unsigned int n, const bool x)
Definition utilities.h:1577
constexpr T pow(const T base, const int iexp)
Definition utilities.h:966
std::string trim(const std::string &input)
Definition utilities.cc:520
double generate_normal_random_number(const double a, const double sigma)
Definition utilities.cc:873
std::vector< Integer > reverse_permutation(const std::vector< Integer > &permutation)
Definition utilities.h:1655
std::vector< Integer > invert_permutation(const std::vector< Integer > &permutation)
Definition utilities.h:1670
int string_to_int(const std::string &s)
Definition utilities.cc:597
void serialize(Archive &ar, ::std_cxx26::inplace_vector< T, N > &t, const unsigned int file_version)
constexpr unsigned int invalid_unsigned_int
Definition types.h:228
STL namespace.