8#include <compile_time_options.h>
13#include <deal.II/base/aligned_vector.h>
14#include <deal.II/base/config.h>
15#include <deal.II/base/partitioner.h>
16#include <deal.II/lac/dynamic_sparsity_pattern.h>
20 template <
int warp_size,
typename MemorySpace = dealii::MemorySpace::Host>
21 class SparsityPatternView;
49 template <
int warp_size>
86 const unsigned int n_internal_dofs,
87 const dealii::DynamicSparsityPattern &sparsity,
88 const std::shared_ptr<const dealii::Utilities::MPI::Partitioner>
90 bool symmetrize_ghost_range =
true,
104 void reinit(
const unsigned int n_internal_dofs,
105 const dealii::DynamicSparsityPattern &sparsity,
106 const std::shared_ptr<const dealii::Utilities::MPI::Partitioner>
108 bool symmetrize_ghost_range =
true,
116 template <
typename MemorySpace = dealii::MemorySpace::Host>
157 std::shared_ptr<const dealii::Utilities::MPI::Partitioner> partitioner_;
159 unsigned int n_internal_dofs_;
160 unsigned int n_locally_owned_dofs_;
162 using KokkosHost = dealii::MemorySpace::Host::kokkos_space;
163 mutable Kokkos::View<unsigned int *, KokkosHost> row_starts_host_;
164 mutable Kokkos::View<unsigned int *, KokkosHost> column_indices_host_;
165 mutable Kokkos::View<unsigned int *, KokkosHost> indices_transposed_host_;
167 using KokkosDefault = dealii::MemorySpace::Default::kokkos_space;
168 mutable Kokkos::View<unsigned int *, KokkosDefault> row_starts_default_;
169 mutable Kokkos::View<unsigned int *, KokkosDefault> column_indices_default_;
170 mutable Kokkos::View<unsigned int *, KokkosDefault>
171 indices_transposed_default_;
174 "sparsity_pattern_entries_to_be_sent"};
176 std::vector<std::pair<unsigned int, unsigned int>> send_targets_;
177 std::vector<std::pair<unsigned int, unsigned int>> receive_targets_;
183 template <
typename MemorySpace>
184 void allocate_storage()
const;
186 template <
typename To,
typename From>
187 void deep_copy_storage()
const;
189 template <
typename MemorySpace>
190 void deallocate_storage();
195 template <
int,
typename>
215 template <
int warp_size,
typename MemorySpace>
288 const unsigned int *
columns(
const unsigned int row)
const;
303 const unsigned int column)
const;
316 template <
unsigned int n_components = 1>
317 DEAL_II_HOST_DEVICE
unsigned int
320 const unsigned int component = 0)
const;
334 template <
unsigned int n_components = 1>
335 DEAL_II_HOST_DEVICE
unsigned int
344 template <
unsigned int n_components = 1>
345 DEAL_II_HOST_DEVICE
unsigned int
348 const unsigned int component = 0)
const;
357 template <
unsigned int n_components = 1>
358 DEAL_II_HOST_DEVICE
const unsigned int *
371 template <
unsigned int n_components = 1>
381 unsigned int n_internal_dofs_;
382 unsigned int n_locally_owned_dofs_;
384 using KokkosSpace =
typename MemorySpace::kokkos_space;
385 Kokkos::View<const unsigned int *, KokkosSpace> row_starts_;
386 Kokkos::View<const unsigned int *, KokkosSpace> column_indices_;
387 Kokkos::View<const unsigned int *, KokkosSpace> indices_transposed_;
400 template <
int warp_size>
401 template <
typename MemorySpace>
405 this->
template prepare_read_access<MemorySpace>();
411 template <
int warp_size>
412 template <
typename MemorySpace>
413 void SparsityPattern<warp_size>::allocate_storage()
const
415 using HostSpace = dealii::MemorySpace::Host;
416 using Aligned = Kokkos::MemoryTraits<Kokkos::Aligned>;
420 if constexpr (std::is_same_v<MemorySpace, HostSpace>) {
421 row_starts_host_ = Kokkos::View<unsigned int *, KokkosHost, Aligned>(
422 Kokkos::view_alloc(Kokkos::WithoutInitializing,
423 "sparsity_pattern_row_starts"),
424 row_starts_default_.extent(0));
426 column_indices_host_ = Kokkos::View<unsigned int *, KokkosHost, Aligned>(
427 Kokkos::view_alloc(Kokkos::WithoutInitializing,
428 "sparsity_pattern_column_indices"),
429 column_indices_default_.extent(0));
431 indices_transposed_host_ =
432 Kokkos::View<unsigned int *, KokkosHost, Aligned>(
433 Kokkos::view_alloc(Kokkos::WithoutInitializing,
434 "sparsity_pattern_indices_transposed"),
435 indices_transposed_default_.extent(0));
438 row_starts_default_ = Kokkos::View<unsigned int *, KokkosDefault>(
439 Kokkos::view_alloc(Kokkos::WithoutInitializing,
440 "sparsity_pattern_row_starts"),
441 row_starts_host_.extent(0));
443 column_indices_default_ = Kokkos::View<unsigned int *, KokkosDefault>(
444 Kokkos::view_alloc(Kokkos::WithoutInitializing,
445 "sparsity_pattern_column_indices"),
446 column_indices_host_.extent(0));
448 indices_transposed_default_ = Kokkos::View<unsigned int *, KokkosDefault>(
449 Kokkos::view_alloc(Kokkos::WithoutInitializing,
450 "sparsity_pattern_indices_transposed"),
451 indices_transposed_host_.extent(0));
456 template <
int warp_size>
457 template <
typename To,
typename From>
458 void SparsityPattern<warp_size>::deep_copy_storage()
const
460 using HostSpace = dealii::MemorySpace::Host;
462 if constexpr (std::is_same_v<To, HostSpace>) {
463 Kokkos::deep_copy( row_starts_host_, row_starts_default_);
464 Kokkos::deep_copy( column_indices_host_,
465 column_indices_default_);
466 Kokkos::deep_copy( indices_transposed_host_,
467 indices_transposed_default_);
469 Kokkos::deep_copy( row_starts_default_, row_starts_host_);
470 Kokkos::deep_copy( column_indices_default_,
471 column_indices_host_);
472 Kokkos::deep_copy( indices_transposed_default_,
473 indices_transposed_host_);
478 template <
int warp_size>
479 template <
typename MemorySpace>
480 void SparsityPattern<warp_size>::deallocate_storage()
482 using HostSpace = dealii::MemorySpace::Host;
484 if constexpr (std::is_same_v<MemorySpace, HostSpace>) {
485 row_starts_host_ = {};
486 column_indices_host_ = {};
487 indices_transposed_host_ = {};
490 row_starts_default_ = {};
491 column_indices_default_ = {};
492 indices_transposed_default_ = {};
497 template <
int warp_size,
typename MemorySpace>
499 const SparsityPattern<warp_size> &sparsity_pattern)
501 reinit(sparsity_pattern);
505 template <
int warp_size,
typename MemorySpace>
507 const SparsityPattern<warp_size> &sparsity_pattern)
509 n_internal_dofs_ = sparsity_pattern.n_internal_dofs_;
510 n_locally_owned_dofs_ = sparsity_pattern.n_locally_owned_dofs_;
512 using HostSpace = dealii::MemorySpace::Host;
513 using DefaultSpace = dealii::MemorySpace::Default;
515 static_assert(std::is_same_v<MemorySpace, HostSpace> ||
516 std::is_same_v<MemorySpace, DefaultSpace>,
517 "Unexpected memory space");
524 !std::is_same_v<MemorySpace, HostSpace>) {
525 row_starts_ = sparsity_pattern.row_starts_default_;
526 column_indices_ = sparsity_pattern.column_indices_default_;
527 indices_transposed_ = sparsity_pattern.indices_transposed_default_;
529 row_starts_ = sparsity_pattern.row_starts_host_;
530 column_indices_ = sparsity_pattern.column_indices_host_;
531 indices_transposed_ = sparsity_pattern.indices_transposed_host_;
536 template <
int warp_size,
typename MemorySpace>
537 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
unsigned int
540 return n_internal_dofs_;
544 template <
int warp_size,
typename MemorySpace>
545 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
unsigned int
548 return n_locally_owned_dofs_;
552 template <
int warp_size,
typename MemorySpace>
553 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
unsigned int
556 Assert(row_starts_.size() > 0, dealii::ExcNotInitialized());
558 return row_starts_.size() - 1;
562 template <
int warp_size,
typename MemorySpace>
563 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
unsigned int
566 Assert(row_starts_.size() > 0, dealii::ExcNotInitialized());
568 return row_starts_(row_starts_.size() - 1);
572 template <
int warp_size,
typename MemorySpace>
573 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
unsigned int
575 const unsigned int row)
const
577 AssertIndexRange(row, n_rows());
579 if (row < n_internal_dofs_)
586 template <
int warp_size,
typename MemorySpace>
587 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
const unsigned int *
589 const unsigned int row)
const
591 AssertIndexRange(row, n_rows());
593 if (row < n_internal_dofs_)
594 return column_indices_.data() + row_starts_(row /
warp_size) +
597 return column_indices_.data() + row_starts_(row);
601 template <
int warp_size,
typename MemorySpace>
602 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
unsigned int
604 const unsigned int row)
const
606 AssertIndexRange(row, n_rows());
608 if (row < n_internal_dofs_) {
609 const unsigned int warp = row /
warp_size;
610 return (row_starts_(warp + 1) - row_starts_(warp)) /
warp_size;
612 return row_starts_(row + 1) - row_starts_(row);
617 template <
int warp_size,
typename MemorySpace>
618 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
unsigned int
620 const unsigned int row,
const unsigned int column)
const
622 const auto &row_length = this->row_length(row);
623 const auto &stride_size = this->stride_of_row(row);
627 const unsigned int *js = columns(row);
628 for (
unsigned int k = 0; k < row_length; ++k)
629 if (js[k * stride_size] == column)
632 Assert(
false, dealii::ExcMessage(
"Column index not found in given row"));
637 template <
int warp_size,
typename MemorySpace>
638 template <
unsigned int n_components>
639 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
unsigned int
641 const unsigned int row,
642 const unsigned int column_index,
643 const unsigned int comp)
const
645 AssertIndexRange(row, n_rows());
646 AssertIndexRange(column_index, row_length(row));
647 AssertIndexRange(comp, n_components);
649 const unsigned int warp = row /
warp_size;
650 const unsigned int lane = row %
warp_size;
652 if (row < n_internal_dofs_) {
653 const unsigned int scalar_offset =
654 row_starts_(warp) + column_index *
warp_size;
655 return scalar_offset * n_components + comp *
warp_size + lane;
658 const unsigned int scalar_offset = row_starts_(row) + column_index;
660 return scalar_offset * n_components + comp;
665 template <
int warp_size,
typename MemorySpace>
666 template <
unsigned int n_components>
667 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
unsigned int
669 const unsigned int row,
670 const unsigned int column_index,
671 const unsigned int component)
const
673 AssertIndexRange(row, n_rows());
674 AssertIndexRange(column_index, row_length(row));
675 AssertIndexRange(component, n_components);
679 const unsigned int scalar_offset = offset(row, column_index);
680 const unsigned int transposed_scalar_offset =
681 indices_transposed_(scalar_offset);
684 const unsigned int j = column_indices_(scalar_offset);
686 unsigned int transposed_offset = transposed_scalar_offset;
687 if constexpr (n_components > 1) {
688 if (j < n_internal_dofs_) {
692 return transposed_offset + component *
warp_size;
696 transposed_offset *= n_components;
697 return transposed_offset + component;
702 return transposed_offset;
707 template <
int warp_size,
typename MemorySpace>
708 template <
unsigned int n_components>
709 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
unsigned int
711 const unsigned int row,
const unsigned int column_index)
const
713 AssertIndexRange(row, n_rows());
714 AssertIndexRange(column_index, row_length(row));
715 AssertIndexRange(row, n_internal_dofs_);
717 const unsigned int warp = row /
warp_size;
718 const unsigned int lane = row %
warp_size;
720 const unsigned int scalar_offset =
721 row_starts_(warp) + column_index *
warp_size;
723 return scalar_offset * n_components + lane;
727 template <
int warp_size,
typename MemorySpace>
728 template <
unsigned int n_components>
729 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
const unsigned int *
731 const unsigned int row,
const unsigned int column_index)
const
733 static_assert(n_components == 1,
734 "Vectorized transposed access to multiple components is not "
736 AssertIndexRange(row, row_starts_.size() - 1);
737 AssertIndexRange(column_index, row_length(row));
738 AssertIndexRange(row, n_internal_dofs_);
740 const unsigned int warp = row /
warp_size;
741 const unsigned int lane = row %
warp_size;
743 const unsigned int scalar_offset =
744 row_starts_(warp) + column_index *
warp_size;
747 return indices_transposed_.data() + scalar_offset + lane;
751 template <
int warp_size,
typename MemorySpace>
752 template <
unsigned int n_components>
753 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
unsigned int
756 const auto scalar_offset = row_starts_(n_locally_owned_dofs_);
757 return scalar_offset * n_components;
TransferPolicy transfer_policy() const
DEAL_II_HOST_DEVICE unsigned int offset_internal(const unsigned int row, const unsigned int column_index) const
DEAL_II_HOST_DEVICE unsigned int n_nonzero_elements() const
DEAL_II_HOST_DEVICE const unsigned int * transposed_offset_internal(const unsigned int row, const unsigned int column_index) const
DEAL_II_HOST_DEVICE unsigned int n_internal_dofs() const
void reinit(const SparsityPattern< warp_size > &sparsity_pattern)
DEAL_II_HOST_DEVICE unsigned int stride_of_row(const unsigned int row) const
SparsityPatternView(const SparsityPattern< warp_size > &sparsity_pattern)
DEAL_II_HOST_DEVICE unsigned int row_length(const unsigned int row) const
DEAL_II_HOST_DEVICE const unsigned int * columns(const unsigned int row) const
SparsityPatternView()=default
DEAL_II_HOST_DEVICE unsigned int offset(const unsigned int row, const unsigned int column_index, const unsigned int component=0) const
DEAL_II_HOST_DEVICE unsigned int n_locally_owned_dofs() const
DEAL_II_HOST_DEVICE unsigned int ghost_offset() const
DEAL_II_HOST_DEVICE unsigned int n_rows() const
DEAL_II_HOST_DEVICE unsigned int transposed_offset(const unsigned int row, const unsigned int column_index, const unsigned int component=0) const
DEAL_II_HOST_DEVICE unsigned int column_index(const unsigned int row, const unsigned int column) const
ACCESSOR_READ_ONLY(entries_to_be_sent)
SparsityPatternView< warp_size, MemorySpace > view() const
void reinit(const unsigned int n_internal_dofs, const dealii::DynamicSparsityPattern &sparsity, const std::shared_ptr< const dealii::Utilities::MPI::Partitioner > &partitioner, bool symmetrize_ghost_range=true, const TransferPolicy transfer_policy=TransferPolicy::explicit_transfers)
ACCESSOR_READ_ONLY(receive_targets)
ACCESSOR_READ_ONLY(send_targets)
ACCESSOR_READ_ONLY_NO_DEREFERENCE(partitioner)
constexpr unsigned int warp_size
constexpr bool have_separate_memory_spaces
unsigned int column_index