Block-Structured AMR Software Framework
Loading...
Searching...
No Matches
AMReX_ParticleTile.H
Go to the documentation of this file.
1#ifndef AMREX_PARTICLETILE_H_
2#define AMREX_PARTICLETILE_H_
3#include <AMReX_Config.H>
4
5#include <AMReX_Extension.H>
6#include <AMReX_Particle.H>
9#include <AMReX_Vector.H>
10#include <AMReX_REAL.H>
11#include <AMReX_RealVect.H>
12
13#include <array>
14#include <atomic>
15#include <string>
16#include <type_traits>
17#include <vector>
18
19
20namespace amrex {
21
22// Forward Declaration
23template <int NArrayReal, int NArrayInt>
24struct ConstSoAParticle;
25template <int NArrayReal, int NArrayInt>
26struct SoAParticle;
27
28template <typename T_ParticleType, int NArrayReal, int NArrayInt>
29struct ConstParticleTileData;
30
32template <typename T_ParticleType, int NArrayReal, int NArrayInt>
34{
35 static constexpr int NAR = NArrayReal;
36 static constexpr int NAI = NArrayInt;
37
38 using ParticleType = T_ParticleType;
39 using ParticleRefType = T_ParticleType&;
42 using IntType = int;
43
44 static constexpr int NStructReal = ParticleType::NReal;
45 static constexpr int NStructInt = ParticleType::NInt;
46
48
49 static constexpr bool is_particle_tile_data = true;
50
52
53 using AOS_PTR = std::conditional_t<T_ParticleType::is_soa_particle,
56
57 uint64_t* m_idcpu;
60
65
67 decltype(auto) pos (const int dir, const int index) const &
68 {
69 if constexpr(!ParticleType::is_soa_particle) {
70 return this->m_aos[index].pos(dir);
71 } else {
72 return this->m_rdata[dir][index];
73 }
74 }
75
77 decltype(auto) id (const int index) const &
78 {
79 if constexpr(!ParticleType::is_soa_particle) {
80 return this->m_aos[index].id();
81 } else {
82 return ParticleIDWrapper(this->m_idcpu[index]);
83 }
84 }
85
87 decltype(auto) cpu (const int index) const &
88 {
89 if constexpr(!ParticleType::is_soa_particle) {
90 return this->m_aos[index].cpu();
91 } else {
92 return ParticleCPUWrapper(this->m_idcpu[index]);
93 }
94 }
95
97 decltype(auto) idcpu (const int index) const &
98 {
99 if constexpr(ParticleType::is_soa_particle) {
100 return this->m_idcpu[index];
101 } else {
102 return this->m_aos[index].idcpu();
103 }
104 }
105
107 ParticleReal * rdata (const int attribute_index) const
108 {
109 return this->m_rdata[attribute_index];
110 }
111
113 int * idata (const int attribute_index) const
114 {
115 return this->m_idata[attribute_index];
116 }
117
119 decltype(auto) operator[] (const int index) const
120 {
121 if constexpr (!ParticleType::is_soa_particle) {
122 return m_aos[index];
123 } else {
124 return SoAParticle<NAR, NAI>(*this, index);
125 }
126 }
127
129 void packParticleData (char* buffer, int src_index, std::size_t dst_offset,
130 const int* comm_real, const int * comm_int) const noexcept
131 {
132 AMREX_ASSERT(src_index < m_size);
133 auto* dst = buffer + dst_offset;
134 if constexpr (!ParticleType::is_soa_particle) {
135 memcpy(dst, m_aos + src_index, sizeof(ParticleType));
136 dst += sizeof(ParticleType);
137 } else {
138 memcpy(dst, m_idcpu + src_index, sizeof(uint64_t));
139 dst += sizeof(uint64_t);
140 }
141 int array_start_index = 0;
142 if constexpr (!ParticleType::is_soa_particle) {
143 array_start_index = AMREX_SPACEDIM + NStructReal;
144 }
145 for (int i = 0; i < NAR; ++i)
146 {
147 if (comm_real[array_start_index + i])
148 {
149 memcpy(dst, m_rdata[i] + src_index, sizeof(ParticleReal));
150 dst += sizeof(ParticleReal);
151 }
152 }
153 int runtime_start_index = array_start_index + NAR;
154 for (int i = 0; i < m_num_runtime_real; ++i)
155 {
156 if (comm_real[runtime_start_index + i])
157 {
158 memcpy(dst, m_runtime_rdata[i] + src_index, sizeof(ParticleReal));
159 dst += sizeof(ParticleReal);
160 }
161 }
162 array_start_index = 2 + NStructInt;
163 for (int i = 0; i < NAI; ++i)
164 {
165 if (comm_int[array_start_index + i])
166 {
167 memcpy(dst, m_idata[i] + src_index, sizeof(int));
168 dst += sizeof(int);
169 }
170 }
171 runtime_start_index = 2 + NStructInt + NAI;
172 for (int i = 0; i < m_num_runtime_int; ++i)
173 {
174 if (comm_int[runtime_start_index + i])
175 {
176 memcpy(dst, m_runtime_idata[i] + src_index, sizeof(int));
177 dst += sizeof(int);
178 }
179 }
180 }
181
183 void unpackParticleData (const char* buffer, Long src_offset, int dst_index,
184 const int* comm_real, const int* comm_int) const noexcept
185 {
186 AMREX_ASSERT(dst_index < m_size);
187 const auto* src = buffer + src_offset;
188 if constexpr (!ParticleType::is_soa_particle) {
189 memcpy(m_aos + dst_index, src, sizeof(ParticleType));
190 src += sizeof(ParticleType);
191 } else {
192 memcpy(m_idcpu + dst_index, src, sizeof(uint64_t));
193 src += sizeof(uint64_t);
194 }
195 int array_start_index = 0;
196 if constexpr (!ParticleType::is_soa_particle) {
197 array_start_index = AMREX_SPACEDIM + NStructReal;
198 }
199 if constexpr (NAR > 0) {
200 for (int i = 0; i < NAR; ++i)
201 {
202 if (comm_real[array_start_index + i])
203 {
204 memcpy(m_rdata[i] + dst_index, src, sizeof(ParticleReal));
205 src += sizeof(ParticleReal);
206 }
207 }
208 }
209 int runtime_start_index = array_start_index + NAR;
210 for (int i = 0; i < m_num_runtime_real; ++i)
211 {
212 if (comm_real[runtime_start_index + i])
213 {
214 memcpy(m_runtime_rdata[i] + dst_index, src, sizeof(ParticleReal));
215 src += sizeof(ParticleReal);
216 }
217 }
218 array_start_index = 2 + NStructInt;
219 if constexpr (NAI > 0) {
220 for (int i = 0; i < NAI; ++i)
221 {
222 if (comm_int[array_start_index + i])
223 {
224 memcpy(m_idata[i] + dst_index, src, sizeof(int));
225 src += sizeof(int);
226 }
227 }
228 }
229 runtime_start_index = 2 + NStructInt + NAI;
230 for (int i = 0; i < m_num_runtime_int; ++i)
231 {
232 if (comm_int[runtime_start_index + i])
233 {
234 memcpy(m_runtime_idata[i] + dst_index, src, sizeof(int));
235 src += sizeof(int);
236 }
237 }
238 }
239
241 SuperParticleType getSuperParticle (int index) const noexcept
242 requires (!ParticleType::is_soa_particle)
243 {
244 AMREX_ASSERT(index < m_size);
246 for (int i = 0; i < AMREX_SPACEDIM; ++i) {
247 sp.pos(i) = m_aos[index].pos(i);
248 }
249 for (int i = 0; i < NStructReal; ++i) {
250 sp.rdata(i) = m_aos[index].rdata(i);
251 }
252 if constexpr (NAR >0) {
253 for (int i = 0; i < NAR; ++i) {
254 sp.rdata(NStructReal+i) = m_rdata[i][index];
255 }
256 }
257 sp.id() = m_aos[index].id();
258 sp.cpu() = m_aos[index].cpu();
259 for (int i = 0; i < NStructInt; ++i) {
260 sp.idata(i) = m_aos[index].idata(i);
261 }
262 if constexpr (NAI > 0) {
263 for (int i = 0; i < NAI; ++i) {
264 sp.idata(NStructInt+i) = m_idata[i][index];
265 }
266 }
267 return sp;
268 }
269
271 SuperParticleType getSuperParticle (int index) const noexcept
272 requires (ParticleType::is_soa_particle)
273 {
274 AMREX_ASSERT(index < m_size);
276 sp.m_idcpu = m_idcpu[index];
277 for (int i = 0; i < AMREX_SPACEDIM; ++i) {sp.pos(i) = m_rdata[i][index];}
278 for (int i = 0; i < NAR; ++i) {
279 sp.rdata(i) = m_rdata[i][index];
280 }
281 for (int i = 0; i < NAI; ++i) {
282 sp.idata(i) = m_idata[i][index];
283 }
284 return sp;
285 }
286
288 void setSuperParticle (const SuperParticleType& sp, int index) const noexcept
289 requires (!ParticleType::is_soa_particle)
290 {
291 for (int i = 0; i < AMREX_SPACEDIM; ++i) {
292 m_aos[index].pos(i) = sp.pos(i);
293 }
294 for (int i = 0; i < NStructReal; ++i) {
295 m_aos[index].rdata(i) = sp.rdata(i);
296 }
297 for (int i = 0; i < NAR; ++i) {
298 m_rdata[i][index] = sp.rdata(NStructReal+i);
299 }
300 m_aos[index].id() = sp.id();
301 m_aos[index].cpu() = sp.cpu();
302 for (int i = 0; i < NStructInt; ++i) {
303 m_aos[index].idata(i) = sp.idata(i);
304 }
305 for (int i = 0; i < NAI; ++i) {
306 m_idata[i][index] = sp.idata(NStructInt+i);
307 }
308 }
309
311 void setSuperParticle (const SuperParticleType& sp, int index) const noexcept
312 requires (ParticleType::is_soa_particle)
313 {
314 m_idcpu[index] = sp.m_idcpu;
315 for (int i = 0; i < NAR; ++i) {
316 m_rdata[i][index] = sp.rdata(i);
317 }
318 for (int i = 0; i < NAI; ++i) {
319 m_idata[i][index] = sp.idata(i);
320 }
321 }
322};
323
324// SOA Particle Structure
325template <int T_NArrayReal, int T_NArrayInt>
326struct alignas(sizeof(double)) ConstSoAParticle : SoAParticleBase
327{
328 static constexpr int NArrayReal = T_NArrayReal;
329 static constexpr int NArrayInt = T_NArrayInt;
332 static constexpr bool is_soa_particle = true;
333 static constexpr bool is_rtsoa_particle = false;
334 static constexpr bool is_constsoa_particle = true;
335
337 using IntType = int;
338
340 ConstSoAParticle (ConstPTD const& ptd, long i) : // Note: should this be int instead?
341 m_constparticle_tile_data(ptd), m_index(int(i))
342 {
343 }
344
345 //static Long the_next_id;
346
347 //functions to get id and cpu in the SOA data
348
350 ConstParticleCPUWrapper cpu () const { return this->m_constparticle_tile_data.m_idcpu[m_index]; }
351
353 ConstParticleIDWrapper id () const { return this->m_constparticle_tile_data.m_idcpu[m_index]; }
354
355 //functions to get positions of the particle in the SOA data
356
358 RealVect pos () const & {return RealVect(AMREX_D_DECL(this->m_constparticle_tile_data.m_rdata[0][m_index], this->m_constparticle_tile_data.m_rdata[1][m_index], this->m_constparticle_tile_data.m_rdata[2][m_index]));}
359
361 const RealType& pos (int position_index) const &
362 {
363 AMREX_ASSERT(position_index < AMREX_SPACEDIM);
364 return this->m_constparticle_tile_data.m_rdata[position_index][m_index];
365 }
366
367 static Long NextID ();
368
373
379 static void NextID (Long nextid);
380
381 private :
382
383 static_assert(std::is_trivially_copyable<ConstPTD>(), "ParticleTileData is not trivially copyable");
384
385 ConstPTD m_constparticle_tile_data;
386 int m_index;
387};
388
389template <int T_NArrayReal, int T_NArrayInt>
390struct alignas(sizeof(double)) SoAParticle : SoAParticleBase
391{
392 static constexpr int NArrayReal = T_NArrayReal;
393 static constexpr int NArrayInt = T_NArrayInt;
396 static constexpr bool is_soa_particle = true;
397 static constexpr bool is_rtsoa_particle = false;
398 static constexpr bool is_constsoa_particle = false;
399
402 using IntType = int;
403
405 SoAParticle (PTD const& ptd, long i) : // Note: should this be int instead?
406 m_particle_tile_data(ptd), m_index(int(i))
407 {
408 }
409
411
412 //functions to get id and cpu in the SOA data
413
415 ParticleCPUWrapper cpu () & { return this->m_particle_tile_data.m_idcpu[m_index]; }
416
418 ParticleIDWrapper<> id () & { return this->m_particle_tile_data.m_idcpu[m_index]; }
419
421 uint64_t& idcpu () & { return this->m_particle_tile_data.m_idcpu[m_index]; }
422
424 ConstParticleCPUWrapper cpu () const & { return this->m_particle_tile_data.m_idcpu[m_index]; }
425
427 ConstParticleIDWrapper id () const & { return this->m_particle_tile_data.m_idcpu[m_index]; }
428
430 const uint64_t& idcpu () const & { return this->m_particle_tile_data.m_idcpu[m_index]; }
431
432 //functions to get positions of the particle in the SOA data
433
435 RealVect pos () const & {return RealVect(AMREX_D_DECL(this->m_particle_tile_data.m_rdata[0][m_index], this->m_particle_tile_data.m_rdata[1][m_index], this->m_particle_tile_data.m_rdata[2][m_index]));}
436
438 RealType& pos (int position_index) &
439 {
440 AMREX_ASSERT(position_index < AMREX_SPACEDIM);
441 return this->m_particle_tile_data.m_rdata[position_index][m_index];
442 }
443
445 RealType pos (int position_index) const &
446 {
447 AMREX_ASSERT(position_index < AMREX_SPACEDIM);
448 return this->m_particle_tile_data.m_rdata[position_index][m_index];
449 }
450
451 static Long NextID ();
452
456 static Long UnprotectedNextID ();
457
463 static void NextID (Long nextid);
464
465private :
466
467 static_assert(std::is_trivially_copyable<PTD>(), "ParticleTileData is not trivially copyable");
468
469 PTD m_particle_tile_data;
470 int m_index;
471};
472
473//template <int NArrayReal, int NArrayInt> Long ConstSoAParticle<NArrayReal, NArrayInt>::the_next_id = 1;
474template <int NArrayReal, int NArrayInt> Long SoAParticle<NArrayReal, NArrayInt>::the_next_id = 1;
475
476template <int NArrayReal, int NArrayInt>
477Long
479{
480 Long next;
481// we should be able to test on _OPENMP < 201107 for capture (version 3.1)
482// but we must work around a bug in gcc < 4.9
483#if defined(AMREX_USE_OMP) && defined(_OPENMP) && _OPENMP < 201307
484#pragma omp critical (amrex_particle_nextid)
485#elif defined(AMREX_USE_OMP)
486#pragma omp atomic capture
487#endif
488 next = the_next_id++;
489
491 amrex::Abort("SoAParticle<NArrayReal, NArrayInt>::NextID() -- too many particles");
492 }
493
494 return next;
495}
496
497template <int NArrayReal, int NArrayInt>
498Long
500{
501 Long next = the_next_id++;
503 amrex::Abort("SoAParticle<NArrayReal, NArrayInt>::NextID() -- too many particles");
504 }
505 return next;
506}
507
508template <int NArrayReal, int NArrayInt>
509void
511{
512 the_next_id = nextid;
513}
514
515template <typename T_ParticleType, int NArrayReal, int NArrayInt>
517{
518 static constexpr int NAR = NArrayReal;
519 static constexpr int NAI = NArrayInt;
520 using ParticleType = T_ParticleType;
521 using ParticleRefType = T_ParticleType const&;
523 using IntType = int;
524
525 static constexpr int NStructReal = ParticleType::NReal;
526 static constexpr int NStructInt = ParticleType::NInt;
527
529
530 static constexpr bool is_particle_tile_data = true;
531
533
534 using AOS_PTR = std::conditional_t<T_ParticleType::is_soa_particle,
535 void const * AMREX_RESTRICT, ParticleType const * AMREX_RESTRICT>;
537
538 const uint64_t* m_idcpu;
541
543 decltype(auto) pos (const int dir, const int index) const &
544 {
545 if constexpr(!ParticleType::is_soa_particle) {
546 return this->m_aos[index].pos(dir);
547 } else {
548 return this->m_rdata[dir][index];
549 }
550 }
551
553 decltype(auto) id (const int index) const &
554 {
555 if constexpr(!ParticleType::is_soa_particle) {
556 return this->m_aos[index].id();
557 } else {
558 return ConstParticleIDWrapper(this->m_idcpu[index]);
559 }
560 }
561
563 decltype(auto) cpu (const int index) const &
564 {
565 if constexpr(!ParticleType::is_soa_particle) {
566 return this->m_aos[index].cpu();
567 } else {
568 return ConstParticleCPUWrapper(this->m_idcpu[index]);
569 }
570 }
571
573 decltype(auto) idcpu (const int index) const &
574 {
575 if constexpr(ParticleType::is_soa_particle) {
576 return this->m_idcpu[index];
577 } else {
578 return this->m_aos[index].idcpu();
579 }
580 }
581
583 const ParticleReal * rdata (const int attribute_index) const
584 {
585 return this->m_rdata[attribute_index];
586 }
587
589 const int * idata (const int attribute_index) const
590 {
591 return this->m_idata[attribute_index];
592 }
593
595 decltype(auto) operator[] (const int index) const
596 {
597 if constexpr (!ParticleType::is_soa_particle) {
598 return m_aos[index];
599 } else {
600 return ConstSoAParticle<NAR, NAI>(*this, index);
601 }
602 }
603
608
610 void packParticleData(char* buffer, int src_index, Long dst_offset,
611 const int* comm_real, const int * comm_int) const noexcept
612 {
613 AMREX_ASSERT(src_index < m_size);
614 auto* dst = buffer + dst_offset;
615 if constexpr (!ParticleType::is_soa_particle) {
616 memcpy(dst, m_aos + src_index, sizeof(ParticleType));
617 dst += sizeof(ParticleType);
618 } else {
619 memcpy(dst, m_idcpu + src_index, sizeof(uint64_t));
620 dst += sizeof(uint64_t);
621 }
622 int array_start_index = 0;
623 if constexpr (!ParticleType::is_soa_particle) {
624 array_start_index = AMREX_SPACEDIM + NStructReal;
625 }
626 if constexpr (NArrayReal > 0) {
627 for (int i = 0; i < NArrayReal; ++i)
628 {
629 if (comm_real[array_start_index + i])
630 {
631 memcpy(dst, m_rdata[i] + src_index, sizeof(ParticleReal));
632 dst += sizeof(ParticleReal);
633 }
634 }
635 }
636 int runtime_start_index = array_start_index + NArrayReal;
637 for (int i = 0; i < m_num_runtime_real; ++i)
638 {
639 if (comm_real[runtime_start_index + i])
640 {
641 memcpy(dst, m_runtime_rdata[i] + src_index, sizeof(ParticleReal));
642 dst += sizeof(ParticleReal);
643 }
644 }
645 array_start_index = 2 + NStructInt;
646 if constexpr (NArrayInt > 0) {
647 for (int i = 0; i < NArrayInt; ++i)
648 {
649 if (comm_int[array_start_index + i])
650 {
651 memcpy(dst, m_idata[i] + src_index, sizeof(int));
652 dst += sizeof(int);
653 }
654 }
655 }
656 runtime_start_index = 2 + NStructInt + NArrayInt;
657 for (int i = 0; i < m_num_runtime_int; ++i)
658 {
659 if (comm_int[runtime_start_index + i])
660 {
661 memcpy(dst, m_runtime_idata[i] + src_index, sizeof(int));
662 dst += sizeof(int);
663 }
664 }
665 }
666
668 SuperParticleType getSuperParticle (int index) const noexcept
669 requires (!ParticleType::is_soa_particle)
670 {
671 AMREX_ASSERT(index < m_size);
673 for (int i = 0; i < AMREX_SPACEDIM; ++i) {
674 sp.pos(i) = m_aos[index].pos(i);
675 }
676 for (int i = 0; i < NStructReal; ++i) {
677 sp.rdata(i) = m_aos[index].rdata(i);
678 }
679 if constexpr(NArrayReal > 0) {
680 for (int i = 0; i < NArrayReal; ++i) {
681 sp.rdata(NStructReal+i) = m_rdata[i][index];
682 }
683 }
684 sp.id() = m_aos[index].id();
685 sp.cpu() = m_aos[index].cpu();
686 for (int i = 0; i < NStructInt; ++i) {
687 sp.idata(i) = m_aos[index].idata(i);
688 }
689 if constexpr(NArrayInt > 0) {
690 for (int i = 0; i < NArrayInt; ++i) {
691 sp.idata(NStructInt+i) = m_idata[i][index];
692 }
693 }
694 return sp;
695 }
696
698 SuperParticleType getSuperParticle (int index) const noexcept
699 requires (ParticleType::is_soa_particle)
700 {
701 AMREX_ASSERT(index < m_size);
703 for (int i = 0; i < AMREX_SPACEDIM; ++i) {sp.pos(i) = m_rdata[i][index];}
704 sp.m_idcpu = m_idcpu[index];
705 for (int i = 0; i < NAR; ++i) {
706 sp.rdata(i) = m_rdata[i][index];
707 }
708 for (int i = 0; i < NAI; ++i) {
709 sp.idata(i) = m_idata[i][index];
710 }
711 return sp;
712 }
713};
714
716
720
722{
723 RuntimePtrCacheDirtyFlag () noexcept = default;
724
726
728 : m_value(true)
729 {}
730
732 : m_value(true)
733 {}
734
736 {
737 m_value.store(true, std::memory_order_relaxed);
738 return *this;
739 }
740
742 {
743 m_value.store(true, std::memory_order_relaxed);
744 return *this;
745 }
746
747 void store (bool value, std::memory_order order = std::memory_order_seq_cst) noexcept
748 {
749 m_value.store(value, order);
750 }
751
752 [[nodiscard]] bool load (std::memory_order order = std::memory_order_seq_cst) const noexcept
753 {
754 return m_value.load(order);
755 }
756
757private:
758 std::atomic<bool> m_value {true};
759};
760
761template <typename T_ParticleType, int NArrayReal, int NArrayInt,
762 template<class> class Allocator=DefaultAllocator>
764{
765 template <typename T>
766 using AllocatorType = Allocator<T>;
767
768 using ParticleType = T_ParticleType;
769 static constexpr int NAR = NArrayReal;
770 static constexpr int NAI = NArrayInt;
771 using RealType = typename ParticleType::RealType;
772
773 static constexpr int NStructReal = ParticleType::NReal;
774 static constexpr int NStructInt = ParticleType::NInt;
775
777
778 using AoS = std::conditional_t<
779 ParticleType::is_soa_particle,
782 using ParticleVector = typename AoS::ParticleVector;
783
784 using SoA = std::conditional_t<
785 ParticleType::is_soa_particle,
788 using RealVector = typename SoA::RealVector;
789 using IntVector = typename SoA::IntVector;
790 using StorageParticleType = typename ParticleType::StorageParticleType;
791
794
795 static constexpr bool has_polymorphic_allocator =
797
798 ParticleTile () = default;
799
800#ifndef _WIN32 // workaround windows compiler bug
801 ~ParticleTile () = default;
802
803 ParticleTile (ParticleTile const&) = delete;
804 ParticleTile (ParticleTile &&) noexcept = default;
805
806 ParticleTile& operator= (ParticleTile const&) = delete;
807 ParticleTile& operator= (ParticleTile &&) noexcept = default;
808#endif
809
810 void define (
811 int a_num_runtime_real,
812 int a_num_runtime_int,
813 std::vector<std::string>* soa_rdata_names=nullptr,
814 std::vector<std::string>* soa_idata_names=nullptr,
815 Arena* a_arena=nullptr
816 )
817 {
818 GetStructOfArrays().define(a_num_runtime_real, a_num_runtime_int, soa_rdata_names, soa_idata_names);
819
820 if constexpr (has_polymorphic_allocator) {
821 if (m_defined) {
822 // it is not allowed to change the arena after the tile has been defined
823 if constexpr (ParticleType::is_soa_particle) {
825 a_arena == GetStructOfArrays().GetIdCPUData().arena(),
826 "ParticleTile with PolymorphicArenaAllocator redefined with "
827 "different memory arena");
828 } else {
830 a_arena == m_aos_tile().arena(),
831 "ParticleTile with PolymorphicArenaAllocator redefined with "
832 "different memory arena");
833 }
834 }
835
836 AMREX_ALWAYS_ASSERT_WITH_MESSAGE(a_arena != nullptr,
837 "ParticleTile with PolymorphicArenaAllocator defined with no memory arena! "
838 "Make sure to call setArena() on the ParticleContainer before initialization or "
839 "to pass an Arena to ParticleTile::define()");
840
841 if constexpr (ParticleType::is_soa_particle) {
842 GetStructOfArrays().GetIdCPUData().setArena(a_arena);
843 } else {
844 m_aos_tile().setArena(a_arena);
845 }
846 for (int j = 0; j < NumRealComps(); ++j) {
847 GetStructOfArrays().GetRealData(j).setArena(a_arena);
848 }
849 for (int j = 0; j < NumIntComps(); ++j) {
850 GetStructOfArrays().GetIntData(j).setArena(a_arena);
851 }
852
853 m_runtime_r_ptrs.setArena(a_arena);
854 m_runtime_i_ptrs.setArena(a_arena);
855 m_runtime_r_cptrs.setArena(a_arena);
856 m_runtime_i_cptrs.setArena(a_arena);
857 }
858
859 m_runtime_r_ptrs.resize(a_num_runtime_real);
860 m_runtime_i_ptrs.resize(a_num_runtime_int);
861 m_runtime_r_cptrs.resize(a_num_runtime_real);
862 m_runtime_i_cptrs.resize(a_num_runtime_int);
863
864 m_defined = true;
865 invalidateRuntimePtrCaches();
866 }
867
868 // Get id data
869 decltype(auto) id (int index) & {
870 if constexpr (!ParticleType::is_soa_particle) {
871 return m_aos_tile[index].id();
872 } else {
873 return ParticleIDWrapper(m_soa_tile.GetIdCPUData()[index]);
874 }
875 }
876
877 // const
878 decltype(auto) id (int index) const & {
879 if constexpr (!ParticleType::is_soa_particle) {
880 return m_aos_tile[index].id();
881 } else {
882 return ConstParticleIDWrapper(m_soa_tile.GetIdCPUData()[index]);
883 }
884 }
885
886 // Get cpu data
887 decltype(auto) cpu (int index) & {
888 if constexpr (!ParticleType::is_soa_particle) {
889 return m_aos_tile[index].cpu();
890 } else {
891 return ParticleCPUWrapper(m_soa_tile.GetIdCPUData()[index]);
892 }
893 }
894
895 // const
896 decltype(auto) cpu (int index) const & {
897 if constexpr (!ParticleType::is_soa_particle) {
898 return m_aos_tile[index].cpu();
899 } else {
900 return ConstParticleCPUWrapper(m_soa_tile.GetIdCPUData()[index]);
901 }
902 }
903
904 // Get positions data
905 RealType& pos (int index, int position_index) & {
906 if constexpr (!ParticleType::is_soa_particle) {
907 return m_aos_tile[index].pos(position_index);
908 } else {
909 static_assert(NArrayReal == ParticleType::PTD::NAR, "ParticleTile mismatch in R");
910 static_assert(NArrayInt == ParticleType::PTD::NAI, "ParticleTile mismatch in I");
911 static_assert(0 == ParticleType::StorageParticleType::NReal, "ParticleTile 2 mismatch in R");
912 static_assert(0 == ParticleType::StorageParticleType::NInt, "ParticleTile 2 mismatch in I");
913
914 return m_soa_tile.GetRealData(position_index)[index];
915 }
916 }
917
918 // const
919 RealType pos (int index, int position_index) const &
920 {
921 if constexpr (!ParticleType::is_soa_particle) {
922 return m_aos_tile[index].pos(position_index);
923 } else {
924 return m_soa_tile.GetRealData(position_index)[index];
925 }
926 }
927
928 AoS& GetArrayOfStructs () { invalidateRuntimePtrCaches(); return m_aos_tile; }
929 const AoS& GetArrayOfStructs () const { return m_aos_tile; }
930
931 SoA& GetStructOfArrays () { invalidateRuntimePtrCaches(); return m_soa_tile; }
932 const SoA& GetStructOfArrays () const { return m_soa_tile; }
933
934 bool empty () const { return size() == 0; }
935
940 std::size_t size () const
941 {
942 if constexpr (!ParticleType::is_soa_particle) {
943 return m_aos_tile.size();
944 } else {
945 return m_soa_tile.size();
946 }
947 }
948
953 int numParticles () const
954 {
955 if constexpr (!ParticleType::is_soa_particle) {
956 return m_aos_tile.numParticles();
957 } else {
958 return m_soa_tile.numParticles();
959 }
960 }
961
966 int numRealParticles () const
967 {
968 if constexpr (!ParticleType::is_soa_particle) {
969 return m_aos_tile.numRealParticles();
970 } else {
971 return m_soa_tile.numRealParticles();
972 }
973 }
974
980 {
981 if constexpr (!ParticleType::is_soa_particle) {
982 return m_aos_tile.numNeighborParticles();
983 } else {
984 return m_soa_tile.numNeighborParticles();
985 }
986 }
987
992 int numTotalParticles () const
993 {
994 if constexpr (!ParticleType::is_soa_particle) {
995 return m_aos_tile.numTotalParticles();
996 } else {
997 return m_soa_tile.numTotalParticles();
998 }
999 }
1000
1001 void setNumNeighbors (int num_neighbors)
1002 {
1003 invalidateRuntimePtrCaches();
1004 if constexpr(!ParticleType::is_soa_particle) {
1005 m_aos_tile.setNumNeighbors(num_neighbors);
1006 }
1007 m_soa_tile.setNumNeighbors(num_neighbors);
1008 }
1009
1010 int getNumNeighbors () const
1011 {
1012 if constexpr (!ParticleType::is_soa_particle) {
1013 AMREX_ASSERT( m_soa_tile.getNumNeighbors() == m_aos_tile.getNumNeighbors() );
1014 return m_aos_tile.getNumNeighbors();
1015 } else {
1016 return m_soa_tile.getNumNeighbors();
1017 }
1018 }
1019
1020 void resize (std::size_t count, GrowthStrategy strategy = GrowthStrategy::Poisson)
1021 {
1022 invalidateRuntimePtrCaches();
1023 if constexpr (!ParticleType::is_soa_particle) {
1024 m_aos_tile.resize(count, strategy);
1025 }
1026 m_soa_tile.resize(count, strategy);
1027 }
1028
1030 {
1031 invalidateRuntimePtrCaches();
1032 if constexpr (!ParticleType::is_soa_particle) {
1033 m_aos_tile.reserve(capacity, strategy);
1034 }
1035 m_soa_tile.reserve(capacity, strategy);
1036 }
1037
1041 void push_back (const ParticleType& p)
1042 requires (!ParticleType::is_soa_particle)
1043 {
1044 invalidateRuntimePtrCaches();
1045 m_aos_tile().push_back(p);
1046 }
1047
1052 requires (NArrayReal != 0 || NArrayInt != 0)
1053 {
1054 invalidateRuntimePtrCaches();
1055 auto np = numParticles();
1056
1057 if constexpr (!ParticleType::is_soa_particle) {
1058 m_aos_tile.resize(np+1);
1059 for (int i = 0; i < AMREX_SPACEDIM; ++i) {
1060 m_aos_tile[np].pos(i) = sp.pos(i);
1061 }
1062 for (int i = 0; i < NStructReal; ++i) {
1063 m_aos_tile[np].rdata(i) = sp.rdata(i);
1064 }
1065 m_aos_tile[np].id() = sp.id();
1066 m_aos_tile[np].cpu() = sp.cpu();
1067 for (int i = 0; i < NStructInt; ++i) {
1068 m_aos_tile[np].idata(i) = sp.idata(i);
1069 }
1070 }
1071
1072 m_soa_tile.resize(np+1);
1073 if constexpr (ParticleType::is_soa_particle) {
1074 m_soa_tile.GetIdCPUData()[np] = sp.m_idcpu;
1075 }
1076 auto& arr_rdata = m_soa_tile.GetRealData();
1077 auto& arr_idata = m_soa_tile.GetIntData();
1078 for (int i = 0; i < NArrayReal; ++i) {
1079 arr_rdata[i][np] = sp.rdata(NStructReal+i);
1080 }
1081 for (int i = 0; i < NArrayInt; ++i) {
1082 arr_idata[i][np] = sp.idata(NStructInt+i);
1083 }
1084 }
1085
1090 void push_back_real (int comp, ParticleReal v) {
1091 invalidateRuntimePtrCaches();
1092 m_soa_tile.GetRealData(comp).push_back(v);
1093 }
1094
1099 void push_back_real (const std::array<ParticleReal, NArrayReal>& v) {
1100 for (int i = 0; i < NArrayReal; ++i) {
1101 m_soa_tile.GetRealData(i).push_back(v[i]);
1102 }
1103 }
1104
1109 void push_back_real (int comp, const ParticleReal* beg, const ParticleReal* end) {
1110 invalidateRuntimePtrCaches();
1111 auto it = m_soa_tile.GetRealData(comp).end();
1112 m_soa_tile.GetRealData(comp).insert(it, beg, end);
1113 }
1114
1122
1128 push_back_real(comp, vec.cbegin(), vec.cend());
1129 }
1130
1135 void push_back_real (int comp, std::size_t npar, ParticleReal v) {
1136 invalidateRuntimePtrCaches();
1137 auto new_size = m_soa_tile.GetRealData(comp).size() + npar;
1138 m_soa_tile.GetRealData(comp).resize(new_size, v);
1139 }
1140
1145 void push_back_int (int comp, int v) {
1146 invalidateRuntimePtrCaches();
1147 m_soa_tile.GetIntData(comp).push_back(v);
1148 }
1149
1154 void push_back_int (const std::array<int, NArrayInt>& v) {
1155 for (int i = 0; i < NArrayInt; ++i) {
1156 m_soa_tile.GetIntData(i).push_back(v[i]);
1157 }
1158 }
1159
1164 void push_back_int (int comp, const int* beg, const int* end) {
1165 invalidateRuntimePtrCaches();
1166 auto it = m_soa_tile.GetIntData(comp).end();
1167 m_soa_tile.GetIntData(comp).insert(it, beg, end);
1168 }
1169
1177
1182 void push_back_int (int comp, amrex::Vector<int> const & vec) {
1183 push_back_int(comp, vec.cbegin(), vec.cend());
1184 }
1185
1190 void push_back_int (int comp, std::size_t npar, int v) {
1191 invalidateRuntimePtrCaches();
1192 auto new_size = m_soa_tile.GetIntData(comp).size() + npar;
1193 m_soa_tile.GetIntData(comp).resize(new_size, v);
1194 }
1195
1196 int NumRealComps () const noexcept { return m_soa_tile.NumRealComps(); }
1197
1198 int NumIntComps () const noexcept { return m_soa_tile.NumIntComps(); }
1199
1200 int NumRuntimeRealComps () const noexcept { return m_runtime_r_ptrs.size(); }
1201
1202 int NumRuntimeIntComps () const noexcept { return m_runtime_i_ptrs.size(); }
1203
1205 {
1206 invalidateRuntimePtrCaches();
1207 if constexpr (ParticleType::is_soa_particle) {
1208 GetStructOfArrays().GetIdCPUData().shrink_to_fit();
1209 } else {
1210 m_aos_tile().shrink_to_fit();
1211 }
1212 for (int j = 0; j < NumRealComps(); ++j)
1213 {
1214 auto& rdata = GetStructOfArrays().GetRealData(j);
1215 rdata.shrink_to_fit();
1216 }
1217
1218 for (int j = 0; j < NumIntComps(); ++j)
1219 {
1220 auto& idata = GetStructOfArrays().GetIntData(j);
1221 idata.shrink_to_fit();
1222 }
1223 }
1224
1226 {
1227 Long nbytes = 0;
1228 if constexpr (ParticleType::is_soa_particle) {
1229 nbytes += GetStructOfArrays().GetIdCPUData().capacity() * sizeof(uint64_t);
1230 } else {
1231 nbytes += m_aos_tile().capacity() * sizeof(ParticleType);
1232 }
1233 for (int j = 0; j < NumRealComps(); ++j)
1234 {
1235 auto& rdata = GetStructOfArrays().GetRealData(j);
1236 nbytes += rdata.capacity() * sizeof(ParticleReal);
1237 }
1238
1239 for (int j = 0; j < NumIntComps(); ++j)
1240 {
1241 auto& idata = GetStructOfArrays().GetIntData(j);
1242 nbytes += idata.capacity()*sizeof(int);
1243 }
1244 return nbytes;
1245 }
1246
1248 {
1249 if constexpr (ParticleType::is_soa_particle) {
1250 GetStructOfArrays().GetIdCPUData().swap(other.GetStructOfArrays().GetIdCPUData());
1251 } else {
1252 m_aos_tile().swap(other.GetArrayOfStructs()());
1253 }
1254 for (int j = 0; j < NumRealComps(); ++j)
1255 {
1256 auto& rdata = GetStructOfArrays().GetRealData(j);
1257 rdata.swap(other.GetStructOfArrays().GetRealData(j));
1258 }
1259
1260 for (int j = 0; j < NumIntComps(); ++j)
1261 {
1262 auto& idata = GetStructOfArrays().GetIntData(j);
1263 idata.swap(other.GetStructOfArrays().GetIntData(j));
1264 }
1265 invalidateRuntimePtrCaches();
1266 other.invalidateRuntimePtrCaches();
1267 }
1268
1270 {
1271 refreshRuntimePtrCaches();
1272
1274 if constexpr (!ParticleType::is_soa_particle) {
1275 ptd.m_aos = m_aos_tile().dataPtr();
1276 } else {
1277 ptd.m_aos = nullptr;
1278 }
1279 if constexpr (ParticleType::is_soa_particle) {
1280 ptd.m_idcpu = m_soa_tile.GetIdCPUData().dataPtr();
1281 } else {
1282 ptd.m_idcpu = nullptr;
1283 }
1284 if constexpr(NArrayReal > 0) {
1285 for (int i = 0; i < NArrayReal; ++i) {
1286 ptd.m_rdata[i] = m_soa_tile.GetRealData(i).dataPtr();
1287 }
1288 }
1289 if constexpr(NArrayInt > 0) {
1290 for (int i = 0; i < NArrayInt; ++i) {
1291 ptd.m_idata[i] = m_soa_tile.GetIntData(i).dataPtr();
1292 }
1293 }
1294 ptd.m_size = size();
1295 ptd.m_num_runtime_real = m_runtime_r_ptrs.size();
1296 ptd.m_num_runtime_int = m_runtime_i_ptrs.size();
1297 ptd.m_runtime_rdata = m_runtime_r_ptrs.dataPtr();
1298 ptd.m_runtime_idata = m_runtime_i_ptrs.dataPtr();
1299
1300 return ptd;
1301 }
1302
1304 {
1305 refreshConstRuntimePtrCaches();
1306
1308 if constexpr (!ParticleType::is_soa_particle) {
1309 ptd.m_aos = m_aos_tile().dataPtr();
1310 } else {
1311 ptd.m_aos = nullptr;
1312 }
1313 if constexpr (ParticleType::is_soa_particle) {
1314 ptd.m_idcpu = m_soa_tile.GetIdCPUData().dataPtr();
1315 } else {
1316 ptd.m_idcpu = nullptr;
1317 }
1318 if constexpr(NArrayReal > 0) {
1319 for (int i = 0; i < NArrayReal; ++i) {
1320 ptd.m_rdata[i] = m_soa_tile.GetRealData(i).dataPtr();
1321 }
1322 }
1323 if constexpr(NArrayInt > 0) {
1324 for (int i = 0; i < NArrayInt; ++i) {
1325 ptd.m_idata[i] = m_soa_tile.GetIntData(i).dataPtr();
1326 }
1327 }
1328 ptd.m_size = size();
1329 ptd.m_num_runtime_real = m_runtime_r_cptrs.size();
1330 ptd.m_num_runtime_int = m_runtime_i_cptrs.size();
1331 ptd.m_runtime_rdata = m_runtime_r_cptrs.dataPtr();
1332 ptd.m_runtime_idata = m_runtime_i_cptrs.dataPtr();
1333
1334 return ptd;
1335 }
1336
1340 {
1341 invalidateRuntimePtrCaches();
1342 if constexpr (!ParticleType::is_soa_particle) {
1343 m_aos_tile.collectVectors(pv);
1344 } else {
1346 }
1347 m_soa_tile.collectVectors(idcpuv, rv, iv);
1348 }
1349
1350 static void reserve (std::map<ParticleTile<T_ParticleType,NArrayReal,NArrayInt,Allocator>*, int> const& addsizes)
1351 {
1352 if constexpr (!IsArenaAllocator<Allocator<int>>::value) {
1353 for (auto [p,s] : addsizes) {
1354 p->reserve(p->size()+s);
1355 }
1356 } else {
1357 using PV = std::conditional_t<ParticleType::is_soa_particle,
1363 for (auto [p,s] : addsizes) {
1364 if (s > 0) {
1369 p->collectVectors(pv, idcpuv, rv, iv);
1370 if constexpr (!ParticleType::is_soa_particle) {
1371 for (auto* v : pv) {
1372 pvs.emplace_back(v, s);
1373 }
1374 }
1375 for (auto* v : idcpuv) {
1376 ids.emplace_back(v, s);
1377 }
1378 for (auto* v : rv) {
1379 rvs.emplace_back(v, s);
1380 }
1381 for (auto* v : iv) {
1382 ivs.emplace_back(v, s);
1383 }
1384 }
1385 }
1386
1387 std::ranges::sort(pvs, [] (auto const& a, auto const& b) {
1388 return (a.first->size() + a.second) >
1389 (b.first->size() + b.second);
1390 });
1391 std::ranges::sort(ids, [] (auto const& a, auto const& b) {
1392 return (a.first->size() + a.second) >
1393 (b.first->size() + b.second);
1394 });
1395 std::ranges::sort(rvs, [] (auto const& a, auto const& b) {
1396 return (a.first->size() + a.second) >
1397 (b.first->size() + b.second);
1398 });
1399 std::ranges::sort(ivs, [] (auto const& a, auto const& b) {
1400 return (a.first->size() + a.second) >
1401 (b.first->size() + b.second);
1402 });
1403
1404 // Handle big vectors first
1405 {
1406 int i_pvs = 0, i_ids = 0, i_rvs = 0, i_ivs = 0;
1407 auto n_pvs = int(pvs.size());
1408 auto n_ids = int(ids.size());
1409 auto n_rvs = int(rvs.size());
1410 auto n_ivs = int(ivs.size());
1411 while ((i_pvs < n_pvs) || (i_ids < n_ids) || (i_rvs < n_rvs) ||
1412 (i_ivs < n_ivs)) {
1413 std::size_t nbytes = 0;
1414 int ii = -1;
1415 if (i_pvs < n_pvs) {
1416 std::size_t my_bytes = (pvs[i_pvs].first->size()
1417 + pvs[i_pvs].second) * sizeof(typename PV::value_type);
1418 if (my_bytes > nbytes) {
1419 nbytes = my_bytes;
1420 ii = 0;
1421 }
1422 }
1423 if (i_ids < n_ids) {
1424 std::size_t my_bytes = (ids[i_ids].first->size()
1425 + ids[i_ids].second) * sizeof(typename SoA::IdCPU::value_type);
1426 if (my_bytes > nbytes) {
1427 nbytes = my_bytes;
1428 ii = 1;
1429 }
1430 }
1431 if (i_rvs < n_rvs) {
1432 std::size_t my_bytes = (rvs[i_rvs].first->size()
1433 + rvs[i_rvs].second) * sizeof(typename RealVector::value_type);
1434 if (my_bytes > nbytes) {
1435 nbytes = my_bytes;
1436 ii = 2;
1437 }
1438 }
1439 if (i_ivs < n_ivs) {
1440 std::size_t my_bytes = (ivs[i_ivs].first->size()
1441 + ivs[i_ivs].second) * sizeof(typename IntVector::value_type);
1442 if (my_bytes > nbytes) {
1443 nbytes = my_bytes;
1444 ii = 3;
1445 }
1446 }
1447 if (ii == 0) {
1448 auto [p,s] = pvs[i_pvs++];
1449 p->reserve(p->size() + s);
1450 } else if (ii == 1) {
1451 auto [p,s] = ids[i_ids++];
1452 p->reserve(p->size() + s);
1453 } else if (ii == 2) {
1454 auto [p,s] = rvs[i_rvs++];
1455 p->reserve(p->size() + s);
1456 } else {
1457 auto [p,s] = ivs[i_ivs++];
1458 p->reserve(p->size() + s);
1459 }
1460 }
1461 }
1462 }
1463 }
1464
1465private:
1466
1467 void invalidateRuntimePtrCaches () noexcept
1468 {
1469 m_runtime_ptrs_dirty.store(true, std::memory_order_release);
1470 m_runtime_cptrs_dirty.store(true, std::memory_order_release);
1471 }
1472
1473 void refreshRuntimePtrCaches ()
1474 {
1475 if (!m_runtime_ptrs_dirty.load(std::memory_order_acquire)) {
1476 return;
1477 }
1478#if defined(AMREX_USE_OMP)
1479#pragma omp critical (amrex_particle_tile_data_cache)
1480#endif
1481 {
1482 if (m_runtime_ptrs_dirty.load(std::memory_order_relaxed)) {
1483 m_runtime_r_ptrs.resize(m_soa_tile.NumRealComps() - NArrayReal);
1484 m_runtime_i_ptrs.resize(m_soa_tile.NumIntComps() - NArrayInt);
1485#ifdef AMREX_USE_GPU
1486 bool copy_real = false;
1487 m_h_runtime_r_ptrs.resize(m_soa_tile.NumRealComps() - NArrayReal, nullptr);
1488 for (std::size_t i = 0; i < m_h_runtime_r_ptrs.size(); ++i) {
1489 if (m_h_runtime_r_ptrs[i] != m_soa_tile.GetRealData(i + NArrayReal).dataPtr()) {
1490 m_h_runtime_r_ptrs[i] = m_soa_tile.GetRealData(i + NArrayReal).dataPtr();
1491 copy_real = true;
1492 }
1493 }
1494 if (copy_real) {
1495 Gpu::htod_memcpy_async(m_runtime_r_ptrs.data(), m_h_runtime_r_ptrs.data(),
1496 m_h_runtime_r_ptrs.size()*sizeof(ParticleReal*));
1497 }
1498
1499 bool copy_int = false;
1500 m_h_runtime_i_ptrs.resize(m_soa_tile.NumIntComps() - NArrayInt, nullptr);
1501 for (std::size_t i = 0; i < m_h_runtime_i_ptrs.size(); ++i) {
1502 if (m_h_runtime_i_ptrs[i] != m_soa_tile.GetIntData(i + NArrayInt).dataPtr()) {
1503 m_h_runtime_i_ptrs[i] = m_soa_tile.GetIntData(i + NArrayInt).dataPtr();
1504 copy_int = true;
1505 }
1506 }
1507 if (copy_int) {
1508 Gpu::htod_memcpy_async(m_runtime_i_ptrs.data(), m_h_runtime_i_ptrs.data(),
1509 m_h_runtime_i_ptrs.size()*sizeof(int*));
1510 }
1511
1512 if (copy_real || copy_int) {
1514 }
1515#else
1516 for (std::size_t i = 0; i < m_runtime_r_ptrs.size(); ++i) {
1517 m_runtime_r_ptrs[i] = m_soa_tile.GetRealData(i + NArrayReal).dataPtr();
1518 }
1519
1520 for (std::size_t i = 0; i < m_runtime_i_ptrs.size(); ++i) {
1521 m_runtime_i_ptrs[i] = m_soa_tile.GetIntData(i + NArrayInt).dataPtr();
1522 }
1523#endif
1524 m_runtime_ptrs_dirty.store(false, std::memory_order_release);
1525 }
1526 }
1527 }
1528
1529 void refreshConstRuntimePtrCaches () const
1530 {
1531 if (!m_runtime_cptrs_dirty.load(std::memory_order_acquire)) {
1532 return;
1533 }
1534#if defined(AMREX_USE_OMP)
1535#pragma omp critical (amrex_const_particle_tile_data_cache)
1536#endif
1537 {
1538 if (m_runtime_cptrs_dirty.load(std::memory_order_relaxed)) {
1539 m_runtime_r_cptrs.resize(m_soa_tile.NumRealComps() - NArrayReal);
1540 m_runtime_i_cptrs.resize(m_soa_tile.NumIntComps() - NArrayInt);
1541#ifdef AMREX_USE_GPU
1542 bool copy_real = false;
1543 m_h_runtime_r_cptrs.resize(m_soa_tile.NumRealComps() - NArrayReal, nullptr);
1544 for (std::size_t i = 0; i < m_h_runtime_r_cptrs.size(); ++i) {
1545 if (m_h_runtime_r_cptrs[i] != m_soa_tile.GetRealData(i + NArrayReal).dataPtr()) {
1546 m_h_runtime_r_cptrs[i] = m_soa_tile.GetRealData(i + NArrayReal).dataPtr();
1547 copy_real = true;
1548 }
1549 }
1550 if (copy_real) {
1551 Gpu::htod_memcpy_async(m_runtime_r_cptrs.data(), m_h_runtime_r_cptrs.data(),
1552 m_h_runtime_r_cptrs.size()*sizeof(ParticleReal*));
1553 }
1554
1555 bool copy_int = false;
1556 m_h_runtime_i_cptrs.resize(m_soa_tile.NumIntComps() - NArrayInt, nullptr);
1557 for (std::size_t i = 0; i < m_h_runtime_i_cptrs.size(); ++i) {
1558 if (m_h_runtime_i_cptrs[i] != m_soa_tile.GetIntData(i + NArrayInt).dataPtr()) {
1559 m_h_runtime_i_cptrs[i] = m_soa_tile.GetIntData(i + NArrayInt).dataPtr();
1560 copy_int = true;
1561 }
1562 }
1563 if (copy_int) {
1564 Gpu::htod_memcpy_async(m_runtime_i_cptrs.data(), m_h_runtime_i_cptrs.data(),
1565 m_h_runtime_i_cptrs.size()*sizeof(int*));
1566 }
1567
1568 if (copy_real || copy_int) {
1570 }
1571#else
1572 for (std::size_t i = 0; i < m_runtime_r_cptrs.size(); ++i) {
1573 m_runtime_r_cptrs[i] = m_soa_tile.GetRealData(i + NArrayReal).dataPtr();
1574 }
1575
1576 for (std::size_t i = 0; i < m_runtime_i_cptrs.size(); ++i) {
1577 m_runtime_i_cptrs[i] = m_soa_tile.GetIntData(i + NArrayInt).dataPtr();
1578 }
1579#endif
1580 m_runtime_cptrs_dirty.store(false, std::memory_order_release);
1581 }
1582 }
1583 }
1584
1585 AoS m_aos_tile;
1586 SoA m_soa_tile;
1587
1588 bool m_defined = false;
1589
1591 amrex::PODVector<int*, Allocator<int*> > m_runtime_i_ptrs;
1592
1594 mutable amrex::PODVector<const int*, Allocator<const int*> >m_runtime_i_cptrs;
1595
1596 amrex::Gpu::HostVector<ParticleReal*> m_h_runtime_r_ptrs;
1597 amrex::Gpu::HostVector<int*> m_h_runtime_i_ptrs;
1598
1599 mutable amrex::Gpu::HostVector<const ParticleReal*> m_h_runtime_r_cptrs;
1600 mutable amrex::Gpu::HostVector<const int*> m_h_runtime_i_cptrs;
1601
1602 RuntimePtrCacheDirtyFlag m_runtime_ptrs_dirty;
1603 mutable RuntimePtrCacheDirtyFlag m_runtime_cptrs_dirty;
1604};
1605
1606} // namespace amrex
1607
1608#endif // AMREX_PARTICLETILE_H_
#define AMREX_ALWAYS_ASSERT_WITH_MESSAGE(EX, MSG)
Definition AMReX_BLassert.H:49
#define AMREX_ASSERT(EX)
Definition AMReX_BLassert.H:38
Compiler- and backend-specific extension macros (e.g., restrict, SIMD, inline).
#define AMREX_FORCE_INLINE
Definition AMReX_Extension.H:124
#define AMREX_RESTRICT
Definition AMReX_Extension.H:37
#define AMREX_GPU_HOST_DEVICE
Definition AMReX_GpuQualifiers.H:20
#define AMREX_D_DECL(a, b, c)
Definition AMReX_SPACE.H:171
Abstract base class for memory arenas.
Definition AMReX_Arena.H:153
Definition AMReX_ArrayOfStructs.H:13
Dynamically allocated vector for trivially copyable data.
Definition AMReX_PODVector.H:308
This class is a thin wrapper around std::vector. Unlike vector, Vector::operator[] provides bound che...
Definition AMReX_Vector.H:29
Long size() const noexcept
Definition AMReX_Vector.H:54
amrex_particle_real ParticleReal
Floating Point Type for Particles.
Definition AMReX_REAL.H:91
amrex_long Long
Definition AMReX_INT.H:30
void streamSynchronize() noexcept
Definition AMReX_GpuDevice.H:310
void htod_memcpy_async(void *p_d, const void *p_h, const std::size_t sz) noexcept
Definition AMReX_GpuDevice.H:421
constexpr Long LastParticleID
Definition AMReX_Particle.H:21
Definition AMReX_Amr.cpp:50
__host__ __device__ void ignore_unused(const Ts &...)
No-op helper that marks variables as intentionally unused.
Definition AMReX.H:259
amrex::ArenaAllocator< T > DefaultAllocator
Definition AMReX_GpuAllocators.H:205
GrowthStrategy
Definition AMReX_PODVector.H:250
RealVectND< 3 > RealVect
Definition AMReX_ParmParse.H:39
void Abort(const std::string &msg)
Print a fatal-error message to stderr and abort execution.
Definition AMReX.cpp:242
const int[]
Definition AMReX_BLProfiler.cpp:1665
__host__ __device__ Dim3 end(BoxND< dim > const &box) noexcept
Return the iterator end coordinate of box as Dim3.
Definition AMReX_Box.H:2257
Definition AMReX_Particle.H:327
Definition AMReX_Particle.H:301
static constexpr bool is_particle_tile_data
Definition AMReX_ParticleTile.H:530
static constexpr int NAI
Definition AMReX_ParticleTile.H:519
int IntType
Definition AMReX_ParticleTile.H:523
GpuArray< const int *, NArrayInt > m_idata
Definition AMReX_ParticleTile.H:540
__host__ __device__ decltype(auto) idcpu(const int index) const &
Definition AMReX_ParticleTile.H:573
__host__ __device__ const int * idata(const int attribute_index) const
Definition AMReX_ParticleTile.H:589
Long m_size
Definition AMReX_ParticleTile.H:532
T_ParticleType ParticleType
Definition AMReX_ParticleTile.H:520
static constexpr int NStructReal
Definition AMReX_ParticleTile.H:525
__host__ __device__ SuperParticleType getSuperParticle(int index) const noexcept
Definition AMReX_ParticleTile.H:698
__host__ __device__ void packParticleData(char *buffer, int src_index, Long dst_offset, const int *comm_real, const int *comm_int) const noexcept
Definition AMReX_ParticleTile.H:610
int m_num_runtime_real
Definition AMReX_ParticleTile.H:604
static constexpr int NStructInt
Definition AMReX_ParticleTile.H:526
const int *__restrict__ *__restrict__ m_runtime_idata
Definition AMReX_ParticleTile.H:607
ParticleReal RealType
Definition AMReX_ParticleTile.H:522
__host__ __device__ SuperParticleType getSuperParticle(int index) const noexcept
Definition AMReX_ParticleTile.H:668
__host__ __device__ decltype(auto) pos(const int dir, const int index) const &
Definition AMReX_ParticleTile.H:543
__host__ __device__ decltype(auto) cpu(const int index) const &
Definition AMReX_ParticleTile.H:563
int m_num_runtime_int
Definition AMReX_ParticleTile.H:605
std::conditional_t< T_ParticleType::is_soa_particle, void const *__restrict__, ParticleType const *__restrict__ > AOS_PTR
Definition AMReX_ParticleTile.H:535
T_ParticleType const & ParticleRefType
Definition AMReX_ParticleTile.H:521
static constexpr int NAR
Definition AMReX_ParticleTile.H:518
AOS_PTR m_aos
Definition AMReX_ParticleTile.H:536
const uint64_t * m_idcpu
Definition AMReX_ParticleTile.H:538
__host__ __device__ const ParticleReal * rdata(const int attribute_index) const
Definition AMReX_ParticleTile.H:583
GpuArray< const ParticleReal *, NArrayReal > m_rdata
Definition AMReX_ParticleTile.H:539
const ParticleReal *__restrict__ *__restrict__ m_runtime_rdata
Definition AMReX_ParticleTile.H:606
Definition AMReX_ParticleTile.H:327
__host__ __device__ ConstParticleIDWrapper id() const
Definition AMReX_ParticleTile.H:353
static constexpr int NArrayReal
Definition AMReX_ParticleTile.H:328
ParticleReal RealType
Definition AMReX_ParticleTile.H:336
__host__ __device__ ConstSoAParticle(ConstPTD const &ptd, long i)
Definition AMReX_ParticleTile.H:340
static constexpr int NArrayInt
Definition AMReX_ParticleTile.H:329
static constexpr bool is_rtsoa_particle
Definition AMReX_ParticleTile.H:333
static void NextID(Long nextid)
Reset on restart.
static constexpr bool is_constsoa_particle
Definition AMReX_ParticleTile.H:334
static Long UnprotectedNextID()
This version can only be used inside omp critical.
__host__ __device__ const RealType & pos(int position_index) const &
Definition AMReX_ParticleTile.H:361
__host__ __device__ RealVect pos() const &
Definition AMReX_ParticleTile.H:358
__host__ __device__ ConstParticleCPUWrapper cpu() const
Definition AMReX_ParticleTile.H:350
int IntType
Definition AMReX_ParticleTile.H:337
Fixed-size array that can be used on GPU.
Definition AMReX_Array.H:52
Definition AMReX_GpuAllocators.H:173
Definition AMReX_GpuAllocators.H:184
uint64_t m_idcpu
Definition AMReX_Particle.H:359
Definition AMReX_Particle.H:259
Definition AMReX_Particle.H:154
Definition AMReX_ParticleTile.H:34
__host__ __device__ SuperParticleType getSuperParticle(int index) const noexcept
Definition AMReX_ParticleTile.H:241
T_ParticleType & ParticleRefType
Definition AMReX_ParticleTile.H:39
__host__ __device__ decltype(auto) cpu(const int index) const &
Definition AMReX_ParticleTile.H:87
uint64_t * m_idcpu
Definition AMReX_ParticleTile.H:57
GpuArray< ParticleReal *, NAR > m_rdata
Definition AMReX_ParticleTile.H:58
__host__ __device__ void unpackParticleData(const char *buffer, Long src_offset, int dst_index, const int *comm_real, const int *comm_int) const noexcept
Definition AMReX_ParticleTile.H:183
__host__ __device__ decltype(auto) idcpu(const int index) const &
Definition AMReX_ParticleTile.H:97
__host__ __device__ ParticleReal * rdata(const int attribute_index) const
Definition AMReX_ParticleTile.H:107
__host__ __device__ void packParticleData(char *buffer, int src_index, std::size_t dst_offset, const int *comm_real, const int *comm_int) const noexcept
Definition AMReX_ParticleTile.H:129
static constexpr int NStructInt
Definition AMReX_ParticleTile.H:45
GpuArray< int *, NAI > m_idata
Definition AMReX_ParticleTile.H:59
ParticleReal RealType
Definition AMReX_ParticleTile.H:41
__host__ __device__ void setSuperParticle(const SuperParticleType &sp, int index) const noexcept
Definition AMReX_ParticleTile.H:311
__host__ __device__ decltype(auto) pos(const int dir, const int index) const &
Definition AMReX_ParticleTile.H:67
T_ParticleType ParticleType
Definition AMReX_ParticleTile.H:38
__host__ __device__ SuperParticleType getSuperParticle(int index) const noexcept
Definition AMReX_ParticleTile.H:271
std::conditional_t< T_ParticleType::is_soa_particle, void *__restrict__, ParticleType *__restrict__ > AOS_PTR
Definition AMReX_ParticleTile.H:54
__host__ __device__ void setSuperParticle(const SuperParticleType &sp, int index) const noexcept
Definition AMReX_ParticleTile.H:288
int m_num_runtime_int
Definition AMReX_ParticleTile.H:62
Long m_size
Definition AMReX_ParticleTile.H:51
static constexpr int NAR
Definition AMReX_ParticleTile.H:35
int IntType
Definition AMReX_ParticleTile.H:42
ParticleReal *__restrict__ *__restrict__ m_runtime_rdata
Definition AMReX_ParticleTile.H:63
int m_num_runtime_real
Definition AMReX_ParticleTile.H:61
static constexpr bool is_particle_tile_data
Definition AMReX_ParticleTile.H:49
__host__ __device__ int * idata(const int attribute_index) const
Definition AMReX_ParticleTile.H:113
AOS_PTR m_aos
Definition AMReX_ParticleTile.H:55
static constexpr int NAI
Definition AMReX_ParticleTile.H:36
int *__restrict__ *__restrict__ m_runtime_idata
Definition AMReX_ParticleTile.H:64
static constexpr int NStructReal
Definition AMReX_ParticleTile.H:44
Definition AMReX_ParticleTile.H:764
typename ParticleType::StorageParticleType StorageParticleType
Definition AMReX_ParticleTile.H:790
int NumRealComps() const noexcept
Definition AMReX_ParticleTile.H:1196
void push_back_real(int comp, amrex::Vector< amrex::ParticleReal > const &vec)
Definition AMReX_ParticleTile.H:1127
int NumIntComps() const noexcept
Definition AMReX_ParticleTile.H:1198
typename ParticleType::RealType RealType
Definition AMReX_ParticleTile.H:771
ParticleTile()=default
int getNumNeighbors() const
Definition AMReX_ParticleTile.H:1010
typename AoS::ParticleVector ParticleVector
Definition AMReX_ParticleTile.H:782
ParticleTile(ParticleTile const &)=delete
std::conditional_t< ParticleType::is_soa_particle, StructOfArrays< NArrayReal, NArrayInt, Allocator, true >, StructOfArrays< NArrayReal, NArrayInt, Allocator, false > > SoA
Definition AMReX_ParticleTile.H:787
const SoA & GetStructOfArrays() const
Definition AMReX_ParticleTile.H:932
static constexpr int NAI
Definition AMReX_ParticleTile.H:770
ParticleTile(ParticleTile &&) noexcept=default
void push_back_real(int comp, const ParticleReal *beg, const ParticleReal *end)
Definition AMReX_ParticleTile.H:1109
static constexpr int NStructInt
Definition AMReX_ParticleTile.H:774
void setNumNeighbors(int num_neighbors)
Definition AMReX_ParticleTile.H:1001
Long capacity() const
Definition AMReX_ParticleTile.H:1225
int numTotalParticles() const
Returns the total number of particles, real and neighbor.
Definition AMReX_ParticleTile.H:992
std::size_t size() const
Returns the total number of particles (real and neighbor)
Definition AMReX_ParticleTile.H:940
static constexpr bool has_polymorphic_allocator
Definition AMReX_ParticleTile.H:795
ParticleTileDataType getParticleTileData()
Definition AMReX_ParticleTile.H:1269
void reserve(std::size_t capacity, GrowthStrategy strategy=GrowthStrategy::Poisson)
Definition AMReX_ParticleTile.H:1029
void push_back(const ParticleType &p)
Definition AMReX_ParticleTile.H:1041
int numNeighborParticles() const
Returns the number of neighbor particles (excluding reals)
Definition AMReX_ParticleTile.H:979
~ParticleTile()=default
const AoS & GetArrayOfStructs() const
Definition AMReX_ParticleTile.H:929
static constexpr int NAR
Definition AMReX_ParticleTile.H:769
ConstParticleTileDataType getConstParticleTileData() const
Definition AMReX_ParticleTile.H:1303
void shrink_to_fit()
Definition AMReX_ParticleTile.H:1204
T_ParticleType ParticleType
Definition AMReX_ParticleTile.H:768
int numParticles() const
Returns the number of real particles (excluding neighbors)
Definition AMReX_ParticleTile.H:953
void push_back_int(int comp, amrex::Vector< int > const &vec)
Definition AMReX_ParticleTile.H:1182
void resize(std::size_t count, GrowthStrategy strategy=GrowthStrategy::Poisson)
Definition AMReX_ParticleTile.H:1020
void swap(ParticleTile< ParticleType, NArrayReal, NArrayInt, Allocator > &other) noexcept
Definition AMReX_ParticleTile.H:1247
void push_back_int(int comp, amrex::Vector< int >::const_iterator beg, amrex::Vector< int >::const_iterator end)
Definition AMReX_ParticleTile.H:1174
void push_back_real(const std::array< ParticleReal, NArrayReal > &v)
Definition AMReX_ParticleTile.H:1099
int NumRuntimeRealComps() const noexcept
Definition AMReX_ParticleTile.H:1200
void collectVectors(Vector< ParticleVector * > &pv, Vector< typename SoA::IdCPU * > &idcpuv, Vector< RealVector * > &rv, Vector< IntVector * > &iv)
Definition AMReX_ParticleTile.H:1337
AoS & GetArrayOfStructs()
Definition AMReX_ParticleTile.H:928
RealType & pos(int index, int position_index) &
Definition AMReX_ParticleTile.H:905
typename SoA::IntVector IntVector
Definition AMReX_ParticleTile.H:789
void push_back_int(const std::array< int, NArrayInt > &v)
Definition AMReX_ParticleTile.H:1154
void push_back_real(int comp, amrex::Vector< amrex::ParticleReal >::const_iterator beg, amrex::Vector< amrex::ParticleReal >::const_iterator end)
Definition AMReX_ParticleTile.H:1119
Allocator< T > AllocatorType
Definition AMReX_ParticleTile.H:766
int NumRuntimeIntComps() const noexcept
Definition AMReX_ParticleTile.H:1202
bool empty() const
Definition AMReX_ParticleTile.H:934
void push_back_int(int comp, int v)
Definition AMReX_ParticleTile.H:1145
RealType pos(int index, int position_index) const &
Definition AMReX_ParticleTile.H:919
decltype(auto) cpu(int index) &
Definition AMReX_ParticleTile.H:887
void define(int a_num_runtime_real, int a_num_runtime_int, std::vector< std::string > *soa_rdata_names=nullptr, std::vector< std::string > *soa_idata_names=nullptr, Arena *a_arena=nullptr)
Definition AMReX_ParticleTile.H:810
SoA & GetStructOfArrays()
Definition AMReX_ParticleTile.H:931
void push_back_int(int comp, std::size_t npar, int v)
Definition AMReX_ParticleTile.H:1190
void push_back_real(int comp, std::size_t npar, ParticleReal v)
Definition AMReX_ParticleTile.H:1135
void push_back_int(int comp, const int *beg, const int *end)
Definition AMReX_ParticleTile.H:1164
typename SoA::RealVector RealVector
Definition AMReX_ParticleTile.H:788
int numRealParticles() const
Returns the number of real particles (excluding neighbors)
Definition AMReX_ParticleTile.H:966
std::conditional_t< ParticleType::is_soa_particle, ThisParticleTileHasNoAoS, ArrayOfStructs< ParticleType, Allocator > > AoS
Definition AMReX_ParticleTile.H:781
void push_back(const SuperParticleType &sp)
Definition AMReX_ParticleTile.H:1051
static constexpr int NStructReal
Definition AMReX_ParticleTile.H:773
void push_back_real(int comp, ParticleReal v)
Definition AMReX_ParticleTile.H:1090
static void reserve(std::map< ParticleTile< T_ParticleType, NArrayReal, NArrayInt, Allocator > *, int > const &addsizes)
Definition AMReX_ParticleTile.H:1350
The struct used to store particles.
Definition AMReX_Particle.H:405
__host__ __device__ RealVect pos() const &
Definition AMReX_Particle.H:456
__host__ __device__ int & idata(int index) &
Definition AMReX_Particle.H:538
__host__ __device__ ParticleCPUWrapper cpu() &
Definition AMReX_Particle.H:424
__host__ __device__ RealType & rdata(int index) &
Definition AMReX_Particle.H:473
__host__ __device__ ParticleIDWrapper id() &
Definition AMReX_Particle.H:427
Definition AMReX_ParticleTile.H:722
RuntimePtrCacheDirtyFlag(RuntimePtrCacheDirtyFlag &&) noexcept
Definition AMReX_ParticleTile.H:731
RuntimePtrCacheDirtyFlag() noexcept=default
void store(bool value, std::memory_order order=std::memory_order_seq_cst) noexcept
Definition AMReX_ParticleTile.H:747
bool load(std::memory_order order=std::memory_order_seq_cst) const noexcept
Definition AMReX_ParticleTile.H:752
RuntimePtrCacheDirtyFlag & operator=(RuntimePtrCacheDirtyFlag const &) noexcept
Definition AMReX_ParticleTile.H:735
Definition AMReX_Particle.H:388
Definition AMReX_ParticleTile.H:391
static constexpr int NArrayReal
Definition AMReX_ParticleTile.H:392
ParticleTileData< SoAParticleBase, NArrayReal, NArrayInt > PTD
Definition AMReX_ParticleTile.H:395
__host__ __device__ uint64_t & idcpu() &
Definition AMReX_ParticleTile.H:421
static Long UnprotectedNextID()
This version can only be used inside omp critical.
Definition AMReX_ParticleTile.H:499
__host__ __device__ ConstParticleCPUWrapper cpu() const &
Definition AMReX_ParticleTile.H:424
static Long the_next_id
Definition AMReX_ParticleTile.H:410
static constexpr int NArrayInt
Definition AMReX_ParticleTile.H:393
__host__ __device__ const uint64_t & idcpu() const &
Definition AMReX_ParticleTile.H:430
__host__ __device__ RealVect pos() const &
Definition AMReX_ParticleTile.H:435
ParticleReal RealType
Definition AMReX_ParticleTile.H:401
__host__ __device__ ParticleCPUWrapper cpu() &
Definition AMReX_ParticleTile.H:415
__host__ __device__ ParticleIDWrapper id() &
Definition AMReX_ParticleTile.H:418
static constexpr bool is_constsoa_particle
Definition AMReX_ParticleTile.H:398
__host__ __device__ RealType & pos(int position_index) &
Definition AMReX_ParticleTile.H:438
static constexpr bool is_rtsoa_particle
Definition AMReX_ParticleTile.H:397
int IntType
Definition AMReX_ParticleTile.H:402
__host__ __device__ SoAParticle(PTD const &ptd, long i)
Definition AMReX_ParticleTile.H:405
__host__ __device__ ConstParticleIDWrapper id() const &
Definition AMReX_ParticleTile.H:427
static Long NextID()
Definition AMReX_ParticleTile.H:478
__host__ __device__ RealType pos(int position_index) const &
Definition AMReX_ParticleTile.H:445
Definition AMReX_StructOfArrays.H:20
Definition AMReX_ParticleTile.H:717
Definition AMReX_ParticleTile.H:715
Definition AMReX_MakeParticle.H:13