DOLFINx 0.8.0
DOLFINx C++ interface
Loading...
Searching...
No Matches
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
17namespace dolfinx::common
18{
25template <typename U, typename V>
26std::pair<std::vector<typename U::value_type>,
27 std::vector<typename V::value_type>>
28sort_unique(const U& indices, const V& values)
29{
30 if (indices.size() != values.size())
31 throw std::runtime_error("Cannot sort two arrays of different lengths");
32
33 using T = typename std::pair<typename U::value_type, typename V::value_type>;
34 std::vector<T> data(indices.size());
35 std::transform(indices.begin(), indices.end(), values.begin(), data.begin(),
36 [](auto& idx, auto& v) -> T { return {idx, v}; });
37
38 // Sort make unique
39 std::sort(data.begin(), data.end());
40 auto it = std::unique(data.begin(), data.end(),
41 [](auto& a, auto& b) { return a.first == b.first; });
42
43 std::vector<typename U::value_type> indices_new;
44 std::vector<typename V::value_type> values_new;
45 indices_new.reserve(data.size());
46 values_new.reserve(data.size());
47 std::transform(data.begin(), it, std::back_inserter(indices_new),
48 [](auto& d) { return d.first; });
49 std::transform(data.begin(), it, std::back_inserter(values_new),
50 [](auto& d) { return d.second; });
51
52 return {std::move(indices_new), std::move(values_new)};
53}
54
62template <class T>
63std::size_t hash_local(const T& x)
64{
65 boost::hash<T> hash;
66 return hash(x);
67}
68
80template <class T>
81std::size_t hash_global(MPI_Comm comm, const T& x)
82{
83 // Compute local hash
84 std::size_t local_hash = hash_local(x);
85
86 // Gather hash keys on root process
87 std::vector<std::size_t> all_hashes(dolfinx::MPI::size(comm));
88 int err = MPI_Gather(&local_hash, 1, dolfinx::MPI::mpi_type<std::size_t>(),
89 all_hashes.data(), 1,
90 dolfinx::MPI::mpi_type<std::size_t>(), 0, comm);
92
93 // Hash the received hash keys
94 boost::hash<std::vector<std::size_t>> hash;
95 std::size_t global_hash = hash(all_hashes);
96
97 // Broadcast hash key to all processes
98 err = MPI_Bcast(&global_hash, 1, dolfinx::MPI::mpi_type<std::size_t>(), 0,
99 comm);
100 dolfinx::MPI::check_error(comm, err);
101
102 return global_hash;
103}
104
105} // namespace dolfinx::common
void check_error(MPI_Comm comm, int code)
Check MPI error code. If the error code is not equal to MPI_SUCCESS, then std::abort is called.
Definition MPI.cpp:80
int size(MPI_Comm comm)
Definition MPI.cpp:72
Miscellaneous classes, functions and types.
Definition dolfinx_common.h:8
std::pair< std::vector< typename U::value_type >, std::vector< typename V::value_type > > sort_unique(const U &indices, const V &values)
Definition utils.h:28
std::size_t hash_global(MPI_Comm comm, const T &x)
Compute a hash for a distributed (MPI) object.
Definition utils.h:81
std::size_t hash_local(const T &x)
Compute a hash of a given object.
Definition utils.h:63