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 #define usingKokkosArrayBaseMembers(T, dimension, index_type) \
20 private: \
21  using ArrayBase<T, dimension, index_type>::_n; \
22  using ArrayBase<T, dimension, index_type>::_s; \
23  using ArrayBase<T, dimension, index_type>::_d; \
24  using ArrayBase<T, dimension, index_type>::_is_offset; \
25  \
26 public: \
27  using typename ArrayBase<T, dimension, index_type>::signed_index_type; \
28  using ArrayBase<T, dimension, index_type>::operator=
29 
30 namespace Moose::Kokkos
31 {
32 
33 // This function simply calls ::Kokkos::kokkos_free, but it is separately defined in KokkosArray.K
34 // because the Kokkos function cannot be directly seen by the host compiler
35 void free(void * ptr);
36 
40 enum class MemcpyType
41 {
46 };
47 
51 enum class LayoutType
52 {
53  LEFT,
54  RIGHT
55 };
56 
60 template <typename T,
61  unsigned int dimension = 1,
62  typename index_type = MOOSE_KOKKOS_INDEX_TYPE,
64 class Array;
65 
69 template <typename>
71 struct is_kokkos_array : std::false_type
72 {
73 };
74 
75 template <typename T, unsigned int dimension, typename index_type, LayoutType layout>
76 struct is_kokkos_array<Array<T, dimension, index_type, layout>> : std::true_type
77 {
78 };
80 
88 template <typename T>
91 {
92  static constexpr bool value = false;
93 };
94 
95 template <typename T, unsigned int dimension, typename index_type, LayoutType layout>
96 struct ArrayDeepCopy<Array<T, dimension, index_type, layout>>
97 {
98  static constexpr bool value = ArrayDeepCopy<T>::value;
99 };
101 
105 template <typename T, unsigned int dimension, typename index_type>
107 {
108  static_assert(std::is_integral_v<index_type>, "Kokkos array index type must be an integral type");
109  static_assert(std::is_unsigned_v<index_type>, "Kokkos array index type must be unsigned");
110  static_assert(!std::is_same_v<bool, index_type>, "Kokkos array index type must not be bool");
111 
112 public:
113  using unsigned_index_type = index_type;
114  using signed_index_type = typename std::make_signed<index_type>::type;
115 
120  ArrayBase(const LayoutType layout) : _layout(layout) {}
121 
122 #ifdef MOOSE_KOKKOS_SCOPE
123 
130  template <typename... size_type>
131  ArrayBase(const LayoutType layout, size_type... n) : _layout(layout)
132  {
133  create(n...);
134  }
135 #endif
136 
141  {
142 #ifndef MOOSE_KOKKOS_SCOPE
143  static_assert(!ArrayDeepCopy<T>::value,
144  "Kokkos array cannot be deep copied outside the Kokkos compilation scope");
145 #endif
146 
147  if constexpr (ArrayDeepCopy<T>::value)
148  deepCopy(array);
149  else
150  shallowCopy(array);
151  }
152 
157 
161  void destroy();
162 
168 
173  unsigned int useCount() const { return _counter.use_count(); }
174 
175 #ifdef MOOSE_KOKKOS_SCOPE
176 
180  KOKKOS_FUNCTION bool isAlloc() const { return _is_host_alloc || _is_device_alloc; }
185  KOKKOS_FUNCTION bool isHostAlloc() const { return _is_host_alloc; }
190  KOKKOS_FUNCTION bool isDeviceAlloc() const { return _is_device_alloc; }
195  KOKKOS_FUNCTION bool isHostAlias() const { return _is_host_alias; }
200  KOKKOS_FUNCTION bool isDeviceAlias() const { return _is_device_alias; }
205  KOKKOS_FUNCTION index_type size() const { return _size; }
211  KOKKOS_FUNCTION index_type n(unsigned int dim) const { return _n[dim]; }
217  KOKKOS_FUNCTION T * data() const
218  {
219  KOKKOS_IF_ON_HOST(return _host_data;)
220 
221  return _device_data;
222  }
228  KOKKOS_FUNCTION T & first() const
229  {
230  KOKKOS_IF_ON_HOST(return _host_data[0];)
231 
232  return _device_data[0];
233  }
239  KOKKOS_FUNCTION T & last() const
240  {
241  KOKKOS_IF_ON_HOST(return _host_data[_size - 1];)
242 
243  return _device_data[_size - 1];
244  }
251  KOKKOS_FUNCTION T & operator[](index_type i) const
252  {
253  KOKKOS_ASSERT(i < _size);
254 
255  KOKKOS_IF_ON_HOST(return _host_data[i];)
256 
257  return _device_data[i];
258  }
259 
264  T * hostData() const { return _host_data; }
269  T * deviceData() const { return _device_data; }
274  auto hostView() const
275  {
276  return ::Kokkos::View<T *, ::Kokkos::HostSpace, ::Kokkos::MemoryTraits<::Kokkos::Unmanaged>>(
277  _host_data, _size);
278  }
283  auto deviceView() const
284  {
285  return ::Kokkos::View<T *, MemSpace, ::Kokkos::MemoryTraits<::Kokkos::Unmanaged>>(_device_data,
286  _size);
287  }
292  template <typename... size_type>
293  void init(size_type... n)
294  {
295  createInternal<false, false, false>(n...);
296  }
302  template <bool initialize = true>
303  void create(const std::vector<index_type> & n)
304  {
305  createInternal<true, true, initialize>(n);
306  }
312  template <bool initialize = true, typename... size_type>
313  void create(size_type... n)
314  {
315  createInternal<true, true, initialize>(n...);
316  }
322  template <bool initialize = true>
323  void createHost(const std::vector<index_type> & n)
324  {
325  createInternal<true, false, initialize>(n);
326  }
332  template <bool initialize = true, typename... size_type>
333  void createHost(size_type... n)
334  {
335  createInternal<true, false, initialize>(n...);
336  }
341  void createDevice(const std::vector<index_type> & n) { createInternal<false, true, false>(n); }
346  template <typename... size_type>
347  void createDevice(size_type... n)
348  {
349  createInternal<false, true, false>(n...);
350  }
355  void aliasHost(T * ptr);
360  void aliasDevice(T * ptr);
365  void offset(const std::vector<signed_index_type> & d);
370  template <typename... offset_type>
371  void offset(offset_type... d);
375  void copyToDevice();
379  void copyToHost();
387  void copyIn(const T * ptr, MemcpyType dir, index_type n, index_type offset = 0);
395  void copyOut(T * ptr, MemcpyType dir, index_type n, index_type offset = 0);
399  void copyToDeviceNested();
406  void moveToDevice(bool should_free_host = true);
413  void moveToHost(bool should_free_device = true);
420  void deepCopy(const ArrayBase<T, dimension, index_type> & array);
426 
431  auto & operator=(const T & scalar);
432 
436  class iterator
437  {
438  public:
439  using iterator_category = std::forward_iterator_tag;
440  using value_type = T;
441  using difference_type = std::ptrdiff_t;
442  using pointer = T *;
443  using reference = T &;
444 
445  KOKKOS_FUNCTION iterator() : it(nullptr) {}
446  KOKKOS_FUNCTION explicit iterator(T * p) : it(p) {}
447 
448  KOKKOS_FUNCTION reference operator*() const { return *it; }
449  KOKKOS_FUNCTION pointer operator->() const { return it; }
450  KOKKOS_FUNCTION pointer operator&() const { return it; }
451  KOKKOS_FUNCTION iterator & operator++()
452  {
453  ++it;
454  return *this;
455  }
456  KOKKOS_FUNCTION iterator operator++(int)
457  {
458  iterator pre = *this;
459  ++it;
460  return pre;
461  }
462  KOKKOS_FUNCTION friend bool operator==(const iterator & a, const iterator & b)
463  {
464  return a.it == b.it;
465  }
466  KOKKOS_FUNCTION friend bool operator!=(const iterator & a, const iterator & b)
467  {
468  return a.it != b.it;
469  }
470 
471  private:
473  };
474 
479  KOKKOS_FUNCTION iterator begin() const
480  {
481  KOKKOS_IF_ON_HOST(return iterator(_host_data);)
482 
483  return iterator(_device_data);
484  }
489  KOKKOS_FUNCTION iterator end() const
490  {
491  KOKKOS_IF_ON_HOST(return iterator(_host_data + _size);)
492 
493  return iterator(_device_data + _size);
494  }
495 #endif
496 
497 protected:
501  index_type _n[dimension] = {0};
505  index_type _s[dimension] = {0};
509  signed_index_type _d[dimension] = {0};
513  bool _is_offset = false;
517  bool _is_malloc = false;
518 
519 #ifdef MOOSE_KOKKOS_SCOPE
520 
527  template <bool host, bool device, bool initialize, typename... size_type>
528  void createInternal(size_type... n);
536  template <bool host, bool device, bool initialize>
537  void createInternal(const std::vector<index_type> & n);
545  template <bool initialize>
546  void createInternal(const std::vector<index_type> & n, bool host, bool device);
555  template <typename TargetSpace, typename SourceSpace>
556  void copyInternal(T * target, const T * source, index_type n);
557 #endif
558 
559 private:
560 #ifdef MOOSE_KOKKOS_SCOPE
561 
565  template <bool initialize>
566  void allocHost();
570  void allocDevice();
571 #endif
572 
575  void freeHost();
579  void freeDevice();
580 
584  std::shared_ptr<unsigned int> _counter;
588  bool _is_init = false;
592  bool _is_host_alloc = false;
596  bool _is_device_alloc = false;
600  bool _is_host_alias = false;
604  bool _is_device_alias = false;
608  T * _host_data = nullptr;
612  T * _device_data = nullptr;
616  index_type _size = 0;
621 };
622 
623 template <typename T, unsigned int dimension, typename index_type>
624 void
626 {
627  if (!_is_host_alloc)
628  return;
629 
630  if (_is_host_alias)
631  {
632  _host_data = nullptr;
633  _is_host_alias = false;
634  }
635  else
636  {
637  if (!_is_malloc)
638  // Allocated by new
639  delete[] _host_data;
640  else
641  {
642  // Allocated by malloc
643  for (index_type i = 0; i < _size; ++i)
644  _host_data[i].~T();
645 
646  std::free(_host_data);
647  }
648  }
649 
650  _is_host_alloc = false;
651  _is_malloc = false;
652 }
653 
654 template <typename T, unsigned int dimension, typename index_type>
655 void
657 {
658  if (!_is_device_alloc)
659  return;
660 
661  if (_is_device_alias)
662  {
663  _device_data = nullptr;
664  _is_device_alias = false;
665  }
666  else
667  Moose::Kokkos::free(_device_data);
668 
669  _is_device_alloc = false;
670 }
671 
672 template <typename T, unsigned int dimension, typename index_type>
673 void
675 {
676  if (!_counter)
677  return;
678 
679  if (_counter.use_count() > 1)
680  {
681  _host_data = nullptr;
682  _device_data = nullptr;
683  }
684  else if (_counter.use_count() == 1)
685  {
686  freeHost();
687  freeDevice();
688  }
689 
690  _size = 0;
691 
692  for (unsigned int i = 0; i < dimension; ++i)
693  {
694  _n[i] = 0;
695  _s[i] = 0;
696  _d[i] = 0;
697  }
698 
699  _is_init = false;
700  _is_offset = false;
701  _is_malloc = false;
702  _is_host_alloc = false;
703  _is_device_alloc = false;
704  _is_host_alias = false;
705  _is_device_alias = false;
706 
707  _counter.reset();
708 }
709 
710 template <typename T, unsigned int dimension, typename index_type>
711 void
713 {
714  if (_layout != array._layout)
715  mooseError("Kokkos array error: cannot shallow copy arrays with different layouts.");
716 
717  destroy();
718 
719  _counter = array._counter;
720 
721  _size = array._size;
722 
723  for (unsigned int i = 0; i < dimension; ++i)
724  {
725  _n[i] = array._n[i];
726  _s[i] = array._s[i];
727  _d[i] = array._d[i];
728  }
729 
730  _is_init = array._is_init;
731  _is_offset = array._is_offset;
732  _is_malloc = array._is_malloc;
733  _is_host_alloc = array._is_host_alloc;
734  _is_device_alloc = array._is_device_alloc;
735  _is_host_alias = array._is_host_alias;
736  _is_device_alias = array._is_device_alias;
737 
738  _host_data = array._host_data;
739  _device_data = array._device_data;
740 }
741 
742 #ifdef MOOSE_KOKKOS_SCOPE
743 template <typename T, unsigned int dimension, typename index_type>
744 void
746 {
747  if (!_is_init)
748  mooseError("Kokkos array error: attempted to alias host data before array initialization.");
749 
750  if (_is_host_alloc && !_is_host_alias)
751  mooseError("Kokkos array error: cannot alias host data because host data was not aliased.");
752 
753  _host_data = ptr;
754  _is_host_alloc = true;
755  _is_host_alias = true;
756 }
757 
758 template <typename T, unsigned int dimension, typename index_type>
759 void
761 {
762  if (!_is_init)
763  mooseError("Kokkos array error: attempted to alias device data before array initialization.");
764 
765  if (_is_device_alloc && !_is_device_alias)
766  mooseError("Kokkos array error: cannot alias device data because device data was not aliased.");
767 
768  _device_data = ptr;
769  _is_device_alloc = true;
770  _is_device_alias = true;
771 }
772 
773 template <typename T, unsigned int dimension, typename index_type>
774 template <bool initialize>
775 void
777 {
778  if (_is_host_alloc)
779  return;
780 
781  if constexpr (initialize)
782  {
783  static_assert(
784  std::is_default_constructible<T>::value,
785  "Data type is not default-constructible. Initialization argument should be set to false.");
786 
787  _host_data = new T[_size];
788  }
789  else
790  _host_data = static_cast<T *>(std::malloc(_size * sizeof(T)));
791 
792  _is_host_alloc = true;
793  _is_malloc = !initialize;
794 }
795 
796 template <typename T, unsigned int dimension, typename index_type>
797 void
799 {
800  if (_is_device_alloc)
801  return;
802 
803  _device_data =
804  static_cast<T *>(::Kokkos::kokkos_malloc<ExecSpace::memory_space>(_size * sizeof(T)));
805 
806  _is_device_alloc = true;
807 }
808 
809 template <typename T, unsigned int dimension, typename index_type>
810 template <bool host, bool device, bool initialize>
811 void
812 ArrayBase<T, dimension, index_type>::createInternal(const std::vector<index_type> & n)
813 {
814  if (n.size() != dimension)
815  mooseError("Kokkos array error: the number of dimensions provided (",
816  n.size(),
817  ") must match the array dimension (",
818  dimension,
819  ").");
820 
821  if (_counter)
822  destroy();
823 
824  _counter = std::make_shared<unsigned int>();
825 
826  uint64_t overflow_checker = 1;
827 
828  _size = 1;
829  _s[0] = 1;
830 
831  for (const auto i : make_range(dimension))
832  {
833  overflow_checker *= n[i];
834 
835  _n[i] = n[i];
836  _size *= n[i];
837  }
838 
839  if (overflow_checker > std::numeric_limits<index_type>::max())
840  mooseError("Kokkos array error: the dimensions provided (",
841  Moose::stringify(n),
842  ") has the total size of ",
843  overflow_checker,
844  " which exceeds the limit of ",
845  MooseUtils::prettyCppType<index_type>(),
846  ".");
847 
848  if (_layout == LayoutType::LEFT)
849  {
850  _s[0] = 1;
851 
852  for (unsigned int i = 1; i < dimension; ++i)
853  _s[i] = _s[i - 1] * _n[i - 1];
854  }
855  else
856  {
857  _s[dimension - 1] = 1;
858 
859  for (int i = dimension - 2; i >= 0; --i)
860  _s[i] = _s[i + 1] * _n[i + 1];
861  }
862 
863  if constexpr (host)
864  allocHost<initialize>();
865 
866  if constexpr (device)
867  allocDevice();
868 
869  _is_init = true;
870 }
871 
872 template <typename T, unsigned int dimension, typename index_type>
873 template <bool initialize>
874 void
875 ArrayBase<T, dimension, index_type>::createInternal(const std::vector<index_type> & n,
876  bool host,
877  bool device)
878 {
879  if (host && device)
880  createInternal<true, true, initialize>(n);
881  else if (host && !device)
882  createInternal<true, false, initialize>(n);
883  else if (!host && device)
884  createInternal<false, true, initialize>(n);
885  else
886  createInternal<false, false, initialize>(n);
887 }
888 
889 template <typename T, unsigned int dimension, typename index_type>
890 template <bool host, bool device, bool initialize, typename... size_type>
891 void
893 {
894  static_assert((std::is_convertible<size_type, index_type>::value && ...),
895  "All arguments must be convertible to index_type");
896  static_assert(sizeof...(n) == dimension, "Number of arguments should match array dimension");
897 
898  std::vector<index_type> dims;
899  (dims.push_back(n), ...);
900 
901  createInternal<host, device, initialize>(dims);
902 }
903 
904 template <typename T, unsigned int dimension, typename index_type>
905 template <typename TargetSpace, typename SourceSpace>
906 void
907 ArrayBase<T, dimension, index_type>::copyInternal(T * target, const T * source, index_type n)
908 {
909  ::Kokkos::Impl::DeepCopy<TargetSpace, SourceSpace>(target, source, n * sizeof(T));
910  ::Kokkos::fence();
911 }
912 
913 template <typename T, unsigned int dimension, typename index_type>
914 void
915 ArrayBase<T, dimension, index_type>::offset(const std::vector<signed_index_type> & d)
916 {
917  if (d.size() > dimension)
918  mooseError("Kokkos array error: the number of offsets provided (",
919  d.size(),
920  ") cannot be larger than the array dimension (",
921  dimension,
922  ").");
923 
924  for (const auto i : index_range(d))
925  _d[i] = d[i];
926 
927  _is_offset = true;
928 }
929 
930 template <typename T, unsigned int dimension, typename index_type>
931 template <typename... offset_type>
932 void
934 {
935  static_assert((std::is_convertible<offset_type, signed_index_type>::value && ...),
936  "All arguments must be convertible to signed_index_type");
937  static_assert(sizeof...(d) == dimension, "Number of arguments should match array dimension");
938 
939  std::vector<signed_index_type> offsets;
940  (offsets.push_back(d), ...);
941 
942  offset(offsets);
943 }
944 
945 template <typename T, unsigned int dimension, typename index_type>
946 void
948 {
949  // If host side memory is not allocated, do nothing
950  if (!_is_host_alloc)
951  return;
952 
953  // If device side memory is not allocated,
954  if (!_is_device_alloc)
955  {
956  if (_counter.use_count() == 1)
957  // allocate memory if this array is not shared with other arrays
958  allocDevice();
959  else
960  // print error if this array is shared with other arrays
961  mooseError("Kokkos array error: cannot copy from host to device because device memory "
962  "was not allocated. Cannot allocate device memory for copy because the array is "
963  "being shared.");
964  }
965 
966  // Copy from host to device
967  copyInternal<MemSpace, ::Kokkos::HostSpace>(_device_data, _host_data, _size);
968 }
969 
970 template <typename T, unsigned int dimension, typename index_type>
971 void
973 {
974  // If device side memory is not allocated, do nothing
975  if (!_is_device_alloc)
976  return;
977 
978  // If host side memory is not allocated,
979  if (!_is_host_alloc)
980  {
981  if (_counter.use_count() == 1)
982  // allocate memory if this array is not shared with other arrays
983  allocHost<false>();
984  else
985  // print error if this array is shared with other arrays
986  mooseError("Kokkos array error: cannot copy from device to host because host memory "
987  "was not allocated. Cannot allocate host memory for copy because the array is "
988  "being shared.");
989  }
990 
991  // Copy from device to host
992  copyInternal<::Kokkos::HostSpace, MemSpace>(_host_data, _device_data, _size);
993 }
994 
995 template <typename T, unsigned int dimension, typename index_type>
996 void
998 {
999  static_assert(!is_kokkos_array<T>::value,
1000  "moveToDevice() not allowed for a nested array whose data type is another array.");
1001 
1002  if (should_free_host && _counter.use_count() > 1)
1003  mooseError("Kokkos array error: cannot move array from host to device because there is at "
1004  "least one shallow copy of this array still alive.");
1005 
1006  copyToDevice();
1007 
1008  if (_counter.use_count() == 1)
1009  freeHost();
1010 }
1011 
1012 template <typename T, unsigned int dimension, typename index_type>
1013 void
1015 {
1016  if (should_free_device && _counter.use_count() > 1)
1017  mooseError("Kokkos array error: cannot move array from device to host because there is at "
1018  "least one shallow copy of this array still alive.");
1019 
1020  copyToHost();
1021 
1022  if (_counter.use_count() == 1)
1023  freeDevice();
1024 }
1025 
1026 template <typename T, unsigned int dimension, typename index_type>
1027 void
1029  MemcpyType dir,
1030  index_type n,
1031  index_type offset)
1032 {
1033  if (n > _size)
1034  mooseError("Kokkos array error: cannot copy in data larger than the array size.");
1035 
1036  if (offset > _size)
1037  mooseError("Kokkos array error: offset cannot be larger than the array size.");
1038 
1039  if (dir == MemcpyType::HOST_TO_HOST)
1040  {
1041  // If host side memory is not allocated, print error
1042  if (!_is_host_alloc)
1043  mooseError(
1044  "Kokkos array error: cannot copy in to the array because host memory was not allocated.");
1045 
1046  // Copy from host to host
1047  copyInternal<::Kokkos::HostSpace, ::Kokkos::HostSpace>(_host_data + offset, ptr, n);
1048  }
1049  else if (dir == MemcpyType::HOST_TO_DEVICE)
1050  {
1051  // If device side memory is not allocated, print error
1052  if (!_is_device_alloc)
1053  mooseError("Kokkos array error: cannot copy in to the array because device memory was not "
1054  "allocated.");
1055 
1056  // Copy from host to device
1057  copyInternal<MemSpace, ::Kokkos::HostSpace>(_device_data + offset, ptr, n);
1058  }
1059  else if (dir == MemcpyType::DEVICE_TO_HOST)
1060  {
1061  // If host side memory is not allocated, print error
1062  if (!_is_host_alloc)
1063  mooseError(
1064  "Kokkos array error: cannot copy in to the array because host memory was not allocated.");
1065 
1066  // Copy from device to host
1067  copyInternal<::Kokkos::HostSpace, MemSpace>(_host_data + offset, ptr, n);
1068  }
1069  else if (dir == MemcpyType::DEVICE_TO_DEVICE)
1070  {
1071  // If device side memory is not allocated, print error
1072  if (!_is_device_alloc)
1073  mooseError("Kokkos array error: cannot copy in to the array because device memory was not "
1074  "allocated.");
1075 
1076  // Copy from device to device
1077  copyInternal<MemSpace, MemSpace>(_device_data + offset, ptr, n);
1078  }
1079 }
1080 
1081 template <typename T, unsigned int dimension, typename index_type>
1082 void
1084  MemcpyType dir,
1085  index_type n,
1086  index_type offset)
1087 {
1088  if (n > _size)
1089  mooseError("Kokkos array error: cannot copy out data larger than the array size.");
1090 
1091  if (offset > _size)
1092  mooseError("Kokkos array error: offset cannot be larger than the array size.");
1093 
1094  if (dir == MemcpyType::HOST_TO_HOST)
1095  {
1096  // If host side memory is not allocated, print error
1097  if (!_is_host_alloc)
1098  mooseError("Kokkos array error: cannot copy out from the array because host memory was not "
1099  "allocated.");
1100 
1101  // Copy from host to host
1102  copyInternal<::Kokkos::HostSpace, ::Kokkos::HostSpace>(ptr, _host_data + offset, n);
1103  }
1104  else if (dir == MemcpyType::HOST_TO_DEVICE)
1105  {
1106  // If host side memory is not allocated, print error
1107  if (!_is_host_alloc)
1108  mooseError("Kokkos array error: cannot copy out from the array because host memory was not "
1109  "allocated.");
1110 
1111  // Copy from host to device
1112  copyInternal<MemSpace, ::Kokkos::HostSpace>(ptr, _host_data + offset, n);
1113  }
1114  else if (dir == MemcpyType::DEVICE_TO_HOST)
1115  {
1116  // If device side memory is not allocated, print error
1117  if (!_is_device_alloc)
1118  mooseError("Kokkos array error: cannot copy out from the array because device memory was not "
1119  "allocated.");
1120 
1121  // Copy from device to host
1122  copyInternal<::Kokkos::HostSpace, MemSpace>(ptr, _device_data + offset, n);
1123  }
1124  else if (dir == MemcpyType::DEVICE_TO_DEVICE)
1125  {
1126  // If device side memory is not allocated, print error
1127  if (!_is_device_alloc)
1128  mooseError("Kokkos array error: cannot copy out from the array because device memory was not "
1129  "allocated.");
1130 
1131  // Copy from device to device
1132  copyInternal<MemSpace, MemSpace>(ptr, _device_data + offset, n);
1133  }
1134 }
1135 
1136 template <typename T>
1137 void
1138 copyToDeviceInner(T & /* data */)
1139 {
1140 }
1141 
1142 template <typename T, unsigned int dimension, typename index_type, LayoutType layout>
1143 void
1145 {
1146  data.copyToDeviceNested();
1147 }
1148 
1149 template <typename T, unsigned int dimension, typename index_type>
1150 void
1152 {
1153  for (index_type i = 0; i < _size; ++i)
1154  copyToDeviceInner(_host_data[i]);
1155 
1156  copyToDevice();
1157 }
1158 
1159 template <typename T, unsigned int dimension, typename index_type>
1160 void
1162 {
1163  if (_layout != array._layout)
1164  mooseError("Kokkos array error: cannot deep copy arrays with different layouts.");
1165 
1167  mooseError(
1168  "Kokkos array error: cannot deep copy using constructor from array without host data.");
1169 
1170  std::vector<index_type> n(std::begin(array._n), std::end(array._n));
1171 
1172  createInternal<false>(n, array._is_host_alloc, array._is_device_alloc);
1173 
1174  if constexpr (ArrayDeepCopy<T>::value)
1175  {
1176  for (index_type i = 0; i < _size; ++i)
1177  new (_host_data + i) T(array._host_data[i]);
1178 
1179  copyToDevice();
1180  }
1181  else
1182  {
1183  if (_is_host_alloc)
1184  std::memcpy(_host_data, array._host_data, _size * sizeof(T));
1185 
1186  if (_is_device_alloc)
1187  copyInternal<MemSpace, MemSpace>(_device_data, array._device_data, _size);
1188  }
1189 
1190  for (unsigned int i = 0; i < dimension; ++i)
1191  {
1192  _d[i] = array._d[i];
1193  _s[i] = array._s[i];
1194  }
1195 
1196  _is_offset = array._is_offset;
1197 }
1198 
1199 template <typename T, unsigned int dimension, typename index_type>
1200 void
1202 {
1203  ArrayBase<T, dimension, index_type> clone(_layout);
1204 
1205  clone.shallowCopy(*this);
1206  this->shallowCopy(array);
1207  array.shallowCopy(clone);
1208 }
1209 
1210 template <typename T, unsigned int dimension, typename index_type>
1211 auto &
1213 {
1214  if (_is_host_alloc)
1215  std::fill_n(_host_data, _size, scalar);
1216 
1217  if (_is_device_alloc)
1218  ::Kokkos::Experimental::fill_n(ExecSpace(), deviceView(), _size, scalar);
1219 
1220  return *this;
1221 }
1222 
1223 template <typename T, unsigned int dimension, typename index_type, LayoutType layout>
1224 void
1225 dataStore(std::ostream & stream, Array<T, dimension, index_type, layout> & array, void * context)
1226 {
1228 
1229  bool is_alloc = array.isAlloc();
1230  dataStore(stream, is_alloc, nullptr);
1231 
1232  if (!is_alloc)
1233  return;
1234 
1235  std::string type = typeid(T).name();
1236  dataStore(stream, type, nullptr);
1237 
1238  unsigned int dim = dimension;
1239  dataStore(stream, dim, nullptr);
1240 
1241  for (unsigned int dim = 0; dim < dimension; ++dim)
1242  {
1243  auto n = array.n(dim);
1244  dataStore(stream, n, nullptr);
1245  }
1246 
1247  if (array.isDeviceAlloc())
1248  {
1249  // We use malloc/free because we just want a memory copy
1250  // If T is a Kokkos array and we use new/delete or vector to copy it out,
1251  // the arrays will be destroyed on cleanup
1252 
1253  T * data = static_cast<T *>(std::malloc(array.size() * sizeof(T)));
1254 
1255  array.copyOut(data, MemcpyType::DEVICE_TO_HOST, array.size());
1256 
1257  for (index_type i = 0; i < array.size(); ++i)
1258  dataStore(stream, data[i], context);
1259 
1260  std::free(data);
1261  }
1262  else
1263  for (auto & value : array)
1264  dataStore(stream, value, context);
1265 }
1266 
1267 template <typename T, unsigned int dimension, typename index_type, LayoutType layout>
1268 void
1269 dataLoad(std::istream & stream, Array<T, dimension, index_type, layout> & array, void * context)
1270 {
1272 
1273  bool is_alloc;
1274  dataLoad(stream, is_alloc, nullptr);
1275 
1276  if (!is_alloc)
1277  return;
1278 
1279  std::string from_type_name;
1280  dataLoad(stream, from_type_name, nullptr);
1281 
1282  if (from_type_name != typeid(T).name())
1283  mooseError("Kokkos array error: cannot load array because the stored array is of type '",
1284  MooseUtils::prettyCppType(libMesh::demangle(from_type_name.c_str())),
1285  "' but the loading array is of type '",
1287  "'.");
1288 
1289  unsigned int from_dimension;
1290  dataLoad(stream, from_dimension, nullptr);
1291 
1292  if (from_dimension != dimension)
1293  mooseError("Kokkos array error: cannot load array because the stored array is ",
1294  from_dimension,
1295  "D but the loading array is ",
1296  dimension,
1297  "D.");
1298 
1299  std::vector<index_type> from_n(dimension);
1300  std::vector<index_type> n(dimension);
1301 
1302  for (unsigned int dim = 0; dim < dimension; ++dim)
1303  {
1304  dataLoad(stream, from_n[dim], nullptr);
1305  n[dim] = array.n(dim);
1306  }
1307 
1308  if (from_n != n)
1309  mooseError("Kokkos array error: cannot load array because the stored array has dimensions (",
1310  Moose::stringify(from_n),
1311  ") but the loading array has dimensions (",
1312  Moose::stringify(n),
1313  ").");
1314 
1315  if (array.isHostAlloc())
1316  {
1317  for (auto & value : array)
1318  dataLoad(stream, value, context);
1319 
1320  if (array.isDeviceAlloc())
1321  array.copyToDevice();
1322  }
1323  else
1324  {
1325  std::vector<T> data(array.size());
1326 
1327  for (auto & value : data)
1328  dataLoad(stream, value, context);
1329 
1330  array.copyIn(data.data(), MemcpyType::HOST_TO_DEVICE, array.size());
1331  }
1332 }
1333 #endif
1334 
1350 template <typename T, unsigned int dimension, typename index_type, LayoutType layout>
1352 class Array : public ArrayBase<T, dimension, index_type>
1353 {
1354 #ifdef MOOSE_KOKKOS_SCOPE
1355  usingKokkosArrayBaseMembers(T, dimension, index_type);
1356 #endif
1357 
1358 public:
1362  Array() : ArrayBase<T, dimension, index_type>(layout) {}
1367  : ArrayBase<T, dimension, index_type>(array)
1368  {
1369  }
1370 #ifdef MOOSE_KOKKOS_SCOPE
1371 
1377  template <typename... size_type>
1378  Array(size_type... n) : ArrayBase<T, dimension, index_type>(layout, n...)
1379  {
1380  }
1381 #endif
1382 
1388  {
1389  this->shallowCopy(array);
1390 
1391  return *this;
1392  }
1393 
1394 #ifdef MOOSE_KOKKOS_SCOPE
1395 
1401  template <typename... indices>
1402  KOKKOS_FUNCTION T & operator()(indices... i) const;
1409  KOKKOS_FUNCTION T & operator()(const signed_index_type (&idx)[dimension]) const
1410  {
1411  return operatorInternal(idx, std::make_integer_sequence<unsigned int, dimension>{});
1412  }
1413 #endif
1414 
1415 private:
1416 #ifdef MOOSE_KOKKOS_SCOPE
1417 
1420  template <unsigned int... i>
1421  KOKKOS_FUNCTION T & operatorInternal(const signed_index_type (&idx)[dimension],
1422  std::integer_sequence<unsigned int, i...>) const
1423  {
1424  return operator()(idx[i]...);
1425  }
1426 #endif
1427 };
1428 
1429 #ifdef MOOSE_KOKKOS_SCOPE
1430 template <typename T, unsigned int dimension, typename index_type, LayoutType layout>
1431 template <typename... indices>
1432 KOKKOS_FUNCTION T &
1434 {
1435  static_assert((std::is_convertible<indices, signed_index_type>::value && ...),
1436  "All arguments must be convertible to signed_index_type");
1437  static_assert(sizeof...(i) == dimension, "Number of arguments should match array dimension");
1438 
1439 #ifndef NDEBUG
1440  {
1441  signed_index_type idx[dimension] = {static_cast<signed_index_type>(i)...};
1442 
1443  for (unsigned int d = 0; d < sizeof...(i); ++d)
1444  KOKKOS_ASSERT(idx[d] - _d[d] >= 0 && static_cast<index_type>(idx[d] - _d[d]) < _n[d]);
1445  }
1446 #endif
1447 
1448  index_type idx = 0;
1449  unsigned int d = 0;
1450 
1451  if (_is_offset)
1452  {
1453  if constexpr (layout == LayoutType::LEFT)
1454  (((idx += (d == 0 ? static_cast<signed_index_type>(i) - _d[d]
1455  : (static_cast<signed_index_type>(i) - _d[d]) * _s[d])),
1456  ++d),
1457  ...);
1458  else
1459  (((idx += (d == dimension - 1 ? static_cast<signed_index_type>(i) - _d[d]
1460  : (static_cast<signed_index_type>(i) - _d[d]) * _s[d])),
1461  ++d),
1462  ...);
1463  }
1464  else
1465  {
1466  if constexpr (layout == LayoutType::LEFT)
1467  (((idx +=
1468  (d == 0 ? static_cast<signed_index_type>(i) : static_cast<signed_index_type>(i) * _s[d])),
1469  ++d),
1470  ...);
1471  else
1472  (((idx += (d == dimension - 1 ? static_cast<signed_index_type>(i)
1473  : static_cast<signed_index_type>(i) * _s[d])),
1474  ++d),
1475  ...);
1476  }
1477 
1478  return this->operator[](idx);
1479 }
1480 #endif
1481 
1482 template <typename T, typename index_type>
1483 class Array<T, 1, index_type, LayoutType::LEFT> : public ArrayBase<T, 1, index_type>
1484 {
1485 #ifdef MOOSE_KOKKOS_SCOPE
1486  usingKokkosArrayBaseMembers(T, 1, index_type);
1487 #endif
1488 
1489 public:
1493  Array() : ArrayBase<T, 1, index_type>(LayoutType::LEFT) {}
1498  : ArrayBase<T, 1, index_type>(array)
1499  {
1500  }
1501 #ifdef MOOSE_KOKKOS_SCOPE
1502 
1508  Array(index_type n) : ArrayBase<T, 1, index_type>(LayoutType::LEFT, n) {}
1515  Array(const std::vector<T> & vector) : ArrayBase<T, 1, index_type>(LayoutType::LEFT)
1516  {
1517  *this = vector;
1518  }
1519 #endif
1520 
1526  {
1527  this->shallowCopy(array);
1528 
1529  return *this;
1530  }
1531 
1532 #ifdef MOOSE_KOKKOS_SCOPE
1533 
1540  template <bool host, bool device>
1541  void copyVector(const std::vector<T> & vector)
1542  {
1543  this->template createInternal<host, device, false>({static_cast<index_type>(vector.size())});
1544 
1545  if (host)
1546  std::memcpy(this->hostData(), vector.data(), this->size() * sizeof(T));
1547 
1548  if (device)
1549  this->template copyInternal<MemSpace, ::Kokkos::HostSpace>(
1550  this->deviceData(), vector.data(), this->size());
1551  }
1559  template <bool host, bool device>
1560  void copySet(const std::set<T> & set)
1561  {
1562  std::vector<T> vector(set.begin(), set.end());
1563 
1564  copyVector<host, device>(vector);
1565  }
1566 
1572  auto & operator=(const std::vector<T> & vector)
1573  {
1574  copyVector<true, true>(vector);
1575 
1576  return *this;
1577  }
1583  auto & operator=(const std::set<T> & set)
1584  {
1585  copySet<true, true>(set);
1586 
1587  return *this;
1588  }
1595  KOKKOS_FUNCTION T & operator()(signed_index_type i) const
1596  {
1597  KOKKOS_ASSERT(i - _d[0] >= 0 && static_cast<index_type>(i - _d[0]) < _n[0]);
1598 
1599  if (_is_offset)
1600  return this->operator[](i - _d[0]);
1601  else
1602  return this->operator[](i);
1603  }
1607 
1612  void axby(const T a,
1614  const char op,
1615  const T b,
1617  const bool accumulate = false);
1621  void scal(const T a, const Array<T, 1, index_type, LayoutType::LEFT> & x);
1625  void scal(const T a);
1633  T nrm2();
1635 #endif
1636 };
1638 
1639 template <typename T, typename index_type = MOOSE_KOKKOS_INDEX_TYPE>
1641 template <typename T,
1642  typename index_type = MOOSE_KOKKOS_INDEX_TYPE,
1643  LayoutType layout = LayoutType::LEFT>
1645 template <typename T,
1646  typename index_type = MOOSE_KOKKOS_INDEX_TYPE,
1647  LayoutType layout = LayoutType::LEFT>
1649 template <typename T,
1650  typename index_type = MOOSE_KOKKOS_INDEX_TYPE,
1651  LayoutType layout = LayoutType::LEFT>
1653 template <typename T,
1654  typename index_type = MOOSE_KOKKOS_INDEX_TYPE,
1655  LayoutType layout = LayoutType::LEFT>
1657 
1658 } // namespace Moose::Kokkos
std::string name(const ElemQuality q)
T * deviceData() const
Get the device data pointer.
Definition: KokkosArray.h:269
The Kokkos array class.
Definition: KokkosArray.h:64
MemcpyType
The enumerator that dictates the memory copy direction.
Definition: KokkosArray.h:40
KOKKOS_FUNCTION index_type n(unsigned int dim) const
Get the size of a dimension.
Definition: KokkosArray.h:211
KOKKOS_FUNCTION iterator(T *p)
Definition: KokkosArray.h:446
auto & operator=(const Array< T, dimension, index_type, layout > &array)
Shallow copy another Kokkos array.
Definition: KokkosArray.h:1387
void moveToHost(bool should_free_device=true)
Copy data from device to host and deallocate device.
Definition: KokkosArray.h:1014
KOKKOS_FUNCTION pointer operator &() const
Definition: KokkosArray.h:450
KOKKOS_FUNCTION T & last() const
Get the last element.
Definition: KokkosArray.h:239
Array(const Array< T, dimension, index_type, layout > &array)
Copy constructor.
Definition: KokkosArray.h:1366
signed_index_type _d[dimension]
Offset of each dimension.
Definition: KokkosArray.h:509
LayoutType
The enumerator that dictates the memory layout.
Definition: KokkosArray.h:51
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:1541
KOKKOS_FUNCTION iterator operator++(int)
Definition: KokkosArray.h:456
Array()
Default constructor.
Definition: KokkosArray.h:1362
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:190
void dataLoad(std::istream &stream, Array< T, dimension, index_type, layout > &array, void *context)
Definition: KokkosArray.h:1269
void createHost(size_type... n)
Allocate array on host only.
Definition: KokkosArray.h:333
KOKKOS_FUNCTION T & operator[](index_type i) const
Get an array entry.
Definition: KokkosArray.h:251
KOKKOS_FUNCTION T & operator()(signed_index_type i) const
Get an array entry.
Definition: KokkosArray.h:1595
KOKKOS_FUNCTION iterator end() const
Get the end iterator.
Definition: KokkosArray.h:489
bool _is_offset
Flag whether the array indices are offset.
Definition: KokkosArray.h:513
void moveToDevice(bool should_free_host=true)
Copy data from host to device and deallocate host.
Definition: KokkosArray.h:997
KOKKOS_FUNCTION T & first() const
Get the first element.
Definition: KokkosArray.h:228
void shallowCopy(const ArrayBase< T, dimension, index_type > &array)
Shallow copy another Kokkos array.
Definition: KokkosArray.h:712
static constexpr std::size_t dim
This is the dimension of all vector and tensor datastructures used in MOOSE.
Definition: Moose.h:163
The type trait that determines if a template type is Kokkos array.
Definition: KokkosArray.h:71
void allocDevice()
Allocate device data for an initialized array that has not allocated device data. ...
Definition: KokkosArray.h:798
bool _is_device_alloc
Flag whether device data was allocated.
Definition: KokkosArray.h:596
T * _host_data
Host data.
Definition: KokkosArray.h:608
bool _is_malloc
Flag whether host data was allocated using malloc.
Definition: KokkosArray.h:517
Array(size_type... n)
Constructor Initialize and allocate array with given dimensions This allocates both host and device d...
Definition: KokkosArray.h:1378
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:1083
index_type _s[dimension]
Stride of each dimension.
Definition: KokkosArray.h:505
void swap(ArrayBase< T, dimension, index_type > &array)
Swap with another Kokkos array.
Definition: KokkosArray.h:1201
void allocHost()
Allocate host data for an initialized array that has not allocated host data.
Definition: KokkosArray.h:776
void createInternal(size_type... n)
The internal method to initialize and allocate this array.
Definition: KokkosArray.h:892
void initialize(EquationSystems &es, const std::string &system_name)
KOKKOS_FUNCTION T & operator()(indices... i) const
Get an array entry.
Definition: KokkosArray.h:1433
bool _is_host_alloc
Flag whether host data was allocated.
Definition: KokkosArray.h:592
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:760
Array(const Array< T, 1, index_type, LayoutType::LEFT > &array)
Copy constructor.
Definition: KokkosArray.h:1497
auto hostView() const
Get the host unmanaged view.
Definition: KokkosArray.h:274
KOKKOS_FUNCTION bool isHostAlloc() const
Get whether the array was allocated on host.
Definition: KokkosArray.h:185
auto deviceView() const
Get the device unmanaged view.
Definition: KokkosArray.h:283
void freeDevice()
Free device data.
Definition: KokkosArray.h:656
KOKKOS_FUNCTION bool isDeviceAlias() const
Get whether the device array was aliased.
Definition: KokkosArray.h:200
KOKKOS_FUNCTION bool isAlloc() const
Get whether the array was allocated either on host or device.
Definition: KokkosArray.h:180
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:1560
index_type _size
Total size.
Definition: KokkosArray.h:616
const LayoutType _layout
Memory layout type.
Definition: KokkosArray.h:620
KOKKOS_FUNCTION pointer operator->() const
Definition: KokkosArray.h:449
~ArrayBase()
Destructor.
Definition: KokkosArray.h:156
bool _is_device_alias
Flag whether the device data points to an external data.
Definition: KokkosArray.h:604
KOKKOS_FUNCTION friend bool operator==(const iterator &a, const iterator &b)
Definition: KokkosArray.h:462
Real value(unsigned n, unsigned alpha, unsigned beta, Real x)
KOKKOS_FUNCTION T & operatorInternal(const signed_index_type(&idx)[dimension], std::integer_sequence< unsigned int, i... >) const
Internal method for calling operator() with array indices.
Definition: KokkosArray.h:1421
void copyToDeviceInner(T &)
Definition: KokkosArray.h:1138
unsigned int useCount() const
Get the reference count.
Definition: KokkosArray.h:173
Array(const std::vector< T > &vector)
Constructor Initialize and allocate array by copying a standard vector variable This allocates and co...
Definition: KokkosArray.h:1515
void create(const std::vector< index_type > &n)
Allocate array on host and device.
Definition: KokkosArray.h:303
KOKKOS_FUNCTION T * data() const
Get the data pointer.
Definition: KokkosArray.h:217
void aliasHost(T *ptr)
Point the host data to an external data instead of allocating it.
Definition: KokkosArray.h:745
The base class for Kokkos arrays.
Definition: KokkosArray.h:106
void copyToDevice()
Copy data from host to device.
Definition: KokkosArray.h:947
KOKKOS_FUNCTION index_type size() const
Get the total array size.
Definition: KokkosArray.h:205
void dataStore(std::ostream &stream, Array< T, dimension, index_type, layout > &array, void *context)
Definition: KokkosArray.h:1225
void create(size_type... n)
Allocate array on host and device.
Definition: KokkosArray.h:313
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:1028
void destroy()
Free all data and reset.
Definition: KokkosArray.h:674
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:140
std::string demangle(const char *name)
std::shared_ptr< unsigned int > _counter
Reference counter.
Definition: KokkosArray.h:584
KOKKOS_FUNCTION iterator & operator++()
Definition: KokkosArray.h:451
KOKKOS_FUNCTION friend bool operator!=(const iterator &a, const iterator &b)
Definition: KokkosArray.h:466
void free(void *ptr)
ArrayBase(const LayoutType layout)
Constructor.
Definition: KokkosArray.h:120
The type trait that determines the default behavior of copy constructor and deepCopy() If this type t...
Definition: KokkosArray.h:90
bool _is_host_alias
Flag whether the host data points to an external data.
Definition: KokkosArray.h:600
KOKKOS_FUNCTION T & operator()(const signed_index_type(&idx)[dimension]) const
Get an array entry using indices stored in an array.
Definition: KokkosArray.h:1409
auto & operator=(const T &scalar)
Assign a scalar value uniformly.
Definition: KokkosArray.h:1212
void createDevice(const std::vector< index_type > &n)
Allocate array on device only.
Definition: KokkosArray.h:341
KOKKOS_FUNCTION reference operator*() const
Definition: KokkosArray.h:448
KOKKOS_FUNCTION iterator begin() const
Get the beginning iterator.
Definition: KokkosArray.h:479
void copyInternal(T *target, const T *source, index_type n)
The internal method to perform a memory copy.
Definition: KokkosArray.h:907
std::forward_iterator_tag iterator_category
Definition: KokkosArray.h:439
IntRange< T > make_range(T beg, T end)
auto & operator=(const Array< T, 1, index_type, LayoutType::LEFT > &array)
Shallow copy another Kokkos array.
Definition: KokkosArray.h:1525
void init(size_type... n)
Initialize array with given dimensions but do not allocate.
Definition: KokkosArray.h:293
T * hostData() const
Get the host data pointer.
Definition: KokkosArray.h:264
T * _device_data
Device data.
Definition: KokkosArray.h:612
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:1583
Array(index_type n)
Constructor Initialize and allocate array with given size This allocates both host and device data...
Definition: KokkosArray.h:1508
void copyToDeviceNested()
Copy all the nested Kokkos arrays including self from host to device.
Definition: KokkosArray.h:1151
void destroy(triangulateio &t, IO_Type)
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:1572
void createDevice(size_type... n)
Allocate array on device only.
Definition: KokkosArray.h:347
bool _is_init
Flag whether array was initialized.
Definition: KokkosArray.h:588
void copyToHost()
Copy data from device to host.
Definition: KokkosArray.h:972
void createHost(const std::vector< index_type > &n)
Allocate array on host only.
Definition: KokkosArray.h:323
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:131
void freeHost()
Free host data.
Definition: KokkosArray.h:625
KOKKOS_FUNCTION bool isHostAlias() const
Get whether the host array was aliased.
Definition: KokkosArray.h:195
auto index_range(const T &sizable)
static constexpr bool value
Definition: KokkosArray.h:92
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:1161
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:1140
index_type _n[dimension]
Size of each dimension.
Definition: KokkosArray.h:501
usingKokkosArrayBaseMembers(T, dimension, index_type)
void offset(const std::vector< signed_index_type > &d)
Apply starting index offsets to each dimension.
Definition: KokkosArray.h:915