DOLFIN-X
DOLFIN-X C++ interface
utils.h
1 // Copyright (C) 2009-2010 Anders Logg
2 //
3 // This file is part of DOLFINX (https://www.fenicsproject.org)
4 //
5 // SPDX-License-Identifier: LGPL-3.0-or-later
6 
7 #pragma once
8 
9 #include <algorithm>
10 #include <boost/functional/hash.hpp>
11 #include <cstring>
12 #include <dolfinx/common/MPI.h>
13 #include <limits>
14 #include <mpi.h>
15 #include <sstream>
16 #include <string>
17 #include <utility>
18 #include <vector>
19 
20 namespace dolfinx::common
21 {
22 
29 template <typename U, typename V>
30 std::pair<U, V> sort_unique(const U& indices, const V& values)
31 {
32  if (indices.size() != values.size())
33  throw std::runtime_error("Cannot sort two arrays of different lengths");
34 
35  std::vector<std::pair<typename U::value_type, typename V::value_type>> data(
36  indices.size());
37  for (std::size_t i = 0; i < indices.size(); ++i)
38  data[i] = {indices[i], values[i]};
39 
40  // Sort make unique
41  std::sort(data.begin(), data.end());
42  auto it = std::unique(data.begin(), data.end(),
43  [](auto& a, auto& b) { return a.first == b.first; });
44 
45  U indices_new;
46  V values_new;
47  indices_new.reserve(data.size());
48  values_new.reserve(data.size());
49  for (auto d = data.begin(); d != it; ++d)
50  {
51  indices_new.push_back(d->first);
52  values_new.push_back(d->second);
53  }
54 
55  return {std::move(indices_new), std::move(values_new)};
56 }
57 
59 std::string indent(std::string block);
60 
63 template <typename T>
64 std::string container_to_string(const T& x, std::string delimiter,
65  int precision, int linebreak = 0)
66 {
67  std::stringstream s;
68  s.precision(precision);
69  if (!x.empty())
70  {
71  if (linebreak == 0)
72  {
73  s << *x.begin();
74  for (auto it = x.begin() + 1; it != x.end(); ++it)
75  s << delimiter << *it;
76  }
77  else
78  {
79  for (std::size_t i = 0; i != x.size(); ++i)
80  {
81  if ((i + 1) % linebreak == 0)
82  s << x[i] << std::endl;
83  else
84  s << x[i] << delimiter;
85  }
86  }
87  }
88  return s.str();
89 }
90 
92 template <class T>
93 std::size_t hash_local(const T& x)
94 {
95  boost::hash<T> hash;
96  return hash(x);
97 }
98 
102 template <class T>
103 std::int64_t hash_global(const MPI_Comm comm, const T& x)
104 {
105  // Compute local hash
106  int64_t local_hash = hash_local(x);
107 
108  // Gather hash keys on root process
109  std::vector<int64_t> all_hashes(dolfinx::MPI::size(comm));
110  MPI_Gather(&local_hash, 1, MPI_INT64_T, all_hashes.data(), 1, MPI_INT64_T, 0,
111  comm);
112 
113  // Hash the received hash keys
114  boost::hash<std::vector<int64_t>> hash;
115  int64_t global_hash = hash(all_hashes);
116 
117  // Broadcast hash key to all processes
118  MPI_Bcast(&global_hash, 1, MPI_INT64_T, 0, comm);
119 
120  return global_hash;
121 }
122 } // namespace dolfinx::common
static int size(MPI_Comm comm)
Return size of the group (number of processes) associated with the communicator.
Definition: MPI.cpp:87
Miscellaneous classes, functions and types.
std::string indent(std::string block)
Indent string block.
Definition: utils.cpp:12
std::size_t hash_local(const T &x)
Return a hash of a given object.
Definition: utils.h:93
std::pair< U, V > sort_unique(const U &indices, const V &values)
Sort two arrays based on the values in array indices. Any duplicate indices and the corresponding val...
Definition: utils.h:30
std::int64_t hash_global(const MPI_Comm comm, const T &x)
Return a hash for a distributed (MPI) object. A hash is computed on each process, and the hash of the...
Definition: utils.h:103
std::string container_to_string(const T &x, std::string delimiter, int precision, int linebreak=0)
Return string representation of given container of ints, floats, etc.
Definition: utils.h:64