XGC1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
view_arithmetic.hpp
Go to the documentation of this file.
1 #ifndef VIEW_ARITHMETIC_HPP
2 #define VIEW_ARITHMETIC_HPP
3 #include "space_settings.hpp"
4 #include "globals.hpp"
5 
6 // Functions to facilitate element-wise addition and subtraction of Views. Could try overloading views, but this works and is simple enough
7 
8 // Struct to hold raw device pointers (At some point there was an OMP bug that disallowed raw pointers sent in lambdas
9 template<typename T>
11  T* x;
12  T* y;
13 
14  ViewArithmeticPointers(T* x, T* y) : x(x), y(y){}
15 };
16 
17 // Add added_view*coeff to dest_view
18 template<typename V1, typename V2, typename T>
19 inline void host_add_ay_to_x(V1& dest_view, const V2& added_view, T coeff){
20  if (dest_view.size() != added_view.size()) exit_XGC("\nWARNING: dest_view and added_view are not the same size");
21 
22  // Access raw pointer of View so that we can loop over the whole array without worrying about dimensions
23  const ViewArithmeticPointers<T> ptrs(dest_view.data(), added_view.data());
24  Kokkos::parallel_for("host_add_ay_to_x", Kokkos::RangePolicy<HostExSpace>( 0, dest_view.size()), KOKKOS_LAMBDA(const int idx){
25  ptrs.x[idx] += coeff*ptrs.y[idx];
26  });
27 }
28 
29 // Multiply x by y
30 template<typename V1, typename V2>
31 inline void host_multiply_x_by_y(V1& dest_view, const V2& multiplier_view){
32  if (dest_view.size() != multiplier_view.size()) exit_XGC("\nWARNING: dest_view and multiplier_view are not the same size");
33 
34  // Access raw pointer of View so that we can loop over the whole array without worrying about dimensions
35  const ViewArithmeticPointers<double> ptrs(dest_view.data(), multiplier_view.data());
36  Kokkos::parallel_for("host_multiply_x_by_y", Kokkos::RangePolicy<HostExSpace>( 0, dest_view.size()), KOKKOS_LAMBDA(const int idx){
37  ptrs.x[idx] *= ptrs.y[idx];
38  });
39 }
40 
41 // Divide x by y
42 template<typename V1, typename V2>
43 inline void host_divide_x_by_y(V1& dest_view, const V2& divisor_view){
44  if (dest_view.size() != divisor_view.size()) exit_XGC("\nWARNING: dest_view and divisor_view are not the same size");
45 
46  // Access raw pointer of View so that we can loop over the whole array without worrying about dimensions
47  const ViewArithmeticPointers<double> ptrs(dest_view.data(), divisor_view.data());
48  Kokkos::parallel_for("host_divide_x_by_y", Kokkos::RangePolicy<HostExSpace>( 0, dest_view.size()), KOKKOS_LAMBDA(const int idx){
49  ptrs.x[idx] /= ptrs.y[idx];
50  });
51 }
52 
53 // Divide x by a. a is converted to a double to take the inverse, so it must be convertible. The view value type must be multipliable by a double.
54 template<typename V1, typename T>
55 inline void divide_x_by_a(const V1& dest_view, T coeff){
56  double coeff_inv = 1.0/coeff;
57 
58  // Cast to 1D with an unmanaged view for a generic element-wise operation
59  View<typename V1::value_type*,CLayout, typename V1::device_type, Kokkos::MemoryTraits<Kokkos::Unmanaged>> view_1D(dest_view.data(), dest_view.size());
60 
61  // Multiply each element by inverse of coeff
62  Kokkos::parallel_for("divide_x_by_a", Kokkos::RangePolicy<typename V1::execution_space>( 0, view_1D.size()), KOKKOS_LAMBDA(const int idx){
63  view_1D(idx) *= coeff_inv;
64  });
65  Kokkos::fence();
66 }
67 
68 // Add added_view to dest_view
69 template<typename V1, typename V2>
70 inline void add_y_to_x(const V1& dest_view, const V2& added_view){
71  if (dest_view.size() != added_view.size()) exit_XGC("\nWARNING: dest_view and added_view are not the same size");
72 
73  // Cast to 1D with an unmanaged view for a generic element-wise operation
74  View<typename V1::value_type*,CLayout, typename V1::device_type, Kokkos::MemoryTraits<Kokkos::Unmanaged>> dest_view_1D(dest_view.data(), dest_view.size());
75  View<typename V2::value_type*,CLayout, typename V2::device_type, Kokkos::MemoryTraits<Kokkos::Unmanaged>> added_view_1D(added_view.data(), added_view.size());
76 
77  // Add each element of added_view to dest_view
78  Kokkos::parallel_for("add_y_to_x", Kokkos::RangePolicy<typename V1::execution_space>( 0, dest_view_1D.size()), KOKKOS_LAMBDA(const int idx){
79  dest_view_1D(idx) += added_view_1D(idx);
80  });
81  Kokkos::fence();
82 }
83 
84 // Add device view to host view. Copies device view to a temporary host view, then adds them
85 template<typename V1, typename V2>
86 inline void add_device_view_to_host_view(V1& dest_view, const V2& device_view){
87  if (dest_view.size() != device_view.size()) exit_XGC("\nWARNING: dest_view and device_view are not the same size");
88 
89  // Create 1D host view and copy device data
90  View<double*,CLayout,HostType> view_tmp_h(NoInit("view_tmp_h"), device_view.size());
91  View<double*,CLayout,typename V2::device_type, Kokkos::MemoryTraits<Kokkos::Unmanaged>> view_tmp_d(device_view.data(),device_view.size());
92  Kokkos::deep_copy(view_tmp_h, view_tmp_d);
93 
94  // Access raw pointer of View so that we can loop over the whole array without worrying about dimensions
95  const ViewArithmeticPointers<double> ptrs(dest_view.data(), view_tmp_h.data());
96  Kokkos::parallel_for("host_view_sum", Kokkos::RangePolicy<HostExSpace>( 0, dest_view.size()), KOKKOS_LAMBDA(const int idx){
97  ptrs.x[idx] += ptrs.y[idx];
98  });
99 }
100 
101 // Sums all elements of a view of any shape
102 template<typename T>
103 inline typename T::value_type sum_view(const T& view){
104  // Cast to 1D with an unmanaged view for a generic element-wise operation
105  View<typename T::value_type*,CLayout, typename T::device_type, Kokkos::MemoryTraits<Kokkos::Unmanaged>> view_1D(view.data(), view.size());
106 
107  typename T::value_type sum = 0;
108  Kokkos::parallel_reduce("sum", Kokkos::RangePolicy<typename T::execution_space>( 0,view.size() ), KOKKOS_LAMBDA( const int i, typename T::value_type& sum_l){
109  sum_l += view_1D(i);
110  }, sum);
111  Kokkos::fence();
112 
113  return sum;
114 }
115 
116 // Finds the max of all elements of a view of any shape
117 template<typename T>
118 inline typename T::value_type max_view(const T& view){
119  // Cast to 1D with an unmanaged view for a generic element-wise operation
120  View<typename T::value_type*,CLayout, typename T::device_type, Kokkos::MemoryTraits<Kokkos::Unmanaged>> view_1D(view.data(), view.size());
121 
122  typename T::value_type maxval = 0;
123  Kokkos::parallel_reduce("maxval", Kokkos::RangePolicy<typename T::execution_space>( 0,view.size() ), KOKKOS_LAMBDA( const int i, typename T::value_type& maxval_l){
124  maxval_l = max(maxval_l, view_1D(i));
125  }, Kokkos::Max<typename T::value_type,HostType>(maxval));
126  Kokkos::fence();
127 
128  return maxval;
129 }
130 
131 #endif
void host_divide_x_by_y(V1 &dest_view, const V2 &divisor_view)
Definition: view_arithmetic.hpp:43
void host_multiply_x_by_y(V1 &dest_view, const V2 &multiplier_view)
Definition: view_arithmetic.hpp:31
T::value_type max_view(const T &view)
Definition: view_arithmetic.hpp:118
void add_device_view_to_host_view(V1 &dest_view, const V2 &device_view)
Definition: view_arithmetic.hpp:86
void host_add_ay_to_x(V1 &dest_view, const V2 &added_view, T coeff)
Definition: view_arithmetic.hpp:19
T * y
Definition: view_arithmetic.hpp:12
ViewArithmeticPointers(T *x, T *y)
Definition: view_arithmetic.hpp:14
T::value_type sum_view(const T &view)
Definition: view_arithmetic.hpp:103
void exit_XGC(std::string msg)
Definition: globals.hpp:37
void add_y_to_x(const V1 &dest_view, const V2 &added_view)
Definition: view_arithmetic.hpp:70
void parallel_for(const std::string name, int n_ptl, Function func, Option option, HostAoSoA aosoa_h, DeviceAoSoA aosoa_d)
Definition: streamed_parallel_for.hpp:252
Definition: view_arithmetic.hpp:10
T * x
Definition: view_arithmetic.hpp:11
Kokkos::ViewAllocateWithoutInitializing NoInit
Definition: space_settings.hpp:69
void divide_x_by_a(const V1 &dest_view, T coeff)
Definition: view_arithmetic.hpp:55