XGC1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
grid_field.hpp
Go to the documentation of this file.
1 #ifndef GRID_FIELD_HPP
2 #define GRID_FIELD_HPP
3 #include "space_settings.hpp"
4 #include "NamelistReader.hpp"
5 
6 #include "globals.hpp"
7 #include "grid.hpp"
8 #include "linear_weights.hpp"
9 #include "gyro_radius.hpp"
10 #include "field.hpp"
11 
12 /* TorType specifies whether the field is a single plane or needs a plane dimension
13  * */
14 enum class TorType{
15  OnePlane,
17 };
18 
19 // General declaration
20 // 2x2 = 4 types of GridField available: With and without gyroaverage dimension, with and without plane dimension
21 template<class Device, VarType VT, PhiInterpType PIT, TorType TT, KinType KT, ScatterType ST = ScatterType::Atomic>
22 struct GridField;
23 
24 // "ScalarGridField"
25 template<class Device, VarType VT, PhiInterpType PIT>
28  using device_type = Device;
29  static constexpr KinType KT = KinType::DriftKin;
30 
31  Kokkos::View<field_type*,Kokkos::LayoutRight,Device> f;
32 
34  GridField(std::string name, int nphi, int nrho, int nnode) : f(name,nnode) {}
35  GridField(std::string name, int nnode) : f(name,nnode) {}
36  field_type* data() const {return f.data();}
37  int size() const {return f.size();}
38  int nnode() const {return f.extent(0);}
39  int nrhop1() const {return 1;}
40  int nphi() const {return 1;}
41 
42  KOKKOS_INLINE_FUNCTION bool is_allocated() const {return f.is_allocated();}
43  KOKKOS_INLINE_FUNCTION field_type& operator ()(int inode) const {return f(inode);}
44 
45  // Scatter to a node
46  KOKKOS_INLINE_FUNCTION void scatter(int node, const SimdPhiWeights<get_phi_wt_usage(PIT)>& phi_wts, int i_simd, double particle_weight) const{
47  f(node).scatter(phi_wts, i_simd, particle_weight);
48  }
49 
50  // Scatter to a triangle
51  KOKKOS_INLINE_FUNCTION void scatter(const Grid<DeviceType>& grid, int ithread, const SimdGridWeights<Order::One, PIT_GLOBAL>& grid_wts, int i_simd, const SimdGyroWeights<DriftKin>& rho_wts, double particle_weight) const{
52  for (int j = 0; j<3; j++){
53  // Find triangle's nodes
54  int node=grid.get_node_index(grid_wts.itr[i_simd], j);
55  double wp=grid_wts.p[j][i_simd];
56 
57  // Scatter to node
58  scatter(node, grid_wts.phi_wts, i_simd, wp*particle_weight);
59  }
60  }
61 
62  // Gather from a triangle
63  KOKKOS_INLINE_FUNCTION void gather(const Grid<Device> &grid, const SimdGridWeights<Order::One, PhiInterpType::None>& grid_wts, const Simd<double>& phi, Simd<double>& fld) const{
64  // Initialize local field to 0
65  fld = 0.0;
66 
67  for (int i_simd = 0; i_simd<SIMD_SIZE; i_simd++){
68  if(grid_wts.is_invalid(i_simd)) continue;
69 
70  // Loop over the 3 vertices of the grid triangle and add up the contributions from each
71  for (int ip = 0; ip<3; ip++){
72  int node = grid.get_node_index(grid_wts.itr[i_simd], ip);
73  double wp = grid_wts.p[ip][i_simd];
74  f(node).gather(fld,i_simd,wp);
75  }
76  }
77  }
78 
79  // Gather from a triangle
80  KOKKOS_INLINE_FUNCTION void gather(const Grid<Device> &grid, const SimdGridWeights<Order::One, PhiInterpType::Planes>& grid_wts, const Simd<double>& phi, Simd<double>& fld) const{
81  // Initialize local field to 0
82  fld = 0.0;
83 
84  for (int i_simd = 0; i_simd<SIMD_SIZE; i_simd++){
85  if(grid_wts.is_invalid(i_simd)) continue;
86 
87  // Loop over the 3 vertices of the grid triangle and add up the contributions from each
88  for (int ip = 0; ip<3; ip++){
89  int node = grid.get_node_index(grid_wts.itr[i_simd], ip);
90  double wp = grid_wts.p[ip][i_simd];
91  f(node).gather(fld,i_simd,wp,grid_wts.phi_wts);
92  }
93  }
94  }
95 
96  KOKKOS_INLINE_FUNCTION void gather(const Grid<Device> &grid, const SimdGridWeights<Order::One, PIT>& grid_wts, const SimdGyroWeights<DriftKin>& rho_wts, Simd<double>& fld, int node_offset=0) const{
97  fld = 0.0;
98  for (int i_simd = 0; i_simd<SIMD_SIZE; i_simd++){
99  // If particle is inactive, set itr_work=1, phi=0D0, iphi=0
100  int itr_work = grid_wts.is_valid(i_simd) ? grid_wts.itr[i_simd] : 1;
101 
102  // Loop over the 3 vertices of the grid triangle and add up the contributions from each
103  for (int ip = 0; ip<3; ip++){
104  int i_node = grid_wts.is_valid(i_simd) ? grid.get_node_index(itr_work, ip) : 0;
105  double wp = grid_wts.is_valid(i_simd) ? grid_wts.p[ip][i_simd] : 0.0; // all these trinary ops are probably unnecessary
106 
107  const int node = i_node - node_offset;
108  f(node).gather(fld,i_simd, wp, grid_wts.phi_wts);
109  }
110  }
111  }
112 
114  int ndoubles_in_grid_field = f.size()*field_type::SIZE();
115  Kokkos::View<double*,Kokkos::LayoutRight,Device,Kokkos::MemoryTraits<Kokkos::Unmanaged>> view_1d_double((double*)(data()), ndoubles_in_grid_field);
116  Kokkos::deep_copy(view_1d_double, 0.0);
117  }
118 
119  // TODO: Generalize this copy and these transposes for ndim etc
120  // Fill View with transposed data where inode is the contiguous index
121  // Ultimately, there should probably be an implementation GridField that has the transposed indices
122  void copy_to_double_view(const View<double*,CLayout,Device>& dest_view) const{
123  // Make an unmanaged view around the input field
124  View<double*,CLayout,Device,Kokkos::MemoryTraits<Kokkos::Unmanaged>> f_unmanaged((double*)data(),nnode());
125 
126  Kokkos::deep_copy(dest_view, f_unmanaged);
127  }
128 
129  View<double*,CLayout,Device,Kokkos::MemoryTraits<Kokkos::Unmanaged>> unmanaged() const{
130  return View<double*,CLayout,Device,Kokkos::MemoryTraits<Kokkos::Unmanaged>>((double*)(f.data()), f.layout());
131  }
132 
133  // Fill View with transposed data where inode is the contiguous index
134  // Ultimately, there should probably be an implementation GridField that has the transposed indices
135  void transpose_copy_to_double_view(const View<double**,CLayout,Device>& dest_view) const{
136  // Retrieve nphi from the Field of this GridField
137  constexpr int n_phi = field_type::NPHI();
138 
139  // Make an unmanaged view around the input field
140  View<double**,CLayout,Device,Kokkos::MemoryTraits<Kokkos::Unmanaged>> f_unmanaged((double*)data(),nnode(), n_phi);
141 
142  // Copy f_unmanaged into iphi = 0 and iphi = 1 of dest_view
143  Kokkos::parallel_for("var_transpose_copy", Kokkos::RangePolicy<typename Device::execution_space>( 0, nnode()), KOKKOS_LAMBDA(const int inode){
144  for(int iphi=0; iphi<n_phi; iphi++){
145  dest_view(iphi, inode) = f_unmanaged(inode, iphi);
146  }
147  });
148  Kokkos::fence();
149  }
150 
151  // Transpose and copy data from a view where inode is the contiguous index
152  void transpose_copy_from_double_view(const View<double**,CLayout,Device>& src_view) const{
153  // Retrieve nphi from the Field of this GridField
154  constexpr int n_phi = field_type::NPHI();
155 
156  // Make an unmanaged view of the data
157  View<double**,CLayout,Device,Kokkos::MemoryTraits<Kokkos::Unmanaged>> f_unmanaged((double*)data(),nnode(), n_phi);
158 
159  // Transpose from src_view into this gridfield
160  Kokkos::parallel_for("var_transpose_copy", Kokkos::RangePolicy<ExSpace>( 0, nnode()), KOKKOS_LAMBDA(const int inode){
161  for(int iphi=0; iphi<n_phi; iphi++){
162  f_unmanaged(inode, iphi) = src_view(iphi, inode);
163  }
164  });
165  Kokkos::fence();
166  }
167 
170  static KOKKOS_INLINE_FUNCTION void view_gather3(const Grid<DeviceType>& grid, const View<double*,CLayout,Device>& view1, const View<double*,CLayout,Device>& view2, const View<double*,CLayout,Device>& view3, const SimdGridWeights<Order::One, PIT_GLOBAL>& grid_wts, double& val1, double& val2, double& val3, int i_simd){
171  val1=0.0;
172  val2=0.0;
173  val3=0.0;
174  for (int ip=0; ip<3; ip++){
175  int nd = grid.get_node_index(grid_wts.itr[i_simd], ip);
176  val1 += view1(nd)*grid_wts.p[ip][i_simd];
177  val2 += view2(nd)*grid_wts.p[ip][i_simd];
178  val3 += view3(nd)*grid_wts.p[ip][i_simd];
179  }
180  }
181 
182  static KOKKOS_INLINE_FUNCTION void view_gather(const Grid<DeviceType>& grid, const View<double*,CLayout,Device>& view, const SimdGridWeights<Order::One, PIT_GLOBAL>& grid_wts, Simd<double>& val){
183  val = 0.0;
184  for (int i_simd = 0; i_simd<SIMD_SIZE; i_simd++){
185  if(grid_wts.itr[i_simd]<=0) continue;
186  for (int ip = 0; ip < 3; ip++){
187  int node = grid.get_node_index(grid_wts.itr[i_simd], ip);
188  val[i_simd] += grid_wts.p[ip][i_simd]*view(node);
189  }
190  }
191  }
192 
193  static KOKKOS_INLINE_FUNCTION void view_vec_odim_gather(const Grid<DeviceType>& grid, const View<Field<VarType::Vector,PhiInterpType::None>**,CLayout,Device>& view, int ind, const SimdGridWeights<Order::One, PhiInterpType::None>& grid_wts, SimdVector& val, int i_simd){
194  val.r[i_simd] = 0.0;
195  val.z[i_simd] = 0.0;
196  val.phi[i_simd] = 0.0;
197  for (int ip = 0; ip<3; ip++){
198  int node = grid.get_node_index(grid_wts.itr[i_simd], ip);
199  double wp = grid_wts.p[ip][i_simd];
200  view(ind,node).gather(val, i_simd, wp);
201  }
202  }
203 
204  static KOKKOS_INLINE_FUNCTION void view_vec_odim_gather(const Grid<DeviceType>& grid, const View<Field<VarType::Vector,PhiInterpType::None>**,CLayout,Device>& view, int ind, const SimdGridWeights<Order::Zero, PhiInterpType::None>& grid_wts, SimdVector& val, int i_simd){
205  val.r[i_simd] = 0.0;
206  val.z[i_simd] = 0.0;
207  val.phi[i_simd] = 0.0;
208  int node = grid_wts.node[i_simd];
209  constexpr double wp = 1.0;
210  view(ind,node).gather(val, i_simd, wp);
211  }
212 
213  static KOKKOS_INLINE_FUNCTION void view_gyro_scatter3(const Grid<DeviceType>& grid, const View<double**,CLayout,Device>& view1, const View<double**,CLayout,Device>& view2, const View<double**,CLayout,Device>& view3, const SimdGridWeights<Order::One, PIT_GLOBAL>& grid_wts, double val1, double val2, double val3, int i_simd, const LinearWeights& rho_wts, bool is_gyro){
214  // Scatter moments into grid array
215  for (int ip = 0; ip < 3; ip++){
216  int node = grid.get_node_index(grid_wts.itr[i_simd], ip);
217  Kokkos::atomic_add(&(view1(rho_wts.i, node)), grid_wts.p[ip][i_simd]*rho_wts.w[0]*val1);
218  Kokkos::atomic_add(&(view2(rho_wts.i, node)), grid_wts.p[ip][i_simd]*rho_wts.w[0]*val2);
219  Kokkos::atomic_add(&(view3(rho_wts.i, node)), grid_wts.p[ip][i_simd]*rho_wts.w[0]*val3);
220  if(is_gyro){
221  Kokkos::atomic_add(&(view1(rho_wts.i+1, node)), grid_wts.p[ip][i_simd]*rho_wts.w[1]*val1);
222  Kokkos::atomic_add(&(view2(rho_wts.i+1, node)), grid_wts.p[ip][i_simd]*rho_wts.w[1]*val2);
223  Kokkos::atomic_add(&(view3(rho_wts.i+1, node)), grid_wts.p[ip][i_simd]*rho_wts.w[1]*val3);
224  }
225  }
226  }
227 
228  // view with outer dimension
229  static KOKKOS_INLINE_FUNCTION void view_odim_scatter(const Grid<DeviceType>& grid, const View<double**,CLayout,Device>& view, int ind, const SimdGridWeights<Order::One, PIT_GLOBAL>& grid_wts, double val, int i_simd){
230  for (int j = 0; j<3; j++){
231  int node=grid.get_node_index(grid_wts.itr[i_simd], j);
232  double wp=grid_wts.p[j][i_simd];
233 
234  Kokkos::atomic_add(&(view(ind,node)), wp*val);
235  }
236  }
237 
238  static KOKKOS_INLINE_FUNCTION void view_scatter(const Grid<DeviceType>& grid, const View<double*,CLayout,Device>& view, const SimdGridWeights<Order::One, PhiInterpType::None>& grid_wts, double val, int i_simd){
239  for (int j = 0; j<3; j++){
240  int node=grid.get_node_index(grid_wts.itr[i_simd], j);
241  double wp=grid_wts.p[j][i_simd];
242 
243  Kokkos::atomic_add(&(view(node)), wp*val);
244  }
245  }
246 
247  static KOKKOS_INLINE_FUNCTION void view_ff_scatter(const Grid<DeviceType>& grid, const View<double**,CLayout,Device>& view, const SimdGridWeights<Order::One, PhiInterpType::Planes>& grid_wts, double wphi, double val, int i_simd){
248  for (int j = 0; j<3; j++){
249  int node=grid.get_node_index(grid_wts.itr[i_simd], j);
250  double wp=grid_wts.p[j][i_simd];
251 
252  Kokkos::atomic_add(&(view(0,node)), wp*wphi*val);
253  Kokkos::atomic_add(&(view(1,node)), wp*(1.0-wphi)*val);
254  }
255  }
256 
257  static KOKKOS_INLINE_FUNCTION void view_odim_variance(const Grid<DeviceType>& grid, const View<double**,CLayout,Device>& view, const View<double**,CLayout,Device>& variance, int ind, const SimdGridWeights<Order::One, PIT_GLOBAL>& grid_wts, double val, int i_simd){
258  for (int j = 0; j<3; j++){
259  int node=grid.get_node_index(grid_wts.itr[i_simd], j);
260  double wp=grid_wts.p[j][i_simd];
261 
262  double tmp = view(ind,node) - wp*val;
263  Kokkos::atomic_add(&(variance(ind,node)), tmp*tmp);
264  }
265  }
266 
267  static KOKKOS_INLINE_FUNCTION void view_rep_scatter3(const Grid<DeviceType>& grid, const View<double***,CLayout,Device>& view, int ind1, int ind2, int ind3, const SimdGridWeights<Order::One, PIT_GLOBAL>& grid_wts, double val1, double val2, double val3, int ithread, int i_simd){
268  // Scatter moments into grid array
269  for (int ip = 0; ip < 3; ip++){
270  int node = grid.get_node_index(grid_wts.itr[i_simd], ip);
271  double wp = grid_wts.p[ip][i_simd];
272 
273  access_add(&(view(ithread,node,ind1)),wp*val1);
274  access_add(&(view(ithread,node,ind2)),wp*val2);
275  access_add(&(view(ithread,node,ind3)),wp*val3);
276  }
277  }
278 };
279 
280 template<class Device, VarType VT, PhiInterpType PIT>
283  using device_type = Device;
284  static constexpr KinType KT = KinType::GyroKin;
285 
286  Kokkos::View<field_type**,Kokkos::LayoutRight,Device> f;
287 
289  GridField(std::string name, int nphi, int nrho, int nnode) : f(name,nnode, nrho+1) {}
290  GridField(std::string name, int nrho, int nnode) : f(name,nnode, nrho+1) {}
291  field_type* data() const {return f.data();}
292  int size() const {return f.size();}
293  int nnode() const {return f.extent(0);}
294  int nrhop1() const {return f.extent(1);}
295  int nphi() const {return 1;}
296  KOKKOS_INLINE_FUNCTION bool is_allocated() const {return f.is_allocated();}
297  KOKKOS_INLINE_FUNCTION field_type& operator ()(int inode, int irho) const {return f(inode, irho);}
298 
299  // Scatter to a node
300  KOKKOS_INLINE_FUNCTION void scatter(int node, const SimdPhiWeights<get_phi_wt_usage(PIT)>& phi_wts, const SimdGyroWeights<GyroKin>& rho_wts, int i_simd, double particle_weight) const{
301  int irho = rho_wts.irho(i_simd);
302  f(node,irho).scatter(rho_wts, phi_wts, i_simd, particle_weight, f(node,irho+1));
303  }
304 
305  // Scatter to a triangle (same as for DriftKin - consolidate)
306  KOKKOS_INLINE_FUNCTION void scatter(const Grid<DeviceType>& grid, int ithread, const SimdGridWeights<Order::One, PIT_GLOBAL>& grid_wts, int i_simd, const SimdGyroWeights<GyroKin>& rho_wts, double particle_weight) const{
307  for (int j = 0; j<3; j++){
308  // Find triangle's nodes
309  int node=grid.get_node_index(grid_wts.itr[i_simd], j);
310  double wp=grid_wts.p[j][i_simd];
311 
312  // Scatter to node
313  scatter(node, grid_wts.phi_wts, rho_wts, i_simd, wp*particle_weight);
314  }
315  }
316 
317  KOKKOS_INLINE_FUNCTION void gather(const Grid<Device> &grid, const SimdGridWeights<Order::One, PIT>& grid_wts, const SimdGyroWeights<GyroKin>& rho_wts, Simd<double>& fld) const{
318  fld = 0.0;
319  for (int i_simd = 0; i_simd<SIMD_SIZE; i_simd++){
320  // If particle is inactive, set itr_work=1, phi=0D0, iphi=0
321  int itr_work = grid_wts.is_valid(i_simd) ? grid_wts.itr[i_simd] : 1;
322 
323  int irho = rho_wts.irho(i_simd);
324 
325  // Loop over the 3 vertices of the grid triangle and add up the contributions from each
326  for (int ip = 0; ip<3; ip++){
327  int node = grid_wts.is_valid(i_simd) ? grid.get_node_index(itr_work, ip) : 0;
328  double wp = grid_wts.is_valid(i_simd) ? grid_wts.p[ip][i_simd] : 0.0; // all these trinary ops are probably unnecessary
329 
330  f(node,irho).gather(fld,i_simd, wp, rho_wts, grid_wts.phi_wts, f(node,irho+1));
331  }
332  }
333  }
334 
336  int ndoubles_in_grid_field = f.size()*field_type::SIZE();
337  Kokkos::View<double*,Kokkos::LayoutRight,Device,Kokkos::MemoryTraits<Kokkos::Unmanaged>> view_1d_double((double*)(f.data()), ndoubles_in_grid_field);
338  Kokkos::deep_copy(view_1d_double, 0.0);
339  }
340 };
341 
342 /******** GridField with array replication ********/
343 template<class Device, VarType VT, PhiInterpType PIT>
346  using device_type = Device;
347  static constexpr KinType KT = KinType::DriftKin;
348 
349  Kokkos::View<field_type**,Kokkos::LayoutRight,Device> f;
350 
352  GridField(std::string name, int nphi, int nrho, int nnode) : f(name,get_num_cpu_threads(), nnode) {}
353  GridField(std::string name, int nnode) : f(name,get_num_cpu_threads(), nnode) {}
354  field_type* data() const {return f.data();}
355  int size() const {return f.size();}
356  int nnode() const {return f.extent(1);}
357  int nrhop1() const {return 1;}
358  int nphi() const {return 1;}
359  KOKKOS_INLINE_FUNCTION bool is_allocated() const {return f.is_allocated();}
360  KOKKOS_INLINE_FUNCTION field_type& operator ()(int ithread, int inode) const {return f(ithread, inode);}
361 
362  // Scatter to a node
363  KOKKOS_INLINE_FUNCTION void scatter(int ithread, int node, const SimdPhiWeights<get_phi_wt_usage(PIT)>& phi_wts, int i_simd, double particle_weight) const{
364  f(ithread,node).scatter(phi_wts, i_simd, particle_weight);
365  }
366 
367  // Scatter to a triangle
368  KOKKOS_INLINE_FUNCTION void scatter(const Grid<DeviceType>& grid, int ithread, const SimdGridWeights<Order::One, PIT_GLOBAL>& grid_wts, int i_simd, const SimdGyroWeights<DriftKin>& rho_wts, double particle_weight) const{
369  for (int j = 0; j<3; j++){
370  // Find triangle's nodes
371  int node=grid.get_node_index(grid_wts.itr[i_simd], j);
372  double wp=grid_wts.p[j][i_simd];
373 
374  // Scatter to node
375  scatter(ithread, node, grid_wts.phi_wts, i_simd, wp*particle_weight);
376  }
377  }
378 
380  int ndoubles_in_grid_field = f.size()*field_type::SIZE();
381  Kokkos::View<double*,Kokkos::LayoutRight,Device,Kokkos::MemoryTraits<Kokkos::Unmanaged>> view_1d_double((double*)(f.data()), ndoubles_in_grid_field);
382  Kokkos::deep_copy(view_1d_double, 0.0);
383  }
384 };
385 
386 template<class Device, VarType VT, PhiInterpType PIT>
389  using device_type = Device;
390  static constexpr KinType KT = KinType::GyroKin;
391 
392  Kokkos::View<field_type***,Kokkos::LayoutRight,Device> f;
393 
395  GridField(std::string name, int nphi, int nrho, int nnode) : f(name,get_num_cpu_threads(),nnode, nrho+1) {}
396  GridField(std::string name, int nrho, int nnode) : f(name,get_num_cpu_threads(),nnode, nrho+1) {}
397  field_type* data() const {return f.data();}
398  int size() const {return f.size();}
399  int nnode() const {return f.extent(1);}
400  int nrhop1() const {return f.extent(2);}
401  int nphi() const {return 1;}
402  KOKKOS_INLINE_FUNCTION bool is_allocated() const {return f.is_allocated();}
403  KOKKOS_INLINE_FUNCTION field_type& operator ()(int ithread, int inode, int irho) const {return f(ithread,inode, irho);}
404 
405  // Scatter to a node
406  KOKKOS_INLINE_FUNCTION void scatter(int ithread, int node, const SimdPhiWeights<get_phi_wt_usage(PIT)>& phi_wts, const SimdGyroWeights<GyroKin>& rho_wts, int i_simd, double particle_weight) const{
407  int irho = rho_wts.irho(i_simd);
408  f(ithread,node,irho).scatter(rho_wts, phi_wts, i_simd, particle_weight, f(ithread,node,irho+1));
409  }
410 
411  // Scatter to a triangle (same as for DriftKin - consolidate)
412  KOKKOS_INLINE_FUNCTION void scatter(const Grid<DeviceType>& grid, int ithread, const SimdGridWeights<Order::One, PIT_GLOBAL>& grid_wts, int i_simd, const SimdGyroWeights<GyroKin>& rho_wts, double particle_weight) const{
413  for (int j = 0; j<3; j++){
414  // Find triangle's nodes
415  int node=grid.get_node_index(grid_wts.itr[i_simd], j);
416  double wp=grid_wts.p[j][i_simd];
417 
418  // Scatter to node
419  scatter(ithread, node, grid_wts.phi_wts, rho_wts, i_simd, wp*particle_weight);
420  }
421  }
422 
424  int ndoubles_in_grid_field = f.size()*field_type::SIZE();
425  Kokkos::View<double*,Kokkos::LayoutRight,Device,Kokkos::MemoryTraits<Kokkos::Unmanaged>> view_1d_double((double*)(f.data()), ndoubles_in_grid_field);
426  Kokkos::deep_copy(view_1d_double, 0.0);
427  }
428 };
429 /************/
430 
431 template<class Device, VarType VT, PhiInterpType PIT>
434  using device_type = Device;
435  static constexpr KinType KT = KinType::DriftKin;
436 
437  Kokkos::View<field_type**,Kokkos::LayoutRight,Device> f;
438 
440  GridField(std::string name, int nphi, int nrho, int nnode) : f(name,nphi, nnode) {}
441  GridField(std::string name, int nphi, int nnode) : f(name,nphi, nnode) {}
442  field_type* data() const {return f.data();}
443  int size() const {return f.size();}
444  int nnode() const {return f.extent(1);}
445  int nrhop1() const {return 1;}
446  int nphi() const {return f.extent(0);}
447  KOKKOS_INLINE_FUNCTION bool is_allocated() const {return f.is_allocated();}
448  KOKKOS_INLINE_FUNCTION field_type& operator ()(int iphi, int inode) const {return f(iphi, inode);}
449 
452  new_field.f = my_subview(f, subfield_idx);
453  return new_field;
454  }
455 
456  Kokkos::View<double**,Kokkos::LayoutRight,Device,Kokkos::MemoryTraits<Kokkos::Unmanaged>> unmanaged() const{
457  return Kokkos::View<double**,Kokkos::LayoutRight,Device,Kokkos::MemoryTraits<Kokkos::Unmanaged>>((double*)(f.data()), f.layout());
458  }
459 };
460 
461 template<class Device, VarType VT, PhiInterpType PIT>
464  using device_type = Device;
465  static constexpr KinType KT = KinType::GyroKin;
466 
467  Kokkos::View<field_type***,Kokkos::LayoutRight,Device> f;
468 
470  GridField(std::string name, int nphi, int nrho, int nnode) : f(name,nphi, nnode, nrho+1) {}
471  field_type* data() const {return f.data();}
472  int size() const {return f.size();}
473  int nnode() const {return f.extent(1);}
474  int nrhop1() const {return f.extent(2);}
475  int nphi() const {return f.extent(0);}
476  KOKKOS_INLINE_FUNCTION bool is_allocated() const {return f.is_allocated();}
477  KOKKOS_INLINE_FUNCTION field_type& operator ()(int iphi, int inode, int irho) const {return f(iphi, inode, irho);}
478 };
479 
480 // For convenience
492 
493 
494 // Shallow copy if types are the same
495 template<typename T>
496 inline void grid_field_copy(T& dest, const T& src){
497  dest = src;
498 }
499 
500 // Allocate dest grid_field and copy data from src
501 template<typename T1, typename T2>
502 inline void grid_field_copy(T1& dest, const T2& src){
503  // Allocate device array
504  dest = T1("grid_field",src.nphi(), src.nrhop1()-1, src.nnode());
505  // Deep copy from host to device
506  Kokkos::deep_copy(dest.f, src.f);
507 }
508 
509 #endif
static KOKKOS_INLINE_FUNCTION void view_odim_scatter(const Grid< DeviceType > &grid, const View< double **, CLayout, Device > &view, int ind, const SimdGridWeights< Order::One, PIT_GLOBAL > &grid_wts, double val, int i_simd)
Definition: grid_field.hpp:229
GridField< DeviceType, VarType::Vector2D, PhiInterpType::None, TorType::OnePlane, KinType::GyroKin > Efield2DGyroType
Definition: grid_field.hpp:489
Simd< double > r
Definition: simd.hpp:150
GridField(std::string name, int nphi, int nrho, int nnode)
Definition: grid_field.hpp:34
static KOKKOS_INLINE_FUNCTION void view_gather3(const Grid< DeviceType > &grid, const View< double *, CLayout, Device > &view1, const View< double *, CLayout, Device > &view2, const View< double *, CLayout, Device > &view3, const SimdGridWeights< Order::One, PIT_GLOBAL > &grid_wts, double &val1, double &val2, double &val3, int i_simd)
Definition: grid_field.hpp:170
Definition: simd.hpp:149
KOKKOS_INLINE_FUNCTION void scatter(const Grid< DeviceType > &grid, int ithread, const SimdGridWeights< Order::One, PIT_GLOBAL > &grid_wts, int i_simd, const SimdGyroWeights< DriftKin > &rho_wts, double particle_weight) const
Definition: grid_field.hpp:368
GridField(std::string name, int nphi, int nrho, int nnode)
Definition: grid_field.hpp:440
GridField< DeviceType, VarType::Scalar, PIT_GLOBAL, TorType::MultiplePlanes, KinType::DriftKin > PotType
Definition: grid_field.hpp:486
KOKKOS_INLINE_FUNCTION bool is_allocated() const
Definition: grid_field.hpp:42
GridField(std::string name, int nrho, int nnode)
Definition: grid_field.hpp:290
void transpose_copy_to_double_view(const View< double **, CLayout, Device > &dest_view) const
Definition: grid_field.hpp:135
KOKKOS_INLINE_FUNCTION int irho(int i_simd) const
Definition: gyro_radius.hpp:109
KOKKOS_INLINE_FUNCTION bool is_allocated() const
Definition: grid_field.hpp:296
static KOKKOS_INLINE_FUNCTION void view_gyro_scatter3(const Grid< DeviceType > &grid, const View< double **, CLayout, Device > &view1, const View< double **, CLayout, Device > &view2, const View< double **, CLayout, Device > &view3, const SimdGridWeights< Order::One, PIT_GLOBAL > &grid_wts, double val1, double val2, double val3, int i_simd, const LinearWeights &rho_wts, bool is_gyro)
Definition: grid_field.hpp:213
Simd< int > itr
Definition: grid_weights.hpp:74
GridField(std::string name, int nrho, int nnode)
Definition: grid_field.hpp:396
Definition: grid_weights.hpp:73
void copy_to_double_view(const View< double *, CLayout, Device > &dest_view) const
Definition: grid_field.hpp:122
static KOKKOS_INLINE_FUNCTION void view_ff_scatter(const Grid< DeviceType > &grid, const View< double **, CLayout, Device > &view, const SimdGridWeights< Order::One, PhiInterpType::Planes > &grid_wts, double wphi, double val, int i_simd)
Definition: grid_field.hpp:247
Definition: linear_weights.hpp:8
KOKKOS_INLINE_FUNCTION void gather(const Grid< Device > &grid, const SimdGridWeights< Order::One, PIT > &grid_wts, const SimdGyroWeights< DriftKin > &rho_wts, Simd< double > &fld, int node_offset=0) const
Definition: grid_field.hpp:96
Kokkos::View< field_type **, Kokkos::LayoutRight, Device > f
Definition: grid_field.hpp:286
Definition: globals.hpp:89
Definition: grid_weights.hpp:47
KOKKOS_INLINE_FUNCTION bool is_allocated() const
Definition: grid_field.hpp:447
GridField(std::string name, int nphi, int nnode)
Definition: grid_field.hpp:441
GridField(std::string name, int nnode)
Definition: grid_field.hpp:35
Kokkos::View< double **, Kokkos::LayoutRight, Device, Kokkos::MemoryTraits< Kokkos::Unmanaged > > unmanaged() const
Definition: grid_field.hpp:456
View< double *, CLayout, Device, Kokkos::MemoryTraits< Kokkos::Unmanaged > > unmanaged() const
Definition: grid_field.hpp:129
GridField< DeviceType, VarType::Vector2D, PhiInterpType::None, TorType::MultiplePlanes, KinType::DriftKin > Efield2DType
Definition: grid_field.hpp:485
GridField< DeviceType, VarType::Vector, PhiInterpType::Planes, TorType::MultiplePlanes, KinType::DriftKin > EfieldType
Definition: grid_field.hpp:484
KOKKOS_INLINE_FUNCTION bool is_allocated() const
Definition: grid_field.hpp:359
Kokkos::LayoutRight CLayout
Definition: space_settings.hpp:68
GridField< DeviceType, VarType::Vector2D, PIT_GLOBAL, TorType::OnePlane, KinType::DriftKin > E00Type
Definition: grid_field.hpp:487
KOKKOS_INLINE_FUNCTION bool is_allocated() const
Definition: grid_field.hpp:476
constexpr KOKKOS_INLINE_FUNCTION PhiWtUsage get_phi_wt_usage(PhiInterpType PIT)
Definition: grid_weights.hpp:15
SimdPhiWeights< get_phi_wt_usage(PIT)> phi_wts
Definition: grid_weights.hpp:77
GridField(std::string name, int nphi, int nrho, int nnode)
Definition: grid_field.hpp:352
Definition: grid_field.hpp:22
KOKKOS_INLINE_FUNCTION void gather(const Grid< Device > &grid, const SimdGridWeights< Order::One, PhiInterpType::Planes > &grid_wts, const Simd< double > &phi, Simd< double > &fld) const
Definition: grid_field.hpp:80
GridField< DeviceType, VarType::Scalar, PIT_GLOBAL, TorType::OnePlane, KinType::DriftKin > AxisymPotType
Definition: grid_field.hpp:483
KOKKOS_INLINE_FUNCTION void scatter(const Grid< DeviceType > &grid, int ithread, const SimdGridWeights< Order::One, PIT_GLOBAL > &grid_wts, int i_simd, const SimdGyroWeights< DriftKin > &rho_wts, double particle_weight) const
Definition: grid_field.hpp:51
Definition: grid_weights.hpp:18
TorType
Definition: grid_field.hpp:14
Definition: gyro_radius.hpp:116
KOKKOS_INLINE_FUNCTION void scatter(const Grid< DeviceType > &grid, int ithread, const SimdGridWeights< Order::One, PIT_GLOBAL > &grid_wts, int i_simd, const SimdGyroWeights< GyroKin > &rho_wts, double particle_weight) const
Definition: grid_field.hpp:306
KOKKOS_INLINE_FUNCTION void gather(const Grid< Device > &grid, const SimdGridWeights< Order::One, PIT > &grid_wts, const SimdGyroWeights< GyroKin > &rho_wts, Simd< double > &fld) const
Definition: grid_field.hpp:317
Definition: gyro_radius.hpp:84
Kokkos::View< field_type *, Kokkos::LayoutRight, Device > f
Definition: grid_field.hpp:31
KOKKOS_INLINE_FUNCTION void scatter(int ithread, int node, const SimdPhiWeights< get_phi_wt_usage(PIT)> &phi_wts, const SimdGyroWeights< GyroKin > &rho_wts, int i_simd, double particle_weight) const
Definition: grid_field.hpp:406
KOKKOS_INLINE_FUNCTION void access_add(T *addr, T val)
Definition: access_add.hpp:40
KOKKOS_INLINE_FUNCTION void scatter(int node, const SimdPhiWeights< get_phi_wt_usage(PIT)> &phi_wts, int i_simd, double particle_weight) const
Definition: grid_field.hpp:46
static KOKKOS_INLINE_FUNCTION void view_odim_variance(const Grid< DeviceType > &grid, const View< double **, CLayout, Device > &view, const View< double **, CLayout, Device > &variance, int ind, const SimdGridWeights< Order::One, PIT_GLOBAL > &grid_wts, double val, int i_simd)
Definition: grid_field.hpp:257
void grid_field_copy(T &dest, const T &src)
Definition: grid_field.hpp:496
void transpose_copy_from_double_view(const View< double **, CLayout, Device > &src_view) const
Definition: grid_field.hpp:152
KOKKOS_INLINE_FUNCTION int get_node_index(int triangle_index, int tri_vertex_index) const
Definition: grid.tpp:158
GridField(std::string name, int nphi, int nrho, int nnode)
Definition: grid_field.hpp:289
KOKKOS_INLINE_FUNCTION void scatter(int ithread, int node, const SimdPhiWeights< get_phi_wt_usage(PIT)> &phi_wts, int i_simd, double particle_weight) const
Definition: grid_field.hpp:363
double w[2]
Definition: linear_weights.hpp:10
Definition: globals.hpp:90
GridField< DeviceType, VarType::Scalar, PhiInterpType::None, TorType::OnePlane, KinType::DriftKin > ScalarGridField
Definition: grid_field.hpp:481
void scatter(const Grid< DeviceType > &grid, const MagneticField< DeviceType > &magnetic_field, const GridField< DeviceType, VarType::Scalar, PIT, TorType::OnePlane, KT > &Ah_gf, const Species< DeviceType > &species, bool exclude_private, bool do_cv_adjustment, bool cv_full_weight, const Charge< DeviceType, KT > &charge)
Definition: scatter.cpp:250
GridField< Device, VT, PIT, TorType::OnePlane, KinType::DriftKin > subfield(int subfield_idx) const
Definition: grid_field.hpp:450
static KOKKOS_INLINE_FUNCTION void view_vec_odim_gather(const Grid< DeviceType > &grid, const View< Field< VarType::Vector, PhiInterpType::None > **, CLayout, Device > &view, int ind, const SimdGridWeights< Order::One, PhiInterpType::None > &grid_wts, SimdVector &val, int i_simd)
Definition: grid_field.hpp:193
static KOKKOS_INLINE_FUNCTION void view_scatter(const Grid< DeviceType > &grid, const View< double *, CLayout, Device > &view, const SimdGridWeights< Order::One, PhiInterpType::None > &grid_wts, double val, int i_simd)
Definition: grid_field.hpp:238
Simd< double > phi
Definition: simd.hpp:152
KOKKOS_INLINE_FUNCTION void gather(const Grid< Device > &grid, const SimdGridWeights< Order::One, PhiInterpType::None > &grid_wts, const Simd< double > &phi, Simd< double > &fld) const
Definition: grid_field.hpp:63
Simd< double > z
Definition: simd.hpp:151
int i
Definition: linear_weights.hpp:9
KinType
Definition: globals.hpp:88
Definition: field.hpp:45
Kokkos::View< field_type ***, Kokkos::LayoutRight, Device > f
Definition: grid_field.hpp:467
GridField< DeviceType, VarType::Vector2D, PIT_GLOBAL, TorType::OnePlane, KinType::GyroKin > E00GyroType
Definition: grid_field.hpp:491
Kokkos::View< field_type **, Kokkos::LayoutRight, Device > f
Definition: grid_field.hpp:349
Kokkos::View< T *, Kokkos::LayoutRight, Device > my_subview(const Kokkos::View< T ****, Kokkos::LayoutRight, Device > &view, int i, int j, int k)
Definition: my_subview.hpp:8
GridField< DeviceType, VarType::Scalar, PIT_GLOBAL, TorType::OnePlane, KinType::GyroKin > PotGyroType
Definition: grid_field.hpp:490
KOKKOS_INLINE_FUNCTION void scatter(int node, const SimdPhiWeights< get_phi_wt_usage(PIT)> &phi_wts, const SimdGyroWeights< GyroKin > &rho_wts, int i_simd, double particle_weight) const
Definition: grid_field.hpp:300
SimdGridVec p
Definition: grid_weights.hpp:75
KOKKOS_INLINE_FUNCTION bool is_valid(int i_simd) const
Definition: grid_weights.hpp:84
KOKKOS_INLINE_FUNCTION bool is_allocated() const
Definition: grid_field.hpp:402
int get_num_cpu_threads()
Definition: globals.hpp:17
Kokkos::View< field_type ***, Kokkos::LayoutRight, Device > f
Definition: grid_field.hpp:392
GridField(std::string name, int nphi, int nrho, int nnode)
Definition: grid_field.hpp:470
static KOKKOS_INLINE_FUNCTION void view_gather(const Grid< DeviceType > &grid, const View< double *, CLayout, Device > &view, const SimdGridWeights< Order::One, PIT_GLOBAL > &grid_wts, Simd< double > &val)
Definition: grid_field.hpp:182
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
GridField< DeviceType, VarType::Scalar, PIT_GLOBAL, TorType::OnePlane, KinType::DriftKin > OnePlanePotType
Definition: grid_field.hpp:482
KOKKOS_INLINE_FUNCTION void scatter(const Grid< DeviceType > &grid, int ithread, const SimdGridWeights< Order::One, PIT_GLOBAL > &grid_wts, int i_simd, const SimdGyroWeights< GyroKin > &rho_wts, double particle_weight) const
Definition: grid_field.hpp:412
GridField< DeviceType, VarType::Vector, PhiInterpType::Planes, TorType::OnePlane, KinType::GyroKin > EfieldGyroType
Definition: grid_field.hpp:488
Kokkos::View< field_type **, Kokkos::LayoutRight, Device > f
Definition: grid_field.hpp:437
GridField(std::string name, int nphi, int nrho, int nnode)
Definition: grid_field.hpp:395
static KOKKOS_INLINE_FUNCTION void view_rep_scatter3(const Grid< DeviceType > &grid, const View< double ***, CLayout, Device > &view, int ind1, int ind2, int ind3, const SimdGridWeights< Order::One, PIT_GLOBAL > &grid_wts, double val1, double val2, double val3, int ithread, int i_simd)
Definition: grid_field.hpp:267
static KOKKOS_INLINE_FUNCTION void view_vec_odim_gather(const Grid< DeviceType > &grid, const View< Field< VarType::Vector, PhiInterpType::None > **, CLayout, Device > &view, int ind, const SimdGridWeights< Order::Zero, PhiInterpType::None > &grid_wts, SimdVector &val, int i_simd)
Definition: grid_field.hpp:204