40 std::shared_ptr<const dealii::Utilities::MPI::Partitioner>
42 const std::shared_ptr<const dealii::Utilities::MPI::Partitioner>
44 const unsigned int n_comp);
47 template <
typename Number,
49 int simd_length = dealii::VectorizedArray<Number>::size(),
50 typename MemorySpace = dealii::MemorySpace::Host,
62 template <
typename Number,
64 int simd_length = dealii::VectorizedArray<Number>::size()>
67 MultiComponentVector<Number, n_comp, simd_length>>
95 const std::shared_ptr<const dealii::Utilities::MPI::Partitioner>
115 const std::shared_ptr<const dealii::Utilities::MPI::Partitioner>
138 template <
typename MemorySpace = dealii::MemorySpace::Host>
149 template <
typename MemorySpace = dealii::MemorySpace::Host>
168 template <
typename MemorySpace>
175 template <
typename MemorySpace>
183 template <
typename MemorySpace>
202 mutable dealii::LinearAlgebra::distributed::
203 Vector<Number, dealii::MemorySpace::Host>
206 mutable dealii::LinearAlgebra::distributed::
207 Vector<Number, dealii::MemorySpace::Default>
214 template <
typename MemorySpace>
215 void allocate_storage()
const;
217 template <
typename To,
typename From>
218 void deep_copy_storage()
const;
220 template <
typename MemorySpace>
221 void deallocate_storage();
227 template <
typename,
int,
int,
typename,
bool>
248 template <
typename Number,
251 typename MemorySpace,
264 &multi_component_vector)
269 &multi_component_vector)
280 template <
bool other_writable>
286 other_writable> &other)
287 requires(!writable && other_writable);
289 template <
typename MultiComponentVector>
291 requires(writable != std::is_const_v<MultiComponentVector>);
305 dealii::LinearAlgebra::distributed::Vector<Number, MemorySpace>;
331 template <
typename Functor = std::
identity>
333 unsigned int component,
334 const Functor &functor = std::identity{})
const;
353 template <
typename Functor = std::
identity>
355 unsigned int component,
356 const Functor &functor = std::identity{})
const
363 template <
typename Functor = std::
identity>
365 unsigned int component,
366 const Functor &functor = std::identity{})
const
399 template <
typename Number2 = Number>
400 DEAL_II_HOST_DEVICE Number2
read_entry(
const unsigned int i)
const;
412 template <
typename Number2 = Number>
413 DEAL_II_HOST_DEVICE Number2
read_entry(
const unsigned int *js)
const;
423 template <
typename Number2 = Number,
424 typename Tensor = dealii::Tensor<1, n_comp, Number2>>
425 DEAL_II_HOST_DEVICE Tensor
read_tensor(
const unsigned int i)
const;
435 template <
typename Number2 = Number,
436 typename Tensor = dealii::Tensor<1, n_comp, Number2>>
437 DEAL_II_HOST_DEVICE Tensor
read_tensor(
const unsigned int *js)
const;
450 template <
typename Number2 = Number>
452 const unsigned int i)
const
469 template <
typename Number2 = Number,
470 typename Tensor = dealii::Tensor<1, n_comp, Number2>>
472 const unsigned int i)
const
489 template <
typename Number2 = Number>
490 DEAL_II_HOST_DEVICE
void add_entry(
const Number2 &entry,
491 const unsigned int i)
const
508 template <
typename Number2 = Number,
509 typename Tensor = dealii::Tensor<1, n_comp, Number2>>
511 const unsigned int i)
const
538 void compress(dealii::VectorOperation::values operation) const
549 std::conditional_t<writable,
MCV *, const
MCV *> multi_component_vector_;
552 unsigned int n_locally_owned_;
553 unsigned int n_locally_relevant_;
555 template <typename,
int,
int, typename,
bool>
570 template <
typename Number,
int n_comp,
int simd_length>
578 template <
typename Number,
int n_comp,
int simd_length>
586 template <
typename Number,
int n_comp,
int simd_length>
589 const std::shared_ptr<const dealii::Utilities::MPI::Partitioner>
602 this->reset_residency(
true,
true);
603 this->set_transfer_policy(transfer_policy);
607 host_vector_.reinit(vector_partitioner);
616 default_vector_.reinit(0);
618 this->reset_residency(
true,
621 this->set_transfer_policy(transfer_policy);
625 template <
typename Number,
int n_comp,
int simd_length>
628 const std::shared_ptr<const dealii::Utilities::MPI::Partitioner>
641 this->reset_residency(
true,
true);
642 this->set_transfer_policy(transfer_policy);
648 host_vector_.reinit(scalar_partitioner);
650 auto vector_partitioner =
653 host_vector_.reinit(vector_partitioner);
662 default_vector_.reinit(0);
668 this->reset_residency(
true,
671 this->set_transfer_policy(transfer_policy);
675 template <
typename Number,
int n_comp,
int simd_length>
677 const MultiComponentVector &other) -> MultiComponentVector &
680 static_cast<MirroredStorage<MultiComponentVector> &
>(*this) = other;
682 host_vector_ = other.host_vector_;
684 default_vector_ = other.default_vector_;
690 template <
typename Number,
int n_comp,
int simd_length>
692 MultiComponentVector &&other)
noexcept -> MultiComponentVector &
695 static_cast<MirroredStorage<MultiComponentVector> &
>(*this) = other;
697 host_vector_ = std::move(other.host_vector_);
699 default_vector_ = std::move(other.default_vector_);
705 template <
typename Number,
int n_comp,
int simd_length>
706 template <
typename MemorySpace>
707 MultiComponentVectorView<Number, n_comp, simd_length, MemorySpace, true>
710 this->
template prepare_write_access<MemorySpace>();
720 template <
typename Number,
int n_comp,
int simd_length>
721 template <
typename MemorySpace>
722 MultiComponentVectorView<Number, n_comp, simd_length, MemorySpace, false>
725 this->
template prepare_read_access<MemorySpace>();
735 template <
typename Number,
int n_comp,
int simd_length>
736 template <
typename MemorySpace>
738 MultiComponentVector<Number, n_comp, simd_length>::allocate_storage()
const
740 using HostSpace = dealii::MemorySpace::Host;
747 if constexpr (std::is_same_v<MemorySpace, HostSpace>) {
748 Assert(default_vector_.size() != 0, dealii::ExcNotInitialized());
749 host_vector_.reinit(default_vector_.get_partitioner());
751 Assert(host_vector_.size() != 0, dealii::ExcNotInitialized());
752 default_vector_.reinit(host_vector_.get_partitioner());
757 template <
typename Number,
int n_comp,
int simd_length>
758 template <
typename To,
typename From>
760 MultiComponentVector<Number, n_comp, simd_length>::deep_copy_storage()
const
762 using HostSpace = dealii::MemorySpace::Host;
764 if constexpr (std::is_same_v<To, HostSpace>) {
765 host_vector_.import_elements(default_vector_,
766 dealii::VectorOperation::insert);
768 default_vector_.import_elements(host_vector_,
769 dealii::VectorOperation::insert);
774 template <
typename Number,
int n_comp,
int simd_length>
775 template <
typename MemorySpace>
776 void MultiComponentVector<Number, n_comp, simd_length>::deallocate_storage()
778 using HostSpace = dealii::MemorySpace::Host;
780 if constexpr (std::is_same_v<MemorySpace, HostSpace>) {
781 host_vector_.reinit(0);
784 default_vector_.reinit(0);
789 template <
typename Number,
int n_components,
int simd_length>
790 template <
typename MemorySpace>
794 using HostSpace = dealii::MemorySpace::Host;
795 using DefaultSpace = dealii::MemorySpace::Default;
796 static_assert(std::is_same_v<MemorySpace, HostSpace> ||
797 std::is_same_v<MemorySpace, DefaultSpace>,
798 "Unexpected memory space");
800 Assert(this->
template is_resident<MemorySpace>(),
801 dealii::ExcMessage(
"The chosen memory space is not resident."));
804 !std::is_same_v<MemorySpace, HostSpace>) {
805 default_vector_.zero_out_ghost_values();
807 host_vector_.zero_out_ghost_values();
812 template <
typename Number,
int n_components,
int simd_length>
813 template <
typename MemorySpace>
817 using HostSpace = dealii::MemorySpace::Host;
818 using DefaultSpace = dealii::MemorySpace::Default;
819 static_assert(std::is_same_v<MemorySpace, HostSpace> ||
820 std::is_same_v<MemorySpace, DefaultSpace>,
821 "Unexpected memory space");
823 Assert(this->
template is_resident<MemorySpace>(),
824 dealii::ExcMessage(
"The chosen memory space is not resident."));
827 !std::is_same_v<MemorySpace, HostSpace>) {
828 default_vector_.update_ghost_values();
830 host_vector_.update_ghost_values();
835 template <
typename Number,
int n_components,
int simd_length>
836 template <
typename MemorySpace>
840 using HostSpace = dealii::MemorySpace::Host;
841 using DefaultSpace = dealii::MemorySpace::Default;
842 static_assert(std::is_same_v<MemorySpace, HostSpace> ||
843 std::is_same_v<MemorySpace, DefaultSpace>,
844 "Unexpected memory space");
846 Assert(this->
template is_resident<MemorySpace>(),
847 dealii::ExcMessage(
"The chosen memory space is not resident."));
850 !std::is_same_v<MemorySpace, HostSpace>) {
851 default_vector_.compress(operation);
853 host_vector_.compress(operation);
858 template <
typename Number,
861 typename MemorySpace,
865 &multi_component_vector)
868 reinit(multi_component_vector);
872 template <
typename Number,
875 typename MemorySpace,
879 const MultiComponentVector<Number, n_comp, simd_l>
880 &multi_component_vector)
883 reinit(multi_component_vector);
887 template <
typename Number,
890 typename MemorySpace,
892 template <
bool other_writable>
900 other_writable> &other)
901 requires(!writable && other_writable)
902 : multi_component_vector_(other.multi_component_vector_)
904 , n_locally_owned_(other.n_locally_owned_)
905 , n_locally_relevant_(other.n_locally_relevant_)
910 template <
typename Number,
913 typename MemorySpace,
915 template <
typename MultiComponentVector>
918 reinit(MultiComponentVector &multi_component_vector)
919 requires(writable != std::is_const_v<MultiComponentVector>)
921 using HostSpace = dealii::MemorySpace::Host;
922 using DefaultSpace = dealii::MemorySpace::Default;
923 static_assert(std::is_same_v<MemorySpace, HostSpace> ||
924 std::is_same_v<MemorySpace, DefaultSpace>,
925 "Unexpected memory space");
927 multi_component_vector_ = &multi_component_vector;
930 !std::is_same_v<MemorySpace, HostSpace>) {
931 auto &vector = multi_component_vector_->default_vector_;
932 const auto &partitioner = vector.get_partitioner();
934 data_ = vector.begin();
935 n_locally_owned_ = partitioner->locally_owned_size();
936 n_locally_relevant_ = n_locally_owned_ + partitioner->n_ghost_indices();
939 auto &vector = multi_component_vector_->host_vector_;
940 const auto &partitioner = vector.get_partitioner();
942 data_ = vector.begin();
943 n_locally_owned_ = partitioner->locally_owned_size();
944 n_locally_relevant_ = n_locally_owned_ + partitioner->n_ghost_indices();
949 template <
typename Number,
952 typename MemorySpace,
954 template <
typename Functor>
961 unsigned int component,
962 const Functor &functor)
const
964 using HostSpace = dealii::MemorySpace::Host;
965 AssertThrow((std::is_same_v<MemorySpace, HostSpace>),
966 dealii::ExcNotImplemented());
970 "Cannot extract from a vector with zero components."));
971 AssertIndexRange(component, n_comp);
973 const auto local_size =
974 scalar_vector.get_partitioner()->locally_owned_size();
976 Assert(n_comp * local_size == n_locally_owned_,
977 dealii::ExcMessage(
"Called with a scalar_vector argument that has "
978 "incompatible local range."));
980 for (
unsigned int i = 0; i < local_size; ++i)
981 scalar_vector.local_element(i) = functor(data_[i * n_comp + component]);
982 scalar_vector.update_ghost_values();
986 template <
typename Number,
989 typename MemorySpace,
991 template <
typename Functor>
998 unsigned int component,
999 const Functor &functor)
const
1002 using HostSpace = dealii::MemorySpace::Host;
1003 AssertThrow((std::is_same_v<MemorySpace, HostSpace>),
1004 dealii::ExcNotImplemented());
1008 "Cannot insert into a vector with zero components."));
1009 AssertIndexRange(component, n_comp);
1011 const auto local_size =
1012 scalar_vector.get_partitioner()->locally_owned_size();
1014 Assert(n_comp * local_size == n_locally_owned_,
1015 dealii::ExcMessage(
"Called with a scalar_vector argument that has "
1016 "incompatible local range."));
1018 for (
unsigned int i = 0; i < local_size; ++i)
1019 data_[i * n_comp + component] = functor(scalar_vector.local_element(i));
1023 template <
typename Number,
1026 typename MemorySpace,
1028 template <
typename Functor>
1035 unsigned int component,
1036 const Functor &functor)
const
1039 using HostSpace = dealii::MemorySpace::Host;
1040 AssertThrow((std::is_same_v<MemorySpace, HostSpace>),
1041 dealii::ExcInternalError());
1045 "Cannot insert into a vector with zero components."));
1046 AssertIndexRange(component, n_comp);
1048 const auto local_size = scalar_vector.size();
1050 Assert(n_comp * local_size >= n_locally_owned_,
1051 dealii::ExcMessage(
"Called with a scalar_vector argument that has "
1052 "incompatible local range."));
1054 for (
unsigned int i = 0; i < local_size; ++i)
1055 data_[i * n_comp + component] = functor(scalar_vector[i]);
1059 template <
typename Num,
int n_comp,
int simd_l,
typename MS,
bool writable>
1070 using HS = dealii::MemorySpace::Host;
1071 using DS = dealii::MemorySpace::Default;
1072 static_assert(std::is_same_v<MS, HS> || std::is_same_v<MS, DS>,
1073 "Unexpected memory space");
1080 const auto &other = v.multi_component_vector_->default_vector_;
1081 multi_component_vector_->default_vector_.sadd(s, a, other);
1083 const auto &other = v.multi_component_vector_->host_vector_;
1084 multi_component_vector_->host_vector_.sadd(s, a, other);
1089 template <
typename Number,
1092 typename MemorySpace,
1094 template <
typename Number2>
1095 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number2
1104 "Attempted to read a scalar value from a tensor-valued vector entry");
1106 AssertIndexRange(i, n_locally_relevant_);
1108 const auto result = read_tensor<Number2>(i);
1113 template <
typename Number,
1116 typename MemorySpace,
1118 template <
typename Number2,
typename Tensor>
1119 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Tensor
1126 static_assert(std::is_same_v<Number2, typename Tensor::value_type>,
1129 AssertIndexRange(i, n_locally_relevant_);
1134 if constexpr (n_comp == 0)
1137 using VA = dealii::VectorizedArray<Number>;
1138 if constexpr (std::is_same_v<VA, Number2>) {
1140 std::array<
unsigned int, VA::size()> indices;
1141 for (
unsigned int k = 0; k < VA::size(); ++k)
1142 indices[k] = k * n_comp;
1144 dealii::vectorized_load_and_transpose(
1145 n_comp, data_ + i * n_comp, indices.data(), &tensor[0]);
1149 for (
unsigned int d = 0; d < n_comp; ++d)
1150 tensor[d] = data_[i * n_comp + d];
1157 template <
typename Number,
1160 typename MemorySpace,
1162 template <
typename Number2>
1163 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number2
1172 "Attempted to read a scalar value from a tensor-valued vector entry");
1174 const auto result = read_tensor<Number2>(js);
1179 template <
typename Number,
1182 typename MemorySpace,
1184 template <
typename Number2,
typename Tensor>
1185 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Tensor
1193 static_assert(std::is_same_v<Number2, typename Tensor::value_type>,
1199 if constexpr (n_comp == 0)
1202 using VA = dealii::VectorizedArray<Number>;
1203 if constexpr (std::is_same_v<VA, Number2>) {
1206 std::array<
unsigned int, VA::size()> indices;
1207 for (
unsigned int k = 0; k < VA::size(); ++k) {
1208 AssertIndexRange(js[k], n_locally_relevant_);
1209 indices[k] = js[k] * n_comp;
1212 dealii::vectorized_load_and_transpose(
1213 n_comp, data_, indices.data(), &tensor[0]);
1218 AssertIndexRange(*js, n_locally_relevant_);
1220 for (
unsigned int d = 0; d < n_comp; ++d)
1221 tensor[d] = data_[js[0] * n_comp + d];
1228 template <
typename Number,
1231 typename MemorySpace,
1233 template <
typename Number2>
1234 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
void
1240 const unsigned int i)
const
1243 static_assert(n_comp == 1,
1244 "Attempted to write a scalar value into a tensor-valued "
1247 AssertIndexRange(i, n_locally_relevant_);
1249 dealii::Tensor<1, n_comp, Number2> tensor;
1252 write_tensor<Number2>(tensor, i);
1256 template <
typename Number,
1259 typename MemorySpace,
1261 template <
typename Number2,
typename Tensor>
1262 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
void
1268 const unsigned int i)
const
1271 static_assert(std::is_same_v<Number2, typename Tensor::value_type>,
1274 AssertIndexRange(i, n_locally_relevant_);
1277 if constexpr (n_comp == 0)
1280 using VA = dealii::VectorizedArray<Number>;
1281 if constexpr (std::is_same_v<VA, Number2>) {
1284 std::array<
unsigned int, VA::size()> indices;
1285 for (
unsigned int k = 0; k < VA::size(); ++k)
1286 indices[k] = k * n_comp;
1288 dealii::vectorized_transpose_and_store(
false,
1292 data_ + i * n_comp);
1297 for (
unsigned int d = 0; d < n_comp; ++d)
1298 data_[i * n_comp + d] = tensor[d];
1303 template <
typename Number,
1306 typename MemorySpace,
1308 template <
typename Number2>
1309 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
void
1315 const unsigned int i)
const
1318 static_assert(n_comp == 1,
1319 "Attempted to write a scalar value into a tensor-valued "
1322 AssertIndexRange(i, n_locally_relevant_);
1324 dealii::Tensor<1, n_comp, Number2> tensor;
1327 add_tensor<Number2>(tensor, i);
1331 template <
typename Number,
1334 typename MemorySpace,
1336 template <
typename Number2,
typename Tensor>
1337 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
void
1343 const unsigned int i)
const
1346 static_assert(std::is_same_v<Number2, typename Tensor::value_type>,
1349 AssertIndexRange(i, n_locally_relevant_);
1352 if constexpr (n_comp == 0)
1355 using VA = dealii::VectorizedArray<Number>;
1356 if constexpr (std::is_same_v<VA, Number2>) {
1359 std::array<
unsigned int, VA::size()> indices;
1360 for (
unsigned int k = 0; k < VA::size(); ++k)
1361 indices[k] = k * n_comp;
1363 dealii::vectorized_transpose_and_store(
true,
1367 data_ + i * n_comp);
1372 for (
unsigned int d = 0; d < n_comp; ++d)
1373 data_[i * n_comp + d] += tensor[d];
1378 template <
typename Number,
1381 typename MemorySpace,
1388 using HostSpace = dealii::MemorySpace::Host;
1389 using DefaultSpace = dealii::MemorySpace::Default;
1390 static_assert(std::is_same_v<MemorySpace, HostSpace> ||
1391 std::is_same_v<MemorySpace, DefaultSpace>,
1392 "Unexpected memory space");
1394 Assert(multi_component_vector_->template is_resident<MemorySpace>(),
1395 dealii::ExcMessage(
"The chosen memory space is not resident."));
1397 multi_component_vector_
1398 ->template zero_out_ghost_values_on_memory_space<MemorySpace>();
1402 template <
typename Number,
1405 typename MemorySpace,
1412 using HostSpace = dealii::MemorySpace::Host;
1413 using DefaultSpace = dealii::MemorySpace::Default;
1414 static_assert(std::is_same_v<MemorySpace, HostSpace> ||
1415 std::is_same_v<MemorySpace, DefaultSpace>,
1416 "Unexpected memory space");
1418 Assert(multi_component_vector_->template is_resident<MemorySpace>(),
1419 dealii::ExcMessage(
"The chosen memory space is not resident."));
1421 multi_component_vector_
1422 ->template update_ghost_values_on_memory_space<MemorySpace>();
1426 template <
typename Number,
1429 typename MemorySpace,
1433 compress(dealii::VectorOperation::values operation)
const
1436 using HostSpace = dealii::MemorySpace::Host;
1437 using DefaultSpace = dealii::MemorySpace::Default;
1438 static_assert(std::is_same_v<MemorySpace, HostSpace> ||
1439 std::is_same_v<MemorySpace, DefaultSpace>,
1440 "Unexpected memory space");
1442 Assert(multi_component_vector_->template is_resident<MemorySpace>(),
1443 dealii::ExcMessage(
"The chosen memory space is not resident."));
1445 multi_component_vector_->template compress_on_memory_space<MemorySpace>(