16#include <deal.II/base/partitioner.templates.h>
18#include <boost/serialization/utility.hpp>
20#include <Kokkos_Core.hpp>
39 , n_ghost_indices_data(0)
40 , n_import_indices_data(0)
41 , n_ghost_indices_in_larger_set(0)
44 , communicator(MPI_COMM_SELF)
45 , have_ghost_indices(false)
50 Partitioner::Partitioner(
const unsigned int size)
52 , locally_owned_range_data(
size)
55 , n_ghost_indices_data(0)
56 , n_import_indices_data(0)
57 , n_ghost_indices_in_larger_set(0)
60 , communicator(MPI_COMM_SELF)
61 , have_ghost_indices(false)
63 locally_owned_range_data.add_range(0,
size);
64 locally_owned_range_data.compress();
65 ghost_indices_data.set_size(
size);
75 , locally_owned_range_data(global_size)
76 , local_range_data{0, local_size}
77 , n_ghost_indices_data(ghost_size)
78 , n_import_indices_data(0)
79 , n_ghost_indices_in_larger_set(0)
82 , communicator(communicator)
83 , have_ghost_indices(true)
87# ifdef DEAL_II_WITH_MPI
89 MPI_Exscan(&local_size,
98 local_range_data = {prefix_sum, prefix_sum + local_size};
100 locally_owned_range_data.add_range(prefix_sum, prefix_sum + local_size);
101 locally_owned_range_data.compress();
106 Partitioner::Partitioner(
const IndexSet &locally_owned_indices,
111 , n_ghost_indices_data(0)
112 , n_import_indices_data(0)
113 , n_ghost_indices_in_larger_set(0)
116 , communicator(communicator_in)
117 , have_ghost_indices(false)
119 set_owned_indices(locally_owned_indices);
120 set_ghost_indices(ghost_indices_in);
125 Partitioner::Partitioner(
const IndexSet &locally_owned_indices,
129 , n_ghost_indices_data(0)
130 , n_import_indices_data(0)
131 , n_ghost_indices_in_larger_set(0)
134 , communicator(communicator_in)
135 , have_ghost_indices(false)
137 set_owned_indices(locally_owned_indices);
143 Partitioner::reinit(
const IndexSet &locally_owned_indices,
147 have_ghost_indices =
false;
148 communicator = communicator_in;
149 set_owned_indices(locally_owned_indices);
150 set_ghost_indices(ghost_indices);
156 Partitioner::set_owned_indices(
const IndexSet &locally_owned_indices)
163 ExcMessage(
"The index set specified in locally_owned_indices "
164 "is not contiguous."));
168 std::pair<types::global_dof_index, types::global_dof_index>(
173 local_range_data.second - local_range_data.first <
175 std::numeric_limits<unsigned int>::max()),
177 "Index overflow: This class supports at most 2^32-1 locally owned vector entries"));
178 locally_owned_range_data.set_size(locally_owned_indices.
size());
179 locally_owned_range_data.add_range(local_range_data.first,
180 local_range_data.second);
181 locally_owned_range_data.compress();
183 ghost_indices_data.set_size(locally_owned_indices.
size());
189 Partitioner::set_ghost_indices(
const IndexSet &ghost_indices_in,
190 const IndexSet &larger_ghost_index_set)
196 ghost_indices_in.
size() == locally_owned_range_data.size(),
198 locally_owned_range_data.size()));
202 import_indices_plain_dev = {};
203 import_entries_dev = {};
204 import_entry_offsets_dev = {};
205 import_entry_positions_dev = {};
207 ghost_indices_data = ghost_indices_in;
208 if (ghost_indices_data.size() != locally_owned_range_data.size())
209 ghost_indices_data.
set_size(locally_owned_range_data.size());
210 ghost_indices_data.subtract_set(locally_owned_range_data);
211 ghost_indices_data.compress();
213 ghost_indices_data.n_elements() <
215 std::numeric_limits<unsigned int>::max()),
217 "Index overflow: This class supports at most 2^32-1 ghost elements"));
218 n_ghost_indices_data = ghost_indices_data.n_elements();
231# ifdef DEAL_II_WITH_MPI
246 my_size += local_range_data.first;
250 const int ierr = MPI_Exscan(
254 Utilities::MPI::mpi_type_id_for_type<types::global_dof_index>,
266 my_shift = local_range_data.first;
270 if (local_range_data.first == 0 && my_shift != 0)
274 local_range_data.first = my_shift;
275 local_range_data.second = my_shift + old_locally_owned_size;
278 const auto [owning_ranks_of_ghosts, import_data] =
280 locally_owned_range_data, ghost_indices_data, communicator);
284 ghost_targets_data = {};
286 if (owning_ranks_of_ghosts.size() > 0)
288 ghost_targets_data.emplace_back(owning_ranks_of_ghosts[0], 0);
289 for (
auto i : owning_ranks_of_ghosts)
291 Assert(i >= ghost_targets_data.back().first,
293 "Expect result of ConsensusAlgorithms::Process to be "
295 if (i == ghost_targets_data.back().first)
296 ghost_targets_data.back().second++;
298 ghost_targets_data.emplace_back(i, 1);
304 n_import_indices_data = 0;
305 import_targets_data = {};
306 import_targets_data.reserve(import_data.size());
307 import_indices_chunks_by_rank_data = {};
308 import_indices_chunks_by_rank_data.reserve(import_data.size());
309 import_indices_chunks_by_rank_data.resize(1);
310 for (
const auto &i : import_data)
313 import_targets_data.emplace_back(i.first, i.second.n_elements());
314 n_import_indices_data += i.second.n_elements();
315 import_indices_chunks_by_rank_data.push_back(
316 import_indices_chunks_by_rank_data.back() +
317 i.second.n_intervals());
321 import_indices_data = {};
322 import_indices_data.reserve(import_indices_chunks_by_rank_data.back());
323 for (
const auto &i : import_data)
325 Assert((i.second & locally_owned_range_data) == i.second,
327 for (
auto interval = i.second.begin_intervals();
328 interval != i.second.end_intervals();
330 import_indices_data.emplace_back(*interval->begin() -
331 local_range_data.first,
332 interval->last() + 1 -
333 local_range_data.first);
355 const std::vector<types::global_dof_index> ghost_indices_ref =
356 ghost_indices_data.get_index_vector();
358 std::vector<types::global_dof_index> indices_to_send(
360 std::vector<types::global_dof_index> ghost_indices(n_ghost_indices());
362 const std::vector<types::global_dof_index> my_indices =
363 locally_owned_range_data.get_index_vector();
364 std::vector<MPI_Request> requests;
365 n_ghost_indices_in_larger_set = n_ghost_indices_data;
366 export_to_ghosted_array_start(
376 const int ierr = MPI_Testall(requests.size(),
379 MPI_STATUSES_IGNORE);
383 "MPI found unfinished requests. Check communication setup"));
385 for (
unsigned int i = 0; i < ghost_indices.size(); ++i)
391 if (larger_ghost_index_set.
size() == 0)
393 ghost_indices_subset_chunks_by_rank_data.clear();
394 ghost_indices_subset_data.emplace_back(0, n_ghost_indices());
395 n_ghost_indices_in_larger_set = n_ghost_indices_data;
400 ghost_indices_data.size());
402 (larger_ghost_index_set & locally_owned_range_data).n_elements() ==
404 ExcMessage(
"Ghost index set should not overlap with owned set."));
405 Assert((larger_ghost_index_set & ghost_indices_data) ==
407 ExcMessage(
"Larger ghost index set must contain the tight "
408 "ghost index set."));
410 n_ghost_indices_in_larger_set = larger_ghost_index_set.
n_elements();
414 std::vector<unsigned int> expanded_numbering;
415 for (const ::IndexSet::size_type index : ghost_indices_data)
418 ExcMessage(
"The given larger ghost index set must contain "
419 "all indices in the actual index set."));
423 std::numeric_limits<unsigned int>::max()),
425 "Index overflow: This class supports at most 2^32-1 ghost elements"));
426 expanded_numbering.push_back(
431 std::vector<std::pair<unsigned int, unsigned int>>
432 ghost_indices_subset;
433 ghost_indices_subset_chunks_by_rank_data.resize(
434 ghost_targets_data.size() + 1);
436 ghost_indices_subset_chunks_by_rank_data[0] = 0;
437 unsigned int shift = 0;
438 for (
unsigned int p = 0; p < ghost_targets_data.size(); ++p)
441 for (
unsigned int ii = 0; ii < ghost_targets_data[p].second; ++ii)
443 const unsigned int i =
shift + ii;
444 if (expanded_numbering[i] == last_index + 1)
446 ghost_indices_subset.back().second++;
449 ghost_indices_subset.emplace_back(expanded_numbering[i],
450 expanded_numbering[i] +
452 last_index = expanded_numbering[i];
454 shift += ghost_targets_data[p].second;
455 ghost_indices_subset_chunks_by_rank_data[p + 1] =
456 ghost_indices_subset.size();
458 ghost_indices_subset_data = std::move(ghost_indices_subset);
465 Partitioner::is_compatible(
const Partitioner &part)
const
471# ifdef DEAL_II_WITH_MPI
474 int communicators_same = 0;
475 const int ierr = MPI_Comm_compare(part.communicator,
477 &communicators_same);
479 if (!(communicators_same == MPI_IDENT ||
480 communicators_same == MPI_CONGRUENT))
484 return (global_size == part.global_size &&
485 local_range_data == part.local_range_data &&
486 ghost_indices_data == part.ghost_indices_data);
492 Partitioner::is_globally_compatible(
const Partitioner &part)
const
500 Partitioner::memory_consumption()
const
503 memory += locally_owned_range_data.memory_consumption();
505 memory += ghost_indices_data.memory_consumption();
506 memory +=
sizeof(n_ghost_indices_data);
509 memory +=
sizeof(import_indices_plain_dev) +
510 sizeof(
unsigned int) * import_indices_plain_dev.size();
511 memory +=
sizeof(import_entries_dev) +
512 sizeof(
unsigned int) * import_entries_dev.size();
513 memory +=
sizeof(import_entry_offsets_dev) +
514 sizeof(
unsigned int) * import_entry_offsets_dev.size();
515 memory +=
sizeof(import_entry_positions_dev) +
516 sizeof(
unsigned int) * import_entry_positions_dev.size();
520 import_indices_chunks_by_rank_data);
524 ghost_indices_subset_chunks_by_rank_data);
537 Partitioner::initialize_import_indices_plain_dev()
const
543 std::vector<unsigned int> import_indices_plain_host;
544 import_indices_plain_host.reserve(n_import_indices_data);
545 for (
const auto &import_range : import_indices_data)
546 for (unsigned
int j = import_range.
first; j < import_range.second; ++j)
547 import_indices_plain_host.push_back(j);
548 AssertDimension(import_indices_plain_host.size(), n_import_indices_data);
553 std::vector<std::pair<unsigned int, unsigned int>> index_and_position;
554 index_and_position.reserve(import_indices_plain_host.size());
555 for (
unsigned int p = 0; p < import_indices_plain_host.size(); ++p)
556 index_and_position.emplace_back(import_indices_plain_host[p], p);
557 std::sort(index_and_position.begin(), index_and_position.end());
559 std::vector<unsigned int> import_entries_host;
560 std::vector<unsigned int> import_entry_offsets_host;
561 std::vector<unsigned int> import_entry_positions_host;
562 import_entry_positions_host.reserve(index_and_position.size());
563 for (
const auto &[index, position] : index_and_position)
565 if (import_entries_host.empty() ||
566 import_entries_host.back() != index)
568 import_entries_host.push_back(index);
569 import_entry_offsets_host.push_back(
570 import_entry_positions_host.size());
572 import_entry_positions_host.push_back(position);
574 import_entry_offsets_host.push_back(import_entry_positions_host.size());
577 const auto copy_to_device = [](
const std::vector<unsigned int> &host,
578 const std::string &name) {
579 Kokkos::View<unsigned int *, MemorySpace::Default::kokkos_space> device(
580 Kokkos::view_alloc(name, Kokkos::WithoutInitializing), host.size());
581 Kokkos::deep_copy(device,
582 Kokkos::View<const unsigned int *, Kokkos::HostSpace>(
583 host.data(), host.size()));
586 import_indices_plain_dev =
587 copy_to_device(import_indices_plain_host,
"import_indices_plain_dev");
589 copy_to_device(import_entries_host,
"import_entries_dev");
590 import_entry_offsets_dev =
591 copy_to_device(import_entry_offsets_host,
"import_entry_offsets_dev");
592 import_entry_positions_dev = copy_to_device(import_entry_positions_host,
593 "import_entry_positions_dev");
603#include "base/partitioner.inst"
* * for(const auto &cell :triangulation.active_cell_iterators())
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