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://www.mooseframework.org
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_IF_ON_HOST(return _host_data[0];)
320
321 return _device_data[0];
322 }
328 KOKKOS_FUNCTION T & last() const
329 {
330 KOKKOS_IF_ON_HOST(return _host_data[_size - 1];)
331
332 return _device_data[_size - 1];
333 }
340 KOKKOS_FUNCTION T & operator[](index_type i) const
341 {
342 KOKKOS_ASSERT(i < _size);
343
344 KOKKOS_IF_ON_HOST(return _host_data[i];)
345
346 return _device_data[i];
347 }
348
353 T * hostData() const { return _host_data; }
358 T * deviceData() const { return _device_data; }
363 auto hostView() const
364 {
365 return ::Kokkos::View<T *, ::Kokkos::HostSpace, ::Kokkos::MemoryTraits<::Kokkos::Unmanaged>>(
367 }
372 auto deviceView() const
373 {
374 return ::Kokkos::View<T *, MemSpace, ::Kokkos::MemoryTraits<::Kokkos::Unmanaged>>(_device_data,
375 _size);
376 }
381 template <typename... size_type>
382 void init(size_type... n)
383 {
384 createInternal<false, false, false>(n...);
385 }
391 template <bool initialize = true>
392 void create(const std::vector<index_type> & n)
393 {
394 createInternal<true, true, initialize>(n);
395 }
401 template <bool initialize = true, typename... size_type>
402 void create(size_type... n)
403 {
404 createInternal<true, true, initialize>(n...);
405 }
411 template <bool initialize = true>
412 void createHost(const std::vector<index_type> & n)
413 {
414 createInternal<true, false, initialize>(n);
415 }
421 template <bool initialize = true, typename... size_type>
422 void createHost(size_type... n)
423 {
424 createInternal<true, false, initialize>(n...);
425 }
430 void createDevice(const std::vector<index_type> & n) { createInternal<false, true, false>(n); }
435 template <typename... size_type>
436 void createDevice(size_type... n)
437 {
438 createInternal<false, true, false>(n...);
439 }
444 void aliasHost(T * ptr);
449 void aliasDevice(T * ptr);
454 void offset(const std::vector<signed_index_type> & d);
459 template <typename... offset_type>
460 void offset(offset_type... d);
476 void copyIn(const T * ptr, MemcpyType dir, index_type n, index_type offset = 0);
484 void copyOut(T * ptr, MemcpyType dir, index_type n, index_type offset = 0);
495 void moveToDevice(bool should_free_host = true);
502 void moveToHost(bool should_free_device = true);
515
520 auto & operator=(const T & scalar);
521
526 {
527 public:
528 using iterator_category = std::forward_iterator_tag;
529 using value_type = T;
530 using difference_type = std::ptrdiff_t;
531 using pointer = T *;
532 using reference = T &;
533
534 KOKKOS_FUNCTION iterator() : it(nullptr) {}
535 KOKKOS_FUNCTION explicit iterator(T * p) : it(p) {}
536
537 KOKKOS_FUNCTION reference operator*() const { return *it; }
538 KOKKOS_FUNCTION pointer operator->() const { return it; }
539 KOKKOS_FUNCTION pointer operator&() const { return it; }
540 KOKKOS_FUNCTION iterator & operator++()
541 {
542 ++it;
543 return *this;
544 }
545 KOKKOS_FUNCTION iterator operator++(int)
546 {
547 iterator pre = *this;
548 ++it;
549 return pre;
550 }
551 KOKKOS_FUNCTION friend bool operator==(const iterator & a, const iterator & b)
552 {
553 return a.it == b.it;
554 }
555 KOKKOS_FUNCTION friend bool operator!=(const iterator & a, const iterator & b)
556 {
557 return a.it != b.it;
558 }
559
560 private:
562 };
563
568 KOKKOS_FUNCTION iterator begin() const
569 {
570 KOKKOS_IF_ON_HOST(return iterator(_host_data);)
571
572 return iterator(_device_data);
573 }
578 KOKKOS_FUNCTION iterator end() const
579 {
580 KOKKOS_IF_ON_HOST(return iterator(_host_data + _size);)
581
582 return iterator(_device_data + _size);
583 }
584#endif
585
586protected:
590 index_type _n[dimension] = {0};
594 index_type _s[dimension] = {0};
598 signed_index_type _d[dimension] = {0};
599
600#ifdef MOOSE_KOKKOS_SCOPE
608 template <bool host, bool device, bool initialize, typename... size_type>
609 void createInternal(size_type... n);
617 template <bool host, bool device, bool initialize>
618 void createInternal(const std::vector<index_type> & n);
626 template <bool initialize>
627 void createInternal(const std::vector<index_type> & n, bool host, bool device);
636 template <typename TargetSpace, typename SourceSpace>
637 void copyInternal(T * target, const T * source, index_type n);
644 template <typename... Args>
645 T & emplaceAt(index_type i, Args &&... args);
646#endif
647
648private:
649#ifdef MOOSE_KOKKOS_SCOPE
654 template <bool initialize>
655 void allocHost();
660#endif
664 void freeHost();
669
673 std::shared_ptr<unsigned int> _counter;
677 std::shared_ptr<std::vector<bool>> _slots_constructed;
681 bool _is_init = false;
685 bool _is_host_alloc = false;
689 bool _is_device_alloc = false;
693 bool _is_host_alias = false;
697 bool _is_device_alias = false;
701 T * _host_data = nullptr;
705 T * _device_data = nullptr;
709 index_type _size = 0;
714};
715
716template <typename T, unsigned int dimension, typename index_type>
717template <bool is_const>
727
728template <typename T, unsigned int dimension, typename index_type>
729template <bool is_const>
732{
733 ++_i;
734 advanceToConstructed();
735 return *this;
736}
737
738template <typename T, unsigned int dimension, typename index_type>
739template <bool is_const>
747
748template <typename T, unsigned int dimension, typename index_type>
749template <bool is_const>
750bool
752 const constructed_entry_iterator & other) const
753{
754 return &_array == &other._array && _i == other._i;
755}
756
757template <typename T, unsigned int dimension, typename index_type>
758template <bool is_const>
759bool
765
766template <typename T, unsigned int dimension, typename index_type>
767template <bool is_const>
768void
770{
771 while (_i < _array._size && !_array.isSlotConstructed(_i))
772 ++_i;
773}
774
775template <typename T, unsigned int dimension, typename index_type>
776template <bool is_const>
783
784template <typename T, unsigned int dimension, typename index_type>
785template <bool is_const>
791
792template <typename T, unsigned int dimension, typename index_type>
793template <bool is_const>
799
800template <typename T, unsigned int dimension, typename index_type>
806
807template <typename T, unsigned int dimension, typename index_type>
808typename ArrayBase<T, dimension, index_type>::template constructed_entry_range<true>
813
814template <typename T, unsigned int dimension, typename index_type>
815bool
817{
818 mooseAssert(i < _size, "isSlotConstructed index out of bounds");
819
821 return _is_host_alloc;
822
823 return (*_slots_constructed)[i];
824}
825
826#ifdef MOOSE_KOKKOS_SCOPE
827template <typename T, unsigned int dimension, typename index_type>
828template <typename... Args>
829T &
831{
832 mooseAssert(_is_host_alloc && _slots_constructed,
833 "emplaceAt requires a malloc-allocated array (create<false>)");
834 mooseAssert(i < _size, "emplaceAt index out of bounds");
835
836 new (_host_data + i) T(std::forward<Args>(args)...);
837 (*_slots_constructed)[i] = true;
838
839 return _host_data[i];
840}
841#endif // MOOSE_KOKKOS_SCOPE
842
843template <typename T, unsigned int dimension, typename index_type>
844void
846{
847 if (!_is_host_alloc)
848 return;
849
850 if (_is_host_alias)
851 {
852 _host_data = nullptr;
853 _is_host_alias = false;
854 }
855 else
856 {
858 // Allocated by new
859 delete[] _host_data;
860 else
861 {
862 // Allocated by malloc
863 for (const auto i : make_range(_size))
864 if (isSlotConstructed(i))
865 _host_data[i].~T();
866
867 std::free(_host_data);
868
869 _slots_constructed.reset();
870 }
871 }
872
873 _is_host_alloc = false;
874}
875
876template <typename T, unsigned int dimension, typename index_type>
877void
879{
880 if (!_is_device_alloc)
881 return;
882
884 {
885 _device_data = nullptr;
886 _is_device_alias = false;
887 }
888 else
890
891 _is_device_alloc = false;
892}
893
894template <typename T, unsigned int dimension, typename index_type>
895void
897{
898 if (!_counter)
899 return;
900
901 if (_counter.use_count() > 1)
902 {
903 _host_data = nullptr;
904 _device_data = nullptr;
905 }
906 else if (_counter.use_count() == 1)
907 {
908 freeHost();
909 freeDevice();
910 }
911
912 _size = 0;
913
914 for (const auto i : make_range(dimension))
915 {
916 _n[i] = 0;
917 _s[i] = 0;
918 _d[i] = 0;
919 }
920
921 _is_init = false;
922 _is_host_alloc = false;
923 _is_device_alloc = false;
924 _is_host_alias = false;
925 _is_device_alias = false;
926
927 _counter.reset();
928 _slots_constructed.reset();
929}
930
931template <typename T, unsigned int dimension, typename index_type>
932void
934{
935 if (_layout != array._layout)
936 mooseError("Kokkos array error: cannot shallow copy arrays with different layouts.");
937
938 destroy();
939
940 _counter = array._counter;
942
943 _size = array._size;
944
945 for (const auto i : make_range(dimension))
946 {
947 _n[i] = array._n[i];
948 _s[i] = array._s[i];
949 _d[i] = array._d[i];
950 }
951
952 _is_init = array._is_init;
957
958 _host_data = array._host_data;
960}
961
962#ifdef MOOSE_KOKKOS_SCOPE
963template <typename T, unsigned int dimension, typename index_type>
964void
966{
967 if (!_is_init)
968 mooseError("Kokkos array error: attempted to alias host data before array initialization.");
969
971 mooseError("Kokkos array error: cannot alias host data because host data was not aliased.");
972
973 _host_data = ptr;
974 _is_host_alloc = true;
975 _is_host_alias = true;
976}
977
978template <typename T, unsigned int dimension, typename index_type>
979void
981{
982 if (!_is_init)
983 mooseError("Kokkos array error: attempted to alias device data before array initialization.");
984
986 mooseError("Kokkos array error: cannot alias device data because device data was not aliased.");
987
988 _device_data = ptr;
989 _is_device_alloc = true;
990 _is_device_alias = true;
991}
992
993template <typename T, unsigned int dimension, typename index_type>
994template <bool initialize>
995void
997{
998 if (_is_host_alloc)
999 return;
1000
1001 if constexpr (initialize)
1002 {
1003 static_assert(
1004 std::is_default_constructible<T>::value,
1005 "Data type is not default-constructible. Initialization argument should be set to false.");
1006
1007 _host_data = new T[_size];
1008 }
1009 else
1010 {
1011 _host_data = static_cast<T *>(std::malloc(_size * sizeof(T)));
1012 _slots_constructed = std::make_shared<std::vector<bool>>(_size, false);
1013 }
1014
1015 _is_host_alloc = true;
1016}
1017
1018template <typename T, unsigned int dimension, typename index_type>
1019void
1021{
1022 if (_is_device_alloc)
1023 return;
1024
1025 _device_data =
1026 static_cast<T *>(::Kokkos::kokkos_malloc<ExecSpace::memory_space>(_size * sizeof(T)));
1027
1028 _is_device_alloc = true;
1029}
1030
1031template <typename T, unsigned int dimension, typename index_type>
1032template <bool host, bool device, bool initialize>
1033void
1035{
1036 if (n.size() != dimension)
1037 mooseError("Kokkos array error: the number of dimensions provided (",
1038 n.size(),
1039 ") must match the array dimension (",
1040 dimension,
1041 ").");
1042
1043 if (_counter)
1044 destroy();
1045
1046 _counter = std::make_shared<unsigned int>();
1047
1048 uint64_t overflow_checker = 1;
1049
1050 _size = 1;
1051 _s[0] = 1;
1052
1053 for (const auto i : make_range(dimension))
1054 {
1055 overflow_checker *= n[i];
1056
1057 _n[i] = n[i];
1058 _size *= n[i];
1059 }
1060
1061 if (overflow_checker > std::numeric_limits<index_type>::max())
1062 mooseError("Kokkos array error: the dimensions provided (",
1064 ") has the total size of ",
1065 overflow_checker,
1066 " which exceeds the limit of ",
1067 MooseUtils::prettyCppType<index_type>(),
1068 ".");
1069
1071 {
1072 _s[0] = 1;
1073
1074 for (const auto i : make_range(1u, dimension))
1075 _s[i] = _s[i - 1] * _n[i - 1];
1076 }
1077 else
1078 {
1079 _s[dimension - 1] = 1;
1080
1081 for (int i = dimension - 2; i >= 0; --i)
1082 _s[i] = _s[i + 1] * _n[i + 1];
1083 }
1084
1085 if constexpr (host)
1086 allocHost<initialize>();
1087
1088 if constexpr (device)
1089 allocDevice();
1090
1091 _is_init = true;
1092}
1093
1094template <typename T, unsigned int dimension, typename index_type>
1095template <bool initialize>
1096void
1098 bool host,
1099 bool device)
1100{
1101 if (host && device)
1102 createInternal<true, true, initialize>(n);
1103 else if (host && !device)
1104 createInternal<true, false, initialize>(n);
1105 else if (!host && device)
1106 createInternal<false, true, initialize>(n);
1107 else
1108 createInternal<false, false, initialize>(n);
1109}
1110
1111template <typename T, unsigned int dimension, typename index_type>
1112template <bool host, bool device, bool initialize, typename... size_type>
1113void
1115{
1116 static_assert((std::is_convertible<size_type, index_type>::value && ...),
1117 "All arguments must be convertible to index_type");
1118 static_assert(sizeof...(n) == dimension, "Number of arguments should match array dimension");
1119
1120 std::vector<index_type> dims;
1121 (dims.push_back(n), ...);
1122
1123 createInternal<host, device, initialize>(dims);
1124}
1125
1126template <typename T, unsigned int dimension, typename index_type>
1127template <typename TargetSpace, typename SourceSpace>
1128void
1129ArrayBase<T, dimension, index_type>::copyInternal(T * target, const T * source, index_type n)
1130{
1131 ::Kokkos::Impl::DeepCopy<TargetSpace, SourceSpace>(target, source, n * sizeof(T));
1132 ::Kokkos::fence();
1133}
1134
1135template <typename T, unsigned int dimension, typename index_type>
1136void
1137ArrayBase<T, dimension, index_type>::offset(const std::vector<signed_index_type> & d)
1138{
1139 if (d.size() > dimension)
1140 mooseError("Kokkos array error: the number of offsets provided (",
1141 d.size(),
1142 ") cannot be larger than the array dimension (",
1143 dimension,
1144 ").");
1145
1146 for (const auto i : index_range(d))
1147 _d[i] = d[i];
1148}
1149
1150template <typename T, unsigned int dimension, typename index_type>
1151template <typename... offset_type>
1152void
1154{
1155 static_assert((std::is_convertible<offset_type, signed_index_type>::value && ...),
1156 "All arguments must be convertible to signed_index_type");
1157 static_assert(sizeof...(d) == dimension, "Number of arguments should match array dimension");
1158
1159 std::vector<signed_index_type> offsets;
1160 (offsets.push_back(d), ...);
1161
1162 offset(offsets);
1163}
1164
1165template <typename T, unsigned int dimension, typename index_type>
1166void
1168{
1169 // If host side memory is not allocated, do nothing
1170 if (!_is_host_alloc)
1171 return;
1172
1173 // If device side memory is not allocated,
1174 if (!_is_device_alloc)
1175 {
1176 if (_counter.use_count() == 1)
1177 // allocate memory if this array is not shared with other arrays
1178 allocDevice();
1179 else
1180 // print error if this array is shared with other arrays
1181 mooseError("Kokkos array error: cannot copy from host to device because device memory "
1182 "was not allocated. Cannot allocate device memory for copy because the array is "
1183 "being shared.");
1184 }
1185
1186 // Copy from host to device
1187 copyInternal<MemSpace, ::Kokkos::HostSpace>(_device_data, _host_data, _size);
1188}
1189
1190template <typename T, unsigned int dimension, typename index_type>
1191void
1193{
1194 // If device side memory is not allocated, do nothing
1195 if (!_is_device_alloc)
1196 return;
1197
1198 // If host side memory is not allocated,
1199 if (!_is_host_alloc)
1200 {
1201 if (_counter.use_count() == 1)
1202 // allocate memory if this array is not shared with other arrays
1203 allocHost<false>();
1204 else
1205 // print error if this array is shared with other arrays
1206 mooseError("Kokkos array error: cannot copy from device to host because host memory "
1207 "was not allocated. Cannot allocate host memory for copy because the array is "
1208 "being shared.");
1209 }
1210
1211 // Copy from device to host
1212 copyInternal<::Kokkos::HostSpace, MemSpace>(_host_data, _device_data, _size);
1213}
1214
1215template <typename T, unsigned int dimension, typename index_type>
1216void
1218{
1219 static_assert(!is_kokkos_array<T>::value,
1220 "moveToDevice() not allowed for a nested array whose data type is another array.");
1221
1222 if (should_free_host && _counter.use_count() > 1)
1223 mooseError("Kokkos array error: cannot move array from host to device because there is at "
1224 "least one shallow copy of this array still alive.");
1225
1226 copyToDevice();
1227
1228 if (_counter.use_count() == 1)
1229 freeHost();
1230}
1231
1232template <typename T, unsigned int dimension, typename index_type>
1233void
1235{
1236 if (should_free_device && _counter.use_count() > 1)
1237 mooseError("Kokkos array error: cannot move array from device to host because there is at "
1238 "least one shallow copy of this array still alive.");
1239
1240 copyToHost();
1241
1242 if (_counter.use_count() == 1)
1243 freeDevice();
1244}
1245
1246template <typename T, unsigned int dimension, typename index_type>
1247void
1249 MemcpyType dir,
1250 index_type n,
1251 index_type offset)
1252{
1253 if (n > _size)
1254 mooseError("Kokkos array error: cannot copy in data larger than the array size.");
1255
1256 if (offset > _size)
1257 mooseError("Kokkos array error: offset cannot be larger than the array size.");
1258
1259 if (dir == MemcpyType::HOST_TO_HOST)
1260 {
1261 // If host side memory is not allocated, print error
1262 if (!_is_host_alloc)
1263 mooseError(
1264 "Kokkos array error: cannot copy in to the array because host memory was not allocated.");
1265
1266 // Copy from host to host
1267 copyInternal<::Kokkos::HostSpace, ::Kokkos::HostSpace>(_host_data + offset, ptr, n);
1268 }
1269 else if (dir == MemcpyType::HOST_TO_DEVICE)
1270 {
1271 // If device side memory is not allocated, print error
1272 if (!_is_device_alloc)
1273 mooseError("Kokkos array error: cannot copy in to the array because device memory was not "
1274 "allocated.");
1275
1276 // Copy from host to device
1277 copyInternal<MemSpace, ::Kokkos::HostSpace>(_device_data + offset, ptr, n);
1278 }
1279 else if (dir == MemcpyType::DEVICE_TO_HOST)
1280 {
1281 // If host side memory is not allocated, print error
1282 if (!_is_host_alloc)
1283 mooseError(
1284 "Kokkos array error: cannot copy in to the array because host memory was not allocated.");
1285
1286 // Copy from device to host
1287 copyInternal<::Kokkos::HostSpace, MemSpace>(_host_data + offset, ptr, n);
1288 }
1289 else if (dir == MemcpyType::DEVICE_TO_DEVICE)
1290 {
1291 // If device side memory is not allocated, print error
1292 if (!_is_device_alloc)
1293 mooseError("Kokkos array error: cannot copy in to the array because device memory was not "
1294 "allocated.");
1295
1296 // Copy from device to device
1297 copyInternal<MemSpace, MemSpace>(_device_data + offset, ptr, n);
1298 }
1299}
1300
1301template <typename T, unsigned int dimension, typename index_type>
1302void
1304 MemcpyType dir,
1305 index_type n,
1306 index_type offset)
1307{
1308 if (n > _size)
1309 mooseError("Kokkos array error: cannot copy out data larger than the array size.");
1310
1311 if (offset > _size)
1312 mooseError("Kokkos array error: offset cannot be larger than the array size.");
1313
1314 if (dir == MemcpyType::HOST_TO_HOST)
1315 {
1316 // If host side memory is not allocated, print error
1317 if (!_is_host_alloc)
1318 mooseError("Kokkos array error: cannot copy out from the array because host memory was not "
1319 "allocated.");
1320
1321 // Copy from host to host
1322 copyInternal<::Kokkos::HostSpace, ::Kokkos::HostSpace>(ptr, _host_data + offset, n);
1323 }
1324 else if (dir == MemcpyType::HOST_TO_DEVICE)
1325 {
1326 // If host side memory is not allocated, print error
1327 if (!_is_host_alloc)
1328 mooseError("Kokkos array error: cannot copy out from the array because host memory was not "
1329 "allocated.");
1330
1331 // Copy from host to device
1332 copyInternal<MemSpace, ::Kokkos::HostSpace>(ptr, _host_data + offset, n);
1333 }
1334 else if (dir == MemcpyType::DEVICE_TO_HOST)
1335 {
1336 // If device side memory is not allocated, print error
1337 if (!_is_device_alloc)
1338 mooseError("Kokkos array error: cannot copy out from the array because device memory was not "
1339 "allocated.");
1340
1341 // Copy from device to host
1342 copyInternal<::Kokkos::HostSpace, MemSpace>(ptr, _device_data + offset, n);
1343 }
1344 else if (dir == MemcpyType::DEVICE_TO_DEVICE)
1345 {
1346 // If device side memory is not allocated, print error
1347 if (!_is_device_alloc)
1348 mooseError("Kokkos array error: cannot copy out from the array because device memory was not "
1349 "allocated.");
1350
1351 // Copy from device to device
1352 copyInternal<MemSpace, MemSpace>(ptr, _device_data + offset, n);
1353 }
1354}
1355
1356template <typename T>
1357void
1358copyToDeviceInner(T & /* data */)
1359{
1360}
1361
1362template <typename T, unsigned int dimension, typename index_type, LayoutType layout>
1363void
1365{
1366 data.copyToDeviceNested();
1367}
1368
1369template <typename T, unsigned int dimension, typename index_type>
1370void
1372{
1373 for (const auto i : make_range(_size))
1375
1376 copyToDevice();
1377}
1378
1379template <typename T, unsigned int dimension, typename index_type>
1380void
1382{
1383 if (_layout != array._layout)
1384 mooseError("Kokkos array error: cannot deep copy arrays with different layouts.");
1385
1387 mooseError(
1388 "Kokkos array error: cannot deep copy using constructor from array without host data.");
1389
1390 std::vector<index_type> n(std::begin(array._n), std::end(array._n));
1391
1392 createInternal<false>(n, array._is_host_alloc, array._is_device_alloc);
1393
1394 if (_is_host_alloc)
1395 for (const auto i : make_range(_size))
1396 if (array.isSlotConstructed(i))
1397 emplaceAt(i, array._host_data[i]);
1398
1400 copyToDevice();
1401 else if (_is_device_alloc)
1402 copyInternal<MemSpace, MemSpace>(_device_data, array._device_data, _size);
1403
1404 for (const auto i : make_range(dimension))
1405 {
1406 _d[i] = array._d[i];
1407 _s[i] = array._s[i];
1408 }
1409}
1410
1411template <typename T, unsigned int dimension, typename index_type>
1412void
1421
1422template <typename T, unsigned int dimension, typename index_type>
1423auto &
1425{
1426 if (_is_host_alloc)
1427 std::fill_n(_host_data, _size, scalar);
1428
1429 if (_is_device_alloc)
1430 ::Kokkos::Experimental::fill_n(ExecSpace(), deviceView(), _size, scalar);
1431
1432 return *this;
1433}
1434
1435template <typename T, unsigned int dimension, typename index_type, LayoutType layout>
1436void
1437dataStore(std::ostream & stream, Array<T, dimension, index_type, layout> & array, void * context)
1438{
1439 using ::dataStore;
1440
1441 bool is_alloc = array.isAlloc();
1442 dataStore(stream, is_alloc, nullptr);
1443
1444 if (!is_alloc)
1445 return;
1446
1447 std::string type = typeid(T).name();
1448 dataStore(stream, type, nullptr);
1449
1450 unsigned int dim = dimension;
1451 dataStore(stream, dim, nullptr);
1452
1453 for (const auto dim : make_range(dimension))
1454 {
1455 auto n = array.n(dim);
1456 dataStore(stream, n, nullptr);
1457 }
1458
1459 if (array.isDeviceAlloc())
1460 {
1461 // We use malloc/free because we just want a memory copy
1462 // If T is a Kokkos array and we use new/delete or vector to copy it out,
1463 // the arrays will be destroyed on cleanup
1464
1465 T * data = static_cast<T *>(std::malloc(array.size() * sizeof(T)));
1466
1468
1469 for (const auto i : make_range(array.size()))
1470 dataStore(stream, data[i], context);
1471
1472 std::free(data);
1473 }
1474 else
1475 for (auto & value : array)
1476 dataStore(stream, value, context);
1477}
1478
1479template <typename T, unsigned int dimension, typename index_type, LayoutType layout>
1480void
1481dataLoad(std::istream & stream, Array<T, dimension, index_type, layout> & array, void * context)
1482{
1483 using ::dataLoad;
1484
1485 bool is_alloc;
1486 dataLoad(stream, is_alloc, nullptr);
1487
1488 if (!is_alloc)
1489 return;
1490
1491 std::string from_type_name;
1492 dataLoad(stream, from_type_name, nullptr);
1493
1494 if (from_type_name != typeid(T).name())
1495 mooseError("Kokkos array error: cannot load array because the stored array is of type '",
1496 MooseUtils::prettyCppType(libMesh::demangle(from_type_name.c_str())),
1497 "' but the loading array is of type '",
1499 "'.");
1500
1501 unsigned int from_dimension;
1502 dataLoad(stream, from_dimension, nullptr);
1503
1504 if (from_dimension != dimension)
1505 mooseError("Kokkos array error: cannot load array because the stored array is ",
1506 from_dimension,
1507 "D but the loading array is ",
1508 dimension,
1509 "D.");
1510
1511 std::vector<index_type> from_n(dimension);
1512 std::vector<index_type> n(dimension);
1513
1514 for (const auto dim : make_range(dimension))
1515 {
1516 dataLoad(stream, from_n[dim], nullptr);
1517 n[dim] = array.n(dim);
1518 }
1519
1520 if (from_n != n)
1521 mooseError("Kokkos array error: cannot load array because the stored array has dimensions (",
1522 Moose::stringify(from_n),
1523 ") but the loading array has dimensions (",
1525 ").");
1526
1527 if (array.isHostAlloc())
1528 {
1529 for (auto & value : array)
1530 dataLoad(stream, value, context);
1531
1532 if (array.isDeviceAlloc())
1533 array.copyToDevice();
1534 }
1535 else
1536 {
1537 std::vector<T> data(array.size());
1538
1539 for (auto & value : data)
1540 dataLoad(stream, value, context);
1541
1542 array.copyIn(data.data(), MemcpyType::HOST_TO_DEVICE, array.size());
1543 }
1544}
1545#endif
1546
1563template <typename T, unsigned int dimension, typename index_type, LayoutType layout>
1564class Array : public ArrayBase<T, dimension, index_type>
1565{
1566#ifdef MOOSE_KOKKOS_SCOPE
1567 usingKokkosArrayBaseMembers(T, dimension, index_type);
1568#endif
1569
1570public:
1574 Array() : ArrayBase<T, dimension, index_type>(layout) {}
1579 : ArrayBase<T, dimension, index_type>(array)
1580 {
1581 }
1582#ifdef MOOSE_KOKKOS_SCOPE
1589 template <typename... size_type>
1590 Array(size_type... n) : ArrayBase<T, dimension, index_type>(layout, n...)
1591 {
1592 }
1593#endif
1594
1600 {
1601 this->shallowCopy(array);
1602
1603 return *this;
1604 }
1605
1606#ifdef MOOSE_KOKKOS_SCOPE
1613 template <typename... indices>
1614 KOKKOS_FUNCTION T & operator()(indices... i) const
1615 {
1616 return this->operator[](linearIndex(i...));
1617 }
1624 KOKKOS_FUNCTION T & operator()(const signed_index_type (&idx)[dimension]) const
1625 {
1626 return this->operator[](linearIndex(idx));
1627 }
1634 template <typename indices, typename... Args>
1635 T & emplace(const indices (&idx)[dimension], Args &&... args);
1636#endif
1637
1638private:
1639#ifdef MOOSE_KOKKOS_SCOPE
1643 template <typename... indices>
1644 KOKKOS_FUNCTION index_type linearIndex(indices... i) const;
1649 template <typename indices>
1650 KOKKOS_FUNCTION index_type linearIndex(const indices (&idx)[dimension]) const
1651 {
1652 return linearIndexHelper(idx, std::make_integer_sequence<unsigned int, dimension>{});
1653 }
1654 template <typename indices, unsigned int... i>
1655 KOKKOS_FUNCTION index_type linearIndexHelper(const indices (&idx)[dimension],
1656 std::integer_sequence<unsigned int, i...>) const
1657 {
1658 return linearIndex(idx[i]...);
1659 }
1661#endif
1662};
1663
1664#ifdef MOOSE_KOKKOS_SCOPE
1665template <typename T, unsigned int dimension, typename index_type, LayoutType layout>
1666template <typename indices, typename... Args>
1667T &
1668Array<T, dimension, index_type, layout>::emplace(const indices (&idx)[dimension], Args &&... args)
1669{
1670 return this->emplaceAt(linearIndex(idx), std::forward<Args>(args)...);
1671}
1672
1673template <typename T, unsigned int dimension, typename index_type, LayoutType layout>
1674template <typename... indices>
1675KOKKOS_FUNCTION index_type
1677{
1678 static_assert((std::is_convertible<indices, signed_index_type>::value && ...),
1679 "All arguments must be convertible to signed_index_type");
1680 static_assert(sizeof...(i) == dimension, "Number of arguments should match array dimension");
1681
1682#ifndef NDEBUG
1683 {
1684 signed_index_type idx[dimension] = {static_cast<signed_index_type>(i)...};
1685
1686 for (unsigned int d = 0; d < sizeof...(i); ++d)
1687 KOKKOS_ASSERT(idx[d] - _d[d] >= 0 && static_cast<index_type>(idx[d] - _d[d]) < _n[d]);
1688 }
1689#endif
1690
1691 index_type idx = 0;
1692 unsigned int d = 0;
1693
1694 if constexpr (layout == LayoutType::LEFT)
1695 (((idx += (d == 0 ? static_cast<signed_index_type>(i) - _d[d]
1696 : (static_cast<signed_index_type>(i) - _d[d]) * _s[d])),
1697 ++d),
1698 ...);
1699 else
1700 (((idx += (d == dimension - 1 ? static_cast<signed_index_type>(i) - _d[d]
1701 : (static_cast<signed_index_type>(i) - _d[d]) * _s[d])),
1702 ++d),
1703 ...);
1704
1705 return idx;
1706}
1707#endif
1708
1709template <typename T, typename index_type>
1710class Array<T, 1, index_type, LayoutType::LEFT> : public ArrayBase<T, 1, index_type>
1711{
1712#ifdef MOOSE_KOKKOS_SCOPE
1714#endif
1715
1716public:
1720 Array() : ArrayBase<T, 1, index_type>(LayoutType::LEFT) {}
1725 : ArrayBase<T, 1, index_type>(array)
1726 {
1727 }
1728#ifdef MOOSE_KOKKOS_SCOPE
1735 Array(index_type n) : ArrayBase<T, 1, index_type>(LayoutType::LEFT, n) {}
1742 Array(const std::vector<T> & vector) : ArrayBase<T, 1, index_type>(LayoutType::LEFT)
1743 {
1744 *this = vector;
1745 }
1746#endif
1747
1753 {
1754 this->shallowCopy(array);
1755
1756 return *this;
1757 }
1758
1759#ifdef MOOSE_KOKKOS_SCOPE
1767 template <bool host, bool device>
1768 void copyVector(const std::vector<T> & vector)
1769 {
1770 this->template createInternal<host, device, false>({static_cast<index_type>(vector.size())});
1771
1772 if (host)
1773 {
1774 if constexpr (std::is_trivially_copyable<T>())
1775 std::memcpy(this->hostData(), vector.data(), this->size() * sizeof(T));
1776 else
1777 std::copy(vector.begin(), vector.end(), this->begin());
1778 }
1779
1780 if (device)
1781 this->template copyInternal<MemSpace, ::Kokkos::HostSpace>(
1782 this->deviceData(), vector.data(), this->size());
1783 }
1791 template <bool host, bool device>
1792 void copySet(const std::set<T> & set)
1793 {
1794 std::vector<T> vector(set.begin(), set.end());
1795
1796 copyVector<host, device>(vector);
1797 }
1798
1804 auto & operator=(const std::vector<T> & vector)
1805 {
1806 copyVector<true, true>(vector);
1807
1808 return *this;
1809 }
1815 auto & operator=(const std::set<T> & set)
1816 {
1817 copySet<true, true>(set);
1818
1819 return *this;
1820 }
1827 KOKKOS_FUNCTION T & operator()(signed_index_type i) const
1828 {
1829 return this->operator[](linearIndex(i));
1830 }
1837 template <typename indices, typename... Args>
1838 T & emplace(const indices (&idx)[1], Args &&... args);
1843
1847 void axby(const T a,
1849 const char op,
1850 const T b,
1852 const bool accumulate = false);
1860 void scal(const T a);
1868 T nrm2();
1870
1871private:
1875 KOKKOS_FUNCTION index_type linearIndex(signed_index_type i) const;
1876#endif
1877};
1879
1880#ifdef MOOSE_KOKKOS_SCOPE
1881template <typename T, typename index_type>
1882template <typename indices, typename... Args>
1883T &
1884Array<T, 1, index_type, LayoutType::LEFT>::emplace(const indices (&idx)[1], Args &&... args)
1885{
1886 return this->emplaceAt(linearIndex(idx[0]), std::forward<Args>(args)...);
1887}
1888
1889template <typename T, typename index_type>
1890KOKKOS_FUNCTION index_type
1893{
1894 KOKKOS_ASSERT(i - _d[0] >= 0 && static_cast<index_type>(i - _d[0]) < _n[0]);
1895
1896 return i - _d[0];
1897}
1898#endif
1899
1900template <typename T, typename index_type = MOOSE_KOKKOS_INDEX_TYPE>
1902template <typename T,
1903 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,
1918
1919} // 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:165
std::string stringify(const T &t)
conversion to string
Definition Conversion.h:64
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