MFEM  v4.5.1
Finite element discretization library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
dtensor.hpp
Go to the documentation of this file.
1 // Copyright (c) 2010-2022, Lawrence Livermore National Security, LLC. Produced
2 // at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3 // LICENSE and NOTICE for details. LLNL-CODE-806117.
4 //
5 // This file is part of the MFEM library. For more information and source code
6 // availability visit https://mfem.org.
7 //
8 // MFEM is free software; you can redistribute it and/or modify it under the
9 // terms of the BSD-3 license. We welcome feedback and contributions, see file
10 // CONTRIBUTING.md for details.
11 
12 #ifndef MFEM_DTENSOR
13 #define MFEM_DTENSOR
14 
15 #include "../general/backends.hpp"
16 
17 namespace mfem
18 {
19 
20 /// A Class to compute the real index from the multi-indices of a tensor
21 template <int N, int Dim, typename T, typename... Args>
22 class TensorInd
23 {
24 public:
25  MFEM_HOST_DEVICE
26  static inline int result(const int* sizes, T first, Args... args)
27  {
28 #if !(defined(MFEM_USE_CUDA) || defined(MFEM_USE_HIP))
29  MFEM_ASSERT(first<sizes[N-1],"Trying to access out of boundary.");
30 #endif
31  return static_cast<int>(first + sizes[N - 1] * TensorInd < N + 1, Dim, Args... >
32  ::result(sizes, args...));
33  }
34 };
35 
36 // Terminal case
37 template <int Dim, typename T, typename... Args>
38 class TensorInd<Dim, Dim, T, Args...>
39 {
40 public:
41  MFEM_HOST_DEVICE
42  static inline int result(const int* sizes, T first, Args... args)
43  {
44 #if !(defined(MFEM_USE_CUDA) || defined(MFEM_USE_HIP))
45  MFEM_ASSERT(first<sizes[Dim-1],"Trying to access out of boundary.");
46 #endif
47  return static_cast<int>(first);
48  }
49 };
50 
51 
52 /// A class to initialize the size of a Tensor
53 template <int N, int Dim, typename T, typename... Args>
54 class Init
55 {
56 public:
57  MFEM_HOST_DEVICE
58  static inline int result(int* sizes, T first, Args... args)
59  {
60  sizes[N - 1] = first;
61  return first * Init < N + 1, Dim, Args... >::result(sizes, args...);
62  }
63 };
64 
65 // Terminal case
66 template <int Dim, typename T, typename... Args>
67 class Init<Dim, Dim, T, Args...>
68 {
69 public:
70  MFEM_HOST_DEVICE
71  static inline int result(int* sizes, T first, Args... args)
72  {
73  sizes[Dim - 1] = first;
74  return first;
75  }
76 };
77 
78 
79 /// A basic generic Tensor class, appropriate for use on the GPU
80 template<int Dim, typename Scalar = double>
82 {
83 protected:
84  int capacity;
85  Scalar *data;
86  int sizes[Dim];
87 
88 public:
89  /// Default constructor
90  DeviceTensor() = delete;
91 
92  /// Constructor to initialize a tensor from the Scalar array data_
93  template <typename... Args> MFEM_HOST_DEVICE
94  DeviceTensor(Scalar* data_, Args... args)
95  {
96  static_assert(sizeof...(args) == Dim, "Wrong number of arguments");
97  // Initialize sizes, and compute the number of values
98  const long int nb = Init<1, Dim, Args...>::result(sizes, args...);
99  capacity = nb;
100  data = (capacity > 0) ? data_ : NULL;
101  }
102 
103  /// Copy constructor (default)
104  DeviceTensor(const DeviceTensor&) = default;
105 
106  /// Copy assignment (default)
107  DeviceTensor& operator=(const DeviceTensor&) = default;
108 
109  /// Conversion to `Scalar *`.
110  MFEM_HOST_DEVICE inline operator Scalar *() const { return data; }
111 
112  /// Const accessor for the data
113  template <typename... Args> MFEM_HOST_DEVICE inline
114  Scalar& operator()(Args... args) const
115  {
116  static_assert(sizeof...(args) == Dim, "Wrong number of arguments");
117  return data[ TensorInd<1, Dim, Args...>::result(sizes, args...) ];
118  }
119 
120  /// Subscript operator where the tensor is viewed as a 1D array.
121  MFEM_HOST_DEVICE inline Scalar& operator[](int i) const
122  {
123  return data[i];
124  }
125 };
126 
127 
128 /** @brief Wrap a pointer as a DeviceTensor with automatically deduced template
129  parameters */
130 template <typename T, typename... Dims> MFEM_HOST_DEVICE
131 inline DeviceTensor<sizeof...(Dims),T> Reshape(T *ptr, Dims... dims)
132 {
133  return DeviceTensor<sizeof...(Dims),T>(ptr, dims...);
134 }
135 
136 
139 
142 
145 
148 
149 } // mfem namespace
150 
151 #endif // MFEM_DTENSOR
DeviceTensor< 2, const double > ConstDeviceMatrix
Definition: dtensor.hpp:144
static MFEM_HOST_DEVICE int result(const int *sizes, T first, Args...args)
Definition: dtensor.hpp:42
DeviceTensor()=delete
Default constructor.
static MFEM_HOST_DEVICE int result(int *sizes, T first, Args...args)
Definition: dtensor.hpp:58
MFEM_HOST_DEVICE Scalar & operator()(Args...args) const
Const accessor for the data.
Definition: dtensor.hpp:114
DeviceTensor< 2, double > DeviceMatrix
Definition: dtensor.hpp:143
MFEM_HOST_DEVICE DeviceTensor(Scalar *data_, Args...args)
Constructor to initialize a tensor from the Scalar array data_.
Definition: dtensor.hpp:94
DeviceTensor< 1, const int > ConstDeviceArray
Definition: dtensor.hpp:138
DeviceTensor< 1, int > DeviceArray
Definition: dtensor.hpp:137
static MFEM_HOST_DEVICE int result(int *sizes, T first, Args...args)
Definition: dtensor.hpp:71
static MFEM_HOST_DEVICE int result(const int *sizes, T first, Args...args)
Definition: dtensor.hpp:26
A basic generic Tensor class, appropriate for use on the GPU.
Definition: dtensor.hpp:81
DeviceTensor< 1, const double > ConstDeviceVector
Definition: dtensor.hpp:141
DeviceTensor< 3, double > DeviceCube
Definition: dtensor.hpp:146
A class to initialize the size of a Tensor.
Definition: dtensor.hpp:54
DeviceTensor< 1, double > DeviceVector
Definition: dtensor.hpp:140
A Class to compute the real index from the multi-indices of a tensor.
Definition: dtensor.hpp:22
kernels::InvariantsEvaluator2D::Buffers Args
Definition: tmop_pa_h2s.cpp:21
int sizes[Dim]
Definition: dtensor.hpp:86
DeviceTensor & operator=(const DeviceTensor &)=default
Copy assignment (default)
MFEM_HOST_DEVICE Scalar & operator[](int i) const
Subscript operator where the tensor is viewed as a 1D array.
Definition: dtensor.hpp:121
MFEM_HOST_DEVICE DeviceTensor< sizeof...(Dims), T > Reshape(T *ptr, Dims...dims)
Wrap a pointer as a DeviceTensor with automatically deduced template parameters.
Definition: dtensor.hpp:131
DeviceTensor< 3, const double > ConstDeviceCube
Definition: dtensor.hpp:147