8#include <compile_time_options.h>
13#include <deal.II/base/mpi.h>
14#include <deal.II/base/partitioner.h>
15#include <deal.II/base/vectorization.h>
16#include <deal.II/lac/la_parallel_vector.h>
39 std::shared_ptr<const dealii::Utilities::MPI::Partitioner>
41 const std::shared_ptr<const dealii::Utilities::MPI::Partitioner>
43 const unsigned int n_comp);
46 template <
typename Number,
48 typename MemorySpace = dealii::MemorySpace::Host,
60 template <
typename Number>
91 const std::shared_ptr<const dealii::Utilities::MPI::Partitioner>
93 const unsigned int n_comp,
113 const std::shared_ptr<const dealii::Utilities::MPI::Partitioner>
115 const unsigned int n_comp,
144 template <
int n_comp, typename MemorySpace = dealii::MemorySpace::Host>
156 template <
int n_comp, typename MemorySpace = dealii::MemorySpace::Host>
169 template <typename MemorySpace = dealii::MemorySpace::Host>
179 template <typename MemorySpace = dealii::MemorySpace::Host>
195 unsigned int n_comp_ = 0;
206 mutable dealii::LinearAlgebra::distributed::
207 Vector<Number, dealii::MemorySpace::Host>
210 mutable dealii::LinearAlgebra::distributed::
211 Vector<Number, dealii::MemorySpace::Default>
218 template <typename MemorySpace>
219 auto &storage() const;
225 template <typename MemorySpace>
226 void allocate_storage() const;
228 template <typename To, typename From>
229 void deep_copy_storage() const;
231 template <typename MemorySpace>
232 void deallocate_storage();
237 template <typename,
int, typename,
bool>
258 template <typename Number,
int n_comp, typename MemorySpace,
bool writable>
273 reinit(multi_component_vector);
280 reinit(multi_component_vector);
291 template <
bool other_writable>
296 other_writable> &other)
297 requires(!writable && other_writable)
298 : multi_component_vector_(other.multi_component_vector_)
300 , n_locally_owned_(other.n_locally_owned_)
301 , n_locally_relevant_(other.n_locally_relevant_)
305 template <
typename MultiComponentVector>
307 requires(writable != std::is_const_v<MultiComponentVector>)
309 Assert(multi_component_vector.n_comp() ==
310 static_cast<unsigned int>(n_comp),
311 dealii::ExcMessage(
"The number of components of the view does "
312 "not match the number of components of the "
315 multi_component_vector_ = &multi_component_vector;
317 auto &vector = multi_component_vector_->template storage<MemorySpace>();
318 const auto &partitioner = vector.get_partitioner();
320 data_ = vector.begin();
321 n_locally_owned_ = partitioner->locally_owned_size();
322 n_locally_relevant_ = n_locally_owned_ + partitioner->n_ghost_indices();
336 dealii::LinearAlgebra::distributed::Vector<Number, MemorySpace>;
366 template <
typename Functor = std::
identity>
368 unsigned int component,
369 const Functor &functor = std::identity{})
const
373 "Cannot extract from a vector with zero components."));
374 AssertIndexRange(component, n_comp);
376 const auto local_size =
static_cast<unsigned int>(
377 scalar_vector.get_partitioner()->locally_owned_size());
379 Assert(n_comp * local_size == n_locally_owned_,
380 dealii::ExcMessage(
"Called with a scalar_vector argument that has "
381 "incompatible local range."));
383 const auto *data = data_;
384 auto *destination = scalar_vector.begin();
386 const auto body = [=](
auto ,
unsigned int i) {
387 destination[i] = functor(data[i * n_comp + component]);
390 loop<MemorySpace, Number>(
391 "extract_component", body, 0, 0, local_size);
393 scalar_vector.update_ghost_values();
413 template <
typename Functor = std::
identity>
415 unsigned int component,
416 const Functor &functor = std::identity{})
const
419 using HostSpace = dealii::MemorySpace::Host;
420 AssertThrow((std::is_same_v<MemorySpace, HostSpace>),
421 dealii::ExcNotImplemented());
425 "Cannot insert into a vector with zero components."));
426 AssertIndexRange(component, n_comp);
428 const auto local_size =
429 scalar_vector.get_partitioner()->locally_owned_size();
431 Assert(n_comp * local_size == n_locally_owned_,
432 dealii::ExcMessage(
"Called with a scalar_vector argument that has "
433 "incompatible local range."));
435 for (
unsigned int i = 0; i < local_size; ++i)
436 data_[i * n_comp + component] = functor(scalar_vector.local_element(i));
443 template <
typename Functor = std::
identity>
445 unsigned int component,
446 const Functor &functor = std::identity{})
const
449 using HostSpace = dealii::MemorySpace::Host;
450 AssertThrow((std::is_same_v<MemorySpace, HostSpace>),
451 dealii::ExcInternalError());
455 "Cannot insert into a vector with zero components."));
456 AssertIndexRange(component, n_comp);
458 const auto local_size = scalar_vector.size();
460 Assert(n_comp * local_size >= n_locally_owned_,
461 dealii::ExcMessage(
"Called with a scalar_vector argument that has "
462 "incompatible local range."));
464 for (
unsigned int i = 0; i < local_size; ++i)
465 data_[i * n_comp + component] = functor(scalar_vector[i]);
485 template <
typename Number2 = Number>
486 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number2
491 "Attempted to read a scalar value from a tensor-valued vector entry");
493 AssertIndexRange(i, n_locally_relevant_);
495 const auto result = read_tensor<Number2>(i);
509 template <
typename Number2 = Number>
510 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number2
515 "Attempted to read a scalar value from a tensor-valued vector entry");
517 const auto result = read_tensor<Number2>(js);
529 template <
typename Number2 = Number,
530 typename Tensor = dealii::Tensor<1, n_comp, Number2>>
531 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Tensor
534 static_assert(std::is_same_v<Number2, typename Tensor::value_type>,
537 AssertIndexRange(i, n_locally_relevant_);
542 if constexpr (n_comp == 0)
545 using VA = dealii::VectorizedArray<Number>;
546 if constexpr (std::is_same_v<VA, Number2>) {
548 std::array<
unsigned int, VA::size()> indices;
549 for (
unsigned int k = 0; k < VA::size(); ++k)
550 indices[k] = k * n_comp;
552 dealii::vectorized_load_and_transpose(
553 n_comp, data_ + i * n_comp, indices.data(), &tensor[0]);
557 for (
unsigned int d = 0; d < n_comp; ++d)
558 tensor[d] = data_[i * n_comp + d];
572 template <
typename Number2 = Number,
573 typename Tensor = dealii::Tensor<1, n_comp, Number2>>
574 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Tensor
577 static_assert(std::is_same_v<Number2, typename Tensor::value_type>,
583 if constexpr (n_comp == 0)
586 using VA = dealii::VectorizedArray<Number>;
587 if constexpr (std::is_same_v<VA, Number2>) {
590 std::array<
unsigned int, VA::size()> indices;
591 for (
unsigned int k = 0; k < VA::size(); ++k) {
592 AssertIndexRange(js[k], n_locally_relevant_);
593 indices[k] = js[k] * n_comp;
596 dealii::vectorized_load_and_transpose(
597 n_comp, data_, indices.data(), &tensor[0]);
602 AssertIndexRange(*js, n_locally_relevant_);
604 for (
unsigned int d = 0; d < n_comp; ++d)
605 tensor[d] = data_[js[0] * n_comp + d];
622 template <
typename Number2 = Number>
623 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
void
627 static_assert(n_comp == 1,
628 "Attempted to write a scalar value into a tensor-valued "
631 AssertIndexRange(i, n_locally_relevant_);
633 dealii::Tensor<1, n_comp, Number2> tensor;
636 write_tensor<Number2>(tensor, i);
653 template <
typename Number2 = Number,
654 typename Tensor = dealii::Tensor<1, n_comp, Number2>>
655 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
void
659 store<
false, Number2>(tensor, i);
676 template <
typename Number2 = Number>
677 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
void add_entry(
const Number2 &entry,
678 const unsigned int i)
const
681 static_assert(n_comp == 1,
682 "Attempted to write a scalar value into a tensor-valued "
685 AssertIndexRange(i, n_locally_relevant_);
687 dealii::Tensor<1, n_comp, Number2> tensor;
690 add_tensor<Number2>(tensor, i);
707 template <
typename Number2 = Number,
708 typename Tensor = dealii::Tensor<1, n_comp, Number2>>
709 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
void
713 store<
true, Number2>(tensor, i);
728 Assert(multi_component_vector_->template is_resident<MemorySpace>(),
729 dealii::ExcMessage(
"The chosen memory space is not resident."));
731 multi_component_vector_->template storage<MemorySpace>()
732 .zero_out_ghost_values();
742 Assert(multi_component_vector_->template is_resident<MemorySpace>(),
743 dealii::ExcMessage(
"The chosen memory space is not resident."));
745 multi_component_vector_->template storage<MemorySpace>()
746 .update_ghost_values();
754 void compress(dealii::VectorOperation::values operation)
const
757 Assert(multi_component_vector_->template is_resident<MemorySpace>(),
758 dealii::ExcMessage(
"The chosen memory space is not resident."));
760 multi_component_vector_->template storage<MemorySpace>().compress(
772 std::conditional_t<writable, MCV *, const MCV *> multi_component_vector_;
775 unsigned int n_locally_owned_;
776 unsigned int n_locally_relevant_;
778 template <
typename,
int,
typename,
bool>
781 template <
bool add,
typename Number2,
typename Tensor>
782 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
void store(
const Tensor &tensor,
783 const unsigned int i)
const
785 static_assert(std::is_same_v<Number2, typename Tensor::value_type>,
788 AssertIndexRange(i, n_locally_relevant_);
791 if constexpr (n_comp == 0)
794 using VA = dealii::VectorizedArray<Number>;
795 if constexpr (std::is_same_v<VA, Number2>) {
798 std::array<
unsigned int, VA::size()> indices;
799 for (
unsigned int k = 0; k < VA::size(); ++k)
800 indices[k] = k * n_comp;
802 dealii::vectorized_transpose_and_store(
803 add, n_comp, &tensor[0], indices.data(), data_ + i * n_comp);
808 for (
unsigned int d = 0; d < n_comp; ++d) {
810 data_[i * n_comp + d] += tensor[d];
812 data_[i * n_comp + d] = tensor[d];
829 template <
typename Number>
837 template <
typename Number>
841 *
this = std::move(other);
845 template <
typename Number>
847 const std::shared_ptr<const dealii::Utilities::MPI::Partitioner>
849 const unsigned int n_comp,
863 host_vector_.reinit(0);
865 default_vector_.reinit(0);
873 host_vector_.reinit(vector_partitioner);
882 default_vector_.reinit(0);
895 template <
typename Number>
897 const std::shared_ptr<const dealii::Utilities::MPI::Partitioner>
899 const unsigned int n_comp,
906 const auto vector_partitioner =
907 n_comp <= 1 ? scalar_partitioner
914 template <
typename Number>
920 static_cast<MirroredStorage<MultiComponentVector> &
>(*this) = other;
921 n_comp_ = other.n_comp_;
923 host_vector_ = other.host_vector_;
925 default_vector_ = other.default_vector_;
931 template <
typename Number>
937 static_cast<MirroredStorage<MultiComponentVector> &
>(*this) = other;
938 n_comp_ = other.n_comp_;
940 host_vector_ = std::move(other.host_vector_);
942 default_vector_ = std::move(other.default_vector_);
948 template <
typename Number>
949 template <
int n_comp,
typename MemorySpace>
950 MultiComponentVectorView<Number, n_comp, MemorySpace, true>
953 Assert(
static_cast<unsigned int>(n_comp) == n_comp_,
954 dealii::ExcMessage(
"The number of components of the view does "
955 "not match the number of components of the "
958 this->
template prepare_write_access<MemorySpace>();
960 return MultiComponentVectorView<Number, n_comp, MemorySpace, true>(*
this);
964 template <
typename Number>
965 template <
int n_comp,
typename MemorySpace>
966 MultiComponentVectorView<Number, n_comp, MemorySpace, false>
969 Assert(
static_cast<unsigned int>(n_comp) == n_comp_,
970 dealii::ExcMessage(
"The number of components of the view does "
971 "not match the number of components of the "
974 this->
template prepare_read_access<MemorySpace>();
976 return MultiComponentVectorView<Number, n_comp, MemorySpace, false>(*
this);
980 template <
typename Number>
981 template <
typename MemorySpace>
984 this->
template prepare_write_access<MemorySpace>();
985 return storage<MemorySpace>();
989 template <
typename Number>
990 template <
typename MemorySpace>
993 this->
template prepare_read_access<MemorySpace>();
994 return storage<MemorySpace>();
998 template <
typename Number>
999 template <
typename MemorySpace>
1000 auto &MultiComponentVector<Number>::storage()
const
1002 using HostSpace = dealii::MemorySpace::Host;
1003 using DefaultSpace = dealii::MemorySpace::Default;
1004 static_assert(std::is_same_v<MemorySpace, HostSpace> ||
1005 std::is_same_v<MemorySpace, DefaultSpace>,
1006 "Unexpected memory space");
1009 !std::is_same_v<MemorySpace, HostSpace>)
1010 return default_vector_;
1012 return host_vector_;
1016 template <
typename Number>
1017 template <
typename MemorySpace>
1018 void MultiComponentVector<Number>::allocate_storage()
const
1020 using HostSpace = dealii::MemorySpace::Host;
1027 if constexpr (std::is_same_v<MemorySpace, HostSpace>) {
1028 Assert(default_vector_.size() != 0, dealii::ExcNotInitialized());
1029 host_vector_.reinit(default_vector_.get_partitioner());
1031 Assert(host_vector_.size() != 0, dealii::ExcNotInitialized());
1032 default_vector_.reinit(host_vector_.get_partitioner());
1037 template <
typename Number>
1038 template <
typename To,
typename From>
1039 void MultiComponentVector<Number>::deep_copy_storage()
const
1041 using HostSpace = dealii::MemorySpace::Host;
1043 if constexpr (std::is_same_v<To, HostSpace>) {
1044 host_vector_.import_elements(default_vector_,
1045 dealii::VectorOperation::insert);
1047 default_vector_.import_elements(host_vector_,
1048 dealii::VectorOperation::insert);
1053 template <
typename Number>
1054 template <
typename MemorySpace>
1055 void MultiComponentVector<Number>::deallocate_storage()
1057 using HostSpace = dealii::MemorySpace::Host;
1059 if constexpr (std::is_same_v<MemorySpace, HostSpace>) {
1060 host_vector_.reinit(0);
1063 default_vector_.reinit(0);
void set_transfer_policy(const TransferPolicy transfer_policy)
void reset_residency(const bool host_resident, const bool default_resident)
TransferPolicy transfer_policy() const
void compress(dealii::VectorOperation::values operation) const
MultiComponentVectorView(MultiComponentVector< Number > &multi_component_vector)
void zero_out_ghost_values() const
DEAL_II_HOST_DEVICE_ALWAYS_INLINE void add_tensor(const Tensor &tensor, const unsigned int i) const
DEAL_II_HOST_DEVICE MultiComponentVectorView(const MultiComponentVectorView< Number, n_comp, MemorySpace, other_writable > &other)
void update_ghost_values() const
DEAL_II_HOST_DEVICE_ALWAYS_INLINE Tensor read_tensor(const unsigned int *js) const
void insert_component(const ScalarVector &scalar_vector, unsigned int component, const Functor &functor=std::identity{}) const
DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number2 read_entry(const unsigned int i) const
DEAL_II_HOST_DEVICE_ALWAYS_INLINE void write_entry(const Number2 &entry, const unsigned int i) const
void extract_component(ScalarVector &scalar_vector, unsigned int component, const Functor &functor=std::identity{}) const
DEAL_II_HOST_DEVICE_ALWAYS_INLINE void write_tensor(const Tensor &tensor, const unsigned int i) const
DEAL_II_HOST_DEVICE_ALWAYS_INLINE Tensor read_tensor(const unsigned int i) const
MultiComponentVectorView()=default
void reinit(MultiComponentVector &multi_component_vector)
void insert_component(const dealii::Vector< Number > &scalar_vector, unsigned int component, const Functor &functor=std::identity{}) const
DEAL_II_HOST_DEVICE_ALWAYS_INLINE void add_entry(const Number2 &entry, const unsigned int i) const
MultiComponentVectorView(const MultiComponentVector< Number > &multi_component_vector)
DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number2 read_entry(const unsigned int *js) const
dealii::LinearAlgebra::distributed::Vector< Number, MemorySpace > ScalarVector
MultiComponentVector()=default
MultiComponentVector(MultiComponentVector &&other) noexcept
void reinit_with_vector_partitioner(const std::shared_ptr< const dealii::Utilities::MPI::Partitioner > &vector_partitioner, const unsigned int n_comp, const TransferPolicy transfer_policy=TransferPolicy::explicit_transfers)
MultiComponentVector(const MultiComponentVector &other)
MultiComponentVectorView< Number, n_comp, MemorySpace, true > view()
MultiComponentVector & operator=(const MultiComponentVector &other)
void reinit_with_scalar_partitioner(const std::shared_ptr< const dealii::Utilities::MPI::Partitioner > &scalar_partitioner, const unsigned int n_comp, const TransferPolicy transfer_policy=TransferPolicy::explicit_transfers)
constexpr bool have_separate_memory_spaces
std::shared_ptr< const dealii::Utilities::MPI::Partitioner > create_vector_partitioner(const std::shared_ptr< const dealii::Utilities::MPI::Partitioner > &scalar_partitioner, const unsigned int n_comp)
#define ACCESSOR_READ_ONLY(member)
DEAL_II_HOST_DEVICE_ALWAYS_INLINE FT add(const FT &flux_left_ij, const FT &flux_right_ij)