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
Implementation of an assert that can safely be called from device code.
Contains definitions of custom data types in Intrepid2.
constexpr KOKKOS_INLINE_FUNCTION 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...
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.
constexpr KOKKOS_INLINE_FUNCTION unsigned getScalarDimensionForView(const ViewType &view)
Returns the size of the Scalar dimension for the View. This is 0 for non-AD types....
constexpr int getVectorSizeForHierarchicalParallelism()
Returns a vector size to be used for the provided Scalar type in the context of hierarchically-parall...
enable_if_t< has_rank_method< Functor >::value, unsigned > KOKKOS_INLINE_FUNCTION getFunctorRank(const Functor &functor)
constexpr KOKKOS_FORCEINLINE_FUNCTION 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....
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.