MFEM v4.9.0
Finite element discretization library
Loading...
Searching...
No Matches
dtensor.hpp
Go to the documentation of this file.
1// Copyright (c) 2010-2025, 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 "../config/config.hpp"
16#include "../general/error.hpp"
17
18namespace mfem
19{
20
21/// A Class to compute the real index from the multi-indices of a tensor
22template <int N, int Dim, typename T, typename... Args>
24{
25public:
26 MFEM_HOST_DEVICE
27 static inline int result(const int* sizes, T first, Args... args)
28 {
29#if !(defined(MFEM_USE_CUDA) || defined(MFEM_USE_HIP))
30 MFEM_ASSERT(first<sizes[N-1],"Trying to access out of boundary.");
31#endif
32 return static_cast<int>(first + sizes[N - 1] * TensorInd < N + 1, Dim, Args... >
33 ::result(sizes, args...));
34 }
35};
36
37// Terminal case
38template <int Dim, typename T, typename... Args>
39class TensorInd<Dim, Dim, T, Args...>
40{
41public:
42 MFEM_HOST_DEVICE
43 static inline int result(const int* sizes, T first, Args... args)
44 {
45#if !(defined(MFEM_USE_CUDA) || defined(MFEM_USE_HIP))
46 MFEM_ASSERT(first<static_cast<T>(sizes[Dim-1]),
47 "Trying to access out of boundary.");
48#endif
49 return static_cast<int>(first);
50 }
51};
52
53
54/// A class to initialize the size of a Tensor
55template <int N, int Dim, typename T, typename... Args>
56class Init
57{
58public:
59 MFEM_HOST_DEVICE
60 static inline int result(int* sizes, T first, Args... args)
61 {
62 sizes[N - 1] = first;
63 return first * Init < N + 1, Dim, Args... >::result(sizes, args...);
64 }
65};
66
67// Terminal case
68template <int Dim, typename T, typename... Args>
69class Init<Dim, Dim, T, Args...>
70{
71public:
72 MFEM_HOST_DEVICE
73 static inline int result(int* sizes, T first, Args... args)
74 {
75 sizes[Dim - 1] = first;
76 return first;
77 }
78};
79
80
81/// A basic generic Tensor class, appropriate for use on the GPU
82template<int Dim, typename Scalar = real_t>
84{
85protected:
87 Scalar *data;
88 int sizes[Dim];
89
90public:
91 /// Default constructor
92 // DeviceTensor() = delete;
93 MFEM_HOST_DEVICE
95
96 /// Constructor to initialize a tensor from the Scalar array data_
97 template <typename... Args> MFEM_HOST_DEVICE
98 DeviceTensor(Scalar* data_, Args... args)
99 {
100 static_assert(sizeof...(args) == Dim, "Wrong number of arguments");
101 // Initialize sizes, and compute the number of values
102 const long int nb = Init<1, Dim, Args...>::result(sizes, args...);
103 capacity = nb;
104 data = (capacity > 0) ? data_ : nullptr;
105 }
106
107 /// Copy constructor (default)
108 DeviceTensor(const DeviceTensor&) = default;
109
110 /// Copy assignment (default)
112
113 /// Conversion to `Scalar *`.
114 MFEM_HOST_DEVICE 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");
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 /// Returns the shape of the tensor.
131 MFEM_HOST_DEVICE inline auto &GetShape() const { return sizes; }
132};
133
134
135/** @brief Wrap a pointer as a DeviceTensor with automatically deduced template
136 parameters */
137template <typename T, typename... Dims> MFEM_HOST_DEVICE
138inline DeviceTensor<sizeof...(Dims),T> Reshape(T *ptr, Dims... dims)
139{
140 return DeviceTensor<sizeof...(Dims),T>(ptr, dims...);
141}
142
143
146
149
152
155
156} // mfem namespace
157
158#endif // MFEM_DTENSOR
A basic generic Tensor class, appropriate for use on the GPU.
Definition dtensor.hpp:84
DeviceTensor(const DeviceTensor &)=default
Copy constructor (default)
MFEM_HOST_DEVICE DeviceTensor()
Default constructor.
Definition dtensor.hpp:94
MFEM_HOST_DEVICE Scalar & operator[](int i) const
Subscript operator where the tensor is viewed as a 1D array.
Definition dtensor.hpp:125
MFEM_HOST_DEVICE DeviceTensor(Scalar *data_, Args... args)
Constructor to initialize a tensor from the Scalar array data_.
Definition dtensor.hpp:98
DeviceTensor & operator=(const DeviceTensor &)=default
Copy assignment (default)
MFEM_HOST_DEVICE Scalar & operator()(Args... args) const
Const accessor for the data.
Definition dtensor.hpp:118
MFEM_HOST_DEVICE auto & GetShape() const
Returns the shape of the tensor.
Definition dtensor.hpp:131
static MFEM_HOST_DEVICE int result(int *sizes, T first, Args... args)
Definition dtensor.hpp:73
A class to initialize the size of a Tensor.
Definition dtensor.hpp:57
static MFEM_HOST_DEVICE int result(int *sizes, T first, Args... args)
Definition dtensor.hpp:60
static MFEM_HOST_DEVICE int result(const int *sizes, T first, Args... args)
Definition dtensor.hpp:43
A Class to compute the real index from the multi-indices of a tensor.
Definition dtensor.hpp:24
static MFEM_HOST_DEVICE int result(const int *sizes, T first, Args... args)
Definition dtensor.hpp:27
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:138