8#include <ryujin/base/compile_time_options.h>
12#include <deal.II/base/mpi.h>
13#include <deal.II/base/partitioner.h>
14#include <deal.II/base/vectorization.h>
15#include <deal.II/lac/la_parallel_vector.h>
38 std::shared_ptr<const dealii::Utilities::MPI::Partitioner>
40 const std::shared_ptr<const dealii::Utilities::MPI::Partitioner>
42 const unsigned int n_comp);
45 template <
typename Number,
47 typename MemorySpace = dealii::MemorySpace::Host,
59 template <
typename Number>
90 const std::shared_ptr<const dealii::Utilities::MPI::Partitioner>
92 const unsigned int n_comp,
112 const std::shared_ptr<const dealii::Utilities::MPI::Partitioner>
114 const unsigned int n_comp,
143 template <
int n_comp, typename MemorySpace = dealii::MemorySpace::Host>
155 template <
int n_comp, typename MemorySpace = dealii::MemorySpace::Host>
168 template <typename MemorySpace = dealii::MemorySpace::Host>
178 template <typename MemorySpace = dealii::MemorySpace::Host>
194 unsigned int n_comp_ = 0;
205 mutable dealii::LinearAlgebra::distributed::
206 Vector<Number, dealii::MemorySpace::Host>
209 mutable dealii::LinearAlgebra::distributed::
210 Vector<Number, dealii::MemorySpace::Default>
217 template <typename MemorySpace>
218 auto &storage() const;
224 template <typename MemorySpace>
225 void allocate_storage() const;
227 template <typename To, typename From>
228 void deep_copy_storage() const;
230 template <typename MemorySpace>
231 void deallocate_storage();
236 template <typename,
int, typename,
bool>
257 template <typename Number,
int n_comp, typename MemorySpace,
bool writable>
272 reinit(multi_component_vector);
279 reinit(multi_component_vector);
290 template <
bool other_writable>
295 other_writable> &other)
296 requires(!writable && other_writable)
297 : multi_component_vector_(other.multi_component_vector_)
299 , n_locally_owned_(other.n_locally_owned_)
300 , n_locally_relevant_(other.n_locally_relevant_)
304 template <
typename MultiComponentVector>
306 requires(writable != std::is_const_v<MultiComponentVector>)
308 Assert(multi_component_vector.n_comp() ==
309 static_cast<unsigned int>(n_comp),
310 dealii::ExcMessage(
"The number of components of the view does "
311 "not match the number of components of the "
314 multi_component_vector_ = &multi_component_vector;
316 auto &vector = multi_component_vector_->template storage<MemorySpace>();
317 const auto &partitioner = vector.get_partitioner();
319 data_ = vector.begin();
320 n_locally_owned_ = partitioner->locally_owned_size();
321 n_locally_relevant_ = n_locally_owned_ + partitioner->n_ghost_indices();
335 dealii::LinearAlgebra::distributed::Vector<Number, MemorySpace>;
365 template <
typename Functor = std::
identity>
367 unsigned int component,
368 const Functor &functor = std::identity{})
const
372 "Cannot extract from a vector with zero components."));
373 AssertIndexRange(component, n_comp);
375 const auto local_size =
static_cast<unsigned int>(
376 scalar_vector.get_partitioner()->locally_owned_size());
378 Assert(n_comp * local_size == n_locally_owned_,
379 dealii::ExcMessage(
"Called with a scalar_vector argument that has "
380 "incompatible local range."));
382 const auto *data = data_;
383 auto *destination = scalar_vector.begin();
385 const auto body = [=](
auto ,
unsigned int i) {
386 destination[i] = functor(data[i * n_comp + component]);
389 loop<MemorySpace, Number>(
390 "extract_component", body, 0, 0, local_size);
392 scalar_vector.update_ghost_values();
412 template <
typename Functor = std::
identity>
414 unsigned int component,
415 const Functor &functor = std::identity{})
const
418 using HostSpace = dealii::MemorySpace::Host;
419 AssertThrow((std::is_same_v<MemorySpace, HostSpace>),
420 dealii::ExcNotImplemented());
424 "Cannot insert into a vector with zero components."));
425 AssertIndexRange(component, n_comp);
427 const auto local_size =
428 scalar_vector.get_partitioner()->locally_owned_size();
430 Assert(n_comp * local_size == n_locally_owned_,
431 dealii::ExcMessage(
"Called with a scalar_vector argument that has "
432 "incompatible local range."));
434 for (
unsigned int i = 0; i < local_size; ++i)
435 data_[i * n_comp + component] = functor(scalar_vector.local_element(i));
442 template <
typename Functor = std::
identity>
444 unsigned int component,
445 const Functor &functor = std::identity{})
const
448 using HostSpace = dealii::MemorySpace::Host;
449 AssertThrow((std::is_same_v<MemorySpace, HostSpace>),
450 dealii::ExcInternalError());
454 "Cannot insert into a vector with zero components."));
455 AssertIndexRange(component, n_comp);
457 const auto local_size = scalar_vector.size();
459 Assert(n_comp * local_size >= n_locally_owned_,
460 dealii::ExcMessage(
"Called with a scalar_vector argument that has "
461 "incompatible local range."));
463 for (
unsigned int i = 0; i < local_size; ++i)
464 data_[i * n_comp + component] = functor(scalar_vector[i]);
484 template <
typename Number2 = Number>
485 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number2
490 "Attempted to read a scalar value from a tensor-valued vector entry");
492 AssertIndexRange(i, n_locally_relevant_);
494 const auto result = read_tensor<Number2>(i);
508 template <
typename Number2 = Number>
509 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number2
514 "Attempted to read a scalar value from a tensor-valued vector entry");
516 const auto result = read_tensor<Number2>(js);
528 template <
typename Number2 = Number,
529 typename Tensor = dealii::Tensor<1, n_comp, Number2>>
530 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Tensor
533 static_assert(std::is_same_v<Number2, typename Tensor::value_type>,
536 AssertIndexRange(i, n_locally_relevant_);
541 if constexpr (n_comp == 0)
544 using VA = dealii::VectorizedArray<Number>;
545 if constexpr (std::is_same_v<VA, Number2>) {
547 std::array<
unsigned int, VA::size()> indices;
548 for (
unsigned int k = 0; k < VA::size(); ++k)
549 indices[k] = k * n_comp;
551 dealii::vectorized_load_and_transpose(
552 n_comp, data_ + i * n_comp, indices.data(), &tensor[0]);
556 for (
unsigned int d = 0; d < n_comp; ++d)
557 tensor[d] = data_[i * n_comp + d];
571 template <
typename Number2 = Number,
572 typename Tensor = dealii::Tensor<1, n_comp, Number2>>
573 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Tensor
576 static_assert(std::is_same_v<Number2, typename Tensor::value_type>,
582 if constexpr (n_comp == 0)
585 using VA = dealii::VectorizedArray<Number>;
586 if constexpr (std::is_same_v<VA, Number2>) {
589 std::array<
unsigned int, VA::size()> indices;
590 for (
unsigned int k = 0; k < VA::size(); ++k) {
591 AssertIndexRange(js[k], n_locally_relevant_);
592 indices[k] = js[k] * n_comp;
595 dealii::vectorized_load_and_transpose(
596 n_comp, data_, indices.data(), &tensor[0]);
601 AssertIndexRange(*js, n_locally_relevant_);
603 for (
unsigned int d = 0; d < n_comp; ++d)
604 tensor[d] = data_[js[0] * n_comp + d];
621 template <
typename Number2 = Number>
622 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
void
626 static_assert(n_comp == 1,
627 "Attempted to write a scalar value into a tensor-valued "
630 AssertIndexRange(i, n_locally_relevant_);
632 dealii::Tensor<1, n_comp, Number2> tensor;
635 write_tensor<Number2>(tensor, i);
652 template <
typename Number2 = Number,
653 typename Tensor = dealii::Tensor<1, n_comp, Number2>>
654 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
void
658 store<
false, Number2>(tensor, i);
675 template <
typename Number2 = Number>
676 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
void add_entry(
const Number2 &entry,
677 const unsigned int i)
const
680 static_assert(n_comp == 1,
681 "Attempted to write a scalar value into a tensor-valued "
684 AssertIndexRange(i, n_locally_relevant_);
686 dealii::Tensor<1, n_comp, Number2> tensor;
689 add_tensor<Number2>(tensor, i);
706 template <
typename Number2 = Number,
707 typename Tensor = dealii::Tensor<1, n_comp, Number2>>
708 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
void
712 store<
true, Number2>(tensor, i);
727 Assert(multi_component_vector_->template is_resident<MemorySpace>(),
728 dealii::ExcMessage(
"The chosen memory space is not resident."));
730 multi_component_vector_->template storage<MemorySpace>()
731 .zero_out_ghost_values();
741 Assert(multi_component_vector_->template is_resident<MemorySpace>(),
742 dealii::ExcMessage(
"The chosen memory space is not resident."));
744 multi_component_vector_->template storage<MemorySpace>()
745 .update_ghost_values();
753 void compress(dealii::VectorOperation::values operation)
const
756 Assert(multi_component_vector_->template is_resident<MemorySpace>(),
757 dealii::ExcMessage(
"The chosen memory space is not resident."));
759 multi_component_vector_->template storage<MemorySpace>().compress(
771 std::conditional_t<writable, MCV *, const MCV *> multi_component_vector_;
774 unsigned int n_locally_owned_;
775 unsigned int n_locally_relevant_;
777 template <
typename,
int,
typename,
bool>
780 template <
bool add,
typename Number2,
typename Tensor>
781 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
void store(
const Tensor &tensor,
782 const unsigned int i)
const
784 static_assert(std::is_same_v<Number2, typename Tensor::value_type>,
787 AssertIndexRange(i, n_locally_relevant_);
790 if constexpr (n_comp == 0)
793 using VA = dealii::VectorizedArray<Number>;
794 if constexpr (std::is_same_v<VA, Number2>) {
797 std::array<
unsigned int, VA::size()> indices;
798 for (
unsigned int k = 0; k < VA::size(); ++k)
799 indices[k] = k * n_comp;
801 dealii::vectorized_transpose_and_store(
802 add, n_comp, &tensor[0], indices.data(), data_ + i * n_comp);
807 for (
unsigned int d = 0; d < n_comp; ++d) {
809 data_[i * n_comp + d] += tensor[d];
811 data_[i * n_comp + d] = tensor[d];
828 template <
typename Number>
836 template <
typename Number>
840 *
this = std::move(other);
844 template <
typename Number>
846 const std::shared_ptr<const dealii::Utilities::MPI::Partitioner>
848 const unsigned int n_comp,
862 host_vector_.reinit(0);
864 default_vector_.reinit(0);
872 host_vector_.reinit(vector_partitioner);
881 default_vector_.reinit(0);
894 template <
typename Number>
896 const std::shared_ptr<const dealii::Utilities::MPI::Partitioner>
898 const unsigned int n_comp,
905 const auto vector_partitioner =
906 n_comp <= 1 ? scalar_partitioner
913 template <
typename Number>
919 static_cast<MirroredStorage<MultiComponentVector> &
>(*this) = other;
920 n_comp_ = other.n_comp_;
922 host_vector_ = other.host_vector_;
924 default_vector_ = other.default_vector_;
930 template <
typename Number>
936 static_cast<MirroredStorage<MultiComponentVector> &
>(*this) = other;
937 n_comp_ = other.n_comp_;
939 host_vector_ = std::move(other.host_vector_);
941 default_vector_ = std::move(other.default_vector_);
947 template <
typename Number>
948 template <
int n_comp,
typename MemorySpace>
949 MultiComponentVectorView<Number, n_comp, MemorySpace, true>
952 Assert(
static_cast<unsigned int>(n_comp) == n_comp_,
953 dealii::ExcMessage(
"The number of components of the view does "
954 "not match the number of components of the "
957 this->
template prepare_write_access<MemorySpace>();
959 return MultiComponentVectorView<Number, n_comp, MemorySpace, true>(*
this);
963 template <
typename Number>
964 template <
int n_comp,
typename MemorySpace>
965 MultiComponentVectorView<Number, n_comp, MemorySpace, false>
968 Assert(
static_cast<unsigned int>(n_comp) == n_comp_,
969 dealii::ExcMessage(
"The number of components of the view does "
970 "not match the number of components of the "
973 this->
template prepare_read_access<MemorySpace>();
975 return MultiComponentVectorView<Number, n_comp, MemorySpace, false>(*
this);
979 template <
typename Number>
980 template <
typename MemorySpace>
983 this->
template prepare_write_access<MemorySpace>();
984 return storage<MemorySpace>();
988 template <
typename Number>
989 template <
typename MemorySpace>
992 this->
template prepare_read_access<MemorySpace>();
993 return storage<MemorySpace>();
997 template <
typename Number>
998 template <
typename MemorySpace>
999 auto &MultiComponentVector<Number>::storage()
const
1001 using HostSpace = dealii::MemorySpace::Host;
1002 using DefaultSpace = dealii::MemorySpace::Default;
1003 static_assert(std::is_same_v<MemorySpace, HostSpace> ||
1004 std::is_same_v<MemorySpace, DefaultSpace>,
1005 "Unexpected memory space");
1008 !std::is_same_v<MemorySpace, HostSpace>)
1009 return default_vector_;
1011 return host_vector_;
1015 template <
typename Number>
1016 template <
typename MemorySpace>
1017 void MultiComponentVector<Number>::allocate_storage()
const
1019 using HostSpace = dealii::MemorySpace::Host;
1026 if constexpr (std::is_same_v<MemorySpace, HostSpace>) {
1027 Assert(default_vector_.size() != 0, dealii::ExcNotInitialized());
1028 host_vector_.reinit(default_vector_.get_partitioner());
1030 Assert(host_vector_.size() != 0, dealii::ExcNotInitialized());
1031 default_vector_.reinit(host_vector_.get_partitioner());
1036 template <
typename Number>
1037 template <
typename To,
typename From>
1038 void MultiComponentVector<Number>::deep_copy_storage()
const
1040 using HostSpace = dealii::MemorySpace::Host;
1042 if constexpr (std::is_same_v<To, HostSpace>) {
1043 host_vector_.import_elements(default_vector_,
1044 dealii::VectorOperation::insert);
1046 default_vector_.import_elements(host_vector_,
1047 dealii::VectorOperation::insert);
1052 template <
typename Number>
1053 template <
typename MemorySpace>
1054 void MultiComponentVector<Number>::deallocate_storage()
1056 using HostSpace = dealii::MemorySpace::Host;
1058 if constexpr (std::is_same_v<MemorySpace, HostSpace>) {
1059 host_vector_.reinit(0);
1062 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)