MFEM  v4.0
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, Lawrence Livermore National Security, LLC. Produced at
2 // the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
3 // reserved. See file COPYRIGHT for details.
4 //
5 // This file is part of the MFEM library. For more information and source code
6 // availability see http://mfem.org.
7 //
8 // MFEM is free software; you can redistribute it and/or modify it under the
9 // terms of the GNU Lesser General Public License (as published by the Free
10 // Software Foundation) version 2.1 dated February 1999.
11 
12 #ifndef MFEM_DTENSOR
13 #define MFEM_DTENSOR
14 
15 #include "../general/cuda.hpp"
16 #include "../general/mem_manager.hpp"
17 
18 namespace mfem
19 {
20 
21 /// A Class to compute the real index from the multi-indices of a tensor
22 template <int N, int Dim, typename T, typename... Args>
23 class TensorInd
24 {
25 public:
26  MFEM_HOST_DEVICE
27  static inline int result(const int* sizes, T first, Args... args)
28  {
29 #ifndef MFEM_USE_CUDA
30  MFEM_ASSERT(first<sizes[N-1],"Trying to access out of boundary.");
31 #endif
32  return first + sizes[N - 1] * TensorInd < N + 1, Dim, Args... >
33  ::result(sizes, args...);
34  }
35 };
36 
37 // Terminal case
38 template <int Dim, typename T, typename... Args>
39 class TensorInd<Dim, Dim, T, Args...>
40 {
41 public:
42  MFEM_HOST_DEVICE
43  static inline int result(const int* sizes, T first, Args... args)
44  {
45 #ifndef MFEM_USE_CUDA
46  MFEM_ASSERT(first<sizes[Dim-1],"Trying to access out of boundary.");
47 #endif
48  return first;
49  }
50 };
51 
52 
53 /// A class to initialize the size of a Tensor
54 template <int N, int Dim, typename T, typename... Args>
55 class Init
56 {
57 public:
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  static inline int result(int* sizes, T first, Args... args)
71  {
72  sizes[Dim - 1] = first;
73  return first;
74  }
75 };
76 
77 
78 /// A basic generic Tensor class, appropriate for use on the GPU
79 template<int Dim, typename Scalar = double>
81 {
82 protected:
83  int capacity;
84  Scalar *data;
85  int sizes[Dim];
86 
87 public:
88  /// Default constructor
89  DeviceTensor() = delete;
90 
91  /// Constructor to initialize a tensor from the Scalar array _data
92  template <typename... Args>
93  DeviceTensor(Scalar* _data, Args... args)
94  {
95  static_assert(sizeof...(args) == Dim, "Wrong number of arguments");
96  // Initialize sizes, and compute the number of values
97  const long int nb = Init<1, Dim, Args...>::result(sizes, args...);
98  capacity = nb;
99  data = (capacity > 0) ? _data : NULL;
100  }
101 
102  /// Copy constructor
103  MFEM_HOST_DEVICE DeviceTensor(const DeviceTensor& t)
104  {
105  capacity = t.capacity;
106  for (int i = 0; i < Dim; ++i)
107  {
108  sizes[i] = t.sizes[i];
109  }
110  data = t.data;
111  }
112 
113  /// Conversion to `Scalar *`.
114  inline operator Scalar *() const { return data; }
115 
116  /// Const accessor for the data
117  template <typename... Args> MFEM_HOST_DEVICE inline
118  Scalar& operator()(Args... args) const
119  {
120  static_assert(sizeof...(args) == Dim, "Wrong number of arguments");
121  return data[ TensorInd<1, Dim, Args...>::result(sizes, args...) ];
122  }
123 
124  /// Subscript operator where the tensor is viewed as a 1D array.
125  MFEM_HOST_DEVICE inline Scalar& operator[](int i) const
126  {
127  return data[i];
128  }
129 };
130 
131 
132 /** @brief Wrap a pointer as a DeviceTensor with automatically deduced template
133  parameters */
134 template <typename T, typename... Dims>
135 inline DeviceTensor<sizeof...(Dims),T> Reshape(T *ptr, Dims... dims)
136 {
137  return DeviceTensor<sizeof...(Dims),T>(ptr, dims...);
138 }
139 
140 
144 
145 } // mfem namespace
146 
147 #endif // MFEM_DTENSOR
static MFEM_HOST_DEVICE int result(const int *sizes, T first, Args...args)
Definition: dtensor.hpp:43
DeviceTensor()=delete
Default constructor.
MFEM_HOST_DEVICE DeviceTensor(const DeviceTensor &t)
Copy constructor.
Definition: dtensor.hpp:103
DeviceTensor(Scalar *_data, Args...args)
Constructor to initialize a tensor from the Scalar array _data.
Definition: dtensor.hpp:93
MFEM_HOST_DEVICE Scalar & operator()(Args...args) const
Const accessor for the data.
Definition: dtensor.hpp:118
DeviceTensor< 2, double > DeviceMatrix
Definition: dtensor.hpp:143
DeviceTensor< sizeof...(Dims), T > Reshape(T *ptr, Dims...dims)
Wrap a pointer as a DeviceTensor with automatically deduced template parameters.
Definition: dtensor.hpp:135
DeviceTensor< 1, int > DeviceArray
Definition: dtensor.hpp:141
static MFEM_HOST_DEVICE int result(const int *sizes, T first, Args...args)
Definition: dtensor.hpp:27
A basic generic Tensor class, appropriate for use on the GPU.
Definition: dtensor.hpp:80
A class to initialize the size of a Tensor.
Definition: dtensor.hpp:55
static int result(int *sizes, T first, Args...args)
Definition: dtensor.hpp:58
DeviceTensor< 1, double > DeviceVector
Definition: dtensor.hpp:142
A Class to compute the real index from the multi-indices of a tensor.
Definition: dtensor.hpp:23
int sizes[Dim]
Definition: dtensor.hpp:85
static int result(int *sizes, T first, Args...args)
Definition: dtensor.hpp:70
MFEM_HOST_DEVICE Scalar & operator[](int i) const
Subscript operator where the tensor is viewed as a 1D array.
Definition: dtensor.hpp:125