XGCa
particles.hpp
Go to the documentation of this file.
1 #ifndef PARTICLES_HPP
2 #define PARTICLES_HPP
3 #include "globals.hpp"
4 
5 // Phase
6 struct SimdPhase{
13 
14  /* Returns a SimdVector2D alias to r and z
15  * */
16  KOKKOS_INLINE_FUNCTION SimdVector2D& x() {
17  return *(reinterpret_cast<SimdVector2D*>(this));
18  }
19 
20  /* Returns a SimdVector2D alias to r and z
21  * */
22  KOKKOS_INLINE_FUNCTION const SimdVector2D& x() const {
23  return *(reinterpret_cast<const SimdVector2D*>(this));
24  }
25 
26  /* Returns a SimdVector alias to r, z, and phi
27  * */
28  KOKKOS_INLINE_FUNCTION SimdVector& v() {
29  return *(reinterpret_cast<SimdVector*>(this));
30  }
31 
32  /* Returns a SimdVector alias to r, z, and phi
33  * */
34  KOKKOS_INLINE_FUNCTION const SimdVector& v() const {
35  return *(reinterpret_cast<const SimdVector*>(this));
36  }
37 };
38 
39 // Constants
44 #ifdef PTL_G2
45  Simd<double> g2;
46 #endif
47 };
48 
49 // SoA particle structure, with inner array of length SIMD_SIZE (generally, VEC_LEN on CPU, 1 on GPU)
54 #ifdef ESC_PTL
55  Simd<long long int> flag;
56 #endif
57 
58  KOKKOS_INLINE_FUNCTION bool is_active(int i_simd) const{
59  return (gid[i_simd]>0);
60  }
61 
62  KOKKOS_INLINE_FUNCTION bool is_inactive(int i_simd) const{
63  return (gid[i_simd]<=0);
64  }
65 
68  KOKKOS_INLINE_FUNCTION void deactivate(const Simd<bool>& mask){
69  for (int i_simd = 0; i_simd<SIMD_SIZE; i_simd++){
70  // Don't reactivate particle
71  gid[i_simd] = (mask[i_simd] && is_active(i_simd)) ? -gid[i_simd] : gid[i_simd];
72  }
73  }
74 
77  KOKKOS_INLINE_FUNCTION void deactivate(int i_simd){
78  // Don't reactivate particle
79  gid[i_simd] = is_active(i_simd) ? -gid[i_simd] : gid[i_simd];
80  }
81 };
82 
83 // Phase
84 struct VecPhase{
85  double r[VEC_LEN];
86  double z[VEC_LEN];
87  double phi[VEC_LEN];
88  double rho[VEC_LEN];
89  double w1[VEC_LEN];
90  double w2[VEC_LEN];
91 };
92 
93 // Constants
94 struct VecConstants{
95  double mu[VEC_LEN];
96  double w0[VEC_LEN];
97  double f0[VEC_LEN];
98 #ifdef PTL_G2
99  double g2[VEC_LEN];
100 #endif
101 };
102 
103 // SoA particle structure, with inner array of length VEC_LEN (just like the AoSoA)
107  long long int gid[VEC_LEN];
108 #ifdef ESC_PTL
109  long long int flag[VEC_LEN];
110 #endif
111 
112  KOKKOS_INLINE_FUNCTION bool is_active(int i_vec) const{
113  return (gid[i_vec]>0);
114  }
115 
116  KOKKOS_INLINE_FUNCTION bool is_inactive(int i_vec) const{
117  return (gid[i_vec]<=0);
118  }
119 };
120 
121 // Other useful ways to access particles
122 template<int T>
124  double data[T*VEC_LEN];
125 };
126 
127 template<int T>
128 struct OneParticle{
129  double data[T];
130 };
131 
132 KOKKOS_INLINE_FUNCTION void update_phases(SimdPhase &ph_new, const SimdPhase &ph, double local_dt, const SimdPhase &dph);
133 
134 KOKKOS_INLINE_FUNCTION void simd_2_AoSoA(VecParticles *part, const SimdParticles &part_one, int a_vec, int s_vec);
135 
136 KOKKOS_INLINE_FUNCTION void AoSoA_2_simd(SimdParticles &part_one, const VecParticles *part, int a_vec, int s_vec);
137 
138 KOKKOS_INLINE_FUNCTION void update_dphm(SimdPhase &dphm,const SimdPhase &dpht);
139 
140 KOKKOS_INLINE_FUNCTION void update_dpht(SimdPhase &dpht,const SimdPhase &dph,const SimdPhase &dphm);
141 
142 template<class Device>
144  int s;
145  int a;
146 
147  KOKKOS_INLINE_FUNCTION AoSoAIndices(int idx);
148 };
149 
152 template<class Device>
153 KOKKOS_INLINE_FUNCTION AoSoAIndices<Device>::AoSoAIndices(int idx){
154  // CPU: access an array of particles
155  s = idx;
156  a = 0;
157 }
158 
159 #ifdef USE_GPU
162 template<>
163 KOKKOS_INLINE_FUNCTION AoSoAIndices<DeviceType>::AoSoAIndices(int idx){
164  // GPU: access an individual particle
165  s = idx / VEC_LEN;
166  a = idx % VEC_LEN;
167 }
168 #endif
169 
172 template<class Device>
173 inline int p_range(int num_particle)
174 {
175  return divide_and_round_up(num_particle, VEC_LEN);
176 }
177 
178 #ifdef USE_GPU
181 template<>
182 inline int p_range<DeviceType>(int num_particle)
183 {
184  return num_particle;
185 }
186 #endif
187 
189 template <typename T>
190 inline long long int add_vec_buffer(T n_ptl) {
191  long long int n = static_cast<long long int>(n_ptl);
192  long long int vec = static_cast<long long int>(VEC_LEN);
193  return divide_and_round_up(n, vec)*vec;
194 }
195 
196 #ifdef USE_CABANA
197 #include <Cabana_AoSoA.hpp>
198 #include <Cabana_DeepCopy.hpp>
199 
200 // Set the type for the particle AoSoA.
201 # ifdef ESC_PTL
202 using ParticleDataTypes = Cabana::MemberTypes<double[PTL_NPHASE],double[PTL_NCONST],long long int, long long int>;
203 # else
204 using ParticleDataTypes = Cabana::MemberTypes<double[PTL_NPHASE],double[PTL_NCONST],long long int>;
205 # endif
206 // Just the phase
207 using PhaseDataTypes = Cabana::MemberTypes<double[PTL_NPHASE]>;
208 #else
209 // Consolidate these when Cabana is removed
212 #endif
213 
214 // Used for Cabana slices (getting one particle property at a time)
215 namespace PtlSlice{
216 #ifdef ESC_PTL
217 enum{Ph=0,Ct,Gid,Flag};
218 #else
219 enum{Ph=0,Ct,Gid};
220 #endif
221 }
222 
223 
224 namespace Particles{
225 
226 #ifdef USE_CABANA
227 // Cabana Wrappers
228 template<class DataType, class Device> using Array = typename Cabana::AoSoA<DataType,Device,VEC_LEN>;
229 
230 template<class DataType, class Device, class Device2>
231 void deep_copy(const Array<DataType,Device>& dest, const Array<DataType,Device2>& src){
232  Cabana::deep_copy(dest, src);
233 }
234 
235 template<class DataType>
236 constexpr size_t sizeof_ptl(){
237  return sizeof( Cabana::Tuple<DataType> );
238 }
239 
240 template<int SliceInd, typename T>
241 typename T::template member_slice_type<SliceInd> slice(const T& ptl){
242  return Cabana::slice<SliceInd>(ptl);
243 }
244 #else
245 
246 // A non-Cabana AoSoA implementation
247 template<class DataType, class Device>
248 class Array{
249  public:
250 
251  using vec_data_type = std::conditional_t<std::is_same_v<DataType, ParticleDataTypes>, VecParticles, VecPhase>;
252 
253  // Same (used in streamed_parallel_for.hpp (should be removed)
255 
256  size_t n;
257 
258  View<vec_data_type*,CLayout,Device> view;
259 
260  Array(){}
261 
262  Array(const std::string& label, size_t n_in)
263  : n(n_in),
264  view(NoInit(label), divide_and_round_up(n, VEC_LEN)) {}
265 
266  size_t size() const{
267  return n;
268  }
269 
270  vec_data_type* data() const{
271  return view.data();
272  }
273 
274  KOKKOS_INLINE_FUNCTION vec_data_type& access(size_t ind) const{
275  return view(ind);
276  }
277 
278  void reserve(size_t n_reserve){
279  // Number of vectors requested to be reserved
280  size_t n_vec_reserve = divide_and_round_up(n_reserve, VEC_LEN);
281 
282  // Number of vectors currently reserved
283  size_t n_vec = view.size();
284 
285  // Reserve only increases, never decreases
286  if(n_vec_reserve>n_vec){
287  // Make new allocation
288  View<vec_data_type*,CLayout,Device> resized_view(NoInit(view.label()), n_vec_reserve);
289 
290  // Copy data to new allocation
291  size_t vecs_in_use = divide_and_round_up(n, VEC_LEN);
293  Kokkos::subview(resized_view, Kokkos::pair<size_t, size_t>( 0, vecs_in_use)),
294  Kokkos::subview(view, Kokkos::pair<size_t, size_t>( 0, vecs_in_use)) );
295 
296  // Reassign view to new allocation
297  view = resized_view;
298  }
299  }
300 
301  void resize(size_t new_n_ptl){
302  // Copy existing particles to a larger allocation if needed
303  reserve(new_n_ptl);
304 
305  n = new_n_ptl;
306  }
307 };
308 
309 template<class DataType, class Device, class Device2>
311  if(dest.n != src.n){
312  printf("Error in Particles::deep_copy: %s.n=(%d) must equal %s.n=(%d).\n", dest.view.label().c_str(), dest.n, src.view.label().c_str(), src.n);
313  fflush(stdout);
314  exit_XGC("Error: Size mismatch in Particles::deep_copy\n");
315  }
316  size_t vecs_in_use = divide_and_round_up(dest.n, VEC_LEN);
318  Kokkos::subview(dest.view, Kokkos::pair<size_t, size_t>( 0, vecs_in_use)),
319  Kokkos::subview(src.view, Kokkos::pair<size_t, size_t>( 0, vecs_in_use)) );
320 }
321 
322 // Hard-coded sizes of ParticleDataTypes and PhaseDataTypes
323 template<class DataType> constexpr size_t sizeof_ptl();
324 #ifdef ESC_PTL
325 template<> constexpr size_t sizeof_ptl<ParticleDataTypes>(){return 11*8;};
326 #else
327 template<> constexpr size_t sizeof_ptl<ParticleDataTypes>(){return 10*8;};
328 #endif
329 template<> constexpr size_t sizeof_ptl<PhaseDataTypes>(){return 6*8;};
330 
331 
332 template<int SliceInd, class DataType, class Device> class Slice;
333 
334 // Hardcode these slices. This is temporary - remove slices completely.
335 //enum{Ph=0,Ct,Gid,Flag};
336 
337 template<class Device>
338 class Slice<PtlSlice::Ph, PhaseDataTypes, Device>{
339  static constexpr int ind = PtlSlice::Ph;
342  public:
343  Slice(const ArrayType& array_in) : array(array_in) {}
344  KOKKOS_INLINE_FUNCTION double& operator ()(int ip, int j) const{
345  int ivec = ip/VEC_LEN;
346  double* ptr = (double*)(&array.view(ivec));
347  int istr = ip%VEC_LEN;
348  return ptr[j*VEC_LEN + istr];
349  }
350 };
351 
352 template<class Device>
354  static constexpr int ind = PtlSlice::Ph;
357  public:
358  Slice(const ArrayType& array_in) : array(array_in) {}
359  KOKKOS_INLINE_FUNCTION double& operator ()(int ip, int j) const{
360  int ivec = ip/VEC_LEN;
361  double* ptr = (double*)(&array.view(ivec).ph);
362  int istr = ip%VEC_LEN;
363  return ptr[j*VEC_LEN + istr];
364  }
365 };
366 
367 template<class Device>
369  static constexpr int ind = PtlSlice::Ct;
372  public:
373  Slice(const ArrayType& array_in) : array(array_in) {}
374  KOKKOS_INLINE_FUNCTION double& operator ()(int ip, int j) const{
375  int ivec = ip/VEC_LEN;
376  double* ptr = (double*)(&array.view(ivec).ct);
377  int istr = ip%VEC_LEN;
378  return ptr[j*VEC_LEN + istr];
379  }
380 };
381 
382 template<class Device>
384  static constexpr int ind = PtlSlice::Gid;
387  public:
388  Slice(const ArrayType& array_in) : array(array_in) {}
389  KOKKOS_INLINE_FUNCTION long long int& operator ()(int ip) const{
390  int ivec = ip/VEC_LEN;
391  long long int* ptr = (long long int*)(&array.view(ivec).gid);
392  int istr = ip%VEC_LEN;
393  return ptr[istr];
394  }
395 };
396 
397 #ifdef ESC_PTL
398 template<class Device>
399 class Slice<PtlSlice::Flag, ParticleDataTypes, Device>{
400  static constexpr int ind = PtlSlice::Flag;
401  using ArrayType = Array<ParticleDataTypes, Device>;
402  const ArrayType array;
403  public:
404  Slice(const ArrayType& array_in) : array(array_in) {}
405  KOKKOS_INLINE_FUNCTION long long int& operator ()(int ip) const{
406  int ivec = ip/VEC_LEN;
407  long long int* ptr = (long long int*)(&array.view(ivec).flag);
408  int istr = ip%VEC_LEN;
409  return ptr[istr];
410  }
411 };
412 #endif
413 
414 template<int SliceInd, class DataType, class Device>
416  return Slice<SliceInd, DataType, Device>(array);
417 }
418 
419 #endif
420 
421 };
422 
423 
424 #include "particles.tpp"
425 #endif
Definition: particles.hpp:248
void reserve(size_t n_reserve)
Definition: particles.hpp:278
size_t n
Definition: particles.hpp:256
Array()
Definition: particles.hpp:260
KOKKOS_INLINE_FUNCTION vec_data_type & access(size_t ind) const
Definition: particles.hpp:274
Array(const std::string &label, size_t n_in)
Definition: particles.hpp:262
size_t size() const
Definition: particles.hpp:266
vec_data_type soa_type
Definition: particles.hpp:254
std::conditional_t< std::is_same_v< DataType, ParticleDataTypes >, VecParticles, VecPhase > vec_data_type
Definition: particles.hpp:251
void resize(size_t new_n_ptl)
Definition: particles.hpp:301
View< vec_data_type *, CLayout, Device > view
Definition: particles.hpp:258
vec_data_type * data() const
Definition: particles.hpp:270
const ArrayType array
Definition: particles.hpp:371
Slice(const ArrayType &array_in)
Definition: particles.hpp:373
const ArrayType array
Definition: particles.hpp:386
Slice(const ArrayType &array_in)
Definition: particles.hpp:388
Slice(const ArrayType &array_in)
Definition: particles.hpp:358
const ArrayType array
Definition: particles.hpp:356
Slice(const ArrayType &array_in)
Definition: particles.hpp:343
const ArrayType array
Definition: particles.hpp:341
Definition: particles.hpp:332
void exit_XGC(std::string msg)
Definition: globals.hpp:38
KOKKOS_INLINE_FUNCTION int divide_and_round_up(int a, int b)
Definition: globals.hpp:249
Definition: particles.hpp:224
constexpr size_t sizeof_ptl< ParticleDataTypes >()
Definition: particles.hpp:327
Slice< SliceInd, DataType, Device > slice(const Array< DataType, Device > &array)
Definition: particles.hpp:415
constexpr size_t sizeof_ptl()
constexpr size_t sizeof_ptl< PhaseDataTypes >()
Definition: particles.hpp:329
void deep_copy(const Array< DataType, Device > &dest, const Array< DataType, Device2 > &src)
Definition: particles.hpp:310
Definition: particles.hpp:215
@ Ph
Definition: particles.hpp:219
@ Gid
Definition: particles.hpp:219
@ Ct
Definition: particles.hpp:219
KOKKOS_INLINE_FUNCTION void update_phases(SimdPhase &ph_new, const SimdPhase &ph, double local_dt, const SimdPhase &dph)
Definition: particles.tpp:6
long long int add_vec_buffer(T n_ptl)
Definition: particles.hpp:190
int p_range< DeviceType >(int num_particle)
Definition: particles.hpp:182
KOKKOS_INLINE_FUNCTION void update_dphm(SimdPhase &dphm, const SimdPhase &dpht)
Definition: particles.tpp:21
KOKKOS_INLINE_FUNCTION void simd_2_AoSoA(VecParticles *part, const SimdParticles &part_one, int a_vec, int s_vec)
Definition: particles.tpp:54
int p_range(int num_particle)
Definition: particles.hpp:173
KOKKOS_INLINE_FUNCTION void update_dpht(SimdPhase &dpht, const SimdPhase &dph, const SimdPhase &dphm)
Definition: particles.tpp:37
KOKKOS_INLINE_FUNCTION void AoSoA_2_simd(SimdParticles &part_one, const VecParticles *part, int a_vec, int s_vec)
Definition: particles.tpp:83
Kokkos::ViewAllocateWithoutInitializing NoInit
Definition: space_settings.hpp:69
Definition: particles.hpp:143
KOKKOS_INLINE_FUNCTION AoSoAIndices(int idx)
Definition: particles.hpp:153
int s
The index in the outer array of the AoSoA.
Definition: particles.hpp:144
int a
The index in the inner array of the AoSoA.
Definition: particles.hpp:145
Definition: particles.hpp:128
double data[T]
Definition: particles.hpp:129
Definition: particles.hpp:40
Simd< double > w0
Full-f weight.
Definition: particles.hpp:42
Simd< double > mu
m*v_perp^2/(2B)
Definition: particles.hpp:41
Simd< double > f0
w0*(marker density)
Definition: particles.hpp:43
Definition: particles.hpp:50
KOKKOS_INLINE_FUNCTION bool is_inactive(int i_simd) const
Definition: particles.hpp:62
Simd< long long int > gid
Definition: particles.hpp:53
SimdPhase ph
Definition: particles.hpp:51
SimdConstants ct
Definition: particles.hpp:52
KOKKOS_INLINE_FUNCTION bool is_active(int i_simd) const
Definition: particles.hpp:58
KOKKOS_INLINE_FUNCTION void deactivate(int i_simd)
Definition: particles.hpp:77
KOKKOS_INLINE_FUNCTION void deactivate(const Simd< bool > &mask)
Definition: particles.hpp:68
Definition: particles.hpp:6
Simd< double > w2
(1 - background distribution)/f0
Definition: particles.hpp:12
KOKKOS_INLINE_FUNCTION SimdVector2D & x()
Definition: particles.hpp:16
Simd< double > w1
delta-f weight
Definition: particles.hpp:11
Simd< double > rho
m*v_para/(q*B) - A_para^h/B (should it be plus or minus?)
Definition: particles.hpp:10
KOKKOS_INLINE_FUNCTION const SimdVector2D & x() const
Definition: particles.hpp:22
Simd< double > z
Cylindrical coordinate Z.
Definition: particles.hpp:8
Simd< double > r
Cylindrical coordinate R (major radial direction)
Definition: particles.hpp:7
Simd< double > phi
Cylindrical coordinate phi (toroidal direction)
Definition: particles.hpp:9
KOKKOS_INLINE_FUNCTION const SimdVector & v() const
Definition: particles.hpp:34
KOKKOS_INLINE_FUNCTION SimdVector & v()
Definition: particles.hpp:28
Definition: simd.hpp:139
Definition: simd.hpp:149
Definition: particles.hpp:94
double f0[VEC_LEN]
Definition: particles.hpp:97
double mu[VEC_LEN]
Definition: particles.hpp:95
double w0[VEC_LEN]
Definition: particles.hpp:96
Definition: particles.hpp:123
double data[T *VEC_LEN]
Definition: particles.hpp:124
Definition: particles.hpp:104
KOKKOS_INLINE_FUNCTION bool is_active(int i_vec) const
Definition: particles.hpp:112
VecPhase ph
Definition: particles.hpp:105
long long int gid[VEC_LEN]
Definition: particles.hpp:107
VecConstants ct
Definition: particles.hpp:106
KOKKOS_INLINE_FUNCTION bool is_inactive(int i_vec) const
Definition: particles.hpp:116
Definition: particles.hpp:84
double r[VEC_LEN]
Definition: particles.hpp:85
double w2[VEC_LEN]
Definition: particles.hpp:90
double phi[VEC_LEN]
Definition: particles.hpp:87
double rho[VEC_LEN]
Definition: particles.hpp:88
double w1[VEC_LEN]
Definition: particles.hpp:89
double z[VEC_LEN]
Definition: particles.hpp:86