16#include <deal.II/base/partitioner.templates.h>
18#include <boost/serialization/utility.hpp>
20#include <Kokkos_Core.hpp>
35 , n_ghost_indices_data(0)
36 , n_import_indices_data(0)
37 , n_ghost_indices_in_larger_set(0)
40 , communicator(MPI_COMM_SELF)
41 , have_ghost_indices(false)
46 Partitioner::Partitioner(
const unsigned int size)
48 , locally_owned_range_data(
size)
51 , n_ghost_indices_data(0)
52 , n_import_indices_data(0)
53 , n_ghost_indices_in_larger_set(0)
56 , communicator(MPI_COMM_SELF)
57 , have_ghost_indices(false)
59 locally_owned_range_data.add_range(0,
size);
60 locally_owned_range_data.compress();
61 ghost_indices_data.set_size(
size);
71 , locally_owned_range_data(global_size)
72 , local_range_data{0, local_size}
73 , n_ghost_indices_data(ghost_size)
74 , n_import_indices_data(0)
75 , n_ghost_indices_in_larger_set(0)
78 , communicator(communicator)
79 , have_ghost_indices(true)
83# ifdef DEAL_II_WITH_MPI
85 MPI_Exscan(&local_size,
94 local_range_data = {prefix_sum, prefix_sum + local_size};
96 locally_owned_range_data.add_range(prefix_sum, prefix_sum + local_size);
97 locally_owned_range_data.compress();
102 Partitioner::Partitioner(
const IndexSet &locally_owned_indices,
107 , n_ghost_indices_data(0)
108 , n_import_indices_data(0)
109 , n_ghost_indices_in_larger_set(0)
112 , communicator(communicator_in)
113 , have_ghost_indices(false)
115 set_owned_indices(locally_owned_indices);
116 set_ghost_indices(ghost_indices_in);
121 Partitioner::Partitioner(
const IndexSet &locally_owned_indices,
125 , n_ghost_indices_data(0)
126 , n_import_indices_data(0)
127 , n_ghost_indices_in_larger_set(0)
130 , communicator(communicator_in)
131 , have_ghost_indices(false)
133 set_owned_indices(locally_owned_indices);
139 Partitioner::reinit(
const IndexSet &locally_owned_indices,
143 have_ghost_indices =
false;
144 communicator = communicator_in;
145 set_owned_indices(locally_owned_indices);
146 set_ghost_indices(ghost_indices);
152 Partitioner::set_owned_indices(
const IndexSet &locally_owned_indices)
159 ExcMessage(
"The index set specified in locally_owned_indices "
160 "is not contiguous."));
164 std::pair<types::global_dof_index, types::global_dof_index>(
169 local_range_data.second - local_range_data.first <
171 std::numeric_limits<unsigned int>::max()),
173 "Index overflow: This class supports at most 2^32-1 locally owned vector entries"));
174 locally_owned_range_data.set_size(locally_owned_indices.
size());
175 locally_owned_range_data.add_range(local_range_data.first,
176 local_range_data.second);
177 locally_owned_range_data.compress();
179 ghost_indices_data.set_size(locally_owned_indices.
size());
185 Partitioner::set_ghost_indices(
const IndexSet &ghost_indices_in,
186 const IndexSet &larger_ghost_index_set)
192 ghost_indices_in.
size() == locally_owned_range_data.size(),
194 locally_owned_range_data.size()));
196 ghost_indices_data = ghost_indices_in;
197 if (ghost_indices_data.size() != locally_owned_range_data.size())
198 ghost_indices_data.
set_size(locally_owned_range_data.size());
199 ghost_indices_data.subtract_set(locally_owned_range_data);
200 ghost_indices_data.compress();
202 ghost_indices_data.n_elements() <
204 std::numeric_limits<unsigned int>::max()),
206 "Index overflow: This class supports at most 2^32-1 ghost elements"));
207 n_ghost_indices_data = ghost_indices_data.n_elements();
220# ifdef DEAL_II_WITH_MPI
235 my_size += local_range_data.first;
239 const int ierr = MPI_Exscan(
243 Utilities::MPI::mpi_type_id_for_type<types::global_dof_index>,
255 my_shift = local_range_data.first;
259 if (local_range_data.first == 0 && my_shift != 0)
263 local_range_data.first = my_shift;
264 local_range_data.second = my_shift + old_locally_owned_size;
267 const auto [owning_ranks_of_ghosts, import_data] =
269 locally_owned_range_data, ghost_indices_data, communicator);
273 ghost_targets_data = {};
275 if (owning_ranks_of_ghosts.size() > 0)
277 ghost_targets_data.emplace_back(owning_ranks_of_ghosts[0], 0);
278 for (
auto i : owning_ranks_of_ghosts)
280 Assert(i >= ghost_targets_data.back().first,
282 "Expect result of ConsensusAlgorithms::Process to be "
284 if (i == ghost_targets_data.back().first)
285 ghost_targets_data.back().second++;
287 ghost_targets_data.emplace_back(i, 1);
293 n_import_indices_data = 0;
294 import_targets_data = {};
295 import_targets_data.reserve(import_data.size());
296 import_indices_chunks_by_rank_data = {};
297 import_indices_chunks_by_rank_data.reserve(import_data.size());
298 import_indices_chunks_by_rank_data.resize(1);
299 for (
const auto &i : import_data)
302 import_targets_data.emplace_back(i.first, i.second.n_elements());
303 n_import_indices_data += i.second.n_elements();
304 import_indices_chunks_by_rank_data.push_back(
305 import_indices_chunks_by_rank_data.back() +
306 i.second.n_intervals());
310 import_indices_data = {};
311 import_indices_data.reserve(import_indices_chunks_by_rank_data.back());
312 for (
const auto &i : import_data)
314 Assert((i.second & locally_owned_range_data) == i.second,
316 for (
auto interval = i.second.begin_intervals();
317 interval != i.second.end_intervals();
319 import_indices_data.emplace_back(*interval->begin() -
320 local_range_data.first,
321 interval->last() + 1 -
322 local_range_data.first);
344 const std::vector<types::global_dof_index> ghost_indices_ref =
345 ghost_indices_data.get_index_vector();
347 std::vector<types::global_dof_index> indices_to_send(
349 std::vector<types::global_dof_index> ghost_indices(n_ghost_indices());
351 const std::vector<types::global_dof_index> my_indices =
352 locally_owned_range_data.get_index_vector();
353 std::vector<MPI_Request> requests;
354 n_ghost_indices_in_larger_set = n_ghost_indices_data;
355 export_to_ghosted_array_start(
365 const int ierr = MPI_Testall(requests.size(),
368 MPI_STATUSES_IGNORE);
372 "MPI found unfinished requests. Check communication setup"));
374 for (
unsigned int i = 0; i < ghost_indices.size(); ++i)
380 if (larger_ghost_index_set.
size() == 0)
382 ghost_indices_subset_chunks_by_rank_data.clear();
383 ghost_indices_subset_data.emplace_back(0, n_ghost_indices());
384 n_ghost_indices_in_larger_set = n_ghost_indices_data;
389 ghost_indices_data.size());
391 (larger_ghost_index_set & locally_owned_range_data).n_elements() ==
393 ExcMessage(
"Ghost index set should not overlap with owned set."));
394 Assert((larger_ghost_index_set & ghost_indices_data) ==
396 ExcMessage(
"Larger ghost index set must contain the tight "
397 "ghost index set."));
399 n_ghost_indices_in_larger_set = larger_ghost_index_set.
n_elements();
403 std::vector<unsigned int> expanded_numbering;
404 for (const ::IndexSet::size_type index : ghost_indices_data)
407 ExcMessage(
"The given larger ghost index set must contain "
408 "all indices in the actual index set."));
412 std::numeric_limits<unsigned int>::max()),
414 "Index overflow: This class supports at most 2^32-1 ghost elements"));
415 expanded_numbering.push_back(
420 std::vector<std::pair<unsigned int, unsigned int>>
421 ghost_indices_subset;
422 ghost_indices_subset_chunks_by_rank_data.resize(
423 ghost_targets_data.size() + 1);
425 ghost_indices_subset_chunks_by_rank_data[0] = 0;
426 unsigned int shift = 0;
427 for (
unsigned int p = 0; p < ghost_targets_data.size(); ++p)
430 for (
unsigned int ii = 0; ii < ghost_targets_data[p].second; ++ii)
432 const unsigned int i =
shift + ii;
433 if (expanded_numbering[i] == last_index + 1)
435 ghost_indices_subset.back().second++;
438 ghost_indices_subset.emplace_back(expanded_numbering[i],
439 expanded_numbering[i] +
441 last_index = expanded_numbering[i];
443 shift += ghost_targets_data[p].second;
444 ghost_indices_subset_chunks_by_rank_data[p + 1] =
445 ghost_indices_subset.size();
447 ghost_indices_subset_data = std::move(ghost_indices_subset);
454 Partitioner::is_compatible(
const Partitioner &part)
const
460# ifdef DEAL_II_WITH_MPI
463 int communicators_same = 0;
464 const int ierr = MPI_Comm_compare(part.communicator,
466 &communicators_same);
468 if (!(communicators_same == MPI_IDENT ||
469 communicators_same == MPI_CONGRUENT))
473 return (global_size == part.global_size &&
474 local_range_data == part.local_range_data &&
475 ghost_indices_data == part.ghost_indices_data);
481 Partitioner::is_globally_compatible(
const Partitioner &part)
const
489 Partitioner::memory_consumption()
const
492 memory += locally_owned_range_data.memory_consumption();
494 memory += ghost_indices_data.memory_consumption();
495 memory +=
sizeof(n_ghost_indices_data);
498 memory +=
sizeof(import_indices_plain_dev) +
499 sizeof(*import_indices_plain_dev.begin()) *
500 import_indices_plain_dev.capacity();
504 import_indices_chunks_by_rank_data);
508 ghost_indices_subset_chunks_by_rank_data);
521 Partitioner::initialize_import_indices_plain_dev()
const
523 const unsigned int n_import_targets = import_targets_data.size();
524 import_indices_plain_dev.reserve(n_import_targets);
525 for (
unsigned int i = 0; i < n_import_targets; ++i)
528 std::vector<std::pair<unsigned int, unsigned int>>::const_iterator
529 my_imports = import_indices_data.begin() +
530 import_indices_chunks_by_rank_data[i],
531 end_my_imports = import_indices_data.begin() +
532 import_indices_chunks_by_rank_data[i + 1];
533 std::vector<unsigned int> import_indices_plain_host;
534 for (; my_imports != end_my_imports; ++my_imports)
536 const unsigned int chunk_size =
537 my_imports->second - my_imports->first;
538 for (
unsigned int j = 0; j < chunk_size; ++j)
539 import_indices_plain_host.push_back(my_imports->first + j);
543 const auto chunk_size = import_indices_plain_host.size();
544 import_indices_plain_dev.emplace_back(
"import_indices_plain_dev" +
547 Kokkos::deep_copy(import_indices_plain_dev.back(),
548 Kokkos::View<unsigned int *, Kokkos::HostSpace>(
549 import_indices_plain_host.data(), chunk_size));
560#include "base/partitioner.inst"
ArrayView< std::remove_reference_t< typename std::iterator_traits< Iterator >::reference >, MemorySpaceType > make_array_view(const Iterator begin, const Iterator end)
bool is_contiguous() const
size_type index_within_set(const size_type global_index) const
size_type n_elements() const
bool is_element(const size_type index) const
void set_size(const size_type size)
size_type nth_index_in_set(const size_type local_index) const
#define DEAL_II_NAMESPACE_OPEN
constexpr bool running_in_debug_mode()
#define DEAL_II_NAMESPACE_CLOSE
#define Assert(cond, exc)
#define AssertDimension(dim1, dim2)
#define AssertThrowMPI(error_code)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
types::global_dof_index locally_owned_size
const unsigned int n_procs
std::enable_if_t< std::is_fundamental_v< T >, std::size_t > memory_consumption(const T &t)
* * if(update_pressure &update_flags) * compute_pressure(constitutive_request
std::pair< std::vector< unsigned int >, std::map< unsigned int, IndexSet > > compute_index_owner_and_requesters(const IndexSet &owned_indices, const IndexSet &indices_to_look_up, const MPI_Comm &comm)
T sum(const T &t, const MPI_Comm mpi_communicator)
bool logical_and(const bool t, const MPI_Comm mpi_communicator)
T logical_or(const T &t, const MPI_Comm mpi_communicator)
unsigned int n_mpi_processes(const MPI_Comm mpi_communicator)
unsigned int this_mpi_process(const MPI_Comm mpi_communicator)
const MPI_Datatype mpi_type_id_for_type
constexpr unsigned int invalid_unsigned_int
unsigned int global_dof_index