ryujin 2.5.0 revision c64172211cf21344cb9b9b0f3a1266aa6400d392
Loading...
Searching...
No Matches
multicomponent_vector.h
Go to the documentation of this file.
1//
2// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3// Copyright (C) 2020 - 2026 by the ryujin authors
4//
5
6#pragma once
7
8#include <ryujin/base/compile_time_options.h>
9#include <ryujin/base/gpu.h>
10#include <ryujin/base/loop.h>
11
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>
16
17namespace ryujin
18{
38 std::shared_ptr<const dealii::Utilities::MPI::Partitioner>
40 const std::shared_ptr<const dealii::Utilities::MPI::Partitioner>
41 &scalar_partitioner,
42 const unsigned int n_comp);
43
44
45 template <typename Number,
46 int n_comp,
47 typename MemorySpace = dealii::MemorySpace::Host,
48 bool writable = true>
50
51
59 template <typename Number>
61 : public MirroredStorage<MultiComponentVector<Number>>
62 {
63 public:
68
70
72
74
90 const std::shared_ptr<const dealii::Utilities::MPI::Partitioner>
91 &vector_partitioner,
92 const unsigned int n_comp,
95
112 const std::shared_ptr<const dealii::Utilities::MPI::Partitioner>
113 &scalar_partitioner,
114 const unsigned int n_comp,
117
121 ACCESSOR_READ_ONLY(n_comp)
122
124
125 MultiComponentVector &operator=(MultiComponentVector &&other) noexcept;
126
128
132
143 template <int n_comp, typename MemorySpace = dealii::MemorySpace::Host>
144 MultiComponentVectorView<Number, n_comp, MemorySpace, true> view();
145
155 template <int n_comp, typename MemorySpace = dealii::MemorySpace::Host>
156 MultiComponentVectorView<Number, n_comp, MemorySpace, false> view() const;
157
168 template <typename MemorySpace = dealii::MemorySpace::Host>
170
178 template <typename MemorySpace = dealii::MemorySpace::Host>
179 const auto &deal_ii_vector() const;
180
181 /*
182 * The is_resident(), copy_to_memory_space(), move_to_memory_space(),
183 * transfer_policy(), and set_transfer_policy() methods are inherited
184 * from the MirroredStorage base class.
185 */
186
187 private:
189
193
194 unsigned int n_comp_ = 0;
195
196 /*
197 * Note: The storage is marked mutable so that the (logically const)
198 * copy_to_memory_space() operation can populate a mirror from within
199 * a const view() under the implicit_transfers policy.
200 *
201 * We avoid setting up the default_vector_ if default and host happen
202 * to be the same memory space (see have_separate_memory_spaces).
203 */
204
205 mutable dealii::LinearAlgebra::distributed::
206 Vector<Number, dealii::MemorySpace::Host>
207 host_vector_;
208
209 mutable dealii::LinearAlgebra::distributed::
210 Vector<Number, dealii::MemorySpace::Default>
211 default_vector_;
212
213 /*
214 * Return the deal.II vector holding the data of the selected memory
215 * space:
216 */
217 template <typename MemorySpace>
218 auto &storage() const;
219
220 /*
221 * Storage primitives used by the MirroredStorage base class:
222 */
223
224 template <typename MemorySpace>
225 void allocate_storage() const;
226
227 template <typename To, typename From>
228 void deep_copy_storage() const;
229
230 template <typename MemorySpace>
231 void deallocate_storage();
232
233
234 friend class MirroredStorage<MultiComponentVector<Number>>;
235
236 template <typename, int, typename, bool>
238
240 };
241
242
257 template <typename Number, int n_comp, typename MemorySpace, bool writable>
259 {
260 public:
265
267
269 MultiComponentVector<Number> &multi_component_vector)
270 requires(writable)
271 {
272 reinit(multi_component_vector);
273 }
274
276 const MultiComponentVector<Number> &multi_component_vector)
277 requires(!writable)
278 {
279 reinit(multi_component_vector);
280 }
281
290 template <bool other_writable>
291 DEAL_II_HOST_DEVICE MultiComponentVectorView(
292 const MultiComponentVectorView<Number,
293 n_comp,
294 MemorySpace,
295 other_writable> &other)
296 requires(!writable && other_writable)
297 : multi_component_vector_(other.multi_component_vector_)
298 , data_(other.data_)
299 , n_locally_owned_(other.n_locally_owned_)
300 , n_locally_relevant_(other.n_locally_relevant_)
301 {
302 }
303
304 template <typename MultiComponentVector>
305 void reinit(MultiComponentVector &multi_component_vector)
306 requires(writable != std::is_const_v<MultiComponentVector>)
307 {
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 "
312 "vector."));
313
314 multi_component_vector_ = &multi_component_vector;
315
316 auto &vector = multi_component_vector_->template storage<MemorySpace>();
317 const auto &partitioner = vector.get_partitioner();
318
319 data_ = vector.begin();
320 n_locally_owned_ = partitioner->locally_owned_size();
321 n_locally_relevant_ = n_locally_owned_ + partitioner->n_ghost_indices();
322 }
323
325
329
335 dealii::LinearAlgebra::distributed::Vector<Number, MemorySpace>;
336
338
342
365 template <typename Functor = std::identity>
366 void extract_component(ScalarVector &scalar_vector,
367 unsigned int component,
368 const Functor &functor = std::identity{}) const
369 {
370 Assert(n_comp > 0,
371 dealii::ExcMessage(
372 "Cannot extract from a vector with zero components."));
373 AssertIndexRange(component, n_comp);
374
375 const auto local_size = static_cast<unsigned int>(
376 scalar_vector.get_partitioner()->locally_owned_size());
377
378 Assert(n_comp * local_size == n_locally_owned_,
379 dealii::ExcMessage("Called with a scalar_vector argument that has "
380 "incompatible local range."));
381
382 const auto *data = data_;
383 auto *destination = scalar_vector.begin();
384
385 const auto body = [=](auto /*sentinel*/, unsigned int i) {
386 destination[i] = functor(data[i * n_comp + component]);
387 };
388
389 loop<MemorySpace, Number>(
390 "extract_component", body, 0, /*no vectorization*/ 0, local_size);
391
392 scalar_vector.update_ghost_values();
393 }
394
412 template <typename Functor = std::identity>
413 void insert_component(const ScalarVector &scalar_vector,
414 unsigned int component,
415 const Functor &functor = std::identity{}) const
416 requires writable
417 {
418 using HostSpace = dealii::MemorySpace::Host;
419 AssertThrow((std::is_same_v<MemorySpace, HostSpace>),
420 dealii::ExcNotImplemented());
421
422 Assert(n_comp > 0,
423 dealii::ExcMessage(
424 "Cannot insert into a vector with zero components."));
425 AssertIndexRange(component, n_comp);
426
427 const auto local_size =
428 scalar_vector.get_partitioner()->locally_owned_size();
429
430 Assert(n_comp * local_size == n_locally_owned_,
431 dealii::ExcMessage("Called with a scalar_vector argument that has "
432 "incompatible local range."));
433
434 for (unsigned int i = 0; i < local_size; ++i)
435 data_[i * n_comp + component] = functor(scalar_vector.local_element(i));
436 }
437
442 template <typename Functor = std::identity>
443 void insert_component(const dealii::Vector<Number> &scalar_vector,
444 unsigned int component,
445 const Functor &functor = std::identity{}) const
446 requires writable
447 {
448 using HostSpace = dealii::MemorySpace::Host;
449 AssertThrow((std::is_same_v<MemorySpace, HostSpace>),
450 dealii::ExcInternalError());
451
452 Assert(n_comp > 0,
453 dealii::ExcMessage(
454 "Cannot insert into a vector with zero components."));
455 AssertIndexRange(component, n_comp);
456
457 const auto local_size = scalar_vector.size();
458
459 Assert(n_comp * local_size >= n_locally_owned_,
460 dealii::ExcMessage("Called with a scalar_vector argument that has "
461 "incompatible local range."));
462
463 for (unsigned int i = 0; i < local_size; ++i)
464 data_[i * n_comp + component] = functor(scalar_vector[i]);
465 }
466
468
473
484 template <typename Number2 = Number>
485 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number2
486 read_entry(const unsigned int i) const
487 {
488 static_assert(
489 n_comp == 1,
490 "Attempted to read a scalar value from a tensor-valued vector entry");
491
492 AssertIndexRange(i, n_locally_relevant_);
493
494 const auto result = read_tensor<Number2>(i);
495 return result[0];
496 }
497
508 template <typename Number2 = Number>
509 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number2
510 read_entry(const unsigned int *js) const
511 {
512 static_assert(
513 n_comp == 1,
514 "Attempted to read a scalar value from a tensor-valued vector entry");
515
516 const auto result = read_tensor<Number2>(js);
517 return result[0];
518 }
519
528 template <typename Number2 = Number,
529 typename Tensor = dealii::Tensor<1, n_comp, Number2>>
530 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Tensor
531 read_tensor(const unsigned int i) const
532 {
533 static_assert(std::is_same_v<Number2, typename Tensor::value_type>,
534 "type mismatch");
535
536 AssertIndexRange(i, n_locally_relevant_);
537
538 Tensor tensor;
539
540 /* Special case of a zero component vector */
541 if constexpr (n_comp == 0)
542 return tensor;
543
544 using VA = dealii::VectorizedArray<Number>;
545 if constexpr (std::is_same_v<VA, Number2>) {
546 /* Vectorized fast access. index must be divisible by the SIMD width */
547 std::array<unsigned int, VA::size()> indices;
548 for (unsigned int k = 0; k < VA::size(); ++k)
549 indices[k] = k * n_comp;
550
551 dealii::vectorized_load_and_transpose(
552 n_comp, data_ + i * n_comp, indices.data(), &tensor[0]);
553
554 } else {
555 /* Non-vectorized sequential access. */
556 for (unsigned int d = 0; d < n_comp; ++d)
557 tensor[d] = data_[i * n_comp + d];
558 }
559
560 return tensor;
561 }
562
571 template <typename Number2 = Number,
572 typename Tensor = dealii::Tensor<1, n_comp, Number2>>
573 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Tensor
574 read_tensor(const unsigned int *js) const
575 {
576 static_assert(std::is_same_v<Number2, typename Tensor::value_type>,
577 "type mismatch");
578
579 Tensor tensor;
580
581 /* Special case of a zero component vector */
582 if constexpr (n_comp == 0)
583 return tensor;
584
585 using VA = dealii::VectorizedArray<Number>;
586 if constexpr (std::is_same_v<VA, Number2>) {
587 /* Vectorized fast access. index must be divisible by the SIMD width */
588
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;
593 }
594
595 dealii::vectorized_load_and_transpose(
596 n_comp, data_, indices.data(), &tensor[0]);
597
598 } else {
599 /* Non-vectorized sequential access. */
600
601 AssertIndexRange(*js, n_locally_relevant_);
602
603 for (unsigned int d = 0; d < n_comp; ++d)
604 tensor[d] = data_[js[0] * n_comp + d];
605 }
606
607 return tensor;
608 }
609
621 template <typename Number2 = Number>
622 DEAL_II_HOST_DEVICE_ALWAYS_INLINE void
623 write_entry(const Number2 &entry, const unsigned int i) const
624 requires writable
625 {
626 static_assert(n_comp == 1,
627 "Attempted to write a scalar value into a tensor-valued "
628 "vector entry");
629
630 AssertIndexRange(i, n_locally_relevant_);
631
632 dealii::Tensor<1, n_comp, Number2> tensor;
633 tensor[0] = entry;
634
635 write_tensor<Number2>(tensor, i);
636 }
637
652 template <typename Number2 = Number,
653 typename Tensor = dealii::Tensor<1, n_comp, Number2>>
654 DEAL_II_HOST_DEVICE_ALWAYS_INLINE void
655 write_tensor(const Tensor &tensor, const unsigned int i) const
656 requires writable
657 {
658 store</*add*/ false, Number2>(tensor, i);
659 }
660
675 template <typename Number2 = Number>
676 DEAL_II_HOST_DEVICE_ALWAYS_INLINE void add_entry(const Number2 &entry,
677 const unsigned int i) const
678 requires writable
679 {
680 static_assert(n_comp == 1,
681 "Attempted to write a scalar value into a tensor-valued "
682 "matrix entry");
683
684 AssertIndexRange(i, n_locally_relevant_);
685
686 dealii::Tensor<1, n_comp, Number2> tensor;
687 tensor[0] = entry;
688
689 add_tensor<Number2>(tensor, i);
690 }
691
706 template <typename Number2 = Number,
707 typename Tensor = dealii::Tensor<1, n_comp, Number2>>
708 DEAL_II_HOST_DEVICE_ALWAYS_INLINE void
709 add_tensor(const Tensor &tensor, const unsigned int i) const
710 requires writable
711 {
712 store</*add*/ true, Number2>(tensor, i);
713 }
714
716
720
725 requires(writable)
726 {
727 Assert(multi_component_vector_->template is_resident<MemorySpace>(),
728 dealii::ExcMessage("The chosen memory space is not resident."));
729
730 multi_component_vector_->template storage<MemorySpace>()
731 .zero_out_ghost_values();
732 }
733
739 requires(writable)
740 {
741 Assert(multi_component_vector_->template is_resident<MemorySpace>(),
742 dealii::ExcMessage("The chosen memory space is not resident."));
743
744 multi_component_vector_->template storage<MemorySpace>()
745 .update_ghost_values();
746 }
747
753 void compress(dealii::VectorOperation::values operation) const
754 requires(writable)
755 {
756 Assert(multi_component_vector_->template is_resident<MemorySpace>(),
757 dealii::ExcMessage("The chosen memory space is not resident."));
758
759 multi_component_vector_->template storage<MemorySpace>().compress(
760 operation);
761 }
762
763 private:
765
769
771 std::conditional_t<writable, MCV *, const MCV *> multi_component_vector_;
772
773 Number *data_;
774 unsigned int n_locally_owned_;
775 unsigned int n_locally_relevant_;
776
777 template <typename, int, typename, bool>
779
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
783 {
784 static_assert(std::is_same_v<Number2, typename Tensor::value_type>,
785 "type mismatch");
786
787 AssertIndexRange(i, n_locally_relevant_);
788
789 /* Special case of a zero component vector */
790 if constexpr (n_comp == 0)
791 return;
792
793 using VA = dealii::VectorizedArray<Number>;
794 if constexpr (std::is_same_v<VA, Number2>) {
795 /* Vectorized fast access. index must be divisible by the SIMD width */
796
797 std::array<unsigned int, VA::size()> indices;
798 for (unsigned int k = 0; k < VA::size(); ++k)
799 indices[k] = k * n_comp;
800
801 dealii::vectorized_transpose_and_store(
802 add, n_comp, &tensor[0], indices.data(), data_ + i * n_comp);
803
804 } else {
805 /* Non-vectorized sequential access. */
806
807 for (unsigned int d = 0; d < n_comp; ++d) {
808 if constexpr (add)
809 data_[i * n_comp + d] += tensor[d];
810 else
811 data_[i * n_comp + d] = tensor[d];
812 }
813 }
814 }
815
817 };
818
819
820#ifndef DOXYGEN
821 /*
822 * -------------------------------------------------------------------------
823 * Inline function definitions
824 * -------------------------------------------------------------------------
825 */
826
827
828 template <typename Number>
830 const MultiComponentVector &other)
831 {
832 *this = other;
833 }
834
835
836 template <typename Number>
838 MultiComponentVector &&other) noexcept
839 {
840 *this = std::move(other);
841 }
842
843
844 template <typename Number>
846 const std::shared_ptr<const dealii::Utilities::MPI::Partitioner>
847 &vector_partitioner,
848 const unsigned int n_comp,
850 {
851 n_comp_ = n_comp;
852
853 /*
854 * Drop the transfer policy for the duration of the reinit so that a
855 * pinned memory space of a previous policy does not interfere:
856 */
858
859 /* Special case of a zero component vector */
860 if (n_comp == 0) {
861 /* Drop possibly stale storage from a previous reinit: */
862 host_vector_.reinit(0);
863 if constexpr (have_separate_memory_spaces)
864 default_vector_.reinit(0);
865
866 /* A zero component vector is trivially resident everywhere: */
867 this->reset_residency(/*host*/ true, /*default*/ true);
868 this->set_transfer_policy(transfer_policy);
869 return;
870 }
871
872 host_vector_.reinit(vector_partitioner);
873
874 /*
875 * The vector is resident on the host memory space only. Device
876 * storage is allocated lazily on the first copy_to_memory_space() /
877 * move_to_memory_space(); drop possibly stale device storage from a
878 * previous reinit:
879 */
880 if constexpr (have_separate_memory_spaces)
881 default_vector_.reinit(0);
882
883 /*
884 * If both memory spaces coincide the single host allocation is
885 * trivially resident on both of them:
886 */
887 this->reset_residency(/*host*/ true,
888 /*default*/ !have_separate_memory_spaces);
889
890 this->set_transfer_policy(transfer_policy);
891 }
892
893
894 template <typename Number>
896 const std::shared_ptr<const dealii::Utilities::MPI::Partitioner>
897 &scalar_partitioner,
898 const unsigned int n_comp,
900 {
901 /*
902 * A scalar vector (and a zero component vector) uses the scalar
903 * partitioner directly:
904 */
905 const auto vector_partitioner =
906 n_comp <= 1 ? scalar_partitioner
907 : create_vector_partitioner(scalar_partitioner, n_comp);
908
909 reinit_with_vector_partitioner(vector_partitioner, n_comp, transfer_policy);
910 }
911
912
913 template <typename Number>
914 auto
917 {
918 /* Copy residency state and transfer policy: */
919 static_cast<MirroredStorage<MultiComponentVector> &>(*this) = other;
920 n_comp_ = other.n_comp_;
921
922 host_vector_ = other.host_vector_;
923 if constexpr (have_separate_memory_spaces)
924 default_vector_ = other.default_vector_;
925
926 return *this;
927 }
928
929
930 template <typename Number>
931 auto
934 {
935 /* Copy residency state and transfer policy: */
936 static_cast<MirroredStorage<MultiComponentVector> &>(*this) = other;
937 n_comp_ = other.n_comp_;
938
939 host_vector_ = std::move(other.host_vector_);
940 if constexpr (have_separate_memory_spaces)
941 default_vector_ = std::move(other.default_vector_);
942
943 return *this;
944 }
945
946
947 template <typename Number>
948 template <int n_comp, typename MemorySpace>
949 MultiComponentVectorView<Number, n_comp, MemorySpace, true>
951 {
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 "
955 "vector."));
956
957 this->template prepare_write_access<MemorySpace>();
958
959 return MultiComponentVectorView<Number, n_comp, MemorySpace, true>(*this);
960 }
961
962
963 template <typename Number>
964 template <int n_comp, typename MemorySpace>
965 MultiComponentVectorView<Number, n_comp, MemorySpace, false>
967 {
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 "
971 "vector."));
972
973 this->template prepare_read_access<MemorySpace>();
974
975 return MultiComponentVectorView<Number, n_comp, MemorySpace, false>(*this);
976 }
977
978
979 template <typename Number>
980 template <typename MemorySpace>
982 {
983 this->template prepare_write_access<MemorySpace>();
984 return storage<MemorySpace>();
985 }
986
987
988 template <typename Number>
989 template <typename MemorySpace>
991 {
992 this->template prepare_read_access<MemorySpace>();
993 return storage<MemorySpace>();
994 }
995
996
997 template <typename Number>
998 template <typename MemorySpace>
999 auto &MultiComponentVector<Number>::storage() const
1000 {
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");
1006
1007 if constexpr (have_separate_memory_spaces &&
1008 !std::is_same_v<MemorySpace, HostSpace>)
1009 return default_vector_;
1010 else
1011 return host_vector_;
1012 }
1013
1014
1015 template <typename Number>
1016 template <typename MemorySpace>
1017 void MultiComponentVector<Number>::allocate_storage() const
1018 {
1019 using HostSpace = dealii::MemorySpace::Host;
1020
1021 /*
1022 * The partitioner is recovered from the other (still resident)
1023 * vector:
1024 */
1025
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());
1029 } else {
1030 Assert(host_vector_.size() != 0, dealii::ExcNotInitialized());
1031 default_vector_.reinit(host_vector_.get_partitioner());
1032 }
1033 }
1034
1035
1036 template <typename Number>
1037 template <typename To, typename From>
1038 void MultiComponentVector<Number>::deep_copy_storage() const
1039 {
1040 using HostSpace = dealii::MemorySpace::Host;
1041
1042 if constexpr (std::is_same_v<To, HostSpace>) {
1043 host_vector_.import_elements(default_vector_,
1044 dealii::VectorOperation::insert);
1045 } else {
1046 default_vector_.import_elements(host_vector_,
1047 dealii::VectorOperation::insert);
1048 }
1049 }
1050
1051
1052 template <typename Number>
1053 template <typename MemorySpace>
1054 void MultiComponentVector<Number>::deallocate_storage()
1055 {
1056 using HostSpace = dealii::MemorySpace::Host;
1057
1058 if constexpr (std::is_same_v<MemorySpace, HostSpace>) {
1059 host_vector_.reinit(0);
1060
1061 } else {
1062 default_vector_.reinit(0);
1063 }
1064 }
1065
1066#endif
1067} // namespace ryujin
void set_transfer_policy(const TransferPolicy transfer_policy)
void reset_residency(const bool host_resident, const bool default_resident)
void compress(dealii::VectorOperation::values operation) const
MultiComponentVectorView(MultiComponentVector< Number > &multi_component_vector)
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)
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
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(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)
TransferPolicy
Definition gpu.h:88
constexpr bool have_separate_memory_spaces
Definition gpu.h:29
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)