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 
64 namespace 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>
146  struct ScalarTraits {
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>
210  struct DeduceLayout {
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>
566  struct RankExpander {
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
SFINAE helper to detect whether a type supports a 5-integral-argument operator(). ...
small utility functions
constexpr int getVectorSizeForHierarchicalParallelism()
Returns a vector size to be used for the provided Scalar type in the context of hierarchically-parall...
SFINAE helper to detect whether a type supports a 1-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().
SFINAE helper to detect whether a type supports a 2-integral-argument operator(). ...
Implementation of an assert that can safely be called from device code.
Helper to get Scalar[*+] where the number of *&#39;s matches the given rank.
scalar type traits
SFINAE helper to detect whether a type supports a 3-integral-argument operator(). ...
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...
Tests whether a class implements rank(). Used in getFunctorRank() method below; allows us to do one t...
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. This method is useful for sizing scratch storage in hierarchically parallel kernels. Whereas get_dimension_scalar() returns 1 for POD types, this returns 0 for POD types.
Contains definitions of custom data types in Intrepid2.
Define layout that will allow us to wrap Sacado Scalar objects in Views without copying.
SFINAE helper to detect whether a type supports a 4-integral-argument operator(). ...
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.
KOKKOS_FORCEINLINE_FUNCTION constexpr std::enable_if< !std::is_pod< T >::value, typename ScalarTraits< T >::scalar_type >::type get_scalar_value(const T &obj)
functions returning the scalar value. for pod types, they return the input object itself...
layout deduction (temporary meta-function)
enable_if_t< has_rank_method< Functor >::value, unsigned > KOKKOS_INLINE_FUNCTION getFunctorRank(const Functor &functor)