https://mooseframework.inl.gov
Loading...
Searching...
No Matches
KokkosArray.h
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://mooseframework.inl.gov
3//*
4//* All rights reserved, see COPYRIGHT for full restrictions
5//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6//*
7//* Licensed under LGPL 2.1, please see LICENSE for details
8//* https://www.gnu.org/licenses/lgpl-2.1.html
9
10#pragma once
11
12#ifdef MOOSE_KOKKOS_SCOPE
13#include "KokkosHeader.h"
14#endif
15
16#include "Conversion.h"
17#include "DataIO.h"
18
19#include <iterator>
20
21#define usingKokkosArrayBaseMembers(T, dimension, index_type) \
22private: \
23 using ArrayBase<T, dimension, index_type>::_n; \
24 using ArrayBase<T, dimension, index_type>::_s; \
25 using ArrayBase<T, dimension, index_type>::_d; \
26 \
27public: \
28 using typename ArrayBase<T, dimension, index_type>::signed_index_type; \
29 using ArrayBase<T, dimension, index_type>::operator=
30
31namespace Moose::Kokkos
32{
33
34// This function simply calls ::Kokkos::kokkos_free, but it is separately defined in KokkosArray.K
35// because the Kokkos function cannot be directly seen by the host compiler
36void free(void * ptr);
37
48
52enum class LayoutType
53{
54 LEFT,
55 RIGHT
56};
57
61template <typename T,
62 unsigned int dimension = 1,
63 typename index_type = MOOSE_KOKKOS_INDEX_TYPE,
65class Array;
66
71template <typename>
72struct is_kokkos_array : std::false_type
73{
74};
75
76template <typename T, unsigned int dimension, typename index_type, LayoutType layout>
77struct is_kokkos_array<Array<T, dimension, index_type, layout>> : std::true_type
78{
79};
81
90template <typename T>
92{
93 static constexpr bool value = false;
94};
95
96template <typename T, unsigned int dimension, typename index_type, LayoutType layout>
97struct ArrayDeepCopy<Array<T, dimension, index_type, layout>>
98{
99 static constexpr bool value = ArrayDeepCopy<T>::value;
100};
102
106template <typename T, unsigned int dimension, typename index_type>
108{
109 static_assert(std::is_integral_v<index_type>, "Kokkos array index type must be an integral type");
110 static_assert(std::is_unsigned_v<index_type>, "Kokkos array index type must be unsigned");
111 static_assert(!std::is_same_v<bool, index_type>, "Kokkos array index type must not be bool");
112
113public:
114 using unsigned_index_type = index_type;
115 using signed_index_type = typename std::make_signed<index_type>::type;
116
121 ArrayBase(const LayoutType layout) : _layout(layout) {}
122
123#ifdef MOOSE_KOKKOS_SCOPE
131 template <typename... size_type>
132 ArrayBase(const LayoutType layout, size_type... n) : _layout(layout)
133 {
134 create(n...);
135 }
136#endif
137
142 {
143#ifndef MOOSE_KOKKOS_SCOPE
144 static_assert(!ArrayDeepCopy<T>::value,
145 "Kokkos array cannot be deep copied outside the Kokkos compilation scope");
146#endif
147
148 if constexpr (ArrayDeepCopy<T>::value)
149 deepCopy(array);
150 else
151 shallowCopy(array);
152 }
153
158
162 void destroy();
163
169
174 unsigned int useCount() const { return _counter.use_count(); }
175
187 bool isSlotConstructed(index_type i) const;
188
189 template <bool is_const>
190 class constructed_entry_range;
191
195 template <bool is_const>
197 {
198 public:
199 using iterator_category = std::forward_iterator_tag;
200 using value_type = T;
201 using difference_type = std::ptrdiff_t;
202 using pointer = std::conditional_t<is_const, const T *, T *>;
203 using reference = std::conditional_t<is_const, const T &, T &>;
204 using array_type = std::conditional_t<is_const, const ArrayBase, ArrayBase>;
205
206 reference operator*() const { return _array._host_data[_i]; }
207 pointer operator->() const { return _array._host_data + _i; }
208 constructed_entry_iterator & operator++();
209 constructed_entry_iterator operator++(int);
210 bool operator==(const constructed_entry_iterator & other) const;
211 bool operator!=(const constructed_entry_iterator & other) const;
212
213 private:
214 friend class constructed_entry_range<is_const>;
215
216 constructed_entry_iterator(array_type & array, index_type i);
217
219
227 index_type _i = 0;
228 };
229
233 template <bool is_const>
235 {
236 public:
237 using array_type = std::conditional_t<is_const, const ArrayBase, ArrayBase>;
239
240 explicit constructed_entry_range(array_type & array);
241
243 iterator end() const;
244
245 private:
250 };
251
256 constructed_entry_range<false> constructedEntries();
257
262 constructed_entry_range<true> constructedEntries() const;
263
264#ifdef MOOSE_KOKKOS_SCOPE
269 KOKKOS_FUNCTION bool isAlloc() const { return _is_host_alloc || _is_device_alloc; }
274 KOKKOS_FUNCTION bool isHostAlloc() const { return _is_host_alloc; }
279 KOKKOS_FUNCTION bool isDeviceAlloc() const { return _is_device_alloc; }
284 KOKKOS_FUNCTION bool isHostAlias() const { return _is_host_alias; }
289 KOKKOS_FUNCTION bool isDeviceAlias() const { return _is_device_alias; }
294 KOKKOS_FUNCTION index_type size() const { return _size; }
300 KOKKOS_FUNCTION index_type n(unsigned int dim) const { return _n[dim]; }
306 KOKKOS_FUNCTION T * data() const
307 {
308 KOKKOS_IF_ON_HOST(return _host_data;)
309
310 return _device_data;
311 }
317 KOKKOS_FUNCTION T & first() const
318 {
319 KOKKOS_ASSERT(_size);
320
321 KOKKOS_IF_ON_HOST(return _host_data[0];)
322
323 return _device_data[0];
324 }
330 KOKKOS_FUNCTION T & last() const
331 {
332 KOKKOS_ASSERT(_size);
333
334 KOKKOS_IF_ON_HOST(return _host_data[_size - 1];)
335
336 return _device_data[_size - 1];
337 }
344 KOKKOS_FUNCTION T & operator[](index_type i) const
345 {
346 KOKKOS_ASSERT(i < _size);
347
348 KOKKOS_IF_ON_HOST(return _host_data[i];)
349
350 return _device_data[i];
351 }
352
357 T * hostData() const { return _host_data; }
362 T * deviceData() const { return _device_data; }
367 auto hostView() const
368 {
369 return ::Kokkos::View<T *, ::Kokkos::HostSpace, ::Kokkos::MemoryTraits<::Kokkos::Unmanaged>>(
371 }
376 auto deviceView() const
377 {
378 return ::Kokkos::View<T *, MemSpace, ::Kokkos::MemoryTraits<::Kokkos::Unmanaged>>(_device_data,
379 _size);
380 }
385 template <typename... size_type>
386 void init(size_type... n)
387 {
388 createInternal<false, false, false>(n...);
389 }
395 template <bool initialize = true>
396 void create(const std::vector<index_type> & n)
397 {
398 createInternal<true, true, initialize>(n);
399 }
405 template <bool initialize = true, typename... size_type>
406 void create(size_type... n)
407 {
408 createInternal<true, true, initialize>(n...);
409 }
415 template <bool initialize = true>
416 void createHost(const std::vector<index_type> & n)
417 {
418 createInternal<true, false, initialize>(n);
419 }
425 template <bool initialize = true, typename... size_type>
426 void createHost(size_type... n)
427 {
428 createInternal<true, false, initialize>(n...);
429 }
434 void createDevice(const std::vector<index_type> & n) { createInternal<false, true, false>(n); }
439 template <typename... size_type>
440 void createDevice(size_type... n)
441 {
442 createInternal<false, true, false>(n...);
443 }
448 void aliasHost(T * ptr);
453 void aliasDevice(T * ptr);
458 void offset(const std::vector<signed_index_type> & d);
463 template <typename... offset_type>
464 void offset(offset_type... d);
480 void copyIn(const T * ptr, MemcpyType dir, index_type n, index_type offset = 0);
488 void copyOut(T * ptr, MemcpyType dir, index_type n, index_type offset = 0);
499 void moveToDevice(bool should_free_host = true);
506 void moveToHost(bool should_free_device = true);
519
524 auto & operator=(const T & scalar);
525
530 {
531 public:
532 using iterator_category = std::forward_iterator_tag;
533 using value_type = T;
534 using difference_type = std::ptrdiff_t;
535 using pointer = T *;
536 using reference = T &;
537
538 KOKKOS_FUNCTION iterator() : it(nullptr) {}
539 KOKKOS_FUNCTION explicit iterator(T * p) : it(p) {}
540
541 KOKKOS_FUNCTION reference operator*() const { return *it; }
542 KOKKOS_FUNCTION pointer operator->() const { return it; }
543 KOKKOS_FUNCTION pointer operator&() const { return it; }
544 KOKKOS_FUNCTION iterator & operator++()
545 {
546 ++it;
547 return *this;
548 }
549 KOKKOS_FUNCTION iterator operator++(int)
550 {
551 iterator pre = *this;
552 ++it;
553 return pre;
554 }
555 KOKKOS_FUNCTION friend bool operator==(const iterator & a, const iterator & b)
556 {
557 return a.it == b.it;
558 }
559 KOKKOS_FUNCTION friend bool operator!=(const iterator & a, const iterator & b)
560 {
561 return a.it != b.it;
562 }
563
564 private:
566 };
567
572 KOKKOS_FUNCTION iterator begin() const
573 {
574 KOKKOS_IF_ON_HOST(return iterator(_host_data);)
575
576 return iterator(_device_data);
577 }
582 KOKKOS_FUNCTION iterator end() const
583 {
584 KOKKOS_IF_ON_HOST(return iterator(_host_data + _size);)
585
586 return iterator(_device_data + _size);
587 }
588#endif
589
590protected:
594 index_type _n[dimension] = {0};
598 index_type _s[dimension] = {0};
602 signed_index_type _d[dimension] = {0};
603
604#ifdef MOOSE_KOKKOS_SCOPE
612 template <bool host, bool device, bool initialize, typename... size_type>
613 void createInternal(size_type... n);
621 template <bool host, bool device, bool initialize>
622 void createInternal(const std::vector<index_type> & n);
630 template <bool initialize>
631 void createInternal(const std::vector<index_type> & n, bool host, bool device);
640 template <typename TargetSpace, typename SourceSpace>
641 void copyInternal(T * target, const T * source, index_type n);
648 template <typename... Args>
649 T & emplaceAt(index_type i, Args &&... args);
650#endif
651
652private:
653#ifdef MOOSE_KOKKOS_SCOPE
658 template <bool initialize>
659 void allocHost();
664#endif
668 void freeHost();
673
677 std::shared_ptr<unsigned int> _counter;
681 std::shared_ptr<std::vector<bool>> _slots_constructed;
685 bool _is_init = false;
689 bool _is_host_alloc = false;
693 bool _is_device_alloc = false;
697 bool _is_host_alias = false;
701 bool _is_device_alias = false;
705 T * _host_data = nullptr;
709 T * _device_data = nullptr;
713 index_type _size = 0;
718};
719
720template <typename T, unsigned int dimension, typename index_type>
721template <bool is_const>
731
732template <typename T, unsigned int dimension, typename index_type>
733template <bool is_const>
736{
737 ++_i;
738 advanceToConstructed();
739 return *this;
740}
741
742template <typename T, unsigned int dimension, typename index_type>
743template <bool is_const>
751
752template <typename T, unsigned int dimension, typename index_type>
753template <bool is_const>
754bool
756 const constructed_entry_iterator & other) const
757{
758 return &_array == &other._array && _i == other._i;
759}
760
761template <typename T, unsigned int dimension, typename index_type>
762template <bool is_const>
763bool
769
770template <typename T, unsigned int dimension, typename index_type>
771template <bool is_const>
772void
774{
775 while (_i < _array._size && !_array.isSlotConstructed(_i))
776 ++_i;
777}
778
779template <typename T, unsigned int dimension, typename index_type>
780template <bool is_const>
787
788template <typename T, unsigned int dimension, typename index_type>
789template <bool is_const>
795
796template <typename T, unsigned int dimension, typename index_type>
797template <bool is_const>
803
804template <typename T, unsigned int dimension, typename index_type>
810
811template <typename T, unsigned int dimension, typename index_type>
812typename ArrayBase<T, dimension, index_type>::template constructed_entry_range<true>
817
818template <typename T, unsigned int dimension, typename index_type>
819bool
821{
822 mooseAssert(i < _size, "isSlotConstructed index out of bounds");
823
825 return _is_host_alloc;
826
827 return (*_slots_constructed)[i];
828}
829
830#ifdef MOOSE_KOKKOS_SCOPE
831template <typename T, unsigned int dimension, typename index_type>
832template <typename... Args>
833T &
835{
836 mooseAssert(_is_host_alloc && _slots_constructed,
837 "emplaceAt requires a malloc-allocated array (create<false>)");
838 mooseAssert(i < _size, "emplaceAt index out of bounds");
839
840 new (_host_data + i) T(std::forward<Args>(args)...);
841 (*_slots_constructed)[i] = true;
842
843 return _host_data[i];
844}
845#endif // MOOSE_KOKKOS_SCOPE
846
847template <typename T, unsigned int dimension, typename index_type>
848void
850{
851 if (!_is_host_alloc)
852 return;
853
854 if (_is_host_alias)
855 {
856 _host_data = nullptr;
857 _is_host_alias = false;
858 }
859 else
860 {
862 // Allocated by new
863 delete[] _host_data;
864 else
865 {
866 // Allocated by malloc
867 for (const auto i : make_range(_size))
868 if (isSlotConstructed(i))
869 _host_data[i].~T();
870
871 std::free(_host_data);
872
873 _slots_constructed.reset();
874 }
875 }
876
877 _is_host_alloc = false;
878}
879
880template <typename T, unsigned int dimension, typename index_type>
881void
883{
884 if (!_is_device_alloc)
885 return;
886
888 {
889 _device_data = nullptr;
890 _is_device_alias = false;
891 }
892 else
894
895 _is_device_alloc = false;
896}
897
898template <typename T, unsigned int dimension, typename index_type>
899void
901{
902 if (!_counter)
903 return;
904
905 if (_counter.use_count() > 1)
906 {
907 _host_data = nullptr;
908 _device_data = nullptr;
909 }
910 else if (_counter.use_count() == 1)
911 {
912 freeHost();
913 freeDevice();
914 }
915
916 _size = 0;
917
918 for (const auto i : make_range(dimension))
919 {
920 _n[i] = 0;
921 _s[i] = 0;
922 _d[i] = 0;
923 }
924
925 _is_init = false;
926 _is_host_alloc = false;
927 _is_device_alloc = false;
928 _is_host_alias = false;
929 _is_device_alias = false;
930
931 _counter.reset();
932 _slots_constructed.reset();
933}
934
935template <typename T, unsigned int dimension, typename index_type>
936void
938{
939 if (_layout != array._layout)
940 mooseError("Kokkos array error: cannot shallow copy arrays with different layouts.");
941
942 destroy();
943
944 _counter = array._counter;
946
947 _size = array._size;
948
949 for (const auto i : make_range(dimension))
950 {
951 _n[i] = array._n[i];
952 _s[i] = array._s[i];
953 _d[i] = array._d[i];
954 }
955
956 _is_init = array._is_init;
961
962 _host_data = array._host_data;
964}
965
966#ifdef MOOSE_KOKKOS_SCOPE
967template <typename T, unsigned int dimension, typename index_type>
968void
970{
971 if (!_is_init)
972 mooseError("Kokkos array error: attempted to alias host data before array initialization.");
973
975 mooseError("Kokkos array error: cannot alias host data because host data was not aliased.");
976
977 _host_data = ptr;
978 _is_host_alloc = true;
979 _is_host_alias = true;
980}
981
982template <typename T, unsigned int dimension, typename index_type>
983void
985{
986 if (!_is_init)
987 mooseError("Kokkos array error: attempted to alias device data before array initialization.");
988
990 mooseError("Kokkos array error: cannot alias device data because device data was not aliased.");
991
992 _device_data = ptr;
993 _is_device_alloc = true;
994 _is_device_alias = true;
995}
996
997template <typename T, unsigned int dimension, typename index_type>
998template <bool initialize>
999void
1001{
1002 if (_is_host_alloc)
1003 return;
1004
1005 if constexpr (initialize)
1006 {
1007 static_assert(
1008 std::is_default_constructible<T>::value,
1009 "Data type is not default-constructible. Initialization argument should be set to false.");
1010
1011 _host_data = new T[_size];
1012 }
1013 else
1014 {
1015 _host_data = static_cast<T *>(std::malloc(_size * sizeof(T)));
1016 _slots_constructed = std::make_shared<std::vector<bool>>(_size, false);
1017 }
1018
1019 _is_host_alloc = true;
1020}
1021
1022template <typename T, unsigned int dimension, typename index_type>
1023void
1025{
1026 if (_is_device_alloc)
1027 return;
1028
1029 _device_data =
1030 static_cast<T *>(::Kokkos::kokkos_malloc<ExecSpace::memory_space>(_size * sizeof(T)));
1031
1032 _is_device_alloc = true;
1033}
1034
1035template <typename T, unsigned int dimension, typename index_type>
1036template <bool host, bool device, bool initialize>
1037void
1039{
1040 if (n.size() != dimension)
1041 mooseError("Kokkos array error: the number of dimensions provided (",
1042 n.size(),
1043 ") must match the array dimension (",
1044 dimension,
1045 ").");
1046
1047 if (_counter)
1048 destroy();
1049
1050 _counter = std::make_shared<unsigned int>();
1051
1052 uint64_t overflow_checker = 1;
1053
1054 _size = 1;
1055 _s[0] = 1;
1056
1057 for (const auto i : make_range(dimension))
1058 {
1059 overflow_checker *= n[i];
1060
1061 _n[i] = n[i];
1062 _size *= n[i];
1063 }
1064
1065 if (overflow_checker > std::numeric_limits<index_type>::max())
1066 mooseError("Kokkos array error: the dimensions provided (",
1068 ") has the total size of ",
1069 overflow_checker,
1070 " which exceeds the limit of ",
1071 MooseUtils::prettyCppType<index_type>(),
1072 ".");
1073
1075 {
1076 _s[0] = 1;
1077
1078 for (const auto i : make_range(1u, dimension))
1079 _s[i] = _s[i - 1] * _n[i - 1];
1080 }
1081 else
1082 {
1083 _s[dimension - 1] = 1;
1084
1085 for (int i = dimension - 2; i >= 0; --i)
1086 _s[i] = _s[i + 1] * _n[i + 1];
1087 }
1088
1089 if constexpr (host)
1090 allocHost<initialize>();
1091
1092 if constexpr (device)
1093 allocDevice();
1094
1095 _is_init = true;
1096}
1097
1098template <typename T, unsigned int dimension, typename index_type>
1099template <bool initialize>
1100void
1102 bool host,
1103 bool device)
1104{
1105 if (host && device)
1106 createInternal<true, true, initialize>(n);
1107 else if (host && !device)
1108 createInternal<true, false, initialize>(n);
1109 else if (!host && device)
1110 createInternal<false, true, initialize>(n);
1111 else
1112 createInternal<false, false, initialize>(n);
1113}
1114
1115template <typename T, unsigned int dimension, typename index_type>
1116template <bool host, bool device, bool initialize, typename... size_type>
1117void
1119{
1120 static_assert((std::is_convertible<size_type, index_type>::value && ...),
1121 "All arguments must be convertible to index_type");
1122 static_assert(sizeof...(n) == dimension, "Number of arguments should match array dimension");
1123
1124 std::vector<index_type> dims;
1125 (dims.push_back(n), ...);
1126
1127 createInternal<host, device, initialize>(dims);
1128}
1129
1130template <typename T, unsigned int dimension, typename index_type>
1131template <typename TargetSpace, typename SourceSpace>
1132void
1133ArrayBase<T, dimension, index_type>::copyInternal(T * target, const T * source, index_type n)
1134{
1135 ::Kokkos::Impl::DeepCopy<TargetSpace, SourceSpace>(target, source, n * sizeof(T));
1136 ::Kokkos::fence();
1137}
1138
1139template <typename T, unsigned int dimension, typename index_type>
1140void
1141ArrayBase<T, dimension, index_type>::offset(const std::vector<signed_index_type> & d)
1142{
1143 if (d.size() > dimension)
1144 mooseError("Kokkos array error: the number of offsets provided (",
1145 d.size(),
1146 ") cannot be larger than the array dimension (",
1147 dimension,
1148 ").");
1149
1150 for (const auto i : index_range(d))
1151 _d[i] = d[i];
1152}
1153
1154template <typename T, unsigned int dimension, typename index_type>
1155template <typename... offset_type>
1156void
1158{
1159 static_assert((std::is_convertible<offset_type, signed_index_type>::value && ...),
1160 "All arguments must be convertible to signed_index_type");
1161 static_assert(sizeof...(d) == dimension, "Number of arguments should match array dimension");
1162
1163 std::vector<signed_index_type> offsets;
1164 (offsets.push_back(d), ...);
1165
1166 offset(offsets);
1167}
1168
1169template <typename T, unsigned int dimension, typename index_type>
1170void
1172{
1173 // If host side memory is not allocated, do nothing
1174 if (!_is_host_alloc)
1175 return;
1176
1177 // If device side memory is not allocated,
1178 if (!_is_device_alloc)
1179 {
1180 if (_counter.use_count() == 1)
1181 // allocate memory if this array is not shared with other arrays
1182 allocDevice();
1183 else
1184 // print error if this array is shared with other arrays
1185 mooseError("Kokkos array error: cannot copy from host to device because device memory "
1186 "was not allocated. Cannot allocate device memory for copy because the array is "
1187 "being shared.");
1188 }
1189
1190 // Copy from host to device
1191 copyInternal<MemSpace, ::Kokkos::HostSpace>(_device_data, _host_data, _size);
1192}
1193
1194template <typename T, unsigned int dimension, typename index_type>
1195void
1197{
1198 // If device side memory is not allocated, do nothing
1199 if (!_is_device_alloc)
1200 return;
1201
1202 // If host side memory is not allocated,
1203 if (!_is_host_alloc)
1204 {
1205 if (_counter.use_count() == 1)
1206 // allocate memory if this array is not shared with other arrays
1207 allocHost<false>();
1208 else
1209 // print error if this array is shared with other arrays
1210 mooseError("Kokkos array error: cannot copy from device to host because host memory "
1211 "was not allocated. Cannot allocate host memory for copy because the array is "
1212 "being shared.");
1213 }
1214
1215 // Copy from device to host
1216 copyInternal<::Kokkos::HostSpace, MemSpace>(_host_data, _device_data, _size);
1217}
1218
1219template <typename T, unsigned int dimension, typename index_type>
1220void
1222{
1223 static_assert(!is_kokkos_array<T>::value,
1224 "moveToDevice() not allowed for a nested array whose data type is another array.");
1225
1226 if (should_free_host && _counter.use_count() > 1)
1227 mooseError("Kokkos array error: cannot move array from host to device because there is at "
1228 "least one shallow copy of this array still alive.");
1229
1230 copyToDevice();
1231
1232 if (_counter.use_count() == 1)
1233 freeHost();
1234}
1235
1236template <typename T, unsigned int dimension, typename index_type>
1237void
1239{
1240 if (should_free_device && _counter.use_count() > 1)
1241 mooseError("Kokkos array error: cannot move array from device to host because there is at "
1242 "least one shallow copy of this array still alive.");
1243
1244 copyToHost();
1245
1246 if (_counter.use_count() == 1)
1247 freeDevice();
1248}
1249
1250template <typename T, unsigned int dimension, typename index_type>
1251void
1253 MemcpyType dir,
1254 index_type n,
1255 index_type offset)
1256{
1257 if (n > _size)
1258 mooseError("Kokkos array error: cannot copy in data larger than the array size.");
1259
1260 if (offset > _size)
1261 mooseError("Kokkos array error: offset cannot be larger than the array size.");
1262
1263 if (dir == MemcpyType::HOST_TO_HOST)
1264 {
1265 // If host side memory is not allocated, print error
1266 if (!_is_host_alloc)
1267 mooseError(
1268 "Kokkos array error: cannot copy in to the array because host memory was not allocated.");
1269
1270 // Copy from host to host
1271 copyInternal<::Kokkos::HostSpace, ::Kokkos::HostSpace>(_host_data + offset, ptr, n);
1272 }
1273 else if (dir == MemcpyType::HOST_TO_DEVICE)
1274 {
1275 // If device side memory is not allocated, print error
1276 if (!_is_device_alloc)
1277 mooseError("Kokkos array error: cannot copy in to the array because device memory was not "
1278 "allocated.");
1279
1280 // Copy from host to device
1281 copyInternal<MemSpace, ::Kokkos::HostSpace>(_device_data + offset, ptr, n);
1282 }
1283 else if (dir == MemcpyType::DEVICE_TO_HOST)
1284 {
1285 // If host side memory is not allocated, print error
1286 if (!_is_host_alloc)
1287 mooseError(
1288 "Kokkos array error: cannot copy in to the array because host memory was not allocated.");
1289
1290 // Copy from device to host
1291 copyInternal<::Kokkos::HostSpace, MemSpace>(_host_data + offset, ptr, n);
1292 }
1293 else if (dir == MemcpyType::DEVICE_TO_DEVICE)
1294 {
1295 // If device side memory is not allocated, print error
1296 if (!_is_device_alloc)
1297 mooseError("Kokkos array error: cannot copy in to the array because device memory was not "
1298 "allocated.");
1299
1300 // Copy from device to device
1301 copyInternal<MemSpace, MemSpace>(_device_data + offset, ptr, n);
1302 }
1303}
1304
1305template <typename T, unsigned int dimension, typename index_type>
1306void
1308 MemcpyType dir,
1309 index_type n,
1310 index_type offset)
1311{
1312 if (n > _size)
1313 mooseError("Kokkos array error: cannot copy out data larger than the array size.");
1314
1315 if (offset > _size)
1316 mooseError("Kokkos array error: offset cannot be larger than the array size.");
1317
1318 if (dir == MemcpyType::HOST_TO_HOST)
1319 {
1320 // If host side memory is not allocated, print error
1321 if (!_is_host_alloc)
1322 mooseError("Kokkos array error: cannot copy out from the array because host memory was not "
1323 "allocated.");
1324
1325 // Copy from host to host
1326 copyInternal<::Kokkos::HostSpace, ::Kokkos::HostSpace>(ptr, _host_data + offset, n);
1327 }
1328 else if (dir == MemcpyType::HOST_TO_DEVICE)
1329 {
1330 // If host side memory is not allocated, print error
1331 if (!_is_host_alloc)
1332 mooseError("Kokkos array error: cannot copy out from the array because host memory was not "
1333 "allocated.");
1334
1335 // Copy from host to device
1336 copyInternal<MemSpace, ::Kokkos::HostSpace>(ptr, _host_data + offset, n);
1337 }
1338 else if (dir == MemcpyType::DEVICE_TO_HOST)
1339 {
1340 // If device side memory is not allocated, print error
1341 if (!_is_device_alloc)
1342 mooseError("Kokkos array error: cannot copy out from the array because device memory was not "
1343 "allocated.");
1344
1345 // Copy from device to host
1346 copyInternal<::Kokkos::HostSpace, MemSpace>(ptr, _device_data + offset, n);
1347 }
1348 else if (dir == MemcpyType::DEVICE_TO_DEVICE)
1349 {
1350 // If device side memory is not allocated, print error
1351 if (!_is_device_alloc)
1352 mooseError("Kokkos array error: cannot copy out from the array because device memory was not "
1353 "allocated.");
1354
1355 // Copy from device to device
1356 copyInternal<MemSpace, MemSpace>(ptr, _device_data + offset, n);
1357 }
1358}
1359
1360template <typename T>
1361void
1362copyToDeviceInner(T & /* data */)
1363{
1364}
1365
1366template <typename T, unsigned int dimension, typename index_type, LayoutType layout>
1367void
1369{
1370 data.copyToDeviceNested();
1371}
1372
1373template <typename T, unsigned int dimension, typename index_type>
1374void
1376{
1377 for (const auto i : make_range(_size))
1379
1380 copyToDevice();
1381}
1382
1383template <typename T, unsigned int dimension, typename index_type>
1384void
1386{
1387 if (_layout != array._layout)
1388 mooseError("Kokkos array error: cannot deep copy arrays with different layouts.");
1389
1391 mooseError(
1392 "Kokkos array error: cannot deep copy using constructor from array without host data.");
1393
1394 std::vector<index_type> n(std::begin(array._n), std::end(array._n));
1395
1396 createInternal<false>(n, array._is_host_alloc, array._is_device_alloc);
1397
1398 if (_is_host_alloc)
1399 for (const auto i : make_range(_size))
1400 if (array.isSlotConstructed(i))
1401 emplaceAt(i, array._host_data[i]);
1402
1404 copyToDevice();
1405 else if (_is_device_alloc)
1406 copyInternal<MemSpace, MemSpace>(_device_data, array._device_data, _size);
1407
1408 for (const auto i : make_range(dimension))
1409 {
1410 _d[i] = array._d[i];
1411 _s[i] = array._s[i];
1412 }
1413}
1414
1415template <typename T, unsigned int dimension, typename index_type>
1416void
1425
1426template <typename T, unsigned int dimension, typename index_type>
1427auto &
1429{
1430 if (_is_host_alloc)
1431 std::fill_n(_host_data, _size, scalar);
1432
1433 if (_is_device_alloc)
1434 ::Kokkos::deep_copy(deviceView(), scalar);
1435
1436 return *this;
1437}
1438
1439template <typename T, unsigned int dimension, typename index_type, LayoutType layout>
1440void
1441dataStore(std::ostream & stream, Array<T, dimension, index_type, layout> & array, void * context)
1442{
1443 using ::dataStore;
1444
1445 bool is_alloc = array.isAlloc();
1446 dataStore(stream, is_alloc, nullptr);
1447
1448 if (!is_alloc)
1449 return;
1450
1451 std::string type = typeid(T).name();
1452 dataStore(stream, type, nullptr);
1453
1454 unsigned int dim = dimension;
1455 dataStore(stream, dim, nullptr);
1456
1457 for (const auto dim : make_range(dimension))
1458 {
1459 auto n = array.n(dim);
1460 dataStore(stream, n, nullptr);
1461 }
1462
1463 if (array.isDeviceAlloc())
1464 {
1465 // We use malloc/free because we just want a memory copy
1466 // If T is a Kokkos array and we use new/delete or vector to copy it out,
1467 // the arrays will be destroyed on cleanup
1468
1469 T * data = static_cast<T *>(std::malloc(array.size() * sizeof(T)));
1470
1472
1473 for (const auto i : make_range(array.size()))
1474 dataStore(stream, data[i], context);
1475
1476 std::free(data);
1477 }
1478 else
1479 for (auto & value : array)
1480 dataStore(stream, value, context);
1481}
1482
1483template <typename T, unsigned int dimension, typename index_type, LayoutType layout>
1484void
1485dataLoad(std::istream & stream, Array<T, dimension, index_type, layout> & array, void * context)
1486{
1487 using ::dataLoad;
1488
1489 bool is_alloc;
1490 dataLoad(stream, is_alloc, nullptr);
1491
1492 if (!is_alloc)
1493 return;
1494
1495 std::string from_type_name;
1496 dataLoad(stream, from_type_name, nullptr);
1497
1498 if (from_type_name != typeid(T).name())
1499 mooseError("Kokkos array error: cannot load array because the stored array is of type '",
1500 MooseUtils::prettyCppType(libMesh::demangle(from_type_name.c_str())),
1501 "' but the loading array is of type '",
1503 "'.");
1504
1505 unsigned int from_dimension;
1506 dataLoad(stream, from_dimension, nullptr);
1507
1508 if (from_dimension != dimension)
1509 mooseError("Kokkos array error: cannot load array because the stored array is ",
1510 from_dimension,
1511 "D but the loading array is ",
1512 dimension,
1513 "D.");
1514
1515 std::vector<index_type> from_n(dimension);
1516 std::vector<index_type> n(dimension);
1517
1518 for (const auto dim : make_range(dimension))
1519 {
1520 dataLoad(stream, from_n[dim], nullptr);
1521 n[dim] = array.n(dim);
1522 }
1523
1524 if (from_n != n)
1525 mooseError("Kokkos array error: cannot load array because the stored array has dimensions (",
1526 Moose::stringify(from_n),
1527 ") but the loading array has dimensions (",
1529 ").");
1530
1531 if (array.isHostAlloc())
1532 {
1533 for (auto & value : array)
1534 dataLoad(stream, value, context);
1535
1536 if (array.isDeviceAlloc())
1537 array.copyToDevice();
1538 }
1539 else
1540 {
1541 std::vector<T> data(array.size());
1542
1543 for (auto & value : data)
1544 dataLoad(stream, value, context);
1545
1546 array.copyIn(data.data(), MemcpyType::HOST_TO_DEVICE, array.size());
1547 }
1548}
1549#endif
1550
1567template <typename T, unsigned int dimension, typename index_type, LayoutType layout>
1568class Array : public ArrayBase<T, dimension, index_type>
1569{
1570#ifdef MOOSE_KOKKOS_SCOPE
1571 usingKokkosArrayBaseMembers(T, dimension, index_type);
1572#endif
1573
1574public:
1578 Array() : ArrayBase<T, dimension, index_type>(layout) {}
1583 : ArrayBase<T, dimension, index_type>(array)
1584 {
1585 }
1586#ifdef MOOSE_KOKKOS_SCOPE
1593 template <typename... size_type>
1594 Array(size_type... n) : ArrayBase<T, dimension, index_type>(layout, n...)
1595 {
1596 }
1597#endif
1598
1604 {
1605 this->shallowCopy(array);
1606
1607 return *this;
1608 }
1609
1610#ifdef MOOSE_KOKKOS_SCOPE
1617 template <typename... indices>
1618 KOKKOS_FUNCTION T & operator()(indices... i) const
1619 {
1620 return this->operator[](linearIndex(i...));
1621 }
1628 KOKKOS_FUNCTION T & operator()(const signed_index_type (&idx)[dimension]) const
1629 {
1630 return this->operator[](linearIndex(idx));
1631 }
1638 template <typename indices, typename... Args>
1639 T & emplace(const indices (&idx)[dimension], Args &&... args);
1640#endif
1641
1642private:
1643#ifdef MOOSE_KOKKOS_SCOPE
1647 template <typename... indices>
1648 KOKKOS_FUNCTION index_type linearIndex(indices... i) const;
1653 template <typename indices>
1654 KOKKOS_FUNCTION index_type linearIndex(const indices (&idx)[dimension]) const
1655 {
1656 return linearIndexHelper(idx, std::make_integer_sequence<unsigned int, dimension>{});
1657 }
1658 template <typename indices, unsigned int... i>
1659 KOKKOS_FUNCTION index_type linearIndexHelper(const indices (&idx)[dimension],
1660 std::integer_sequence<unsigned int, i...>) const
1661 {
1662 return linearIndex(idx[i]...);
1663 }
1665#endif
1666};
1667
1668#ifdef MOOSE_KOKKOS_SCOPE
1669template <typename T, unsigned int dimension, typename index_type, LayoutType layout>
1670template <typename indices, typename... Args>
1671T &
1672Array<T, dimension, index_type, layout>::emplace(const indices (&idx)[dimension], Args &&... args)
1673{
1674 return this->emplaceAt(linearIndex(idx), std::forward<Args>(args)...);
1675}
1676
1677template <typename T, unsigned int dimension, typename index_type, LayoutType layout>
1678template <typename... indices>
1679KOKKOS_FUNCTION index_type
1681{
1682 static_assert((std::is_convertible<indices, signed_index_type>::value && ...),
1683 "All arguments must be convertible to signed_index_type");
1684 static_assert(sizeof...(i) == dimension, "Number of arguments should match array dimension");
1685
1686#ifndef NDEBUG
1687 {
1688 signed_index_type idx[dimension] = {static_cast<signed_index_type>(i)...};
1689
1690 for (unsigned int d = 0; d < sizeof...(i); ++d)
1691 KOKKOS_ASSERT(idx[d] - _d[d] >= 0 && static_cast<index_type>(idx[d] - _d[d]) < _n[d]);
1692 }
1693#endif
1694
1695 index_type idx = 0;
1696 unsigned int d = 0;
1697
1698 if constexpr (layout == LayoutType::LEFT)
1699 (((idx += (d == 0 ? static_cast<signed_index_type>(i) - _d[d]
1700 : (static_cast<signed_index_type>(i) - _d[d]) * _s[d])),
1701 ++d),
1702 ...);
1703 else
1704 (((idx += (d == dimension - 1 ? static_cast<signed_index_type>(i) - _d[d]
1705 : (static_cast<signed_index_type>(i) - _d[d]) * _s[d])),
1706 ++d),
1707 ...);
1708
1709 return idx;
1710}
1711#endif
1712
1713template <typename T, typename index_type>
1714class Array<T, 1, index_type, LayoutType::LEFT> : public ArrayBase<T, 1, index_type>
1715{
1716#ifdef MOOSE_KOKKOS_SCOPE
1718#endif
1719
1720public:
1724 Array() : ArrayBase<T, 1, index_type>(LayoutType::LEFT) {}
1729 : ArrayBase<T, 1, index_type>(array)
1730 {
1731 }
1732#ifdef MOOSE_KOKKOS_SCOPE
1739 Array(index_type n) : ArrayBase<T, 1, index_type>(LayoutType::LEFT, n) {}
1746 Array(const std::vector<T> & vector) : ArrayBase<T, 1, index_type>(LayoutType::LEFT)
1747 {
1748 *this = vector;
1749 }
1750#endif
1751
1757 {
1758 this->shallowCopy(array);
1759
1760 return *this;
1761 }
1762
1763#ifdef MOOSE_KOKKOS_SCOPE
1771 template <bool host, bool device>
1772 void copyVector(const std::vector<T> & vector)
1773 {
1774 this->template createInternal<host, device, false>({static_cast<index_type>(vector.size())});
1775
1776 if (host)
1777 {
1778 if constexpr (std::is_trivially_copyable<T>())
1779 std::memcpy(this->hostData(), vector.data(), this->size() * sizeof(T));
1780 else
1781 std::copy(vector.begin(), vector.end(), this->begin());
1782 }
1783
1784 if (device)
1785 this->template copyInternal<MemSpace, ::Kokkos::HostSpace>(
1786 this->deviceData(), vector.data(), this->size());
1787 }
1795 template <bool host, bool device>
1796 void copySet(const std::set<T> & set)
1797 {
1798 std::vector<T> vector(set.begin(), set.end());
1799
1800 copyVector<host, device>(vector);
1801 }
1802
1808 auto & operator=(const std::vector<T> & vector)
1809 {
1810 copyVector<true, true>(vector);
1811
1812 return *this;
1813 }
1819 auto & operator=(const std::set<T> & set)
1820 {
1821 copySet<true, true>(set);
1822
1823 return *this;
1824 }
1831 KOKKOS_FUNCTION T & operator()(signed_index_type i) const
1832 {
1833 return this->operator[](linearIndex(i));
1834 }
1841 template <typename indices, typename... Args>
1842 T & emplace(const indices (&idx)[1], Args &&... args);
1847
1851 void axby(const T a,
1853 const char op,
1854 const T b,
1856 const bool accumulate = false);
1864 void scal(const T a);
1872 T nrm2();
1874
1875private:
1879 KOKKOS_FUNCTION index_type linearIndex(signed_index_type i) const;
1880#endif
1881};
1883
1884#ifdef MOOSE_KOKKOS_SCOPE
1885template <typename T, typename index_type>
1886template <typename indices, typename... Args>
1887T &
1888Array<T, 1, index_type, LayoutType::LEFT>::emplace(const indices (&idx)[1], Args &&... args)
1889{
1890 return this->emplaceAt(linearIndex(idx[0]), std::forward<Args>(args)...);
1891}
1892
1893template <typename T, typename index_type>
1894KOKKOS_FUNCTION index_type
1897{
1898 KOKKOS_ASSERT(i - _d[0] >= 0 && static_cast<index_type>(i - _d[0]) < _n[0]);
1899
1900 return i - _d[0];
1901}
1902#endif
1903
1904template <typename T, typename index_type = MOOSE_KOKKOS_INDEX_TYPE>
1906template <typename T,
1907 typename index_type = MOOSE_KOKKOS_INDEX_TYPE,
1910template <typename T,
1911 typename index_type = MOOSE_KOKKOS_INDEX_TYPE,
1914template <typename T,
1915 typename index_type = MOOSE_KOKKOS_INDEX_TYPE,
1918template <typename T,
1919 typename index_type = MOOSE_KOKKOS_INDEX_TYPE,
1922
1923} // namespace Moose::Kokkos
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
Iterator over tracked constructed entries.
std::conditional_t< is_const, const T *, T * > pointer
std::ptrdiff_t difference_type
bool operator!=(const constructed_entry_iterator &other) const
pointer operator->() const
reference operator*() const
std::conditional_t< is_const, const ArrayBase, ArrayBase > array_type
bool operator==(const constructed_entry_iterator &other) const
std::conditional_t< is_const, const T &, T & > reference
array_type & _array
Array whose constructed entries are being iterated.
index_type _i
Current slot index in _array.
std::forward_iterator_tag iterator_category
constructed_entry_iterator & operator++()
void advanceToConstructed()
T value_type
Range over tracked constructed entries.
array_type & _array
Array that provides the constructed-entry iteration bounds.
iterator begin() const
std::conditional_t< is_const, const ArrayBase, ArrayBase > array_type
iterator end() const
constructed_entry_iterator< is_const > iterator
KOKKOS_FUNCTION friend bool operator!=(const iterator &a, const iterator &b)
std::forward_iterator_tag iterator_category
KOKKOS_FUNCTION iterator(T *p)
KOKKOS_FUNCTION pointer operator->() const
KOKKOS_FUNCTION pointer operator&() const
KOKKOS_FUNCTION reference operator*() const
KOKKOS_FUNCTION iterator & operator++()
KOKKOS_FUNCTION iterator operator++(int)
KOKKOS_FUNCTION friend bool operator==(const iterator &a, const iterator &b)
The base class for Kokkos arrays.
bool _is_host_alias
Flag whether the host data points to an external data.
bool _is_init
Flag whether array was initialized.
index_type _n[dimension]
Size of each dimension.
typename std::make_signed< index_type >::type signed_index_type
void aliasDevice(T *ptr)
Point the device data to an external data instead of allocating it.
T * deviceData() const
Get the device data pointer.
void createDevice(size_type... n)
Allocate array on device only.
void createInternal(const std::vector< index_type > &n)
The internal method to initialize and allocate this array.
void createInternal(const std::vector< index_type > &n, bool host, bool device)
The internal method to initialize and allocate this array.
std::shared_ptr< unsigned int > _counter
Reference counter.
void copyOut(T *ptr, MemcpyType dir, index_type n, index_type offset=0)
Copy data to an external data from this array.
KOKKOS_FUNCTION bool isHostAlias() const
Get whether the host array was aliased.
unsigned int useCount() const
Get the reference count.
void deepCopy(const ArrayBase< T, dimension, index_type > &array)
Deep copy another Kokkos array If ArrayDeepCopy<T>::value is true, it will copy-construct each entry ...
void copyToHost()
Copy data from device to host.
void swap(ArrayBase< T, dimension, index_type > &array)
Swap with another Kokkos array.
void offset(const std::vector< signed_index_type > &d)
Apply starting index offsets to each dimension.
void init(size_type... n)
Initialize array with given dimensions but do not allocate.
bool _is_host_alloc
Flag whether host data was allocated.
void copyToDevice()
Copy data from host to device.
KOKKOS_FUNCTION T * data() const
Get the data pointer.
auto & operator=(const T &scalar)
Assign a scalar value uniformly.
KOKKOS_FUNCTION iterator end() const
Get the end iterator.
void shallowCopy(const ArrayBase< T, dimension, index_type > &array)
Shallow copy another Kokkos array.
KOKKOS_FUNCTION bool isAlloc() const
Get whether the array was allocated either on host or device.
ArrayBase(const LayoutType layout, size_type... n)
Constructor Initialize and allocate array with given dimensions This allocates both host and device d...
void allocDevice()
Allocate device data for an initialized array that has not allocated device data.
T * _device_data
Device data.
auto deviceView() const
Get the device unmanaged view.
signed_index_type _d[dimension]
Offset of each dimension.
void offset(offset_type... d)
Apply starting index offsets to each dimension.
const LayoutType _layout
Memory layout type.
void moveToDevice(bool should_free_host=true)
Copy data from host to device and deallocate host.
KOKKOS_FUNCTION index_type size() const
Get the total array size.
auto hostView() const
Get the host unmanaged view.
void allocHost()
Allocate host data for an initialized array that has not allocated host data.
ArrayBase(const LayoutType layout)
Constructor.
void copyInternal(T *target, const T *source, index_type n)
The internal method to perform a memory copy.
KOKKOS_FUNCTION T & operator[](index_type i) const
Get an array entry.
T & emplaceAt(index_type i, Args &&... args)
Placement-new construct slot i from args, recording initialization.
KOKKOS_FUNCTION T & last() const
Get the last element.
KOKKOS_FUNCTION bool isDeviceAlias() const
Get whether the device array was aliased.
KOKKOS_FUNCTION index_type n(unsigned int dim) const
Get the size of a dimension.
void createDevice(const std::vector< index_type > &n)
Allocate array on device only.
void copyIn(const T *ptr, MemcpyType dir, index_type n, index_type offset=0)
Copy data from an external data to this array.
KOKKOS_FUNCTION bool isHostAlloc() const
Get whether the array was allocated on host.
T * hostData() const
Get the host data pointer.
void copyToDeviceNested()
Copy all the nested Kokkos arrays including self from host to device.
bool _is_device_alias
Flag whether the device data points to an external data.
bool _is_device_alloc
Flag whether device data was allocated.
KOKKOS_FUNCTION iterator begin() const
Get the beginning iterator.
index_type _size
Total size.
void createHost(size_type... n)
Allocate array on host only.
void freeHost()
Free host data.
bool isSlotConstructed(index_type i) const
Get whether slot i is tracked as constructed.
KOKKOS_FUNCTION T & first() const
Get the first element.
constructed_entry_range< false > constructedEntries()
Get host-side range over entries tracked as constructed.
std::shared_ptr< std::vector< bool > > _slots_constructed
Non-null only for malloc-allocated arrays; tracks which slots have been emplace-constructed.
void createInternal(size_type... n)
The internal method to initialize and allocate this array.
KOKKOS_FUNCTION bool isDeviceAlloc() const
Get whether the array was allocated on device.
void createHost(const std::vector< index_type > &n)
Allocate array on host only.
void aliasHost(T *ptr)
Point the host data to an external data instead of allocating it.
void moveToHost(bool should_free_device=true)
Copy data from device to host and deallocate device.
void freeDevice()
Free device data.
void destroy()
Free all data and reset.
index_type _s[dimension]
Stride of each dimension.
constructed_entry_range< true > constructedEntries() const
Get host-side range over entries tracked as constructed.
ArrayBase(const ArrayBase< T, dimension, index_type > &array)
Copy constructor.
void create(const std::vector< index_type > &n)
Allocate array on host and device.
void create(size_type... n)
Allocate array on host and device.
Array(const std::vector< T > &vector)
Constructor Initialize and allocate array by copying a standard vector variable This allocates and co...
T dot(const Array< T, 1, index_type, LayoutType::LEFT > &x)
Perform dot product between this array and x.
void scal(const T a)
Scale this array with a.
T & emplace(const indices(&idx)[1], Args &&... args)
Placement-new construct an entry from args, recording initialization.
Array(index_type n)
Constructor Initialize and allocate array with given size This allocates both host and device data.
void axby(const T a, const Array< T, 1, index_type, LayoutType::LEFT > &x, const char op, const T b, const Array< T, 1, index_type, LayoutType::LEFT > &y, const bool accumulate=false)
Device BLAS operations.
KOKKOS_FUNCTION index_type linearIndex(signed_index_type i) const
}@
void copyVector(const std::vector< T > &vector)
Copy a standard vector variable This re-initializes and re-allocates array with the size of the vecto...
KOKKOS_FUNCTION T & operator()(signed_index_type i) const
Get an array entry.
Array(const Array< T, 1, index_type, LayoutType::LEFT > &array)
Copy constructor.
auto & operator=(const std::vector< T > &vector)
Copy a standard vector variable This allocates and copies to both host and device data.
void scal(const T a, const Array< T, 1, index_type, LayoutType::LEFT > &x)
Scale x with a and write the result to this array.
auto & operator=(const Array< T, 1, index_type, LayoutType::LEFT > &array)
Shallow copy another Kokkos array.
auto & operator=(const std::set< T > &set)
Copy a standard set variable This allocates and copies to both host and device data.
void copySet(const std::set< T > &set)
Copy a standard set variable This re-initializes and re-allocates array with the size of the set.
The Kokkos array class.
T & emplace(const indices(&idx)[dimension], Args &&... args)
Placement-new construct an entry from args, recording initialization.
KOKKOS_FUNCTION index_type linearIndex(indices... i) const
Get the dimensionless index for a multi-dimensional index.
KOKKOS_FUNCTION T & operator()(indices... i) const
Get an array entry.
KOKKOS_FUNCTION T & operator()(const signed_index_type(&idx)[dimension]) const
Get an array entry using indices stored in an array.
KOKKOS_FUNCTION index_type linearIndex(const indices(&idx)[dimension]) const
Get the dimensionless index for indices stored in an array.
auto & operator=(const Array< T, dimension, index_type, layout > &array)
Shallow copy another Kokkos array.
KOKKOS_FUNCTION index_type linearIndexHelper(const indices(&idx)[dimension], std::integer_sequence< unsigned int, i... >) const
Array(const Array< T, dimension, index_type, layout > &array)
Copy constructor.
usingKokkosArrayBaseMembers(T, dimension, index_type)
Array()
Default constructor.
Array(size_type... n)
Constructor Initialize and allocate array with given dimensions This allocates both host and device d...
void initialize(EquationSystems &es, const std::string &system_name)
std::string prettyCppType(const std::string &cpp_type)
void dataLoad(std::istream &stream, Array< T, dimension, index_type, layout > &array, void *context)
LayoutType
The enumerator that dictates the memory layout.
Definition KokkosArray.h:53
MemcpyType
The enumerator that dictates the memory copy direction.
Definition KokkosArray.h:42
void free(void *ptr)
void dataStore(std::ostream &stream, Array< T, dimension, index_type, layout > &array, void *context)
void copyToDeviceInner(T &)
static constexpr std::size_t dim
This is the dimension of all vector and tensor datastructures used in MOOSE.
Definition Moose.h:175
std::string stringify(const T &t)
conversion to string
Definition Conversion.h:65
std::string demangle(const char *name)
The type trait that determines the default behavior of copy constructor and deepCopy() If this type t...
Definition KokkosArray.h:92
static constexpr bool value
Definition KokkosArray.h:93
The type trait that determines if a template type is Kokkos array.
Definition KokkosArray.h:73