Intrepid2
Intrepid2_Utils.hpp
Go to the documentation of this file.
1// @HEADER
2// ************************************************************************
3//
4// Intrepid2 Package
5// Copyright (2007) Sandia Corporation
6//
7// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8// license for use of this work by or on behalf of the U.S. Government.
9//
10// Redistribution and use in source and binary forms, with or without
11// modification, are permitted provided that the following conditions are
12// met:
13//
14// 1. Redistributions of source code must retain the above copyright
15// notice, this list of conditions and the following disclaimer.
16//
17// 2. Redistributions in binary form must reproduce the above copyright
18// notice, this list of conditions and the following disclaimer in the
19// documentation and/or other materials provided with the distribution.
20//
21// 3. Neither the name of the Corporation nor the names of the
22// contributors may be used to endorse or promote products derived from
23// this software without specific prior written permission.
24//
25// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36//
37// Questions? Contact Kyungjoo Kim (kyukim@sandia.gov), or
38// Mauro Perego (mperego@sandia.gov)
39//
40// ************************************************************************
41// @HEADER
42
49#ifndef __INTREPID2_UTILS_HPP__
50#define __INTREPID2_UTILS_HPP__
51
52#include "Intrepid2_ConfigDefs.hpp"
54#include "Intrepid2_Types.hpp"
55
56#include "Kokkos_Core.hpp"
57#include "Kokkos_Macros.hpp" // provides some preprocessor values used in definitions of INTREPID2_DEPRECATED, etc.
58#include "Kokkos_Random.hpp"
59
60#ifdef HAVE_INTREPID2_SACADO
61#include "Kokkos_LayoutNatural.hpp"
62#endif
63
64namespace Intrepid2 {
65
66#if defined(KOKKOS_OPT_RANGE_AGGRESSIVE_VECTORIZATION) && defined(KOKKOS_ENABLE_PRAGMA_IVDEP) && !defined(__CUDA_ARCH__)
67#define INTREPID2_USE_IVDEP
68#endif
69
70 //
71 // test macros
72 //
73
74#define INTREPID2_TEST_FOR_WARNING(test, msg) \
75 if (test) { \
76 printf("[Intrepid2] Warning in file %s, line %d\n",__FILE__,__LINE__); \
77 printf(" Test that evaluated to true: %s\n", #test); \
78 printf(" %s \n", msg); \
79 }
80
81#define INTREPID2_TEST_FOR_EXCEPTION(test, x, msg) \
82 if (test) { \
83 printf("[Intrepid2] Error in file %s, line %d\n",__FILE__,__LINE__); \
84 printf(" Test that evaluated to true: %s\n", #test); \
85 printf(" %s \n", msg); \
86 throw x(msg); \
87 }
88
89#ifndef KOKKOS_ENABLE_CUDA
90#define INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE(test, x, msg) \
91 if (test) { \
92 std::cout << "[Intrepid2] Error in file " << __FILE__ << ", line " << __LINE__ << "\n"; \
93 std::cout << " Test that evaluated to true: " << #test << "\n"; \
94 std::cout << " " << msg << " \n"; \
95 throw x(msg); \
96 }
97#else
98 #define INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE(test, x, msg) device_assert(!(test));
99#endif
100
101#define INTREPID2_TEST_FOR_ABORT(test, msg) \
102 if (test) { \
103 printf("[Intrepid2] Error in file %s, line %d\n",__FILE__,__LINE__); \
104 printf(" Test that evaluated to true: %s\n", #test); \
105 printf(" %s \n", msg); \
106 Kokkos::abort( "[Intrepid2] Abort\n"); \
107 }
108
109#ifndef KOKKOS_ENABLE_CUDA
110#define INTREPID2_TEST_FOR_ABORT_DEVICE_SAFE(test, msg) \
111 if (test) { \
112 printf("[Intrepid2] Error in file %s, line %d\n",__FILE__,__LINE__); \
113 printf(" Test that evaluated to true: %s\n", #test); \
114 printf(" %s \n", msg); \
115 Kokkos::abort( "[Intrepid2] Abort\n"); \
116 }
117#else
118 #define INTREPID2_TEST_FOR_ABORT_DEVICE_SAFE(test, msg) device_assert(!(test));
119#endif
120
121
122 // check the first error only
123#ifdef INTREPID2_TEST_FOR_DEBUG_ABORT_OVERRIDE_TO_CONTINUE
124#define INTREPID2_TEST_FOR_DEBUG_ABORT(test, info, msg) \
125 if (!(info) && (test)) { \
126 printf("[Intrepid2] Error in file %s, line %d\n",__FILE__,__LINE__); \
127 printf(" Test that evaluated to true: %s\n", #test); \
128 printf(" %s \n", msg); \
129 info = true; \
130 }
131#else
132#define INTREPID2_TEST_FOR_DEBUG_ABORT(test, info, msg) \
133 if (!(info) && (test)) { \
134 printf("[Intrepid2] Error in file %s, line %d\n",__FILE__,__LINE__); \
135 printf(" Test that evaluated to true: %s\n", #test); \
136 printf(" %s \n", msg); \
137 info = true ; \
138 Kokkos::abort( "[Intrepid2] Abort\n"); \
139 }
140#endif
141
145 template<typename T>
147 typedef typename T::scalar_type scalar_type;
148 };
149
150 // this is built in types to support
154 template<>
155 struct ScalarTraits<float> {
156 typedef float scalar_type;
157 };
161 template<>
162 struct ScalarTraits<double> {
163 typedef double scalar_type;
164 };
168 template<>
169 struct ScalarTraits<int> {
170 typedef int scalar_type;
171 };
175 template<>
176 struct ScalarTraits<long int> {
177 typedef long int scalar_type;
178 };
182 template<>
183 struct ScalarTraits<long long> {
184 typedef long long scalar_type;
185 };
186
187
188
192 template<typename ViewSpaceType, typename UserSpaceType>
193 struct ExecSpace {
194 typedef UserSpaceType ExecSpaceType;
195 };
196
200 template<typename ViewSpaceType>
201 struct ExecSpace<ViewSpaceType,void> {
202 typedef ViewSpaceType ExecSpaceType;
203 };
204
205
209 template <typename ViewType>
211 using input_layout = typename ViewType::array_layout;
212 using default_layout = typename ViewType::device_type::execution_space::array_layout;
213 using result_layout =
214 typename std::conditional<
215 std::is_same< input_layout, Kokkos::LayoutStride >::value,
216 default_layout,
217 input_layout >::type;
218 };
219
220
221 //
222 // utilities device comparible
223 //
224
225 // this will be gone
226 template<typename IdxType, typename DimType, typename IterType>
227 KOKKOS_FORCEINLINE_FUNCTION
228 static void
229 unrollIndex(IdxType &i, IdxType &j,
230 const DimType /* dim0 */,
231 const DimType dim1,
232 const IterType iter) {
233 // left index
234 //j = iter/dim0;
235 //i = iter%dim0;
236
237 // right index
238 i = iter/dim1;
239 j = iter%dim1;
240 }
241
242 template<typename IdxType, typename DimType, typename IterType>
243 KOKKOS_FORCEINLINE_FUNCTION
244 static void
245 unrollIndex(IdxType &i, IdxType &j, IdxType &k,
246 const DimType dim0,
247 const DimType dim1,
248 const DimType dim2,
249 const IterType iter) {
250 IdxType tmp;
251
252 //unrollIndex(tmp, k, dim0*dim1, dim2, iter);
253 //unrollIndex( i, j, dim0, dim1, tmp);
254
255 unrollIndex( i, tmp, dim0, dim1*dim2, iter);
256 unrollIndex( j, k, dim1, dim2, tmp);
257 }
258
262 template<typename T>
263 class Util {
264 public:
265 KOKKOS_FORCEINLINE_FUNCTION
266 static T min(const T a, const T b) {
267 return (a < b ? a : b);
268 }
269
270 KOKKOS_FORCEINLINE_FUNCTION
271 static T max(const T a, const T b) {
272 return (a > b ? a : b);
273 }
274
275 KOKKOS_FORCEINLINE_FUNCTION
276 static T abs(const T a) {
277 return (a > 0 ? a : T(-a));
278 }
279
280 };
281
282 template<typename T>
283 KOKKOS_FORCEINLINE_FUNCTION
284 static T min(const T &a, const T &b) {
285 return (a < b ? a : b);
286 }
287
288 template<typename T>
289 KOKKOS_FORCEINLINE_FUNCTION
290 static T max(const T &a, const T &b) {
291 return (a > b ? a : b);
292 }
293
294 template<typename T>
295 KOKKOS_FORCEINLINE_FUNCTION
296 static T abs(const T &a) {
297 return (a > 0 ? a : T(-a));
298 }
299
307 template<typename T>
308 KOKKOS_FORCEINLINE_FUNCTION
309 constexpr typename
310 std::enable_if< !std::is_pod<T>::value, typename ScalarTraits<T>::scalar_type >::type
311 get_scalar_value(const T& obj) {return obj.val();}
312
313 template<typename T>
314 KOKKOS_FORCEINLINE_FUNCTION
315 constexpr typename
316 std::enable_if< std::is_pod<T>::value, typename ScalarTraits<T>::scalar_type >::type
317 get_scalar_value(const T& obj){return obj;}
318
319
326 template<typename T, typename ...P>
327 KOKKOS_INLINE_FUNCTION
328 constexpr typename
329 std::enable_if< std::is_pod<T>::value, unsigned >::type
330 dimension_scalar(const Kokkos::DynRankView<T, P...> /* view */) {return 1;}
331
332 template<typename T, typename ...P>
333 KOKKOS_INLINE_FUNCTION
334 constexpr typename
335 std::enable_if< std::is_pod< typename Kokkos::View<T, P...>::value_type >::value, unsigned >::type
336 dimension_scalar(const Kokkos::View<T, P...> /*view*/) {return 1;}
337
338 template<typename T, typename ...P>
339 KOKKOS_FORCEINLINE_FUNCTION
340 static ordinal_type get_dimension_scalar(const Kokkos::DynRankView<T, P...> &view) {
341 return dimension_scalar(view);
342 }
343
344 template<typename T, typename ...P>
345 KOKKOS_FORCEINLINE_FUNCTION
346 static ordinal_type get_dimension_scalar(const Kokkos::View<T, P...> &view) {
347 return dimension_scalar(view);
348 }
349
358 template<class ViewType, class ... DimArgs>
359 inline
360 Kokkos::DynRankView<typename ViewType::value_type, typename DeduceLayout< ViewType >::result_layout, typename ViewType::device_type >
361 getMatchingViewWithLabel(const ViewType &view, const std::string &label, DimArgs... dims)
362 {
363 using ValueType = typename ViewType::value_type;
364 using ResultLayout = typename DeduceLayout< ViewType >::result_layout;
365 using DeviceType = typename ViewType::device_type;
366 using ViewTypeWithLayout = Kokkos::DynRankView<ValueType, ResultLayout, DeviceType >;
367
368 const bool allocateFadStorage = !std::is_pod<ValueType>::value;
369 if (!allocateFadStorage)
370 {
371 return ViewTypeWithLayout(label,dims...);
372 }
373 else
374 {
375 const int derivative_dimension = get_dimension_scalar(view);
376 return ViewTypeWithLayout(label,dims...,derivative_dimension);
377 }
378 }
379
383 template <typename T>
385 {
386 typedef char one;
387 struct two { char x[2]; };
388
389 template <typename C> static one test( typename std::remove_reference<decltype( std::declval<C>().operator()(0))>::type );
390 template <typename C> static two test(...);
391
392 public:
393 enum { value = sizeof(test<T>(0)) == sizeof(char) };
394 };
395
399 template <typename T>
401 {
402 typedef char one;
403 struct two { char x[2]; };
404
405 template <typename C> static one test( typename std::remove_reference<decltype( std::declval<C>().operator()(0,0))>::type ) ;
406 template <typename C> static two test(...);
407
408 public:
409 enum { value = sizeof(test<T>(0)) == sizeof(char) };
410 };
411
415 template <typename T>
417 {
418 typedef char one;
419 struct two { char x[2]; };
420
421 template <typename C> static one test( typename std::remove_reference<decltype( std::declval<C>().operator()(0,0,0))>::type ) ;
422 template <typename C> static two test(...);
423
424 public:
425 enum { value = sizeof(test<T>(0)) == sizeof(char) };
426 };
427
431 template <typename T>
433 {
434 typedef char one;
435 struct two { char x[2]; };
436
437 template <typename C> static one test( typename std::remove_reference<decltype( std::declval<C>().operator()(0,0,0,0))>::type ) ;
438 template <typename C> static two test(...);
439
440 public:
441 enum { value = sizeof(test<T>(0)) == sizeof(char) };
442 };
443
447 template <typename T>
449 {
450 typedef char one;
451 struct two { char x[2]; };
452
453 template <typename C> static one test( typename std::remove_reference<decltype( std::declval<C>().operator()(0,0,0,0,0))>::type ) ;
454 template <typename C> static two test(...);
455
456 public:
457 enum { value = sizeof(test<T>(0)) == sizeof(char) };
458 };
459
463 template <typename T>
465 {
466 typedef char one;
467 struct two { char x[2]; };
468
469 template <typename C> static one test( typename std::remove_reference<decltype( std::declval<C>().operator()(0,0,0,0,0,0))>::type ) ;
470 template <typename C> static two test(...);
471
472 public:
473 enum { value = sizeof(test<T>(0)) == sizeof(char) };
474 };
475
479 template <typename T>
481 {
482 typedef char one;
483 struct two { char x[2]; };
484
485 template <typename C> static one test( typename std::remove_reference<decltype( std::declval<C>().operator()(0,0,0,0,0,0,0))>::type ) ;
486 template <typename C> static two test(...);
487
488 public:
489 enum { value = sizeof(test<T>(0)) == sizeof(char) };
490 };
491
495 template <typename T, int rank>
497 {
498 public:
499 enum { value = false };
500 };
501
505 template <typename T>
506 class supports_rank<T,1>
507 {
508 public:
509 enum { value = supports_rank_1<T>::value };
510 };
511
513 template <typename T>
514 class supports_rank<T,2>
515 {
516 public:
517 enum { value = supports_rank_2<T>::value };
518 };
519
521 template <typename T>
522 class supports_rank<T,3>
523 {
524 public:
525 enum { value = supports_rank_3<T>::value };
526 };
527
529 template <typename T>
530 class supports_rank<T,4>
531 {
532 public:
533 enum { value = supports_rank_4<T>::value };
534 };
535
537 template <typename T>
538 class supports_rank<T,5>
539 {
540 public:
541 enum { value = supports_rank_5<T>::value };
542 };
543
545 template <typename T>
546 class supports_rank<T,6>
547 {
548 public:
549 enum { value = supports_rank_6<T>::value };
550 };
551
553 template <typename T>
554 class supports_rank<T,7>
555 {
556 public:
557 enum { value = supports_rank_7<T>::value };
558 };
559
560
561
565 template<typename Scalar, int rank>
567
568 };
569
573 template<typename Scalar>
574 struct RankExpander<Scalar,0>
575 {
576 using value_type = Scalar;
577 };
578
582 template<typename Scalar>
583 struct RankExpander<Scalar,1>
584 {
585 using value_type = Scalar*;
586 };
587
591 template<typename Scalar>
592 struct RankExpander<Scalar,2>
593 {
594 using value_type = Scalar**;
595 };
596
600 template<typename Scalar>
601 struct RankExpander<Scalar,3>
602 {
603 using value_type = Scalar***;
604 };
605
609 template<typename Scalar>
610 struct RankExpander<Scalar,4>
611 {
612 using value_type = Scalar****;
613 };
614
618 template<typename Scalar>
619 struct RankExpander<Scalar,5>
620 {
621 using value_type = Scalar*****;
622 };
623
627 template<typename Scalar>
628 struct RankExpander<Scalar,6>
629 {
630 using value_type = Scalar******;
631 };
632
636 template<typename Scalar>
637 struct RankExpander<Scalar,7>
638 {
639 using value_type = Scalar*******;
640 };
641
642// static_assert(supports_rank_4< Kokkos::DynRankView<double> >::value, "rank 4 check of supports_rank");
643//
644// static_assert(supports_rank<Kokkos::DynRankView<double>, 1>::value, "rank 1 check of supports_rank");
645//
646// static_assert(supports_rank<Kokkos::View<double*>, 1>::value, "rank 1 check of supports_rank");
647// static_assert(supports_rank<Kokkos::View<double**>, 2>::value, "rank 2 check of supports_rank");
648// static_assert(supports_rank<Kokkos::View<double***>, 3>::value, "rank 3 check of supports_rank");
649// static_assert(supports_rank<Kokkos::View<double****>, 4>::value, "rank 4 check of supports_rank");
650// static_assert(supports_rank<Kokkos::View<double*****>, 5>::value, "rank 5 check of supports_rank");
651// static_assert(supports_rank<Kokkos::View<double******>, 6>::value, "rank 6 check of supports_rank");
652// static_assert(supports_rank<Kokkos::View<double*******>, 7>::value, "rank 7 check of supports_rank");
653
657 template <typename T>
659 {
660 typedef char one;
661 struct two { char x[2]; };
662
663 template <typename C> static one test( decltype( std::declval<C>().rank() ) ) ;
664 template <typename C> static two test(...);
665
666 public:
667 enum { value = sizeof(test<T>(0)) == sizeof(char) };
668 };
669
670 static_assert( has_rank_method<Kokkos::DynRankView<double> >::value, "DynRankView implements rank(), so this assert should pass -- if not, something may be wrong with has_rank_method.");
671 static_assert(! has_rank_method<Kokkos::View<double> >::value, "View does not implement rank() -- if this assert fails, something may be wrong with has_rank_method.");
672
673 template< bool B, class T >
674 using enable_if_t = typename std::enable_if<B,T>::type;
675
679 template<class Functor>
680 enable_if_t<has_rank_method<Functor>::value, unsigned>
681 KOKKOS_INLINE_FUNCTION
682 getFunctorRank(const Functor &functor)
683 {
684 return functor.rank();
685 }
686
690 template<class Functor>
691 enable_if_t<!has_rank_method<Functor>::value, unsigned>
692 KOKKOS_INLINE_FUNCTION
693 getFunctorRank(const Functor &functor)
694 {
695 return functor.rank;
696 }
697
701#ifdef HAVE_INTREPID2_SACADO
702 template <typename ValueType>
703 struct NaturalLayoutForType {
704 using layout =
705 typename std::conditional<std::is_pod<ValueType>::value,
706 Kokkos::LayoutLeft, // for POD types, use LayoutLeft
707 Kokkos::LayoutNatural<Kokkos::LayoutLeft> >::type; // For FAD types, use LayoutNatural
708 };
709#else
710 template <typename ValueType>
712 using layout = Kokkos::LayoutLeft;
713 };
714#endif
715
716 // define vector sizes for hierarchical parallelism
717 const int VECTOR_SIZE = 1;
718#if defined(SACADO_VIEW_CUDA_HIERARCHICAL_DFAD) && defined(KOKKOS_ENABLE_CUDA)
719 const int FAD_VECTOR_SIZE = 32;
720#else
721 const int FAD_VECTOR_SIZE = 1;
722#endif
723
727 template<typename Scalar>
729 {
730 return std::is_pod<Scalar>::value ? VECTOR_SIZE : FAD_VECTOR_SIZE;
731 }
732
738 template<typename ViewType>
739 KOKKOS_INLINE_FUNCTION
740 constexpr unsigned getScalarDimensionForView(const ViewType &view)
741 {
742 return (std::is_pod<typename ViewType::value_type>::value) ? 0 : get_dimension_scalar(view);
743 }
744} // end namespace Intrepid2
745
746#endif
Implementation of an assert that can safely be called from device code.
Contains definitions of custom data types in Intrepid2.
enable_if_t< has_rank_method< Functor >::value, unsigned > KOKKOS_INLINE_FUNCTION getFunctorRank(const Functor &functor)
KOKKOS_INLINE_FUNCTION constexpr std::enable_if< std::is_pod< T >::value, unsigned >::type dimension_scalar(const Kokkos::DynRankView< T, P... >)
specialization of functions for pod types, returning the scalar dimension (1 for pod types) of a view...
constexpr int getVectorSizeForHierarchicalParallelism()
Returns a vector size to be used for the provided Scalar type in the context of hierarchically-parall...
KOKKOS_FORCEINLINE_FUNCTION constexpr std::enable_if<!std::is_pod< T >::value, typenameScalarTraits< T >::scalar_type >::type get_scalar_value(const T &obj)
functions returning the scalar value. for pod types, they return the input object itself....
KOKKOS_INLINE_FUNCTION constexpr unsigned getScalarDimensionForView(const ViewType &view)
Returns the size of the Scalar dimension for the View. This is 0 for non-AD types....
Kokkos::DynRankView< typename ViewType::value_type, typename DeduceLayout< ViewType >::result_layout, typename ViewType::device_type > getMatchingViewWithLabel(const ViewType &view, const std::string &label, DimArgs... dims)
Creates and returns a view that matches the provided view in Kokkos Layout.
small utility functions
Tests whether a class implements rank(). Used in getFunctorRank() method below; allows us to do one t...
SFINAE helper to detect whether a type supports a 1-integral-argument operator().
SFINAE helper to detect whether a type supports a 2-integral-argument operator().
SFINAE helper to detect whether a type supports a 3-integral-argument operator().
SFINAE helper to detect whether a type supports a 4-integral-argument operator().
SFINAE helper to detect whether a type supports a 5-integral-argument operator().
SFINAE helper to detect whether a type supports a 6-integral-argument operator().
SFINAE helper to detect whether a type supports a 7-integral-argument operator().
SFINAE helper to detect whether a type supports a rank-integral-argument operator().
layout deduction (temporary meta-function)
Define layout that will allow us to wrap Sacado Scalar objects in Views without copying.
Helper to get Scalar[*+] where the number of *'s matches the given rank.