Block-Structured AMR Software Framework
 
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Loading...
Searching...
No Matches
AMReX_TableData.H
Go to the documentation of this file.
1#ifndef AMREX_TABLE_DATA_H_
2#define AMREX_TABLE_DATA_H_
3#include <AMReX_Config.H>
4
5#include <AMReX.H>
6#include <AMReX_Array.H>
8#include <AMReX_GpuDevice.H>
9#include <AMReX_GpuPrint.H>
10
11#include <cstring>
12#include <iostream>
13#include <sstream>
14#include <type_traits>
15
16namespace amrex {
17
18template <typename T, typename IDX = int>
19struct Table1D
20{
21 T* AMREX_RESTRICT p = nullptr;
22 IDX begin = 1;
23 IDX end = 0;
24
25 constexpr Table1D () noexcept = default;
26
27 template <class U=T, std::enable_if_t<std::is_const_v<U>,int> = 0>
29 constexpr Table1D (Table1D<std::remove_const_t<T>> const& rhs) noexcept
30 : p(rhs.p),
31 begin(rhs.begin),
32 end(rhs.end)
33 {}
34
36 constexpr Table1D (T* a_p, IDX a_begin, IDX a_end) noexcept
37 : p(a_p),
38 begin(a_begin),
39 end(a_end)
40 {}
41
43 explicit operator bool () const noexcept { return p != nullptr; }
44
45 template <class U=T, std::enable_if_t<!std::is_void_v<U>,int> = 0>
47 U& operator() (IDX i) const noexcept {
48#if defined(AMREX_DEBUG) || defined(AMREX_BOUND_CHECK)
49 index_assert(i);
50#endif
51 return p[i-begin];
52 }
53
54#if defined(AMREX_DEBUG) || defined(AMREX_BOUND_CHECK)
56 void index_assert (IDX i) const
57 {
58 if (i < begin || i >= end) {
59 if constexpr (std::is_same_v<IDX,int>) {
61 AMREX_DEVICE_PRINTF(" (%d) is out of bound (%d:%d)\n",
62 i, begin, end-1);
64 ))
65 } else if constexpr (std::is_same_v<IDX,long>) {
67 AMREX_DEVICE_PRINTF(" (%ld) is out of bound (%ld:%ld)\n",
68 i, begin, end-1);
70 ))
71 } else if constexpr (std::is_same_v<IDX,long long>) {
73 AMREX_DEVICE_PRINTF(" (%lld) is out of bound (%lld:%lld)\n",
74 i, begin, end-1);
76 ))
77 } else {
78 AMREX_IF_ON_DEVICE(( amrex::Abort(" Out of bound\n"); ))
79 }
81 std::stringstream ss;
82 ss << " (" << i << ") is out of bound ("
83 << begin << ":" << end-1 << ")";
84 amrex::Abort(ss.str());
85 ))
86 }
87 }
88#endif
89};
90
91template <typename T, Order ORDER = Order::F>
92struct Table2D
93{
94 T* AMREX_RESTRICT p = nullptr;
95 Long stride1 = 0;
98
99 constexpr Table2D () noexcept = default;
100
101 template <class U=T, std::enable_if_t<std::is_const_v<U>,int> = 0>
103 constexpr Table2D (Table2D<std::remove_const_t<T>, ORDER> const& rhs) noexcept
104 : p(rhs.p),
105 stride1(rhs.stride1),
106 begin(rhs.begin),
107 end(rhs.end)
108 {}
109
111 constexpr Table2D (T* a_p,
112 GpuArray<int,2> const& a_begin,
113 GpuArray<int,2> const& a_end) noexcept
114 : p(a_p),
115 stride1(len0(a_begin,a_end)),
116 begin(a_begin),
117 end(a_end)
118 {}
119
121 explicit operator bool () const noexcept { return p != nullptr; }
122
123 template <class U=T, std::enable_if_t<!std::is_void_v<U>,int> = 0>
125 U& operator() (int i, int j) const noexcept {
126#if defined(AMREX_DEBUG) || defined(AMREX_BOUND_CHECK)
127 index_assert(i,j);
128#endif
129 if constexpr (ORDER == Order::F) {
130 return p[(i-begin[0])+(j-begin[1])*stride1];
131 } else {
132 return p[(i-begin[0])*stride1+(j-begin[1])];
133 }
134 }
135
136#if defined(AMREX_DEBUG) || defined(AMREX_BOUND_CHECK)
138 void index_assert (int i, int j) const
139 {
140 if (i < begin[0] || i >= end[0] ||
141 j < begin[1] || j >= end[1]) {
143 AMREX_DEVICE_PRINTF(" (%d,%d) is out of bound (%d:%d,%d:%d)\n",
144 i, j, begin[0], end[0]-1, begin[1], end[1]-1);
145 amrex::Abort();
146 ))
148 std::stringstream ss;
149 ss << " (" << i << "," << j << ") is out of bound ("
150 << begin[0] << ":" << end[0]-1
151 << "," << begin[1] << ":" << end[1]-1 << ")";
152 amrex::Abort(ss.str());
153 ))
154 }
155 }
156#endif
157
158private:
159
160 static constexpr int len0 (GpuArray<int,2> const& a_begin,
161 GpuArray<int,2> const& a_end) noexcept
162 {
163 if constexpr (ORDER == Order::F) {
164 return a_end[0] - a_begin[0];
165 } else {
166 return a_end[1] - a_begin[1];
167 }
168 }
169};
170
171template <typename T, Order ORDER = Order::F>
173{
174 T* AMREX_RESTRICT p = nullptr;
175 Long stride1 = 0;
176 Long stride2 = 0;
179
180 constexpr Table3D () noexcept = default;
181
182 template <class U=T, std::enable_if_t<std::is_const_v<U>,int> = 0>
184 constexpr Table3D (Table3D<std::remove_const_t<T>,ORDER> const& rhs) noexcept
185 : p(rhs.p),
186 stride1(rhs.stride1),
187 stride2(rhs.stride2),
188 begin(rhs.begin),
189 end(rhs.end)
190 {}
191
193 constexpr Table3D (T* a_p,
194 GpuArray<int,3> const& a_begin,
195 GpuArray<int,3> const& a_end) noexcept
196 : p(a_p),
197 stride1( len0(a_begin,a_end)),
198 stride2(stride1*len1(a_begin,a_end)),
199 begin(a_begin),
200 end(a_end)
201 {}
202
204 explicit operator bool () const noexcept { return p != nullptr; }
205
206 template <class U=T, std::enable_if_t<!std::is_void_v<U>,int> = 0>
208 U& operator() (int i, int j, int k) const noexcept {
209#if defined(AMREX_DEBUG) || defined(AMREX_BOUND_CHECK)
210 index_assert(i,j,k);
211#endif
212 if constexpr (ORDER == Order::F) {
213 return p[(i-begin[0])+(j-begin[1])*stride1+(k-begin[2])*stride2];
214 } else {
215 return p[(i-begin[0])*stride2+(j-begin[1])*stride1+(k-begin[2])];
216 }
217 }
218
219#if defined(AMREX_DEBUG) || defined(AMREX_BOUND_CHECK)
221 void index_assert (int i, int j, int k) const
222 {
223 if (i < begin[0] || i >= end[0] ||
224 j < begin[1] || j >= end[1] ||
225 k < begin[2] || k >= end[2]) {
227 AMREX_DEVICE_PRINTF(" (%d,%d,%d) is out of bound (%d:%d,%d:%d,%d:%d)\n",
228 i, j, k, begin[0], end[0]-1, begin[1], end[1]-1,
229 begin[2], end[2]-1);
230 amrex::Abort();
231 ))
233 std::stringstream ss;
234 ss << " (" << i << "," << j << "," << k << ") is out of bound ("
235 << begin[0] << ":" << end[0]-1
236 << "," << begin[1] << ":" << end[1]-1
237 << "," << begin[2] << ":" << end[2]-1 << ")";
238 amrex::Abort(ss.str());
239 ))
240 }
241 }
242#endif
243
244private:
245
246 static constexpr int len0 (GpuArray<int,3> const& a_begin,
247 GpuArray<int,3> const& a_end) noexcept
248 {
249 if constexpr (ORDER == Order::F) {
250 return a_end[0] - a_begin[0];
251 } else {
252 return a_end[2] - a_begin[2];
253 }
254 }
255
256 static constexpr int len1 (GpuArray<int,3> const& a_begin,
257 GpuArray<int,3> const& a_end) noexcept
258 {
259 return a_end[1] - a_begin[1];
260 }
261};
262
263template <typename T, Order ORDER = Order::F>
265{
266 T* AMREX_RESTRICT p = nullptr;
267 Long stride1 = 0;
268 Long stride2 = 0;
269 Long stride3 = 0;
272
273 constexpr Table4D () noexcept = default;
274
275 template <class U=T, std::enable_if_t<std::is_const_v<U>,int> = 0>
277 constexpr Table4D (Table4D<std::remove_const_t<T>,ORDER> const& rhs) noexcept
278 : p(rhs.p),
279 stride1(rhs.stride1),
280 stride2(rhs.stride2),
281 stride3(rhs.stride3),
282 begin(rhs.begin),
283 end(rhs.end)
284 {}
285
287 constexpr Table4D (T* a_p,
288 GpuArray<int,4> const& a_begin,
289 GpuArray<int,4> const& a_end) noexcept
290 : p(a_p),
291 stride1( len0(a_begin,a_end)),
292 stride2(stride1*len1(a_begin,a_end)),
293 stride3(stride2*len2(a_begin,a_end)),
294 begin(a_begin),
295 end(a_end)
296 {}
297
299 explicit operator bool () const noexcept { return p != nullptr; }
300
301 template <class U=T, std::enable_if_t<!std::is_void_v<U>,int> = 0>
303 U& operator() (int i, int j, int k, int n) const noexcept {
304#if defined(AMREX_DEBUG) || defined(AMREX_BOUND_CHECK)
305 index_assert(i,j,k,n);
306#endif
307 if constexpr (ORDER == Order::F) {
308 return p[(i-begin[0])+(j-begin[1])*stride1+(k-begin[2])*stride2+(n-begin[3])*stride3];
309 } else {
310 return p[(i-begin[0])*stride3+(j-begin[1])*stride2+(k-begin[2])*stride1+(n-begin[3])];
311 }
312 }
313
314#if defined(AMREX_DEBUG) || defined(AMREX_BOUND_CHECK)
316 void index_assert (int i, int j, int k, int n) const
317 {
318 if (i < begin[0] || i >= end[0] ||
319 j < begin[1] || j >= end[1] ||
320 k < begin[2] || k >= end[2] ||
321 n < begin[3] || n >= end[3]) {
323 AMREX_DEVICE_PRINTF(" (%d,%d,%d,%d) is out of bound (%d:%d,%d:%d,%d:%d,%d:%d)\n",
324 i, j, k, n, begin[0], end[0]-1, begin[1], end[1]-1,
325 begin[2], end[2]-1, begin[3], end[3]-1);
326 amrex::Abort();
327 ))
329 std::stringstream ss;
330 ss << " (" << i << "," << j << "," << k << "," << n << ") is out of bound ("
331 << begin[0] << ":" << end[0]-1
332 << "," << begin[1] << ":" << end[1]-1
333 << "," << begin[2] << ":" << end[2]-1
334 << "," << begin[3] << ":" << end[3]-1 << ")";
335 amrex::Abort(ss.str());
336 ))
337 }
338 }
339#endif
340
341private:
342
343 static constexpr int len0 (GpuArray<int,4> const& a_begin,
344 GpuArray<int,4> const& a_end) noexcept
345 {
346 if constexpr (ORDER == Order::F) {
347 return a_end[0] - a_begin[0];
348 } else {
349 return a_end[3] - a_begin[3];
350 }
351 }
352
353 static constexpr int len1 (GpuArray<int,4> const& a_begin,
354 GpuArray<int,4> const& a_end) noexcept
355 {
356 if constexpr (ORDER == Order::F) {
357 return a_end[1] - a_begin[1];
358 } else {
359 return a_end[2] - a_begin[2];
360 }
361 }
362
363 static constexpr int len2 (GpuArray<int,4> const& a_begin,
364 GpuArray<int,4> const& a_end) noexcept
365 {
366 if constexpr (ORDER == Order::F) {
367 return a_end[2] - a_begin[2];
368 } else {
369 return a_end[1] - a_begin[1];
370 }
371 }
372};
373
412template <typename T, int N, Order ORDER = Order::F>
414 : public DataAllocator
415{
416public:
417
418 template <class U, int M, Order O> friend class TableData;
419 using value_type = T;
420 using table_type = std::conditional_t<N==1, Table1D<T>,
421 std::conditional_t<N==2, Table2D<T, ORDER>,
422 std::conditional_t<N==3, Table3D<T, ORDER>,
423 Table4D<T, ORDER> > > >;
424 using const_table_type = std::conditional_t<N==1, Table1D<T const>,
425 std::conditional_t<N==2, Table2D<T const, ORDER>,
426 std::conditional_t<N==3, Table3D<T const, ORDER>,
428
429 TableData () noexcept = default;
430
431 explicit TableData (Arena* ar) noexcept;
432
433 TableData (Array<int,N> const& lo, Array<int,N> const& hi, Arena* ar = nullptr);
434
435 TableData (TableData<T,N,ORDER> const&) = delete;
436 TableData<T,N,ORDER>& operator= (TableData<T,N,ORDER> const&) = delete;
437
438 TableData (TableData<T,N,ORDER>&& rhs) noexcept;
439 TableData<T,N,ORDER>& operator= (TableData<T,N,ORDER> && rhs) noexcept;
440
441 ~TableData () noexcept;
442
443 [[nodiscard]] constexpr int dim () const noexcept { return N; }
444
445 void resize (Array<int,N> const& lo, Array<int,N> const& hi, Arena* ar = nullptr);
446
447 [[nodiscard]] Long size () const noexcept;
448
449 Array<int,N> const& lo () const noexcept { return m_lo; }
450
451 Array<int,N> const& hi () const noexcept { return m_hi; }
452
453 void clear () noexcept;
454
455 void copy (TableData<T,N,ORDER> const& rhs) noexcept;
456
457 table_type table () noexcept;
458 const_table_type table () const noexcept;
459 const_table_type const_table () const noexcept;
460
461private:
462
463 void define ();
464
465 T* m_dptr = nullptr;
466 Array<int,N> m_lo;
467 Array<int,N> m_hi;
468 Long m_truesize = 0L;
469 bool m_ptr_owner = false;
470};
471
472template <typename T, int N, Order ORDER>
473TableData<T,N,ORDER>::TableData (Array<int,N> const& lo, Array<int,N> const& hi, Arena* ar)
474 : DataAllocator{ar}, m_lo(lo), m_hi(hi)
475{
476 define();
477}
478
479
480template <typename T, int N, Order ORDER>
482 : DataAllocator{rhs.arena()},
483 m_dptr(rhs.m_dptr),
484 m_lo(rhs.m_lo),
485 m_hi(rhs.m_hi),
486 m_truesize(rhs.m_truesize),
487 m_ptr_owner(rhs.m_ptr_owner)
488{
489 rhs.m_dptr = nullptr;
490 rhs.m_ptr_owner = false;
491}
492
493template <typename T, int N, Order ORDER>
494TableData<T,N,ORDER>&
496{
497 if (this != &rhs) {
498 clear();
499 m_arena = rhs.m_arena;
500 m_dptr = rhs.m_dptr;
501 m_lo = rhs.m_lo;
502 m_hi = rhs.m_hi;
503 m_truesize = rhs.m_truesize;
504 m_ptr_owner = rhs.m_ptr_owner;
505 rhs.m_dptr = nullptr;
506 rhs.m_ptr_owner = false;
507 }
508 return *this;
509}
510
511template <typename T, int N, Order ORDER>
513{
514 static_assert(std::is_trivially_copyable<T>() &&
515 std::is_trivially_destructible<T>(),
516 "TableData<T,N,ORDER>: T must be trivially copyable and trivially destructible");
517 static_assert(N>=1 && N <=4, "TableData<T,N,ORDER>: N must be in the range of [1,4]");
518 clear();
519}
520
521template <typename T, int N, Order ORDER>
522void
524{
525 m_lo = lo;
526 m_hi = hi;
527
528 if (ar == nullptr) {
529 ar = m_arena;
530 }
531
532 if (arena() != DataAllocator(ar).arena()) {
533 clear();
534 m_arena = ar;
535 define();
536 } else if (m_dptr == nullptr || !m_ptr_owner) {
537 m_dptr = nullptr;
538 define();
539 } else if (size() > m_truesize) {
540 clear();
541 define();
542 }
543}
544
545template <typename T, int N, Order ORDER>
546Long
548{
549 Long r = 1;
550 for (int i = 0; i < N; ++i) {
551 r *= m_hi[i] - m_lo[i] + 1;
552 }
553 return r;
554}
555
556template <typename T, int N, Order ORDER>
557void
559{
560 if (m_dptr) {
561 if (m_ptr_owner) {
562 this->free(m_dptr);
563 }
564 m_dptr = nullptr;
565 m_truesize = 0;
566 }
567}
568
569template <typename T, int N, Order ORDER>
570void
572{
573 m_truesize = size();
574 AMREX_ASSERT(m_truesize >= 0);
575 if (m_truesize == 0) {
576 return;
577 } else {
578 m_ptr_owner = true;
579 m_dptr = static_cast<T*>(this->alloc(m_truesize*sizeof(T)));
580 }
581}
582
583namespace detail {
584 template <typename T, Order>
585 Table1D<T> make_table (T* p, Array<int,1> const& lo, Array<int,1> const& hi) {
586 return Table1D<T>(p, lo[0], hi[0]+1);
587 }
588 template <typename T, Order ORDER>
590 return Table2D<T,ORDER>(p, {lo[0],lo[1]}, {hi[0]+1,hi[1]+1});
591 }
592 template <typename T, Order ORDER>
593 Table3D<T> make_table (T* p, Array<int,3> const& lo, Array<int,3> const& hi) {
594 return Table3D<T,ORDER>(p, {lo[0],lo[1],lo[2]}, {hi[0]+1,hi[1]+1,hi[2]+1});
595 }
596 template <typename T, Order ORDER>
597 Table4D<T> make_table (T* p, Array<int,4> const& lo, Array<int,4> const& hi) {
598 return Table4D<T,ORDER>(p, {lo[0],lo[1],lo[2],lo[3]}, {hi[0]+1,hi[1]+1,hi[2]+1,hi[3]+1});
599 }
600}
601
602template <typename T, int N, Order ORDER>
603typename TableData<T,N,ORDER>::table_type
605{
606 return detail::make_table<T,ORDER>(m_dptr, m_lo, m_hi);
607}
608
609template <typename T, int N, Order ORDER>
612{
613 return detail::make_table<T const, ORDER>(m_dptr, m_lo, m_hi);
614}
615
616template <typename T, int N, Order ORDER>
619{
620 return detail::make_table<T const, ORDER>(m_dptr, m_lo, m_hi);
621}
622
623template <typename T, int N, Order ORDER>
624void
626{
627 std::size_t count = sizeof(T)*size();
628#ifdef AMREX_USE_GPU
629 bool this_on_device = arena()->isManaged() || arena()->isDevice();
630 bool rhs_on_device = rhs.arena()->isManaged() || rhs.arena()->isDevice();
631 if (this_on_device && rhs_on_device) {
632 Gpu::dtod_memcpy_async(m_dptr, rhs.m_dptr, count);
633 } else if (this_on_device && !rhs_on_device) {
634 Gpu::htod_memcpy_async(m_dptr, rhs.m_dptr, count);
635 } else if (!this_on_device && rhs_on_device) {
636 Gpu::dtoh_memcpy_async(m_dptr, rhs.m_dptr, count);
637 } else
638#endif
639 {
640 std::memcpy(m_dptr, rhs.m_dptr, count);
641 }
642}
643
644}
645
646#endif
#define AMREX_ASSERT(EX)
Definition AMReX_BLassert.H:38
#define AMREX_FORCE_INLINE
Definition AMReX_Extension.H:119
#define AMREX_RESTRICT
Definition AMReX_Extension.H:37
#define AMREX_DEVICE_PRINTF(...)
Definition AMReX_GpuPrint.H:21
#define AMREX_IF_ON_DEVICE(CODE)
Definition AMReX_GpuQualifiers.H:56
#define AMREX_IF_ON_HOST(CODE)
Definition AMReX_GpuQualifiers.H:58
#define AMREX_GPU_HOST_DEVICE
Definition AMReX_GpuQualifiers.H:20
void free(void *)
A virtual base class for objects that manage their own dynamic memory allocation.
Definition AMReX_Arena.H:100
Multi-dimensional array class.
Definition AMReX_TableData.H:415
std::conditional_t< N==1, Table1D< T >, std::conditional_t< N==2, Table2D< T, ORDER >, std::conditional_t< N==3, Table3D< T, ORDER >, Table4D< T, ORDER > > > > table_type
Definition AMReX_TableData.H:423
TableData() noexcept=default
Array< int, N > const & hi() const noexcept
Definition AMReX_TableData.H:451
std::conditional_t< N==1, Table1D< T const >, std::conditional_t< N==2, Table2D< T const, ORDER >, std::conditional_t< N==3, Table3D< T const, ORDER >, Table4D< T const, ORDER > > > > const_table_type
Definition AMReX_TableData.H:427
T value_type
Definition AMReX_TableData.H:419
Table1D< T > make_table(T *p, Array< int, 1 > const &lo, Array< int, 1 > const &hi)
Definition AMReX_TableData.H:585
Definition AMReX_Amr.cpp:49
Order
Definition AMReX_SmallMatrix.H:19
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE Dim3 end(BoxND< dim > const &box) noexcept
Definition AMReX_Box.H:1890
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE Dim3 begin(BoxND< dim > const &box) noexcept
Definition AMReX_Box.H:1881
void Abort(const std::string &msg)
Print out message to cerr and exit via abort().
Definition AMReX.cpp:230
std::array< T, N > Array
Definition AMReX_Array.H:24
Definition AMReX_FabArrayCommI.H:896
Definition AMReX_DataAllocator.H:9
Arena * arena() const noexcept
Definition AMReX_DataAllocator.H:24
Definition AMReX_Array.H:34
Definition AMReX_TableData.H:20
IDX begin
Definition AMReX_TableData.H:22
AMREX_GPU_HOST_DEVICE constexpr Table1D(T *a_p, IDX a_begin, IDX a_end) noexcept
Definition AMReX_TableData.H:36
T *AMREX_RESTRICT p
Definition AMReX_TableData.H:21
IDX end
Definition AMReX_TableData.H:23
constexpr Table1D() noexcept=default
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE U & operator()(IDX i) const noexcept
Definition AMReX_TableData.H:47
Definition AMReX_TableData.H:93
static constexpr int len0(GpuArray< int, 2 > const &a_begin, GpuArray< int, 2 > const &a_end) noexcept
Definition AMReX_TableData.H:160
constexpr Table2D() noexcept=default
AMREX_GPU_HOST_DEVICE constexpr Table2D(T *a_p, GpuArray< int, 2 > const &a_begin, GpuArray< int, 2 > const &a_end) noexcept
Definition AMReX_TableData.H:111
GpuArray< int, 2 > end
Definition AMReX_TableData.H:97
GpuArray< int, 2 > begin
Definition AMReX_TableData.H:96
T *AMREX_RESTRICT p
Definition AMReX_TableData.H:94
Long stride1
Definition AMReX_TableData.H:95
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE U & operator()(int i, int j) const noexcept
Definition AMReX_TableData.H:125
Definition AMReX_TableData.H:173
AMREX_GPU_HOST_DEVICE constexpr Table3D(T *a_p, GpuArray< int, 3 > const &a_begin, GpuArray< int, 3 > const &a_end) noexcept
Definition AMReX_TableData.H:193
static constexpr int len1(GpuArray< int, 3 > const &a_begin, GpuArray< int, 3 > const &a_end) noexcept
Definition AMReX_TableData.H:256
constexpr Table3D() noexcept=default
static constexpr int len0(GpuArray< int, 3 > const &a_begin, GpuArray< int, 3 > const &a_end) noexcept
Definition AMReX_TableData.H:246
Definition AMReX_TableData.H:265
static constexpr int len1(GpuArray< int, 4 > const &a_begin, GpuArray< int, 4 > const &a_end) noexcept
Definition AMReX_TableData.H:353
constexpr Table4D() noexcept=default
static constexpr int len2(GpuArray< int, 4 > const &a_begin, GpuArray< int, 4 > const &a_end) noexcept
Definition AMReX_TableData.H:363
static constexpr int len0(GpuArray< int, 4 > const &a_begin, GpuArray< int, 4 > const &a_end) noexcept
Definition AMReX_TableData.H:343
AMREX_GPU_HOST_DEVICE constexpr Table4D(T *a_p, GpuArray< int, 4 > const &a_begin, GpuArray< int, 4 > const &a_end) noexcept
Definition AMReX_TableData.H:287