41 std::shared_ptr<const dealii::Utilities::MPI::Partitioner>
43 const std::shared_ptr<const dealii::Utilities::MPI::Partitioner>
45 const unsigned int n_comp);
48 template <
typename Number,
50 int simd_length = dealii::VectorizedArray<Number>::size(),
51 typename MemorySpace = dealii::MemorySpace::Host,
63 template <
typename Number,
65 int simd_length = dealii::VectorizedArray<Number>::size()>
68 MultiComponentVector<Number, n_comp, simd_length>>
96 const std::shared_ptr<const dealii::Utilities::MPI::Partitioner>
116 const std::shared_ptr<const dealii::Utilities::MPI::Partitioner>
139 template <
typename MemorySpace = dealii::MemorySpace::Host>
150 template <
typename MemorySpace = dealii::MemorySpace::Host>
164 template <
typename MemorySpace = dealii::MemorySpace::Host>
165 dealii::LinearAlgebra::distributed::Vector<Number, MemorySpace> &
167 requires(n_comp == 1);
176 template <
typename MemorySpace = dealii::MemorySpace::Host>
177 const dealii::LinearAlgebra::distributed::Vector<Number, MemorySpace> &
179 requires(n_comp == 1);
196 template <typename MemorySpace>
203 template <typename MemorySpace>
211 template <typename MemorySpace>
230 mutable dealii::LinearAlgebra::distributed::
231 Vector<Number, dealii::MemorySpace::Host>
234 mutable dealii::LinearAlgebra::distributed::
235 Vector<Number, dealii::MemorySpace::Default>
242 template <typename MemorySpace>
243 void allocate_storage() const;
245 template <typename To, typename From>
246 void deep_copy_storage() const;
248 template <typename MemorySpace>
249 void deallocate_storage();
255 template <typename,
int,
int, typename,
bool>
276 template <typename Number,
279 typename MemorySpace,
292 &multi_component_vector)
297 &multi_component_vector)
308 template <
bool other_writable>
314 other_writable> &other)
315 requires(!writable && other_writable);
317 template <
typename MultiComponentVector>
319 requires(writable != std::is_const_v<MultiComponentVector>);
333 dealii::LinearAlgebra::distributed::Vector<Number, MemorySpace>;
363 template <
typename Functor = std::
identity>
365 unsigned int component,
366 const Functor &functor = std::identity{})
const;
385 template <
typename Functor = std::
identity>
387 unsigned int component,
388 const Functor &functor = std::identity{})
const
395 template <
typename Functor = std::
identity>
397 unsigned int component,
398 const Functor &functor = std::identity{})
const
431 template <
typename Number2 = Number>
432 DEAL_II_HOST_DEVICE Number2
read_entry(
const unsigned int i)
const;
444 template <
typename Number2 = Number>
445 DEAL_II_HOST_DEVICE Number2
read_entry(
const unsigned int *js)
const;
455 template <
typename Number2 = Number,
456 typename Tensor = dealii::Tensor<1, n_comp, Number2>>
457 DEAL_II_HOST_DEVICE Tensor
read_tensor(
const unsigned int i)
const;
467 template <
typename Number2 = Number,
468 typename Tensor = dealii::Tensor<1, n_comp, Number2>>
469 DEAL_II_HOST_DEVICE Tensor
read_tensor(
const unsigned int *js)
const;
482 template <
typename Number2 = Number>
484 const unsigned int i)
const
501 template <
typename Number2 = Number,
502 typename Tensor = dealii::Tensor<1, n_comp, Number2>>
504 const unsigned int i)
const
521 template <
typename Number2 = Number>
522 DEAL_II_HOST_DEVICE
void add_entry(
const Number2 &entry,
523 const unsigned int i)
const
540 template <
typename Number2 = Number,
541 typename Tensor = dealii::Tensor<1, n_comp, Number2>>
543 const unsigned int i)
const
562 void update_ghost_values() const
570 void compress(dealii::VectorOperation::values operation) const
581 std::conditional_t<writable,
MCV *, const
MCV *> multi_component_vector_;
584 unsigned int n_locally_owned_;
585 unsigned int n_locally_relevant_;
587 template <typename,
int,
int, typename,
bool>
602 template <
typename Number,
int n_comp,
int simd_length>
610 template <
typename Number,
int n_comp,
int simd_length>
618 template <
typename Number,
int n_comp,
int simd_length>
621 const std::shared_ptr<const dealii::Utilities::MPI::Partitioner>
639 host_vector_.reinit(vector_partitioner);
648 default_vector_.reinit(0);
657 template <
typename Number,
int n_comp,
int simd_length>
660 const std::shared_ptr<const dealii::Utilities::MPI::Partitioner>
680 host_vector_.reinit(scalar_partitioner);
682 auto vector_partitioner =
684 host_vector_.reinit(vector_partitioner);
694 default_vector_.reinit(0);
707 template <
typename Number,
int n_comp,
int simd_length>
712 static_cast<MirroredStorage<MultiComponentVector> &
>(*this) = other;
714 host_vector_ = other.host_vector_;
716 default_vector_ = other.default_vector_;
722 template <
typename Number,
int n_comp,
int simd_length>
727 static_cast<MirroredStorage<MultiComponentVector> &
>(*this) = other;
729 host_vector_ = std::move(other.host_vector_);
731 default_vector_ = std::move(other.default_vector_);
737 template <
typename Number,
int n_comp,
int simd_length>
738 template <
typename MemorySpace>
739 MultiComponentVectorView<Number, n_comp, simd_length, MemorySpace, true>
742 this->
template prepare_write_access<MemorySpace>();
752 template <
typename Number,
int n_comp,
int simd_length>
753 template <
typename MemorySpace>
754 MultiComponentVectorView<Number, n_comp, simd_length, MemorySpace, false>
757 this->
template prepare_read_access<MemorySpace>();
767 template <
typename Number,
int n_comp,
int simd_length>
768 template <
typename MemorySpace>
769 dealii::LinearAlgebra::distributed::Vector<Number, MemorySpace> &
771 requires(n_comp == 1)
773 this->
template prepare_write_access<MemorySpace>();
775 if constexpr (std::is_same_v<MemorySpace, dealii::MemorySpace::Host>)
778 return default_vector_;
782 template <
typename Number,
int n_comp,
int simd_length>
783 template <
typename MemorySpace>
784 const dealii::LinearAlgebra::distributed::Vector<Number, MemorySpace> &
786 requires(n_comp == 1)
788 this->
template prepare_read_access<MemorySpace>();
790 if constexpr (std::is_same_v<MemorySpace, dealii::MemorySpace::Host>)
793 return default_vector_;
797 template <
typename Number,
int n_comp,
int simd_length>
798 template <
typename MemorySpace>
800 MultiComponentVector<Number, n_comp, simd_length>::allocate_storage()
const
802 using HostSpace = dealii::MemorySpace::Host;
809 if constexpr (std::is_same_v<MemorySpace, HostSpace>) {
810 Assert(default_vector_.size() != 0, dealii::ExcNotInitialized());
811 host_vector_.reinit(default_vector_.get_partitioner());
813 Assert(host_vector_.size() != 0, dealii::ExcNotInitialized());
814 default_vector_.reinit(host_vector_.get_partitioner());
819 template <
typename Number,
int n_comp,
int simd_length>
820 template <
typename To,
typename From>
822 MultiComponentVector<Number, n_comp, simd_length>::deep_copy_storage()
const
824 using HostSpace = dealii::MemorySpace::Host;
826 if constexpr (std::is_same_v<To, HostSpace>) {
827 host_vector_.import_elements(default_vector_,
828 dealii::VectorOperation::insert);
830 default_vector_.import_elements(host_vector_,
831 dealii::VectorOperation::insert);
836 template <
typename Number,
int n_comp,
int simd_length>
837 template <
typename MemorySpace>
838 void MultiComponentVector<Number, n_comp, simd_length>::deallocate_storage()
840 using HostSpace = dealii::MemorySpace::Host;
842 if constexpr (std::is_same_v<MemorySpace, HostSpace>) {
843 host_vector_.reinit(0);
846 default_vector_.reinit(0);
851 template <
typename Number,
int n_components,
int simd_length>
852 template <
typename MemorySpace>
856 using HostSpace = dealii::MemorySpace::Host;
857 using DefaultSpace = dealii::MemorySpace::Default;
858 static_assert(std::is_same_v<MemorySpace, HostSpace> ||
859 std::is_same_v<MemorySpace, DefaultSpace>,
860 "Unexpected memory space");
862 Assert(this->
template is_resident<MemorySpace>(),
863 dealii::ExcMessage(
"The chosen memory space is not resident."));
866 !std::is_same_v<MemorySpace, HostSpace>) {
867 default_vector_.zero_out_ghost_values();
869 host_vector_.zero_out_ghost_values();
874 template <
typename Number,
int n_components,
int simd_length>
875 template <
typename MemorySpace>
879 using HostSpace = dealii::MemorySpace::Host;
880 using DefaultSpace = dealii::MemorySpace::Default;
881 static_assert(std::is_same_v<MemorySpace, HostSpace> ||
882 std::is_same_v<MemorySpace, DefaultSpace>,
883 "Unexpected memory space");
885 Assert(this->
template is_resident<MemorySpace>(),
886 dealii::ExcMessage(
"The chosen memory space is not resident."));
889 !std::is_same_v<MemorySpace, HostSpace>) {
890 default_vector_.update_ghost_values();
892 host_vector_.update_ghost_values();
897 template <
typename Number,
int n_components,
int simd_length>
898 template <
typename MemorySpace>
902 using HostSpace = dealii::MemorySpace::Host;
903 using DefaultSpace = dealii::MemorySpace::Default;
904 static_assert(std::is_same_v<MemorySpace, HostSpace> ||
905 std::is_same_v<MemorySpace, DefaultSpace>,
906 "Unexpected memory space");
908 Assert(this->
template is_resident<MemorySpace>(),
909 dealii::ExcMessage(
"The chosen memory space is not resident."));
912 !std::is_same_v<MemorySpace, HostSpace>) {
913 default_vector_.compress(operation);
915 host_vector_.compress(operation);
920 template <
typename Number,
923 typename MemorySpace,
927 &multi_component_vector)
930 reinit(multi_component_vector);
934 template <
typename Number,
937 typename MemorySpace,
941 const MultiComponentVector<Number, n_comp, simd_l>
942 &multi_component_vector)
945 reinit(multi_component_vector);
949 template <
typename Number,
952 typename MemorySpace,
954 template <
bool other_writable>
962 other_writable> &other)
963 requires(!writable && other_writable)
964 : multi_component_vector_(other.multi_component_vector_)
966 , n_locally_owned_(other.n_locally_owned_)
967 , n_locally_relevant_(other.n_locally_relevant_)
972 template <
typename Number,
975 typename MemorySpace,
977 template <
typename MultiComponentVector>
981 requires(writable != std::is_const_v<MultiComponentVector>)
983 using HostSpace = dealii::MemorySpace::Host;
984 using DefaultSpace = dealii::MemorySpace::Default;
985 static_assert(std::is_same_v<MemorySpace, HostSpace> ||
986 std::is_same_v<MemorySpace, DefaultSpace>,
987 "Unexpected memory space");
989 multi_component_vector_ = &multi_component_vector;
992 !std::is_same_v<MemorySpace, HostSpace>) {
993 auto &vector = multi_component_vector_->default_vector_;
994 const auto &partitioner = vector.get_partitioner();
996 data_ = vector.begin();
997 n_locally_owned_ = partitioner->locally_owned_size();
998 n_locally_relevant_ = n_locally_owned_ + partitioner->n_ghost_indices();
1001 auto &vector = multi_component_vector_->host_vector_;
1002 const auto &partitioner = vector.get_partitioner();
1004 data_ = vector.begin();
1005 n_locally_owned_ = partitioner->locally_owned_size();
1006 n_locally_relevant_ = n_locally_owned_ + partitioner->n_ghost_indices();
1011 template <
typename Number,
1014 typename MemorySpace,
1016 template <
typename Functor>
1022 writable>::extract_component(
ScalarVector &scalar_vector,
1023 unsigned int component,
1024 const Functor &functor)
const
1028 "Cannot extract from a vector with zero components."));
1029 AssertIndexRange(component, n_comp);
1031 const auto local_size =
static_cast<unsigned int>(
1032 scalar_vector.get_partitioner()->locally_owned_size());
1034 Assert(n_comp * local_size == n_locally_owned_,
1035 dealii::ExcMessage(
"Called with a scalar_vector argument that has "
1036 "incompatible local range."));
1038 const auto *data = data_;
1039 auto *destination = scalar_vector.begin();
1041 const auto body = [=](
auto ,
unsigned int i) {
1042 destination[i] = functor(data[i * n_comp + component]);
1045 loop<MemorySpace, Number>(
1046 "extract_component", body, 0, 0, local_size);
1048 scalar_vector.update_ghost_values();
1052 template <
typename Number,
1055 typename MemorySpace,
1057 template <
typename Functor>
1063 writable>::insert_component(
const ScalarVector &scalar_vector,
1064 unsigned int component,
1065 const Functor &functor)
const
1068 using HostSpace = dealii::MemorySpace::Host;
1069 AssertThrow((std::is_same_v<MemorySpace, HostSpace>),
1070 dealii::ExcNotImplemented());
1074 "Cannot insert into a vector with zero components."));
1075 AssertIndexRange(component, n_comp);
1077 const auto local_size =
1078 scalar_vector.get_partitioner()->locally_owned_size();
1080 Assert(n_comp * local_size == n_locally_owned_,
1081 dealii::ExcMessage(
"Called with a scalar_vector argument that has "
1082 "incompatible local range."));
1084 for (
unsigned int i = 0; i < local_size; ++i)
1085 data_[i * n_comp + component] = functor(scalar_vector.local_element(i));
1089 template <
typename Number,
1092 typename MemorySpace,
1094 template <
typename Functor>
1100 writable>::insert_component(
const dealii::Vector<Number> &scalar_vector,
1101 unsigned int component,
1102 const Functor &functor)
const
1105 using HostSpace = dealii::MemorySpace::Host;
1106 AssertThrow((std::is_same_v<MemorySpace, HostSpace>),
1107 dealii::ExcInternalError());
1111 "Cannot insert into a vector with zero components."));
1112 AssertIndexRange(component, n_comp);
1114 const auto local_size = scalar_vector.size();
1116 Assert(n_comp * local_size >= n_locally_owned_,
1117 dealii::ExcMessage(
"Called with a scalar_vector argument that has "
1118 "incompatible local range."));
1120 for (
unsigned int i = 0; i < local_size; ++i)
1121 data_[i * n_comp + component] = functor(scalar_vector[i]);
1125 template <
typename Num,
int n_comp,
int simd_l,
typename MS,
bool writable>
1136 using HS = dealii::MemorySpace::Host;
1137 using DS = dealii::MemorySpace::Default;
1138 static_assert(std::is_same_v<MS, HS> || std::is_same_v<MS, DS>,
1139 "Unexpected memory space");
1146 const auto &other = v.multi_component_vector_->default_vector_;
1147 multi_component_vector_->default_vector_.sadd(s, a, other);
1149 const auto &other = v.multi_component_vector_->host_vector_;
1150 multi_component_vector_->host_vector_.sadd(s, a, other);
1155 template <
typename Number,
1158 typename MemorySpace,
1160 template <
typename Number2>
1161 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number2
1170 "Attempted to read a scalar value from a tensor-valued vector entry");
1172 AssertIndexRange(i, n_locally_relevant_);
1174 const auto result = read_tensor<Number2>(i);
1179 template <
typename Number,
1182 typename MemorySpace,
1184 template <
typename Number2,
typename Tensor>
1185 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Tensor
1190 writable>::read_tensor(
const unsigned int i)
const
1192 static_assert(std::is_same_v<Number2, typename Tensor::value_type>,
1195 AssertIndexRange(i, n_locally_relevant_);
1200 if constexpr (n_comp == 0)
1203 using VA = dealii::VectorizedArray<Number>;
1204 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 indices[k] = k * n_comp;
1210 dealii::vectorized_load_and_transpose(
1211 n_comp, data_ + i * n_comp, indices.data(), &tensor[0]);
1215 for (
unsigned int d = 0; d < n_comp; ++d)
1216 tensor[d] = data_[i * n_comp + d];
1223 template <
typename Number,
1226 typename MemorySpace,
1228 template <
typename Number2>
1229 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number2
1238 "Attempted to read a scalar value from a tensor-valued vector entry");
1240 const auto result = read_tensor<Number2>(js);
1245 template <
typename Number,
1248 typename MemorySpace,
1250 template <
typename Number2,
typename Tensor>
1251 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Tensor
1256 writable>::read_tensor(
const unsigned int *js)
1259 static_assert(std::is_same_v<Number2, typename Tensor::value_type>,
1265 if constexpr (n_comp == 0)
1268 using VA = dealii::VectorizedArray<Number>;
1269 if constexpr (std::is_same_v<VA, Number2>) {
1272 std::array<
unsigned int, VA::size()> indices;
1273 for (
unsigned int k = 0; k < VA::size(); ++k) {
1274 AssertIndexRange(js[k], n_locally_relevant_);
1275 indices[k] = js[k] * n_comp;
1278 dealii::vectorized_load_and_transpose(
1279 n_comp, data_, indices.data(), &tensor[0]);
1284 AssertIndexRange(*js, n_locally_relevant_);
1286 for (
unsigned int d = 0; d < n_comp; ++d)
1287 tensor[d] = data_[js[0] * n_comp + d];
1294 template <
typename Number,
1297 typename MemorySpace,
1299 template <
typename Number2>
1300 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
void
1306 const unsigned int i)
const
1309 static_assert(n_comp == 1,
1310 "Attempted to write a scalar value into a tensor-valued "
1313 AssertIndexRange(i, n_locally_relevant_);
1315 dealii::Tensor<1, n_comp, Number2> tensor;
1318 write_tensor<Number2>(tensor, i);
1322 template <
typename Number,
1325 typename MemorySpace,
1327 template <
typename Number2,
typename Tensor>
1328 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
void
1333 writable>::write_tensor(
const Tensor &tensor,
1334 const unsigned int i)
const
1337 static_assert(std::is_same_v<Number2, typename Tensor::value_type>,
1340 AssertIndexRange(i, n_locally_relevant_);
1343 if constexpr (n_comp == 0)
1346 using VA = dealii::VectorizedArray<Number>;
1347 if constexpr (std::is_same_v<VA, Number2>) {
1350 std::array<
unsigned int, VA::size()> indices;
1351 for (
unsigned int k = 0; k < VA::size(); ++k)
1352 indices[k] = k * n_comp;
1354 dealii::vectorized_transpose_and_store(
false,
1358 data_ + i * n_comp);
1363 for (
unsigned int d = 0; d < n_comp; ++d)
1364 data_[i * n_comp + d] = tensor[d];
1369 template <
typename Number,
1372 typename MemorySpace,
1374 template <
typename Number2>
1375 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
void
1380 writable>::add_entry(
const Number2 &entry,
1381 const unsigned int i)
const
1384 static_assert(n_comp == 1,
1385 "Attempted to write a scalar value into a tensor-valued "
1388 AssertIndexRange(i, n_locally_relevant_);
1390 dealii::Tensor<1, n_comp, Number2> tensor;
1393 add_tensor<Number2>(tensor, i);
1397 template <
typename Number,
1400 typename MemorySpace,
1402 template <
typename Number2,
typename Tensor>
1403 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
void
1408 writable>::add_tensor(
const Tensor &tensor,
1409 const unsigned int i)
const
1412 static_assert(std::is_same_v<Number2, typename Tensor::value_type>,
1415 AssertIndexRange(i, n_locally_relevant_);
1418 if constexpr (n_comp == 0)
1421 using VA = dealii::VectorizedArray<Number>;
1422 if constexpr (std::is_same_v<VA, Number2>) {
1425 std::array<
unsigned int, VA::size()> indices;
1426 for (
unsigned int k = 0; k < VA::size(); ++k)
1427 indices[k] = k * n_comp;
1429 dealii::vectorized_transpose_and_store(
true,
1433 data_ + i * n_comp);
1438 for (
unsigned int d = 0; d < n_comp; ++d)
1439 data_[i * n_comp + d] += tensor[d];
1444 template <
typename Number,
1447 typename MemorySpace,
1454 using HostSpace = dealii::MemorySpace::Host;
1455 using DefaultSpace = dealii::MemorySpace::Default;
1456 static_assert(std::is_same_v<MemorySpace, HostSpace> ||
1457 std::is_same_v<MemorySpace, DefaultSpace>,
1458 "Unexpected memory space");
1460 Assert(multi_component_vector_->template is_resident<MemorySpace>(),
1461 dealii::ExcMessage(
"The chosen memory space is not resident."));
1463 multi_component_vector_
1464 ->template zero_out_ghost_values_on_memory_space<MemorySpace>();
1468 template <
typename Number,
1471 typename MemorySpace,
1478 using HostSpace = dealii::MemorySpace::Host;
1479 using DefaultSpace = dealii::MemorySpace::Default;
1480 static_assert(std::is_same_v<MemorySpace, HostSpace> ||
1481 std::is_same_v<MemorySpace, DefaultSpace>,
1482 "Unexpected memory space");
1484 Assert(multi_component_vector_->template is_resident<MemorySpace>(),
1485 dealii::ExcMessage(
"The chosen memory space is not resident."));
1487 multi_component_vector_
1488 ->template update_ghost_values_on_memory_space<MemorySpace>();
1492 template <
typename Number,
1495 typename MemorySpace,
1499 compress(dealii::VectorOperation::values operation)
const
1502 using HostSpace = dealii::MemorySpace::Host;
1503 using DefaultSpace = dealii::MemorySpace::Default;
1504 static_assert(std::is_same_v<MemorySpace, HostSpace> ||
1505 std::is_same_v<MemorySpace, DefaultSpace>,
1506 "Unexpected memory space");
1508 Assert(multi_component_vector_->template is_resident<MemorySpace>(),
1509 dealii::ExcMessage(
"The chosen memory space is not resident."));
1511 multi_component_vector_->template compress_on_memory_space<MemorySpace>(