Reference documentation for deal.II version 9.1.0-pre
utilities.h
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2005 - 2018 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15 
16 #ifndef dealii_utilities_h
17 #define dealii_utilities_h
18 
19 #include <deal.II/base/config.h>
20 
21 #include <deal.II/base/exceptions.h>
22 
23 #include <functional>
24 #include <string>
25 #include <tuple>
26 #include <type_traits>
27 #include <utility>
28 #include <vector>
29 
30 #ifdef DEAL_II_WITH_TRILINOS
31 # include <Epetra_Comm.h>
32 # include <Epetra_Map.h>
33 # ifdef DEAL_II_WITH_MPI
34 # include <Epetra_MpiComm.h>
35 # else
36 # include <Epetra_SerialComm.h>
37 # endif
38 #endif
39 
40 #include <boost/archive/binary_iarchive.hpp>
41 #include <boost/archive/binary_oarchive.hpp>
42 #include <boost/serialization/array.hpp>
43 #include <boost/serialization/complex.hpp>
44 #include <boost/serialization/vector.hpp>
45 
46 #ifdef DEAL_II_WITH_ZLIB
47 # include <boost/iostreams/device/back_inserter.hpp>
48 # include <boost/iostreams/filter/gzip.hpp>
49 # include <boost/iostreams/filtering_stream.hpp>
50 # include <boost/iostreams/stream.hpp>
51 #endif
52 
53 DEAL_II_NAMESPACE_OPEN
54 
55 
64 namespace Utilities
65 {
72  std::string
74 
91  std::string
92  int_to_string(const unsigned int value,
93  const unsigned int digits = numbers::invalid_unsigned_int);
94 
105  template <typename number>
106  std::string
107  to_string(const number value,
108  const unsigned int digits = numbers::invalid_unsigned_int);
109 
114  unsigned int
115  needed_digits(const unsigned int max_number);
116 
121  int
122  string_to_int(const std::string &s);
123 
135  std::string
136  dim_string(const int dim, const int spacedim);
137 
142  std::vector<int>
143  string_to_int(const std::vector<std::string> &s);
144 
149  double
150  string_to_double(const std::string &s);
151 
152 
157  std::vector<double>
158  string_to_double(const std::vector<std::string> &s);
159 
160 
203  std::vector<std::string>
204  split_string_list(const std::string &s, const std::string &delimiter = ",");
205 
206 
211  std::vector<std::string>
212  split_string_list(const std::string &s, const char delimiter);
213 
214 
224  std::vector<std::string>
225  break_text_into_lines(const std::string &original_text,
226  const unsigned int width,
227  const char delimiter = ' ');
228 
233  bool
234  match_at_string_start(const std::string &name, const std::string &pattern);
235 
244  std::pair<int, unsigned int>
245  get_integer_at_position(const std::string &name, const unsigned int position);
246 
251  std::string
252  replace_in_string(const std::string &input,
253  const std::string &from,
254  const std::string &to);
255 
261  std::string
262  trim(const std::string &input);
263 
289  double
290  generate_normal_random_number(const double a, const double sigma);
291 
292 
301  template <int N, typename T>
302  T
303  fixed_power(const T t);
304 
329  template <int a, int N>
330  struct DEAL_II_DEPRECATED fixed_int_power
331  {
332  static const int value = a * fixed_int_power<a, N - 1>::value;
333  };
334 
342  template <int a>
343  struct DEAL_II_DEPRECATED fixed_int_power<a, 0>
344  {
345  static const int value = 1;
346  };
347 
352  constexpr unsigned int
353  pow(const unsigned int base, const unsigned int iexp)
354  {
355  return iexp == 0 ? 1 : base * ::Utilities::pow(base, iexp - 1);
356  }
357 
379  template <typename Iterator, typename T>
380  Iterator
381  lower_bound(Iterator first, Iterator last, const T &val);
382 
383 
389  template <typename Iterator, typename T, typename Comp>
390  Iterator
391  lower_bound(Iterator first, Iterator last, const T &val, const Comp comp);
392 
398  std::vector<unsigned int>
399  reverse_permutation(const std::vector<unsigned int> &permutation);
400 
406  std::vector<unsigned int>
407  invert_permutation(const std::vector<unsigned int> &permutation);
408 
414  std::vector<unsigned long long int>
415  reverse_permutation(const std::vector<unsigned long long int> &permutation);
416 
422  std::vector<unsigned long long int>
423  invert_permutation(const std::vector<unsigned long long int> &permutation);
424 
442  template <typename T>
443  size_t
444  pack(const T & object,
445  std::vector<char> &dest_buffer,
446  const bool allow_compression = true);
447 
458  template <typename T>
459  std::vector<char>
460  pack(const T &object, const bool allow_compression = true);
461 
494  template <typename T>
495  T
496  unpack(const std::vector<char> &buffer, const bool allow_compression = true);
497 
508  template <typename T>
509  T
510  unpack(const std::vector<char>::const_iterator &cbegin,
511  const std::vector<char>::const_iterator &cend,
512  const bool allow_compression = true);
513 
548  template <typename T, int N>
549  void
550  unpack(const std::vector<char> &buffer,
551  T (&unpacked_object)[N],
552  const bool allow_compression = true);
553 
564  template <typename T, int N>
565  void
566  unpack(const std::vector<char>::const_iterator &cbegin,
567  const std::vector<char>::const_iterator &cend,
568  T (&unpacked_object)[N],
569  const bool allow_compression = true);
570 
628  template <typename To, typename From>
629  std::unique_ptr<To>
630  dynamic_unique_cast(std::unique_ptr<From> &&p)
631  {
632  // Let's see if we can cast from 'From' to 'To'. If so, do the cast,
633  // and then release the pointer from the old
634  // owner
635  if (To *cast = dynamic_cast<To *>(p.get()))
636  {
637  std::unique_ptr<To> result(cast);
638  p.release();
639  return result;
640  }
641  else
642  throw std::bad_cast();
643  }
644 
650  namespace System
651  {
659  double
660  get_cpu_load();
661 
695  const std::string
697 
702  struct MemoryStats
703  {
707  unsigned long int VmPeak;
708 
712  unsigned long int VmSize;
713 
717  unsigned long int VmHWM;
718 
723  unsigned long int VmRSS;
724  };
725 
726 
731  void
733 
734 
738  std::string
739  get_hostname();
740 
741 
745  std::string
746  get_time();
747 
752  std::string
753  get_date();
754 
769  void
770  posix_memalign(void **memptr, size_t alignment, size_t size);
771  } // namespace System
772 
773 
774 #ifdef DEAL_II_WITH_TRILINOS
775 
780  namespace Trilinos
781  {
791  const Epetra_Comm &
792  comm_world();
793 
803  const Epetra_Comm &
804  comm_self();
805 
838  Epetra_Comm *
839  duplicate_communicator(const Epetra_Comm &communicator);
840 
863  void
864  destroy_communicator(Epetra_Comm &communicator);
865 
874  unsigned int
875  get_n_mpi_processes(const Epetra_Comm &mpi_communicator);
876 
883  unsigned int
884  get_this_mpi_process(const Epetra_Comm &mpi_communicator);
885 
896  Epetra_Map
897  duplicate_map(const Epetra_BlockMap &map, const Epetra_Comm &comm);
898  } // namespace Trilinos
899 
900 #endif
901 
902 
903 } // namespace Utilities
904 
905 
906 // --------------------- inline functions
907 
908 namespace Utilities
909 {
910  template <int N, typename T>
911  inline T
912  fixed_power(const T n)
913  {
914  Assert(N >= 0, ExcNotImplemented());
915  switch (N)
916  {
917  case 0:
918  return ::internal::NumberType<T>::value(1);
919  case 1:
920  return n;
921  case 2:
922  return n * n;
923  case 3:
924  return n * n * n;
925  case 4:
926  return n * n * n * n;
927  default:
928  T result = n;
929  for (int d = 1; d < N; ++d)
930  result *= n;
931  return result;
932  }
933  }
934 
935 
936 
937  template <typename Iterator, typename T>
938  inline Iterator
939  lower_bound(Iterator first, Iterator last, const T &val)
940  {
941  return Utilities::lower_bound(first, last, val, std::less<T>());
942  }
943 
944 
945 
946  template <typename Iterator, typename T, typename Comp>
947  inline Iterator
948  lower_bound(Iterator first, Iterator last, const T &val, const Comp comp)
949  {
950  // verify that the two iterators are properly ordered. since
951  // we need operator- for the iterator type anyway, do the
952  // test as follows, rather than via 'last >= first'
953  Assert(last - first >= 0,
954  ExcMessage(
955  "The given iterators do not satisfy the proper ordering."));
956 
957  unsigned int len = static_cast<unsigned int>(last - first);
958 
959  if (len == 0)
960  return first;
961 
962  while (true)
963  {
964  // if length equals 8 or less,
965  // then do a rolled out
966  // search. use a switch without
967  // breaks for that and roll-out
968  // the loop somehow
969  if (len < 8)
970  {
971  switch (len)
972  {
973  case 7:
974  if (!comp(*first, val))
975  return first;
976  ++first;
977  DEAL_II_FALLTHROUGH;
978  case 6:
979  if (!comp(*first, val))
980  return first;
981  ++first;
982  DEAL_II_FALLTHROUGH;
983  case 5:
984  if (!comp(*first, val))
985  return first;
986  ++first;
987  DEAL_II_FALLTHROUGH;
988  case 4:
989  if (!comp(*first, val))
990  return first;
991  ++first;
992  DEAL_II_FALLTHROUGH;
993  case 3:
994  if (!comp(*first, val))
995  return first;
996  ++first;
997  DEAL_II_FALLTHROUGH;
998  case 2:
999  if (!comp(*first, val))
1000  return first;
1001  ++first;
1002  DEAL_II_FALLTHROUGH;
1003  case 1:
1004  if (!comp(*first, val))
1005  return first;
1006  return first + 1;
1007  default:
1008  // indices seem
1009  // to not be
1010  // sorted
1011  // correctly!? or
1012  // did len
1013  // become==0
1014  // somehow? that
1015  // shouldn't have
1016  // happened
1017  Assert(false, ExcInternalError());
1018  }
1019  }
1020 
1021 
1022 
1023  const unsigned int half = len >> 1;
1024  const Iterator middle = first + half;
1025 
1026  // if the value is larger than
1027  // that pointed to by the
1028  // middle pointer, then the
1029  // insertion point must be
1030  // right of it
1031  if (comp(*middle, val))
1032  {
1033  first = middle + 1;
1034  len -= half + 1;
1035  }
1036  else
1037  len = half;
1038  }
1039  }
1040 
1041 
1042  // --------------------- non-inline functions
1043 
1044  template <typename T>
1045  size_t
1046  pack(const T & object,
1047  std::vector<char> &dest_buffer,
1048  const bool allow_compression)
1049  {
1050  // the data is never compressed when we can't use zlib.
1051  (void)allow_compression;
1052 
1053  // see if the object is small and copyable via memcpy. if so, use
1054  // this fast path. otherwise, we have to go through the BOOST
1055  // serialization machinery
1056  //
1057  // we have to work around the fact that GCC 4.8.x claims to be C++
1058  // conforming, but is not actually as it does not implement
1059  // std::is_trivially_copyable.
1060 #if __GNUG__ && __GNUC__ < 5
1061  if (__has_trivial_copy(T) && sizeof(T) < 256)
1062 #else
1063 # ifdef DEAL_II_WITH_CXX17
1064  if constexpr (std::is_trivially_copyable<T>() && sizeof(T) < 256)
1065 # else
1066  if (std::is_trivially_copyable<T>() && sizeof(T) < 256)
1067 # endif
1068 #endif
1069  {
1070  const size_t previous_size = dest_buffer.size();
1071  dest_buffer.resize(previous_size + sizeof(T));
1072 
1073  std::memcpy(dest_buffer.data() + previous_size, &object, sizeof(T));
1074 
1075  return sizeof(T);
1076  }
1077  else
1078  {
1079  // use buffer as the target of a compressing
1080  // stream into which we serialize the current object
1081  const size_t previous_size = dest_buffer.size();
1082 #ifdef DEAL_II_WITH_ZLIB
1083  if (allow_compression)
1084  {
1085  boost::iostreams::filtering_ostream out;
1086  out.push(
1087  boost::iostreams::gzip_compressor(boost::iostreams::gzip_params(
1088  boost::iostreams::gzip::best_compression)));
1089  out.push(boost::iostreams::back_inserter(dest_buffer));
1090 
1091  boost::archive::binary_oarchive archive(out);
1092  archive << object;
1093  out.flush();
1094  }
1095  else
1096 #endif
1097  {
1098  std::ostringstream out;
1099  boost::archive::binary_oarchive archive(out);
1100  archive << object;
1101 
1102  const std::string &s = out.str();
1103  dest_buffer.reserve(dest_buffer.size() + s.size());
1104  std::move(s.begin(), s.end(), std::back_inserter(dest_buffer));
1105  }
1106 
1107  return (dest_buffer.size() - previous_size);
1108  }
1109  }
1110 
1111 
1112  template <typename T>
1113  std::vector<char>
1114  pack(const T &object, const bool allow_compression)
1115  {
1116  std::vector<char> buffer;
1117  pack<T>(object, buffer, allow_compression);
1118  return buffer;
1119  }
1120 
1121 
1122  template <typename T>
1123  T
1124  unpack(const std::vector<char>::const_iterator &cbegin,
1125  const std::vector<char>::const_iterator &cend,
1126  const bool allow_compression)
1127  {
1128  // the data is never compressed when we can't use zlib.
1129  (void)allow_compression;
1130 
1131  // see if the object is small and copyable via memcpy. if so, use
1132  // this fast path. otherwise, we have to go through the BOOST
1133  // serialization machinery
1134  //
1135  // we have to work around the fact that GCC 4.8.x claims to be C++
1136  // conforming, but is not actually as it does not implement
1137  // std::is_trivially_copyable.
1138 #if __GNUG__ && __GNUC__ < 5
1139  if (__has_trivial_copy(T) && sizeof(T) < 256)
1140 #else
1141 # ifdef DEAL_II_WITH_CXX17
1142  if constexpr (std::is_trivially_copyable<T>() && sizeof(T) < 256)
1143 # else
1144  if (std::is_trivially_copyable<T>() && sizeof(T) < 256)
1145 # endif
1146 #endif
1147  {
1148  Assert(std::distance(cbegin, cend) == sizeof(T), ExcInternalError());
1149  T object;
1150  std::memcpy(&object, &*cbegin, sizeof(T));
1151  return object;
1152  }
1153  else
1154  {
1155  std::string decompressed_buffer;
1156  T object;
1157 
1158  // first decompress the buffer
1159 #ifdef DEAL_II_WITH_ZLIB
1160  if (allow_compression)
1161  {
1162  boost::iostreams::filtering_ostream decompressing_stream;
1163  decompressing_stream.push(boost::iostreams::gzip_decompressor());
1164  decompressing_stream.push(
1165  boost::iostreams::back_inserter(decompressed_buffer));
1166  decompressing_stream.write(&*cbegin, std::distance(cbegin, cend));
1167  }
1168  else
1169 #endif
1170  {
1171  decompressed_buffer.assign(cbegin, cend);
1172  }
1173 
1174  // then restore the object from the buffer
1175  std::istringstream in(decompressed_buffer);
1176  boost::archive::binary_iarchive archive(in);
1177 
1178  archive >> object;
1179  return object;
1180  }
1181  }
1182 
1183 
1184  template <typename T>
1185  T
1186  unpack(const std::vector<char> &buffer, const bool allow_compression)
1187  {
1188  return unpack<T>(buffer.cbegin(), buffer.cend(), allow_compression);
1189  }
1190 
1191 
1192  template <typename T, int N>
1193  void
1194  unpack(const std::vector<char>::const_iterator &cbegin,
1195  const std::vector<char>::const_iterator &cend,
1196  T (&unpacked_object)[N],
1197  const bool allow_compression)
1198  {
1199  // see if the object is small and copyable via memcpy. if so, use
1200  // this fast path. otherwise, we have to go through the BOOST
1201  // serialization machinery
1202  //
1203  // we have to work around the fact that GCC 4.8.x claims to be C++
1204  // conforming, but is not actually as it does not implement
1205  // std::is_trivially_copyable.
1206  if (
1207 #if __GNUG__ && __GNUC__ < 5
1208  __has_trivial_copy(T)
1209 #else
1210  std::is_trivially_copyable<T>()
1211 #endif
1212  && sizeof(T) * N < 256)
1213  {
1214  Assert(std::distance(cbegin, cend) == sizeof(T) * N,
1215  ExcInternalError());
1216  std::memcpy(unpacked_object, &*cbegin, sizeof(T) * N);
1217  }
1218  else
1219  {
1220  std::string decompressed_buffer;
1221 
1222  // first decompress the buffer
1223  (void)allow_compression;
1224 #ifdef DEAL_II_WITH_ZLIB
1225  if (allow_compression)
1226  {
1227  boost::iostreams::filtering_ostream decompressing_stream;
1228  decompressing_stream.push(boost::iostreams::gzip_decompressor());
1229  decompressing_stream.push(
1230  boost::iostreams::back_inserter(decompressed_buffer));
1231  decompressing_stream.write(&*cbegin, std::distance(cbegin, cend));
1232  }
1233  else
1234 #endif
1235  {
1236  decompressed_buffer.assign(cbegin, cend);
1237  }
1238 
1239  // then restore the object from the buffer
1240  std::istringstream in(decompressed_buffer);
1241  boost::archive::binary_iarchive archive(in);
1242 
1243  archive >> unpacked_object;
1244  }
1245  }
1246 
1247 
1248  template <typename T, int N>
1249  void
1250  unpack(const std::vector<char> &buffer,
1251  T (&unpacked_object)[N],
1252  const bool allow_compression)
1253  {
1254  unpack<T, N>(buffer.cbegin(),
1255  buffer.cend(),
1256  unpacked_object,
1257  allow_compression);
1258  }
1259 
1260 } // namespace Utilities
1261 
1262 
1263 DEAL_II_NAMESPACE_CLOSE
1264 
1265 #ifndef DOXYGEN
1266 namespace boost
1267 {
1268  namespace serialization
1269  {
1270  // Provides boost and c++11 with a way to serialize tuples and pairs
1271  // automatically
1272  template <int N>
1273  struct Serialize
1274  {
1275  template <class Archive, typename... Args>
1276  static void
1277  serialize(Archive &ar, std::tuple<Args...> &t, const unsigned int version)
1278  {
1279  ar &std::get<N - 1>(t);
1280  Serialize<N - 1>::serialize(ar, t, version);
1281  }
1282  };
1283 
1284  template <>
1285  struct Serialize<0>
1286  {
1287  template <class Archive, typename... Args>
1288  static void
1289  serialize(Archive &ar, std::tuple<Args...> &t, const unsigned int version)
1290  {
1291  (void)ar;
1292  (void)t;
1293  (void)version;
1294  }
1295  };
1296 
1297  template <class Archive, typename... Args>
1298  void
1299  serialize(Archive &ar, std::tuple<Args...> &t, const unsigned int version)
1300  {
1301  Serialize<sizeof...(Args)>::serialize(ar, t, version);
1302  }
1303  } // namespace serialization
1304 } // namespace boost
1305 #endif
1306 
1307 #endif
Iterator lower_bound(Iterator first, Iterator last, const T &val)
Definition: utilities.h:939
std::vector< std::string > split_string_list(const std::string &s, const std::string &delimiter=",")
Definition: utilities.cc:279
static const unsigned int invalid_unsigned_int
Definition: types.h:173
constexpr unsigned int pow(const unsigned int base, const unsigned int iexp)
Definition: utilities.h:353
std::string dealii_version_string()
Definition: utilities.cc:88
unsigned int get_n_mpi_processes(const Epetra_Comm &mpi_communicator)
Definition: utilities.cc:841
std::string trim(const std::string &input)
Definition: utilities.cc:143
std::pair< int, unsigned int > get_integer_at_position(const std::string &name, const unsigned int position)
Definition: utilities.cc:428
const Epetra_Comm & comm_self()
Definition: utilities.cc:779
std::string get_date()
Definition: utilities.cc:717
std::string to_string(const number value, const unsigned int digits=numbers::invalid_unsigned_int)
Definition: utilities.cc:105
void get_memory_stats(MemoryStats &stats)
Definition: utilities.cc:652
std::unique_ptr< To > dynamic_unique_cast(std::unique_ptr< From > &&p)
Definition: utilities.h:630
double string_to_double(const std::string &s)
Definition: utilities.cc:240
double get_cpu_load()
Definition: utilities.cc:622
T fixed_power(const T t)
Definition: utilities.h:912
static::ExceptionBase & ExcMessage(std::string arg1)
double generate_normal_random_number(const double a, const double sigma)
Definition: utilities.cc:470
#define Assert(cond, exc)
Definition: exceptions.h:1227
unsigned long int VmSize
Definition: utilities.h:712
bool match_at_string_start(const std::string &name, const std::string &pattern)
Definition: utilities.cc:413
void posix_memalign(void **memptr, size_t alignment, size_t size)
Definition: utilities.cc:732
std::vector< unsigned int > invert_permutation(const std::vector< unsigned int > &permutation)
Definition: utilities.cc:503
std::string int_to_string(const unsigned int value, const unsigned int digits=numbers::invalid_unsigned_int)
Definition: utilities.cc:96
size_t pack(const T &object, std::vector< char > &dest_buffer, const bool allow_compression=true)
Definition: utilities.h:1046
std::string replace_in_string(const std::string &input, const std::string &from, const std::string &to)
Definition: utilities.cc:124
std::string dim_string(const int dim, const int spacedim)
Definition: utilities.cc:170
void destroy_communicator(Epetra_Comm &communicator)
Definition: utilities.cc:822
Definition: cuda.h:32
std::vector< std::string > break_text_into_lines(const std::string &original_text, const unsigned int width, const char delimiter= ' ')
Definition: utilities.cc:333
std::string get_hostname()
Definition: utilities.cc:686
unsigned long int VmHWM
Definition: utilities.h:717
const Epetra_Comm & comm_world()
Definition: utilities.cc:763
T unpack(const std::vector< char > &buffer, const bool allow_compression=true)
Definition: utilities.h:1186
int string_to_int(const std::string &s)
Definition: utilities.cc:201
std::vector< unsigned int > reverse_permutation(const std::vector< unsigned int > &permutation)
Definition: utilities.cc:489
static::ExceptionBase & ExcNotImplemented()
unsigned long int VmRSS
Definition: utilities.h:723
unsigned int get_this_mpi_process(const Epetra_Comm &mpi_communicator)
Definition: utilities.cc:848
const std::string get_current_vectorization_level()
Definition: utilities.cc:630
Epetra_Map duplicate_map(const Epetra_BlockMap &map, const Epetra_Comm &comm)
Definition: utilities.cc:856
std::string get_time()
Definition: utilities.cc:701
unsigned long int VmPeak
Definition: utilities.h:707
unsigned int needed_digits(const unsigned int max_number)
Definition: utilities.cc:180
static::ExceptionBase & ExcInternalError()