105 row_starts_host_ = Kokkos::View<unsigned int *, KokkosHost, Aligned>(
106 "sparsity_pattern_row_starts", sparsity.n_rows() + 1);
108 column_indices_host_ = Kokkos::View<unsigned int *, KokkosHost, Aligned>(
109 "sparsity_pattern_column_indices", sparsity.n_nonzero_elements());
111 indices_transposed_host_ =
112 Kokkos::View<unsigned int *, KokkosHost, Aligned>(
113 "sparsity_pattern_indices_transposed",
114 sparsity.n_nonzero_elements());
118 row_starts_host_[0] = 0;
120 unsigned int *col_ptr = column_indices_host_.data();
121 unsigned int *transposed_ptr = indices_transposed_host_.data();
123 for (
unsigned int i = 0; i < n_internal_dofs; i +=
warp_size) {
124 auto jts = generate_iterators<warp_size>(
125 [&](
auto k) {
return sparsity.begin(i + k); });
128 for (
unsigned int k = 0; k <
warp_size; ++k) {
129 const unsigned int column = jts[k]->column();
131 const std::size_t position = sparsity(column, i + k);
132 if (column < n_internal_dofs) {
133 const unsigned int my_row_length = sparsity.row_length(column);
134 const std::size_t position_diag = sparsity(column, column);
135 const std::size_t pos_within_row = position - position_diag;
136 const unsigned int lane = column %
warp_size;
137 *transposed_ptr++ = position - lane * my_row_length -
138 pos_within_row + lane +
141 *transposed_ptr++ = position;
145 col_ptr - column_indices_host_.data();
150 row_starts_host_[n_internal_dofs] =
151 row_starts_host_[n_internal_dofs /
warp_size];
153 for (
unsigned int i = n_internal_dofs; i < sparsity.n_rows(); ++i) {
154 for (
auto j = sparsity.begin(i); j != sparsity.end(i); ++j) {
155 const unsigned int column = j->column();
157 const std::size_t position = sparsity(column, i);
158 if (column < n_internal_dofs) {
159 const unsigned int my_row_length = sparsity.row_length(column);
160 const std::size_t position_diag = sparsity(column, column);
161 const std::size_t pos_within_row = position - position_diag;
162 const unsigned int lane = column %
warp_size;
163 *transposed_ptr++ = position - lane * my_row_length - pos_within_row +
166 *transposed_ptr++ = position;
168 row_starts_host_[i + 1] = col_ptr - column_indices_host_.data();
172 const auto distance = std::distance(column_indices_host_.data(), col_ptr);
173 Assert(
static_cast<std::size_t
>(distance) == column_indices_host_.size(),
174 dealii::ExcInternalError());
181 receive_targets_.clear();
182 send_targets_.clear();
184 std::vector<ExchangeDescription> entries_to_be_sent;
186 if (sparsity.n_rows() > n_locally_owned_dofs_) {
187 const unsigned int mpi_tag =
188 dealii::Utilities::MPI::internal::Tags::partitioner_export_start + 0;
190 const auto &ghost_targets = partitioner->ghost_targets();
191 const auto &import_targets = partitioner->import_targets();
192 const auto &mpi_communicator = partitioner->get_mpi_communicator();
194 const unsigned int n_requests =
195 ghost_targets.size() + import_targets.size();
196 std::vector<MPI_Request> requests(n_requests);
212 receive_targets_.resize(ghost_targets.size());
213 for (
unsigned int p = 0; p < receive_targets_.size(); ++p) {
214 receive_targets_[p].first = ghost_targets[p].first;
219 unsigned int ghost_targets_index = 0;
221 unsigned int index = 0;
222 unsigned int previous_index = 0;
224 unsigned int row_count = 0;
225 for (
unsigned int i = n_locally_owned_dofs_; i < sparsity.n_rows();
227 index += sparsity.row_length(i);
229 const auto ghost_target = ghost_targets[ghost_targets_index];
230 if (row_count == ghost_target.second) {
231 receive_targets_[ghost_targets_index].second = index;
233 unsigned int n_entries = index - previous_index;
234 const int ierr = MPI_Isend(
237 dealii::Utilities::MPI::mpi_type_id_for_type<unsigned int>,
241 &requests[ghost_targets_index]);
242 AssertThrowMPI(ierr);
245 ++ghost_targets_index;
246 previous_index = index;
251 Assert(ghost_targets_index == partitioner->ghost_targets().size(),
252 dealii::ExcInternalError());
262 std::vector<unsigned int> send_ranges(import_targets.size());
263 for (
unsigned int p = 0; p < import_targets.size(); ++p) {
264 const int ierr = MPI_Irecv(
267 dealii::Utilities::MPI::mpi_type_id_for_type<unsigned int>,
268 import_targets[p].first,
271 &requests[ghost_targets.size() + p]);
272 AssertThrowMPI(ierr);
277 MPI_Waitall(requests.size(), requests.data(), MPI_STATUSES_IGNORE);
278 AssertThrowMPI(ierr);
287 std::vector<dealii::types::global_dof_index> requested_entries;
290 unsigned int ghost_targets_index = 0;
292 unsigned int row_count = 0;
293 for (
unsigned int i = n_locally_owned_dofs_; i < sparsity.n_rows();
295 const auto i_global = partitioner_->local_to_global(i);
296 for (
auto idx = sparsity.begin(i); idx != sparsity.end(i); ++idx) {
297 const unsigned int j = idx->column();
298 const auto j_global = partitioner_->local_to_global(j);
299 requested_entries.push_back(i_global);
300 requested_entries.push_back(j_global);
304 if (row_count == ghost_targets[ghost_targets_index].second) {
306 ++ghost_targets_index;
311 Assert(ghost_targets_index == partitioner->ghost_targets().size(),
312 dealii::ExcInternalError());
315 const auto ghost_offset = row_starts_host_(n_locally_owned_dofs_);
316 const auto n_nonzero_elements =
317 row_starts_host_(row_starts_host_.size() - 1);
318 Assert(requested_entries.size() ==
319 2 * (n_nonzero_elements - ghost_offset),
320 dealii::ExcInternalError());
323 for (
unsigned int p = 0; p < receive_targets_.size(); ++p) {
324 const auto request_offset =
325 p == 0 ? 0 : receive_targets_[p - 1].second;
326 const auto request_size = receive_targets_[p].second - request_offset;
329 MPI_Isend(requested_entries.data() + 2 * request_offset,
331 dealii::Utilities::MPI::mpi_type_id_for_type<
332 dealii::types::global_dof_index>,
333 receive_targets_[p].first,
337 AssertThrowMPI(ierr);
345 send_targets_.resize(import_targets.size());
347 const unsigned int n_entries_to_be_sent =
348 std::accumulate(send_ranges.begin(), send_ranges.end(), 0);
349 std::vector<dealii::types::global_dof_index> entries_buffer(
350 2 * n_entries_to_be_sent );
354 unsigned int index = 0;
356 for (
unsigned int p = 0; p < send_targets_.size(); ++p) {
357 const auto n_entries = send_ranges[p];
360 MPI_Irecv(entries_buffer.data() + 2 * index ,
362 dealii::Utilities::MPI::mpi_type_id_for_type<
363 dealii::types::global_dof_index>,
364 import_targets[p].first,
367 &requests[ghost_targets.size() + p]);
368 AssertThrowMPI(ierr);
371 send_targets_[p].first = import_targets[p].first;
372 send_targets_[p].second = index;
378 MPI_Waitall(requests.size(), requests.data(), MPI_STATUSES_IGNORE);
379 AssertThrowMPI(ierr);
382 entries_to_be_sent.reserve(n_entries_to_be_sent);
383 for (
unsigned int e = 0; e < n_entries_to_be_sent; ++e) {
384 const auto i_global = entries_buffer[2 * e];
385 const auto j_global = entries_buffer[2 * e + 1];
386 const auto i = partitioner_->global_to_local(i_global);
387 const auto j = partitioner_->global_to_local(j_global);
389 const std::size_t position = sparsity(i, j);
391 position != sparsity.invalid_entry,
392 dealii::ExcMessage(
"Inconsistent global view of sparsity pattern: "
393 "the requested column index is not present on "
394 "the row stored on the owning MPI rank."));
396 const std::size_t position_diag = sparsity(i, i);
397 const std::size_t position_within_row = position - position_diag;
399 entries_to_be_sent.emplace_back(ExchangeDescription{
400 i,
static_cast<unsigned int>(position_within_row)});
411 entries_to_be_sent_.reinit(entries_to_be_sent.size(),
413 std::copy(entries_to_be_sent.begin(),
414 entries_to_be_sent.end(),
415 entries_to_be_sent_.view());
417 this->reset_residency(
true,
421 this->set_transfer_policy(transfer_policy);