Block-Structured AMR Software Framework
 
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Loading...
Searching...
No Matches
AMReX_Particle.H
Go to the documentation of this file.
1#ifndef AMREX_PARTICLE_H_
2#define AMREX_PARTICLE_H_
3#include <AMReX_Config.H>
4
5#include <AMReX_REAL.H>
6#include <AMReX_FArrayBox.H>
7#include <AMReX_IntVect.H>
8#include <AMReX_RealVect.H>
9#include <AMReX_ParmParse.H>
10#include <AMReX_Geometry.H>
11
12#include <string>
13
14namespace amrex {
15
17 namespace LongParticleIds {
18 constexpr Long GhostParticleID = 549755813887L; // 2**39-1
19 constexpr Long VirtualParticleID = GhostParticleID - 1;
20 constexpr Long LastParticleID = GhostParticleID - 2;
21 constexpr Long DoSplitParticleID = GhostParticleID - 3;
22 constexpr Long NoSplitParticleID = GhostParticleID - 4;
23 }
24
25 using namespace LongParticleIds;
26
30 namespace ParticleIdCpus {
31 constexpr std::uint64_t Invalid = 16777216; // corresponds to id = -1, cpu = 0
32 }
33
34 using namespace ParticleIdCpus;
35
37{
38 uint64_t* m_idata;
39
40 ~ParticleIDWrapper () noexcept = default;
41
43 ParticleIDWrapper (uint64_t& idata) noexcept
44 : m_idata(&idata)
45 {}
46
48 ParticleIDWrapper (const ParticleIDWrapper& rhs) = default;
49
51
54 {
55 return this->operator=(Long(pidw)); // NOLINT
56 }
57
60 {
61 return this->operator=(Long(pidw)); // NOLINT
62 }
63
65 ParticleIDWrapper& operator= (const Long id) noexcept
66 {
67 // zero out the 40 leftmost bits, which store the sign and the abs of the id;
68 (*m_idata) &= 0x00FFFFFF;
69
70 uint64_t val;
71 uint64_t sign = id >= 0;
72 if (sign)
73 {
74 // 2**39-1, the max value representable in this fashion
75 AMREX_ASSERT(id <= 549755813887L);
76 val = id;
77 }
78 else
79 {
80 // -2**39-1, the min value representable in this fashion
81 AMREX_ASSERT(id >= -549755813887L);
82 val = -id;
83 }
84
85 (*m_idata) |= (sign << 63); // put the sign in the leftmost bit
86 (*m_idata) |= (val << 24); // put the val in the next 39
87 return *this;
88 }
89
91 operator Long () const noexcept
92 {
93 Long r = 0;
94
95 uint64_t sign = (*m_idata) >> 63; // extract leftmost sign bit
96 uint64_t val = (((*m_idata) >> 24) & 0x7FFFFFFFFF); // extract next 39 id bits
97
98 Long lval = static_cast<Long>(val); // bc we take -
99 r = (sign) ? lval : -lval;
100 return r;
101 }
102
109 void make_invalid () const noexcept
110 {
111 // RHS mask: 0111...
112 (*m_idata) &= ~(uint64_t(1) << 63);
113 }
114
121 void make_valid () const noexcept
122 {
123 // RHS mask: 1000...
124 (*m_idata) |= uint64_t(1) << 63;
125 }
126
132 bool is_valid () const noexcept
133 {
134 // the leftmost bit is our id's valid sign
135 return (*m_idata) >> 63;
136 }
137};
138
140{
141 uint64_t* m_idata;
142
143 ~ParticleCPUWrapper () noexcept = default;
144
146 ParticleCPUWrapper (uint64_t& idata) noexcept
147 : m_idata(&idata)
148 {}
149
152
154
157 {
158 return this->operator=(int(pcpuw)); // NOLINT
159 }
160
163 {
164 return this->operator=(int(pcpuw)); // NOLINT
165 }
166
168 ParticleCPUWrapper& operator= (const int cpu) noexcept
169 {
170 // zero out the first 24 bits, which are used to store the cpu number
171 (*m_idata) &= (~ 0x00FFFFFF);
172
173 AMREX_ASSERT(cpu >= 0);
174 AMREX_ASSERT(cpu <= 16777215); // 2**24-1, the max representable number
175
176 (*m_idata) |= cpu;
177 return *this;
178 }
179
181 operator int () const noexcept
182 {
183 return static_cast<int>((*m_idata) & 0x00FFFFFF);
184 }
185};
186
188{
189 const uint64_t* m_idata;
190
192 ConstParticleIDWrapper (const uint64_t& idata) noexcept
193 : m_idata(&idata)
194 {}
195
197 operator Long () const noexcept
198 {
199 Long r = 0;
200
201 uint64_t sign = (*m_idata) >> 63; // extract leftmost sign bit
202 uint64_t val = (((*m_idata) >> 24) & 0x7FFFFFFFFF); // extract next 39 id bits
203
204 Long lval = static_cast<Long>(val); // bc we take -
205 r = (sign) ? lval : -lval;
206 return r;
207 }
208
214 bool is_valid () const noexcept
215 {
216 // the leftmost bit is our id's valid sign
217 return (*m_idata) >> 63;
218 }
219};
220
222{
223 const uint64_t* m_idata;
224
226 ConstParticleCPUWrapper (const uint64_t& idata) noexcept
227 : m_idata(&idata)
228 {}
229
231 operator int () const noexcept { return static_cast<int>((*m_idata) & 0x00FFFFFF); }
232};
233
240std::uint64_t SetParticleIDandCPU (Long id, int cpu) noexcept{
241 std::uint64_t idcpu = 0;
242 ParticleIDWrapper{idcpu} = id;
243 ParticleCPUWrapper{idcpu} = cpu;
244 return idcpu;
245}
246
247template <typename T, int NReal, int NInt>
249{
250 T m_pos[AMREX_SPACEDIM];
251 T m_rdata[NReal];
252 uint64_t m_idcpu = 0;
253 int m_idata[NInt];
254};
255
256template <typename T, int NInt>
257struct ParticleBase<T,0,NInt>
258{
259 T m_pos[AMREX_SPACEDIM];
260 uint64_t m_idcpu = 0;
261 int m_idata[NInt];
262};
263
264template <typename T, int NReal>
265struct ParticleBase<T,NReal,0>
266{
267 T m_pos[AMREX_SPACEDIM];
268 T m_rdata[NReal];
269 uint64_t m_idcpu = 0;
270};
271
272template <typename T>
273struct ParticleBase<T,0,0>
274{
275 T m_pos[AMREX_SPACEDIM];
276 uint64_t m_idcpu = 0;
277};
278
279
281{
282 static constexpr int NReal=0;
283 static constexpr int NInt=0;
284 static constexpr bool is_soa_particle = true;
285};
286
292template <int T_NReal, int T_NInt=0>
294 : ParticleBase<ParticleReal,T_NReal,T_NInt>
295{
296 static constexpr bool is_soa_particle = false;
298 using ConstType = Particle const;
299
301 static constexpr int NReal = T_NReal;
302
304 static constexpr int NInt = T_NInt;
305
307 using RealType = ParticleReal;
308
309 static Long the_next_id;
310
313
316
319
322
324 void atomicSetID (const Long id) {
325 uint64_t tmp = 0;
326 ParticleIDWrapper wrapper(tmp);
327 wrapper = id;
328#if defined(AMREX_USE_OMP)
329#pragma omp atomic write
330 this->m_idcpu = wrapper.m_idata;
331#else
332 auto *old_ptr = reinterpret_cast<unsigned long long*>(&(this->m_idcpu));
333 amrex::Gpu::Atomic::Exch(old_ptr, (unsigned long long) wrapper.m_idata);
334#endif
335 }
336
338 RealVect pos () const & {return RealVect(AMREX_D_DECL(this->m_pos[0], this->m_pos[1], this->m_pos[2]));}
339
341 RealType& pos (int index) &
342 {
343 AMREX_ASSERT(index < AMREX_SPACEDIM);
344 return this->m_pos[index];
345 }
346
348 RealType pos (int index) const &
349 {
350 AMREX_ASSERT(index < AMREX_SPACEDIM);
351 return this->m_pos[index];
352 }
353
354 template <int U = T_NReal, std::enable_if_t<U != 0, int> = 0>
356 RealType& rdata (int index) &
357 {
358 AMREX_ASSERT(index < NReal);
359 return this->m_rdata[index];
360 }
361
362 template <int U = T_NReal, std::enable_if_t<U == 0, int> = 0>
364 RealType& rdata (int /*index*/) &
365 {
366 AMREX_ALWAYS_ASSERT(false);
367 return this->pos(0); // bc we must return something
368 }
369
370 template <int U = T_NReal, std::enable_if_t<U != 0, int> = 0>
372 const RealType& rdata (int index) const &
373 {
374 AMREX_ASSERT(index < NReal);
375 return this->m_rdata[index];
376 }
377
378 template <int U = T_NReal, std::enable_if_t<U == 0, int> = 0>
380 RealType rdata (int /*index*/) const &
381 {
382 AMREX_ALWAYS_ASSERT(false);
383 return this->pos(0); // because we must return something
384 }
385
387 RealType rdata (int /*index*/) && = delete;
388
389 template <int U = T_NReal, std::enable_if_t<U != 0, int> = 0>
391 RealVect rvec (AMREX_D_DECL(int indx, int indy, int indz)) const &
392 {
393 AMREX_ASSERT(AMREX_D_TERM(indx < NReal, && indy < NReal, && indz < NReal));
394 return RealVect(AMREX_D_DECL(this->m_rdata[indx],
395 this->m_rdata[indy],
396 this->m_rdata[indz]));
397 }
398
399 template <int U = T_NReal, std::enable_if_t<U == 0, int> = 0>
401 RealVect rvec (AMREX_D_DECL(int /*indx*/, int /*indy*/, int /*indz*/)) const &
402 {
403 AMREX_ALWAYS_ASSERT(false);
404 return RealVect(AMREX_D_DECL(0.0, 0.0, 0.0)); // bc we must return something
405 }
406
407 template <int U = T_NReal, std::enable_if_t<U != 0, int> = 0>
409 RealVect rvec (const IntVect& indices) const &
410 {
411 AMREX_ASSERT(indices.allLT(NReal));
412 return RealVect(AMREX_D_DECL(this->m_rdata[indices[0]],
413 this->m_rdata[indices[1]],
414 this->m_rdata[indices[2]]));
415 }
416
417 template <int U = T_NReal, std::enable_if_t<U == 0, int> = 0>
419 RealVect rvec (const IntVect& /*indices*/) const &
420 {
421 AMREX_ALWAYS_ASSERT(false);
422 return RealVect(AMREX_D_DECL(0.0, 0.0, 0.0)); // bc we must return something
423 }
424
425 template <int U = T_NInt, std::enable_if_t<U != 0, int> = 0>
427 int& idata (int index) &
428 {
429 AMREX_ASSERT(index < NInt);
430 return this->m_idata[index];
431 }
432
433 template <int U = T_NInt, std::enable_if_t<U == 0, int> = 0>
435 uint64_t& idata (int /*index*/) &
436 {
437 AMREX_ALWAYS_ASSERT(false);
438 return this->m_idcpu; //bc we must return something
439 }
440
441 template <int U = T_NInt, std::enable_if_t<U != 0, int> = 0>
443 const int& idata (int index) const &
444 {
445 AMREX_ASSERT(index < NInt);
446 return this->m_idata[index];
447 }
448
449 template <int U = T_NInt, std::enable_if_t<U == 0, int> = 0>
451 int idata (int /*index*/) const &
452 {
453 AMREX_ALWAYS_ASSERT(false);
454 return this->m_idcpu; //bc we must return something
455 }
456
458 RealType idata (int /*index*/) && = delete;
459
468 [[nodiscard]] static Long NextID ();
469
473 [[nodiscard]] static Long UnprotectedNextID ();
474
480 static void NextID (Long nextid);
481};
482
483template <int NReal, int NInt> Long Particle<NReal, NInt>::the_next_id = 1;
484
485template <int NReal, int NInt>
486Long
488{
489 Long next;
490// we should be able to test on _OPENMP < 201107 for capture (version 3.1)
491// but we must work around a bug in gcc < 4.9
492#if defined(AMREX_USE_OMP) && defined(_OPENMP) && _OPENMP < 201307
493#pragma omp critical (amrex_particle_nextid)
494#elif defined(AMREX_USE_OMP)
495#pragma omp atomic capture
496#endif
497 next = the_next_id++;
498
500 amrex::Abort("Particle<NReal, NInt>::NextID() -- too many particles");
501 }
502
503 return next;
504}
505
506template <int NReal, int NInt>
507Long
509{
510 Long next = the_next_id++;
512 amrex::Abort("Particle<NReal, NInt>::NextID() -- too many particles");
513 }
514 return next;
515}
516
517template <int NReal, int NInt>
518void
520{
521 the_next_id = nextid;
522}
523
524template <int NReal, int NInt>
525std::ostream&
526operator<< (std::ostream& os, const Particle<NReal, NInt>& p)
527{
528 os << p.id() << ' '
529 << p.cpu() << ' ';
530
531 for (int i = 0; i < AMREX_SPACEDIM; i++) {
532 os << p.pos(i) << ' ';
533 }
534
535 for (int i = 0; i < NReal; i++) {
536 os << p.rdata(i) << ' ';
537 }
538
539 for (int i = 0; i < NInt; i++) {
540 os << p.idata(i) << ' ';
541 }
542
543 if (!os.good()) {
544 amrex::Error("operator<<(ostream&,Particle<NReal, NInt>&) failed");
545 }
546
547 return os;
548}
549
550template <int NReal>
551std::ostream&
552operator<< (std::ostream& os, const Particle<NReal, 0>& p)
553{
554 os << p.id() << ' '
555 << p.cpu() << ' ';
556
557 for (int i = 0; i < AMREX_SPACEDIM; i++) {
558 os << p.pos(i) << ' ';
559 }
560
561 for (int i = 0; i < NReal; i++) {
562 os << p.rdata(i) << ' ';
563 }
564
565 if (!os.good()) {
566 amrex::Error("operator<<(ostream&,Particle<NReal, NInt>&) failed");
567 }
568
569 return os;
570}
571
572template <int NInt>
573std::ostream&
574operator<< (std::ostream& os, const Particle<0, NInt>& p)
575{
576 os << p.id() << ' '
577 << p.cpu() << ' ';
578
579 for (int i = 0; i < AMREX_SPACEDIM; i++) {
580 os << p.pos(i) << ' ';
581 }
582
583 for (int i = 0; i < NInt; i++) {
584 os << p.idata(i) << ' ';
585 }
586
587 if (!os.good()) {
588 amrex::Error("operator<<(ostream&,Particle<NReal, NInt>&) failed");
589 }
590
591 return os;
592}
593
594template <int NReal=0, int NInt=0>
595std::ostream&
596operator<< (std::ostream& os, const Particle<0, 0>& p)
597{
598 os << p.id() << ' '
599 << p.cpu() << ' ';
600
601 for (int i = 0; i < AMREX_SPACEDIM; i++) {
602 os << p.pos(i) << ' ';
603 }
604
605 if (!os.good()) {
606 amrex::Error("operator<<(ostream&,Particle<NReal, NInt>&) failed");
607 }
608
609 return os;
610}
611
612} // namespace amrex
613
614#endif // AMREX_PARTICLE_H_
#define AMREX_ASSERT(EX)
Definition AMReX_BLassert.H:38
#define AMREX_ALWAYS_ASSERT(EX)
Definition AMReX_BLassert.H:50
#define AMREX_FORCE_INLINE
Definition AMReX_Extension.H:119
#define AMREX_GPU_HOST_DEVICE
Definition AMReX_GpuQualifiers.H:20
#define AMREX_D_TERM(a, b, c)
Definition AMReX_SPACE.H:129
A Real vector in SpaceDim-dimensional space.
Definition AMReX_RealVect.H:32
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE T Exch(T *address, T val) noexcept
Definition AMReX_GpuAtomic.H:485
constexpr Long GhostParticleID
Definition AMReX_Particle.H:18
constexpr Long NoSplitParticleID
Definition AMReX_Particle.H:22
constexpr Long VirtualParticleID
Definition AMReX_Particle.H:19
constexpr Long DoSplitParticleID
Definition AMReX_Particle.H:21
constexpr Long LastParticleID
Definition AMReX_Particle.H:20
constexpr std::uint64_t Invalid
Definition AMReX_Particle.H:31
Definition AMReX_Amr.cpp:49
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE std::uint64_t SetParticleIDandCPU(Long id, int cpu) noexcept
Definition AMReX_Particle.H:240
void Error(const std::string &msg)
Print out message to cerr and exit via amrex::Abort().
Definition AMReX.cpp:224
void Abort(const std::string &msg)
Print out message to cerr and exit via abort().
Definition AMReX.cpp:230
const int[]
Definition AMReX_BLProfiler.cpp:1664
std::ostream & operator<<(std::ostream &os, AmrMesh const &amr_mesh)
Definition AMReX_AmrMesh.cpp:1236
Definition AMReX_Particle.H:222
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE ConstParticleCPUWrapper(const uint64_t &idata) noexcept
Definition AMReX_Particle.H:226
const uint64_t * m_idata
Definition AMReX_Particle.H:223
Definition AMReX_Particle.H:188
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE ConstParticleIDWrapper(const uint64_t &idata) noexcept
Definition AMReX_Particle.H:192
const uint64_t * m_idata
Definition AMReX_Particle.H:189
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool is_valid() const noexcept
Definition AMReX_Particle.H:214
Definition AMReX_Particle.H:249
T m_rdata[NReal]
Definition AMReX_Particle.H:251
uint64_t m_idcpu
Definition AMReX_Particle.H:252
int m_idata[NInt]
Definition AMReX_Particle.H:253
T m_pos[AMREX_SPACEDIM]
Definition AMReX_Particle.H:250
Definition AMReX_Particle.H:140
ParticleCPUWrapper(ParticleCPUWrapper &&)=delete
~ParticleCPUWrapper() noexcept=default
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE ParticleCPUWrapper & operator=(const ParticleCPUWrapper &pcpuw) noexcept
Definition AMReX_Particle.H:156
uint64_t * m_idata
Definition AMReX_Particle.H:141
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE ParticleCPUWrapper(const ParticleCPUWrapper &rhs)=default
Definition AMReX_Particle.H:37
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE ParticleIDWrapper(const ParticleIDWrapper &rhs)=default
uint64_t * m_idata
Definition AMReX_Particle.H:38
~ParticleIDWrapper() noexcept=default
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE ParticleIDWrapper & operator=(const ParticleIDWrapper &pidw) noexcept
Definition AMReX_Particle.H:53
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool is_valid() const noexcept
Definition AMReX_Particle.H:132
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void make_valid() const noexcept
Definition AMReX_Particle.H:121
ParticleIDWrapper(ParticleIDWrapper &&)=delete
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void make_invalid() const noexcept
Definition AMReX_Particle.H:109
The struct used to store particles.
Definition AMReX_Particle.H:295
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE RealType pos(int index) const &
Definition AMReX_Particle.H:348
ParticleReal RealType
The floating point type used for the particles.
Definition AMReX_Particle.H:307
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE ParticleIDWrapper id() &
Definition AMReX_Particle.H:315
static Long NextID()
Returns the next particle ID for this processor. Particle IDs start at 1 and are never reused....
Definition AMReX_Particle.H:487
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE RealVect rvec(AMREX_D_DECL(int, int, int)) const &
Definition AMReX_Particle.H:401
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE RealType rdata(int) const &
Definition AMReX_Particle.H:380
static Long the_next_id
Definition AMReX_Particle.H:309
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE RealType & pos(int index) &
Definition AMReX_Particle.H:341
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE RealType & rdata(int) &
Definition AMReX_Particle.H:364
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE RealVect pos() const &
Definition AMReX_Particle.H:338
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE ConstParticleIDWrapper id() const &
Definition AMReX_Particle.H:321
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE const int & idata(int index) const &
Definition AMReX_Particle.H:443
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE RealVect rvec(const IntVect &indices) const &
Definition AMReX_Particle.H:409
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE RealVect rvec(AMREX_D_DECL(int indx, int indy, int indz)) const &
Definition AMReX_Particle.H:391
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE RealType rdata(int) &&=delete
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE RealType & rdata(int index) &
Definition AMReX_Particle.H:356
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE const RealType & rdata(int index) const &
Definition AMReX_Particle.H:372
static Long UnprotectedNextID()
This version can only be used inside omp critical.
Definition AMReX_Particle.H:508
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE RealVect rvec(const IntVect &) const &
Definition AMReX_Particle.H:419
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE int idata(int) const &
Definition AMReX_Particle.H:451
static constexpr int NReal
number of extra Real components in the particle struct
Definition AMReX_Particle.H:301
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE ConstParticleCPUWrapper cpu() const &
Definition AMReX_Particle.H:318
static constexpr int NInt
number of extra integer components in the particle struct
Definition AMReX_Particle.H:304
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE RealType idata(int) &&=delete
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE ParticleCPUWrapper cpu() &
Definition AMReX_Particle.H:312
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void atomicSetID(const Long id)
Definition AMReX_Particle.H:324
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE uint64_t & idata(int) &
Definition AMReX_Particle.H:435
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE int & idata(int index) &
Definition AMReX_Particle.H:427
Particle const ConstType
Definition AMReX_Particle.H:298
Definition AMReX_Particle.H:281
static constexpr int NInt
Definition AMReX_Particle.H:283
static constexpr int NReal
Definition AMReX_Particle.H:282
Definition AMReX_MakeParticle.H:13