Loading...
Searching...
No Matches
utils.h
// Copyright (C) 2009-2025 Anders Logg and Garth N. Wells
//
// This file is part of DOLFINx (https://www.fenicsproject.org)
//
// SPDX-License-Identifier: LGPL-3.0-or-later
#pragma once
#include "MPI.h"
#include <algorithm>
#include <boost/functional/hash.hpp>
#include <dolfinx/graph/AdjacencyList.h>
#include <mpi.h>
#include <string>
#include <tuple>
#include <utility>
#include <vector>
namespace dolfinx::common
{
template <typename U, typename V>
std::pair<std::vector<typename U::value_type>,
std::vector<typename V::value_type>>
sort_unique(const U& indices, const V& values)
{
if (indices.size() != values.size())
throw std::runtime_error("Cannot sort two arrays of different lengths");
using T = typename std::pair<typename U::value_type, typename V::value_type>;
std::vector<T> data(indices.size());
std::ranges::transform(indices, values, data.begin(),
[](auto& idx, auto& v) -> T { return {idx, v}; });
// Sort make unique
std::ranges::sort(data);
auto it = std::ranges::unique(data, [](auto& a, auto& b)
{ return a.first == b.first; })
.begin();
std::vector<typename U::value_type> indices_new;
std::vector<typename V::value_type> values_new;
indices_new.reserve(data.size());
values_new.reserve(data.size());
std::transform(data.begin(), it, std::back_inserter(indices_new),
[](auto& d) { return d.first; });
std::transform(data.begin(), it, std::back_inserter(values_new),
[](auto& d) { return d.second; });
return {std::move(indices_new), std::move(values_new)};
}
template <class T>
std::size_t hash_local(const T& x)
{
boost::hash<T> hash;
return hash(x);
}
template <class T>
std::size_t hash_global(MPI_Comm comm, const T& x)
{
// Compute local hash
std::size_t local_hash = hash_local(x);
// Gather hash keys on root process
std::vector<std::size_t> all_hashes(dolfinx::MPI::size(comm));
int err = MPI_Gather(&local_hash, 1, dolfinx::MPI::mpi_t<std::size_t>,
all_hashes.data(), 1, dolfinx::MPI::mpi_t<std::size_t>,
0, comm);
dolfinx::MPI::check_error(comm, err);
// Hash the received hash keys
boost::hash<std::vector<std::size_t>> hash;
std::size_t global_hash = hash(all_hashes);
// Broadcast hash key to all processes
err = MPI_Bcast(&global_hash, 1, dolfinx::MPI::mpi_t<std::size_t>, 0, comm);
dolfinx::MPI::check_error(comm, err);
return global_hash;
}
std::string comm_to_json(
const graph::AdjacencyList<std::tuple<int, std::size_t, std::int8_t>,
std::pair<std::int32_t, std::int32_t>>& g);
} // namespace dolfinx::common
dolfinx::graph::AdjacencyList
This class provides a static adjacency list data structure.
Definition AdjacencyList.h:38
dolfinx::MPI::mpi_t
MPI_Datatype mpi_t
Retrieves the MPI data type associated to the provided type.
Definition MPI.h:280
dolfinx::MPI::check_error
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
dolfinx::MPI::size
int size(MPI_Comm comm)
Definition MPI.cpp:72
dolfinx::common
Miscellaneous classes, functions and types.
Definition dolfinx_common.h:8
dolfinx::common::sort_unique
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.
Definition utils.h:34
dolfinx::common::hash_global
std::size_t hash_global(MPI_Comm comm, const T &x)
Compute a hash for a distributed (MPI) object.
Definition utils.h:88
dolfinx::common::hash_local
std::size_t hash_local(const T &x)
Compute a hash of a given object.
Definition utils.h:70
dolfinx::common::comm_to_json
std::string comm_to_json(const graph::AdjacencyList< std::tuple< int, std::size_t, std::int8_t >, std::pair< std::int32_t, std::int32_t > > &g)
Build communication graph data as a JSON string.