https://mooseframework.inl.gov
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) \
22 private: \
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  \
27 public: \
28  using typename ArrayBase<T, dimension, index_type>::signed_index_type; \
29  using ArrayBase<T, dimension, index_type>::operator=
30 
31 namespace 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
36 void free(void * ptr);
37 
41 enum class MemcpyType
42 {
47 };
48 
52 enum class LayoutType
53 {
54  LEFT,
55  RIGHT
56 };
57 
61 template <typename T,
62  unsigned int dimension = 1,
63  typename index_type = MOOSE_KOKKOS_INDEX_TYPE,
65 class Array;
66 
70 template <typename>
72 struct is_kokkos_array : std::false_type
73 {
74 };
75 
76 template <typename T, unsigned int dimension, typename index_type, LayoutType layout>
77 struct is_kokkos_array<Array<T, dimension, index_type, layout>> : std::true_type
78 {
79 };
81 
89 template <typename T>
92 {
93  static constexpr bool value = false;
94 };
95 
96 template <typename T, unsigned int dimension, typename index_type, LayoutType layout>
97 struct ArrayDeepCopy<Array<T, dimension, index_type, layout>>
98 {
99  static constexpr bool value = ArrayDeepCopy<T>::value;
100 };
102 
106 template <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 
113 public:
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
124 
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>
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; }
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 
218  void advanceToConstructed();
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 
242  iterator begin() const;
243  iterator end() const;
244 
245  private:
250  };
251 
257 
263 
264 #ifdef MOOSE_KOKKOS_SCOPE
265 
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>>(
366  _host_data, _size);
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);
464  void copyToDevice();
468  void copyToHost();
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);
488  void copyToDeviceNested();
495  void moveToDevice(bool should_free_host = true);
502  void moveToHost(bool should_free_device = true);
509  void deepCopy(const ArrayBase<T, dimension, index_type> & array);
515 
520  auto & operator=(const T & scalar);
521 
525  class iterator
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 
586 protected:
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
601 
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 
648 private:
649 #ifdef MOOSE_KOKKOS_SCOPE
650 
654  template <bool initialize>
655  void allocHost();
659  void allocDevice();
660 #endif
661 
664  void freeHost();
668  void freeDevice();
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 
716 template <typename T, unsigned int dimension, typename index_type>
717 template <bool is_const>
721  is_const>::array_type & array,
722  index_type i)
723  : _array(array), _i(i)
724 {
726 }
727 
728 template <typename T, unsigned int dimension, typename index_type>
729 template <bool is_const>
732 {
733  ++_i;
734  advanceToConstructed();
735  return *this;
736 }
737 
738 template <typename T, unsigned int dimension, typename index_type>
739 template <bool is_const>
742 {
743  constructed_entry_iterator pre = *this;
744  ++(*this);
745  return pre;
746 }
747 
748 template <typename T, unsigned int dimension, typename index_type>
749 template <bool is_const>
750 bool
752  const constructed_entry_iterator & other) const
753 {
754  return &_array == &other._array && _i == other._i;
755 }
756 
757 template <typename T, unsigned int dimension, typename index_type>
758 template <bool is_const>
759 bool
761  const constructed_entry_iterator & other) const
762 {
763  return !(*this == other);
764 }
765 
766 template <typename T, unsigned int dimension, typename index_type>
767 template <bool is_const>
768 void
770 {
771  while (_i < _array._size && !_array.isSlotConstructed(_i))
772  ++_i;
773 }
774 
775 template <typename T, unsigned int dimension, typename index_type>
776 template <bool is_const>
779  is_const>::array_type & array)
780  : _array(array)
781 {
782 }
783 
784 template <typename T, unsigned int dimension, typename index_type>
785 template <bool is_const>
788 {
789  return iterator(_array, 0);
790 }
791 
792 template <typename T, unsigned int dimension, typename index_type>
793 template <bool is_const>
796 {
797  return iterator(_array, _array._size);
798 }
799 
800 template <typename T, unsigned int dimension, typename index_type>
803 {
804  return constructed_entry_range<false>(*this);
805 }
806 
807 template <typename T, unsigned int dimension, typename index_type>
808 typename ArrayBase<T, dimension, index_type>::template constructed_entry_range<true>
810 {
811  return constructed_entry_range<true>(*this);
812 }
813 
814 template <typename T, unsigned int dimension, typename index_type>
815 bool
817 {
818  mooseAssert(i < _size, "isSlotConstructed index out of bounds");
819 
820  if (!_slots_constructed)
821  return _is_host_alloc;
822 
823  return (*_slots_constructed)[i];
824 }
825 
826 #ifdef MOOSE_KOKKOS_SCOPE
827 template <typename T, unsigned int dimension, typename index_type>
828 template <typename... Args>
829 T &
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 
843 template <typename T, unsigned int dimension, typename index_type>
844 void
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  {
857  if (!_slots_constructed)
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 
868 
869  _slots_constructed.reset();
870  }
871  }
872 
873  _is_host_alloc = false;
874 }
875 
876 template <typename T, unsigned int dimension, typename index_type>
877 void
879 {
880  if (!_is_device_alloc)
881  return;
882 
883  if (_is_device_alias)
884  {
885  _device_data = nullptr;
886  _is_device_alias = false;
887  }
888  else
890 
891  _is_device_alloc = false;
892 }
893 
894 template <typename T, unsigned int dimension, typename index_type>
895 void
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 
931 template <typename T, unsigned int dimension, typename index_type>
932 void
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;
959  _device_data = array._device_data;
960 }
961 
962 #ifdef MOOSE_KOKKOS_SCOPE
963 template <typename T, unsigned int dimension, typename index_type>
964 void
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 
978 template <typename T, unsigned int dimension, typename index_type>
979 void
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 
993 template <typename T, unsigned int dimension, typename index_type>
994 template <bool initialize>
995 void
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 
1018 template <typename T, unsigned int dimension, typename index_type>
1019 void
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 
1031 template <typename T, unsigned int dimension, typename index_type>
1032 template <bool host, bool device, bool initialize>
1033 void
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 
1070  if (_layout == LayoutType::LEFT)
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 
1094 template <typename T, unsigned int dimension, typename index_type>
1095 template <bool initialize>
1096 void
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 
1111 template <typename T, unsigned int dimension, typename index_type>
1112 template <bool host, bool device, bool initialize, typename... size_type>
1113 void
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 
1126 template <typename T, unsigned int dimension, typename index_type>
1127 template <typename TargetSpace, typename SourceSpace>
1128 void
1129 ArrayBase<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 
1135 template <typename T, unsigned int dimension, typename index_type>
1136 void
1137 ArrayBase<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 
1150 template <typename T, unsigned int dimension, typename index_type>
1151 template <typename... offset_type>
1152 void
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 
1165 template <typename T, unsigned int dimension, typename index_type>
1166 void
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 
1190 template <typename T, unsigned int dimension, typename index_type>
1191 void
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 
1215 template <typename T, unsigned int dimension, typename index_type>
1216 void
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 
1232 template <typename T, unsigned int dimension, typename index_type>
1233 void
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 
1246 template <typename T, unsigned int dimension, typename index_type>
1247 void
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 
1301 template <typename T, unsigned int dimension, typename index_type>
1302 void
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 
1356 template <typename T>
1357 void
1358 copyToDeviceInner(T & /* data */)
1359 {
1360 }
1361 
1362 template <typename T, unsigned int dimension, typename index_type, LayoutType layout>
1363 void
1365 {
1366  data.copyToDeviceNested();
1367 }
1368 
1369 template <typename T, unsigned int dimension, typename index_type>
1370 void
1372 {
1373  for (const auto i : make_range(_size))
1375 
1376  copyToDevice();
1377 }
1378 
1379 template <typename T, unsigned int dimension, typename index_type>
1380 void
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 
1411 template <typename T, unsigned int dimension, typename index_type>
1412 void
1414 {
1416 
1417  clone.shallowCopy(*this);
1418  this->shallowCopy(array);
1419  array.shallowCopy(clone);
1420 }
1421 
1422 template <typename T, unsigned int dimension, typename index_type>
1423 auto &
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 
1435 template <typename T, unsigned int dimension, typename index_type, LayoutType layout>
1436 void
1437 dataStore(std::ostream & stream, Array<T, dimension, index_type, layout> & array, void * context)
1438 {
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 
1467  array.copyOut(data, MemcpyType::DEVICE_TO_HOST, array.size());
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 
1479 template <typename T, unsigned int dimension, typename index_type, LayoutType layout>
1480 void
1481 dataLoad(std::istream & stream, Array<T, dimension, index_type, layout> & array, void * context)
1482 {
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 
1562 template <typename T, unsigned int dimension, typename index_type, LayoutType layout>
1564 class Array : public ArrayBase<T, dimension, index_type>
1565 {
1566 #ifdef MOOSE_KOKKOS_SCOPE
1567  usingKokkosArrayBaseMembers(T, dimension, index_type);
1568 #endif
1569 
1570 public:
1574  Array() : ArrayBase<T, dimension, index_type>(layout) {}
1579  : ArrayBase<T, dimension, index_type>(array)
1580  {
1581  }
1582 #ifdef MOOSE_KOKKOS_SCOPE
1583 
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
1607 
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 
1638 private:
1639 #ifdef MOOSE_KOKKOS_SCOPE
1640 
1643  template <typename... indices>
1644  KOKKOS_FUNCTION index_type linearIndex(indices... i) const;
1648  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
1665 template <typename T, unsigned int dimension, typename index_type, LayoutType layout>
1666 template <typename indices, typename... Args>
1667 T &
1668 Array<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 
1673 template <typename T, unsigned int dimension, typename index_type, LayoutType layout>
1674 template <typename... indices>
1675 KOKKOS_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 
1709 template <typename T, typename index_type>
1710 class Array<T, 1, index_type, LayoutType::LEFT> : public ArrayBase<T, 1, index_type>
1711 {
1712 #ifdef MOOSE_KOKKOS_SCOPE
1713  usingKokkosArrayBaseMembers(T, 1, index_type);
1714 #endif
1715 
1716 public:
1720  Array() : ArrayBase<T, 1, index_type>(LayoutType::LEFT) {}
1725  : ArrayBase<T, 1, index_type>(array)
1726  {
1727  }
1728 #ifdef MOOSE_KOKKOS_SCOPE
1729 
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
1760 
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);
1842 
1847  void axby(const T a,
1849  const char op,
1850  const T b,
1852  const bool accumulate = false);
1856  void scal(const T a, const Array<T, 1, index_type, LayoutType::LEFT> & x);
1860  void scal(const T a);
1868  T nrm2();
1870 
1871 private:
1875  KOKKOS_FUNCTION index_type linearIndex(signed_index_type i) const;
1876 #endif
1877 };
1879 
1880 #ifdef MOOSE_KOKKOS_SCOPE
1881 template <typename T, typename index_type>
1882 template <typename indices, typename... Args>
1883 T &
1884 Array<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 
1889 template <typename T, typename index_type>
1890 KOKKOS_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 
1900 template <typename T, typename index_type = MOOSE_KOKKOS_INDEX_TYPE>
1902 template <typename T,
1903  typename index_type = MOOSE_KOKKOS_INDEX_TYPE,
1904  LayoutType layout = LayoutType::LEFT>
1906 template <typename T,
1907  typename index_type = MOOSE_KOKKOS_INDEX_TYPE,
1908  LayoutType layout = LayoutType::LEFT>
1910 template <typename T,
1911  typename index_type = MOOSE_KOKKOS_INDEX_TYPE,
1912  LayoutType layout = LayoutType::LEFT>
1914 template <typename T,
1915  typename index_type = MOOSE_KOKKOS_INDEX_TYPE,
1916  LayoutType layout = LayoutType::LEFT>
1918 
1919 } // namespace Moose::Kokkos
KOKKOS_FUNCTION index_type linearIndex(indices... i) const
Get the dimensionless index for a multi-dimensional index.
Definition: KokkosArray.h:1676
std::string name(const ElemQuality q)
T * deviceData() const
Get the device data pointer.
Definition: KokkosArray.h:358
The Kokkos array class.
Definition: KokkosArray.h:65
MemcpyType
The enumerator that dictates the memory copy direction.
Definition: KokkosArray.h:41
KOKKOS_FUNCTION index_type n(unsigned int dim) const
Get the size of a dimension.
Definition: KokkosArray.h:300
KOKKOS_FUNCTION iterator(T *p)
Definition: KokkosArray.h:535
auto & operator=(const Array< T, dimension, index_type, layout > &array)
Shallow copy another Kokkos array.
Definition: KokkosArray.h:1599
void moveToHost(bool should_free_device=true)
Copy data from device to host and deallocate device.
Definition: KokkosArray.h:1234
KOKKOS_FUNCTION pointer operator &() const
Definition: KokkosArray.h:539
KOKKOS_FUNCTION T & last() const
Get the last element.
Definition: KokkosArray.h:328
Array(const Array< T, dimension, index_type, layout > &array)
Copy constructor.
Definition: KokkosArray.h:1578
signed_index_type _d[dimension]
Offset of each dimension.
Definition: KokkosArray.h:598
LayoutType
The enumerator that dictates the memory layout.
Definition: KokkosArray.h:52
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...
Definition: KokkosArray.h:1768
KOKKOS_FUNCTION iterator operator++(int)
Definition: KokkosArray.h:545
array_type & _array
Array that provides the constructed-entry iteration bounds.
Definition: KokkosArray.h:249
KOKKOS_FUNCTION T & operator()(indices... i) const
Get an array entry.
Definition: KokkosArray.h:1614
Array()
Default constructor.
Definition: KokkosArray.h:1574
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:311
KOKKOS_FUNCTION bool isDeviceAlloc() const
Get whether the array was allocated on device.
Definition: KokkosArray.h:279
void dataLoad(std::istream &stream, Array< T, dimension, index_type, layout > &array, void *context)
Definition: KokkosArray.h:1481
std::conditional_t< is_const, const T *, T * > pointer
Definition: KokkosArray.h:202
iterator begin() const
Definition: KokkosArray.h:787
index_type _i
Current slot index in _array.
Definition: KokkosArray.h:227
void createHost(size_type... n)
Allocate array on host only.
Definition: KokkosArray.h:422
std::conditional_t< is_const, const ArrayBase, ArrayBase > array_type
Definition: KokkosArray.h:204
KOKKOS_FUNCTION T & operator[](index_type i) const
Get an array entry.
Definition: KokkosArray.h:340
KOKKOS_FUNCTION T & operator()(signed_index_type i) const
Get an array entry.
Definition: KokkosArray.h:1827
KOKKOS_FUNCTION iterator end() const
Get the end iterator.
Definition: KokkosArray.h:578
void moveToDevice(bool should_free_host=true)
Copy data from host to device and deallocate host.
Definition: KokkosArray.h:1217
bool operator!=(const ReporterProducerEnum &producer_mode, const ReporterMode &mode)
Definition: ReporterMode.h:91
bool isSlotConstructed(index_type i) const
Get whether slot i is tracked as constructed.
Definition: KokkosArray.h:816
KOKKOS_FUNCTION T & first() const
Get the first element.
Definition: KokkosArray.h:317
void shallowCopy(const ArrayBase< T, dimension, index_type > &array)
Shallow copy another Kokkos array.
Definition: KokkosArray.h:933
static constexpr std::size_t dim
This is the dimension of all vector and tensor datastructures used in MOOSE.
Definition: Moose.h:165
iterator end() const
Definition: KokkosArray.h:795
The type trait that determines if a template type is Kokkos array.
Definition: KokkosArray.h:72
void allocDevice()
Allocate device data for an initialized array that has not allocated device data. ...
Definition: KokkosArray.h:1020
bool _is_device_alloc
Flag whether device data was allocated.
Definition: KokkosArray.h:689
std::conditional_t< is_const, const ArrayBase, ArrayBase > array_type
Definition: KokkosArray.h:237
T * _host_data
Host data.
Definition: KokkosArray.h:701
Array(size_type... n)
Constructor Initialize and allocate array with given dimensions This allocates both host and device d...
Definition: KokkosArray.h:1590
void copyOut(T *ptr, MemcpyType dir, index_type n, index_type offset=0)
Copy data to an external data from this array.
Definition: KokkosArray.h:1303
index_type _s[dimension]
Stride of each dimension.
Definition: KokkosArray.h:594
void swap(ArrayBase< T, dimension, index_type > &array)
Swap with another Kokkos array.
Definition: KokkosArray.h:1413
void allocHost()
Allocate host data for an initialized array that has not allocated host data.
Definition: KokkosArray.h:996
void createInternal(size_type... n)
The internal method to initialize and allocate this array.
Definition: KokkosArray.h:1114
void initialize(EquationSystems &es, const std::string &system_name)
Range over tracked constructed entries.
Definition: KokkosArray.h:190
bool _is_host_alloc
Flag whether host data was allocated.
Definition: KokkosArray.h:685
auto max(const L &left, const R &right)
void aliasDevice(T *ptr)
Point the device data to an external data instead of allocating it.
Definition: KokkosArray.h:980
KOKKOS_FUNCTION index_type linearIndexHelper(const indices(&idx)[dimension], std::integer_sequence< unsigned int, i... >) const
Definition: KokkosArray.h:1655
constructed_entry_iterator & operator++()
Definition: KokkosArray.h:731
void advanceToConstructed()
Definition: KokkosArray.h:769
Array(const Array< T, 1, index_type, LayoutType::LEFT > &array)
Copy constructor.
Definition: KokkosArray.h:1724
auto hostView() const
Get the host unmanaged view.
Definition: KokkosArray.h:363
KOKKOS_FUNCTION bool isHostAlloc() const
Get whether the array was allocated on host.
Definition: KokkosArray.h:274
auto deviceView() const
Get the device unmanaged view.
Definition: KokkosArray.h:372
void freeDevice()
Free device data.
Definition: KokkosArray.h:878
KOKKOS_FUNCTION bool isDeviceAlias() const
Get whether the device array was aliased.
Definition: KokkosArray.h:289
bool operator!=(const constructed_entry_iterator &other) const
Definition: KokkosArray.h:760
KOKKOS_FUNCTION bool isAlloc() const
Get whether the array was allocated either on host or device.
Definition: KokkosArray.h:269
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...
Definition: KokkosArray.h:1792
index_type _size
Total size.
Definition: KokkosArray.h:709
const LayoutType _layout
Memory layout type.
Definition: KokkosArray.h:713
KOKKOS_FUNCTION pointer operator->() const
Definition: KokkosArray.h:538
~ArrayBase()
Destructor.
Definition: KokkosArray.h:157
bool operator==(const std::unique_ptr< Attribute > &lhs, const std::unique_ptr< Attribute > &rhs)
TheWarehouse uses this operator function for indexing and caching queries.
Definition: TheWarehouse.C:31
bool _is_device_alias
Flag whether the device data points to an external data.
Definition: KokkosArray.h:697
KOKKOS_FUNCTION friend bool operator==(const iterator &a, const iterator &b)
Definition: KokkosArray.h:551
Iterator over tracked constructed entries.
Definition: KokkosArray.h:196
Real value(unsigned n, unsigned alpha, unsigned beta, Real x)
void copyToDeviceInner(T &)
Definition: KokkosArray.h:1358
unsigned int useCount() const
Get the reference count.
Definition: KokkosArray.h:174
std::forward_iterator_tag iterator_category
Definition: KokkosArray.h:199
Array(const std::vector< T > &vector)
Constructor Initialize and allocate array by copying a standard vector variable This allocates and co...
Definition: KokkosArray.h:1742
void create(const std::vector< index_type > &n)
Allocate array on host and device.
Definition: KokkosArray.h:392
constructed_entry_range< false > constructedEntries()
Get host-side range over entries tracked as constructed.
Definition: KokkosArray.h:802
KOKKOS_FUNCTION T * data() const
Get the data pointer.
Definition: KokkosArray.h:306
void aliasHost(T *ptr)
Point the host data to an external data instead of allocating it.
Definition: KokkosArray.h:965
The base class for Kokkos arrays.
Definition: KokkosArray.h:107
T & emplaceAt(index_type i, Args &&... args)
Placement-new construct slot i from args, recording initialization.
Definition: KokkosArray.h:830
void copyToDevice()
Copy data from host to device.
Definition: KokkosArray.h:1167
KOKKOS_FUNCTION index_type size() const
Get the total array size.
Definition: KokkosArray.h:294
void dataStore(std::ostream &stream, Array< T, dimension, index_type, layout > &array, void *context)
Definition: KokkosArray.h:1437
void create(size_type... n)
Allocate array on host and device.
Definition: KokkosArray.h:402
void copyIn(const T *ptr, MemcpyType dir, index_type n, index_type offset=0)
Copy data from an external data to this array.
Definition: KokkosArray.h:1248
void destroy()
Free all data and reset.
Definition: KokkosArray.h:896
std::string stringify(const T &t)
conversion to string
Definition: Conversion.h:64
ArrayBase(const ArrayBase< T, dimension, index_type > &array)
Copy constructor.
Definition: KokkosArray.h:141
std::string demangle(const char *name)
std::shared_ptr< unsigned int > _counter
Reference counter.
Definition: KokkosArray.h:673
KOKKOS_FUNCTION iterator & operator++()
Definition: KokkosArray.h:540
KOKKOS_FUNCTION friend bool operator!=(const iterator &a, const iterator &b)
Definition: KokkosArray.h:555
void free(void *ptr)
ArrayBase(const LayoutType layout)
Constructor.
Definition: KokkosArray.h:121
The type trait that determines the default behavior of copy constructor and deepCopy() If this type t...
Definition: KokkosArray.h:91
bool _is_host_alias
Flag whether the host data points to an external data.
Definition: KokkosArray.h:693
KOKKOS_FUNCTION T & operator()(const signed_index_type(&idx)[dimension]) const
Get an array entry using indices stored in an array.
Definition: KokkosArray.h:1624
auto & operator=(const T &scalar)
Assign a scalar value uniformly.
Definition: KokkosArray.h:1424
std::conditional_t< is_const, const T &, T & > reference
Definition: KokkosArray.h:203
void createDevice(const std::vector< index_type > &n)
Allocate array on device only.
Definition: KokkosArray.h:430
KOKKOS_FUNCTION reference operator*() const
Definition: KokkosArray.h:537
KOKKOS_FUNCTION iterator begin() const
Get the beginning iterator.
Definition: KokkosArray.h:568
void copyInternal(T *target, const T *source, index_type n)
The internal method to perform a memory copy.
Definition: KokkosArray.h:1129
T & emplace(const indices(&idx)[dimension], Args &&... args)
Placement-new construct an entry from args, recording initialization.
Definition: KokkosArray.h:1668
std::shared_ptr< std::vector< bool > > _slots_constructed
Non-null only for malloc-allocated arrays; tracks which slots have been emplace-constructed.
Definition: KokkosArray.h:677
pointer operator->() const
Definition: KokkosArray.h:207
std::forward_iterator_tag iterator_category
Definition: KokkosArray.h:528
IntRange< T > make_range(T beg, T end)
infix_ostream_iterator< T, charT, traits > & operator++()
Definition: InfixIterator.h:58
array_type & _array
Array whose constructed entries are being iterated.
Definition: KokkosArray.h:223
auto & operator=(const Array< T, 1, index_type, LayoutType::LEFT > &array)
Shallow copy another Kokkos array.
Definition: KokkosArray.h:1752
void init(size_type... n)
Initialize array with given dimensions but do not allocate.
Definition: KokkosArray.h:382
constructed_entry_iterator(array_type &array, index_type i)
Definition: KokkosArray.h:719
reference operator*() const
Definition: KokkosArray.h:206
T * hostData() const
Get the host data pointer.
Definition: KokkosArray.h:353
T * _device_data
Device data.
Definition: KokkosArray.h:705
auto & operator=(const std::set< T > &set)
Copy a standard set variable This allocates and copies to both host and device data.
Definition: KokkosArray.h:1815
T value_type
Definition: KokkosArray.h:200
bool operator==(const constructed_entry_iterator &other) const
Definition: KokkosArray.h:751
Array(index_type n)
Constructor Initialize and allocate array with given size This allocates both host and device data...
Definition: KokkosArray.h:1735
void copyToDeviceNested()
Copy all the nested Kokkos arrays including self from host to device.
Definition: KokkosArray.h:1371
auto & operator=(const std::vector< T > &vector)
Copy a standard vector variable This allocates and copies to both host and device data...
Definition: KokkosArray.h:1804
void createDevice(size_type... n)
Allocate array on device only.
Definition: KokkosArray.h:436
constructed_entry_range(array_type &array)
Definition: KokkosArray.h:777
bool _is_init
Flag whether array was initialized.
Definition: KokkosArray.h:681
void copyToHost()
Copy data from device to host.
Definition: KokkosArray.h:1192
void createHost(const std::vector< index_type > &n)
Allocate array on host only.
Definition: KokkosArray.h:412
ArrayBase(const LayoutType layout, size_type... n)
Constructor Initialize and allocate array with given dimensions This allocates both host and device d...
Definition: KokkosArray.h:132
std::ptrdiff_t difference_type
Definition: KokkosArray.h:201
void freeHost()
Free host data.
Definition: KokkosArray.h:845
KOKKOS_FUNCTION bool isHostAlias() const
Get whether the host array was aliased.
Definition: KokkosArray.h:284
auto index_range(const T &sizable)
KOKKOS_FUNCTION index_type linearIndex(const indices(&idx)[dimension]) const
Get the dimensionless index for indices stored in an array.
Definition: KokkosArray.h:1650
static constexpr bool value
Definition: KokkosArray.h:93
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 ...
Definition: KokkosArray.h:1381
unsigned int idx(const ElemType type, const unsigned int nx, const unsigned int i, const unsigned int j)
std::string prettyCppType(const std::string &cpp_type)
Definition: MooseUtils.C:1151
index_type _n[dimension]
Size of each dimension.
Definition: KokkosArray.h:590
void offset(const std::vector< signed_index_type > &d)
Apply starting index offsets to each dimension.
Definition: KokkosArray.h:1137