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