Note: this is documentation for an old release. View the latest documentation at docs.fenicsproject.org/dolfinx/v0.9.0/cpp/doxygen/dd/d09/common_2utils_8h_source.html
DOLFINx  0.5.1
DOLFINx C++ interface
utils.h
1 // Copyright (C) 2009-2022 Anders Logg and Garth N. Wells
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 <dolfinx/common/MPI.h>
12 #include <mpi.h>
13 #include <utility>
14 #include <vector>
15 
16 namespace dolfinx::common
17 {
18 
19 namespace impl
20 {
22 template <int N, class InputIt, class OutputIt>
23 inline void copy_N(InputIt first, OutputIt result)
24 {
25  for (int i = 0; i < N; ++i)
26  *result++ = *first++;
27 }
28 } // namespace impl
29 
36 template <typename U, typename V>
37 std::pair<std::vector<typename U::value_type>,
38  std::vector<typename V::value_type>>
39 sort_unique(const U& indices, const V& values)
40 {
41  if (indices.size() != values.size())
42  throw std::runtime_error("Cannot sort two arrays of different lengths");
43 
44  using T = typename std::pair<typename U::value_type, typename V::value_type>;
45  std::vector<T> data(indices.size());
46  std::transform(indices.begin(), indices.end(), values.begin(), data.begin(),
47  [](auto& idx, auto& v) -> T {
48  return {idx, v};
49  });
50 
51  // Sort make unique
52  std::sort(data.begin(), data.end());
53  auto it = std::unique(data.begin(), data.end(),
54  [](auto& a, auto& b) { return a.first == b.first; });
55 
56  std::vector<typename U::value_type> indices_new;
57  std::vector<typename V::value_type> values_new;
58  indices_new.reserve(data.size());
59  values_new.reserve(data.size());
60  std::transform(data.begin(), it, std::back_inserter(indices_new),
61  [](auto& d) { return d.first; });
62  std::transform(data.begin(), it, std::back_inserter(values_new),
63  [](auto& d) { return d.second; });
64 
65  return {std::move(indices_new), std::move(values_new)};
66 }
67 
75 template <class T>
76 std::size_t hash_local(const T& x)
77 {
78  boost::hash<T> hash;
79  return hash(x);
80 }
81 
93 template <class T>
94 std::size_t hash_global(MPI_Comm comm, const T& x)
95 {
96  // Compute local hash
97  std::size_t local_hash = hash_local(x);
98 
99  // Gather hash keys on root process
100  std::vector<std::size_t> all_hashes(dolfinx::MPI::size(comm));
101  MPI_Gather(&local_hash, 1, dolfinx::MPI::mpi_type<std::size_t>(),
102  all_hashes.data(), 1, dolfinx::MPI::mpi_type<std::size_t>(), 0,
103  comm);
104 
105  // Hash the received hash keys
106  boost::hash<std::vector<std::size_t>> hash;
107  std::size_t global_hash = hash(all_hashes);
108 
109  // Broadcast hash key to all processes
110  MPI_Bcast(&global_hash, 1, dolfinx::MPI::mpi_type<std::size_t>(), 0, comm);
111 
112  return global_hash;
113 }
114 
115 } // namespace dolfinx::common
int size(MPI_Comm comm)
Return size of the group (number of processes) associated with the communicator.
Definition: MPI.cpp:84
Miscellaneous classes, functions and types.
std::size_t hash_local(const T &x)
Compute a hash of a given object.
Definition: utils.h:76
std::size_t hash_global(MPI_Comm comm, const T &x)
Compute a hash for a distributed (MPI) object.
Definition: utils.h:94
std::pair< std::vector< typename U::value_type >, std::vector< typename V::value_type > > 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:39