Block-Structured AMR Software Framework
 
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Loading...
Searching...
No Matches
AMReX_NeighborParticlesCPUImpl.H
Go to the documentation of this file.
1#ifndef AMREX_NEIGHBORPARTICLESCPUIMPL_H_
2#define AMREX_NEIGHBORPARTICLESCPUIMPL_H_
3#include <AMReX_Config.H>
4
5namespace amrex {
6
7template <int NStructReal, int NStructInt, int NArrayReal, int NArrayInt>
8void
9NeighborParticleContainer<NStructReal, NStructInt, NArrayReal, NArrayInt>
10::fillNeighborsCPU () {
11 BL_PROFILE("NeighborParticleContainer::fillNeighborsCPU");
12 if (!areMasksValid()) {
13 BuildMasks();
14 GetNeighborCommTags();
15 }
16 cacheNeighborInfo();
17 updateNeighborsCPU(false);
18}
19
20template <int NStructReal, int NStructInt, int NArrayReal, int NArrayInt>
21void
22NeighborParticleContainer<NStructReal, NStructInt, NArrayReal, NArrayInt>
23::sumNeighborsCPU (int real_start_comp, int real_num_comp,
24 int int_start_comp, int int_num_comp)
25{
26 BL_PROFILE("NeighborParticleContainer::sumNeighborsCPU");
27
28 if ( ! enableInverse() )
29 {
30 amrex::Abort("Need to enable inverse to true to use sumNeighbors. \n");
31 }
32
34
35 std::map<int, Vector<char> > isend_data;
36
37 for (int lev = 0; lev < this->numLevels(); ++lev)
38 {
39 for (MyParIter pti(*this, lev); pti.isValid(); ++pti)
40 {
41 PairIndex src_index(pti.index(), pti.LocalTileIndex());
42 const auto& tags = inverse_tags[lev][src_index];
43 const auto& neighbs = neighbors[lev][src_index].GetArrayOfStructs();
44 AMREX_ASSERT(tags.size() == neighbs.size());
45
46 const int num_neighbs = neighbs.size();
47 for (int i = 0; i < num_neighbs; ++i)
48 {
49 const auto& neighb = neighbs[i];
50 const auto& tag = tags[i];
51 const int dst_grid = tag.src_grid;
52 const int global_rank = this->ParticleDistributionMap(lev)[dst_grid];
53 const int dst_proc = ParallelContext::global_to_local_rank(global_rank);
54 const int dst_tile = tag.src_tile;
55 const int dst_index = tag.src_index;
56 const int dst_level = tag.src_level;
57
58 if (dst_proc == MyProc)
59 {
60 auto pair = std::make_pair(dst_grid, dst_tile);
61 auto& dst_ptile = this->GetParticles(dst_level)[pair];
62 auto& dst_parts = dst_ptile.GetArrayOfStructs();
63 auto& p = dst_parts[dst_index];
64
65 for (int comp = real_start_comp; comp < real_start_comp + real_num_comp; ++comp)
66 {
67 p.rdata(comp) += neighb.rdata(comp);
68 }
69
70 for (int comp = int_start_comp; comp < int_start_comp + int_num_comp; ++comp)
71 {
72 p.idata(comp) += neighb.idata(comp);
73 }
74 }
75
76 else
77 {
78 auto& sdata = isend_data[dst_proc];
79 auto old_size = sdata.size();
80 auto new_size = old_size + real_num_comp*sizeof(Real) + int_num_comp*sizeof(int) + 4*sizeof(int);
81 sdata.resize(new_size);
82 char* dst = &sdata[old_size];
83 std::memcpy(dst, &dst_grid, sizeof(int)); dst += sizeof(int);
84 std::memcpy(dst, &dst_tile, sizeof(int)); dst += sizeof(int);
85 std::memcpy(dst, &dst_index, sizeof(int)); dst += sizeof(int);
86 std::memcpy(dst, &dst_level, sizeof(int)); dst += sizeof(int);
87 for (int comp = real_start_comp; comp < real_start_comp + real_num_comp; ++comp)
88 {
89 Real data = neighb.rdata(comp);
90 std::memcpy(dst, &data, sizeof(Real));
91 dst += sizeof(Real);
92 }
93 for (int comp = int_start_comp; comp < int_start_comp + int_num_comp; ++comp)
94 {
95 int data = neighb.idata(comp);
96 std::memcpy(dst, &data, sizeof(int));
97 dst += sizeof(int);
98 }
99 }
100 }
101 }
102 }
103
104 sumNeighborsMPI(isend_data, real_start_comp, real_num_comp, int_start_comp, int_num_comp);
105}
106
107template <int NStructReal, int NStructInt, int NArrayReal, int NArrayInt>
108void
110sumNeighborsMPI (std::map<int, Vector<char> >& not_ours,
111 int real_start_comp, int real_num_comp,
112 int int_start_comp, int int_num_comp)
113{
114 BL_PROFILE("NeighborParticleContainer::sumNeighborsMPI");
115
116#ifdef AMREX_USE_MPI
117 const int NProcs = ParallelContext::NProcsSub();
118
119 Vector<Long> isnds(NProcs, 0);
120 Vector<Long> ircvs(NProcs, 0);
121 for (int i = 0; i < NProcs; ++i) {
122 ircvs[i] = 0;
123 }
124
125 {
126 // each proc figures out how many bytes it will send, and how
127 // many it will receive
128
129 Long num_isnds = 0;
130 for (const auto& kv : not_ours)
131 {
132 num_isnds += kv.second.size();
133 isnds[kv.first] = kv.second.size();
134 }
135
137
138 if (num_isnds == 0) { return; }
139
140 const int num_ircvs = neighbor_procs.size();
141 Vector<MPI_Status> stats(num_ircvs);
142 Vector<MPI_Request> rreqs(num_ircvs);
143
144 const int SeqNum = ParallelDescriptor::SeqNum();
145
146 // Post receives
147 for (int i = 0; i < num_ircvs; ++i)
148 {
149 const int Who = neighbor_procs[i];
150 const Long Cnt = 1;
151
152 AMREX_ASSERT(Who >= 0 && Who < NProcs);
153
154 rreqs[i] = ParallelDescriptor::Arecv(&ircvs[Who], Cnt, Who, SeqNum,
156 }
157
158 // Send.
159 for (int i = 0; i < num_ircvs; ++i) {
160 const int Who = neighbor_procs[i];
161 const Long Cnt = 1;
162
163 AMREX_ASSERT(Who >= 0 && Who < NProcs);
164
165 ParallelDescriptor::Send(&isnds[Who], Cnt, Who, SeqNum,
167 }
168
169 if (num_ircvs > 0) { ParallelDescriptor::Waitall(rreqs, stats); }
170 }
171
172 Vector<int> RcvProc;
173 Vector<std::size_t> rOffset; // Offset (in bytes) in the receive buffer
174 std::size_t TotRcvBytes = 0;
175 for (int i = 0; i < NProcs; ++i) {
176 if (ircvs[i] > 0) {
177 RcvProc.push_back(i);
178 rOffset.push_back(TotRcvBytes);
179 TotRcvBytes += ircvs[i];
180 }
181 }
182
183 const auto nrcvs = int(RcvProc.size());
184 Vector<MPI_Status> stats(nrcvs);
185 Vector<MPI_Request> rreqs(nrcvs);
186
187 const int SeqNum = ParallelDescriptor::SeqNum();
188
189 // Allocate data for rcvs as one big chunk.
190 Vector<char> recvdata(TotRcvBytes);
191
192 // Post receives.
193 for (int i = 0; i < nrcvs; ++i) {
194 const auto Who = RcvProc[i];
195 const auto offset = rOffset[i];
196 const auto Cnt = ircvs[Who];
197
198 AMREX_ASSERT(Cnt > 0);
199 AMREX_ASSERT(Cnt < std::numeric_limits<int>::max());
200 AMREX_ASSERT(Who >= 0 && Who < NProcs);
201
202 rreqs[i] = ParallelDescriptor::Arecv(&recvdata[offset], Cnt, Who, SeqNum,
204 }
205
206 // Send.
207 for (const auto& kv : not_ours) {
208 const auto Who = kv.first;
209 const auto Cnt = kv.second.size();
210
211 AMREX_ASSERT(Cnt > 0);
212 AMREX_ASSERT(Who >= 0 && Who < NProcs);
213 AMREX_ASSERT(Cnt < std::numeric_limits<int>::max());
214
215 ParallelDescriptor::Send(kv.second.data(), Cnt, Who, SeqNum,
217 }
218
219 // unpack the received data and put them into the proper neighbor buffers
220 if (nrcvs > 0)
221 {
222 ParallelDescriptor::Waitall(rreqs, stats);
223
224 const size_t data_size = real_num_comp*sizeof(Real) + int_num_comp*sizeof(int) + 4 * sizeof(int);
225
226 if (recvdata.size() % data_size != 0) {
227 amrex::Print() << recvdata.size() << " " << data_size << "\n";
228 if (this->m_verbose) {
229 amrex::AllPrint() << "NeighborParticles::sumNeighbors: sizes = "
230 << recvdata.size() << ", " << data_size << "\n";
231 }
232 amrex::Abort("NeighborParticles::sumNeighbors: How did this happen?");
233 }
234
235 auto npart = int(recvdata.size() / data_size);
236
237 char* buffer = recvdata.data();
238 for (int j = 0; j < npart; ++j)
239 {
240 int grid, tile, index, lev;
241 std::memcpy(&grid, buffer, sizeof(int)); buffer += sizeof(int);
242 std::memcpy(&tile, buffer, sizeof(int)); buffer += sizeof(int);
243 std::memcpy(&index, buffer, sizeof(int)); buffer += sizeof(int);
244 std::memcpy(&lev, buffer, sizeof(int)); buffer += sizeof(int);
245
246 auto pair = std::make_pair(grid, tile);
247 auto& ptile = this->GetParticles(lev)[pair];
248 auto& parts = ptile.GetArrayOfStructs();
249 auto& p = parts[index];
250
251 for (int comp = real_start_comp; comp < real_start_comp + real_num_comp; ++comp)
252 {
253 Real data;
254 std::memcpy(&data, buffer, sizeof(Real));
255 p.rdata(comp) += data;
256 buffer += sizeof(Real);
257 }
258
259 for (int comp = int_start_comp; comp < int_start_comp + int_num_comp; ++comp)
260 {
261 int data;
262 std::memcpy(&data, buffer, sizeof(int));
263 p.idata(comp) += data;
264 buffer += sizeof(int);
265 }
266 }
267 }
268#else
269 amrex::ignore_unused(not_ours, real_start_comp, real_num_comp, int_start_comp, int_num_comp);
270#endif
271}
272
273template <int NStructReal, int NStructInt, int NArrayReal, int NArrayInt>
274void
276::updateNeighborsCPU (bool reuse_rcv_counts) {
277
278 BL_PROFILE_VAR("NeighborParticleContainer::updateNeighborsCPU", update);
279
280 const int MyProc = ParallelContext::MyProcSub();
281
282 for (int lev = 0; lev < this->numLevels(); ++lev) {
283 const Periodicity& periodicity = this->Geom(lev).periodicity();
284 const RealBox& prob_domain = this->Geom(lev).ProbDomain();
285
286 int num_threads = OpenMP::get_max_threads();
287
288 for (MyParIter pti(*this, lev); pti.isValid(); ++pti) {
289 PairIndex src_index(pti.index(), pti.LocalTileIndex());
290 auto src = pti.GetParticleTile().getParticleTileData();
291 for (int j = 0; j < num_threads; ++j) {
292 auto& tags = buffer_tag_cache[lev][src_index][j];
293 int num_tags = tags.size();
294#ifdef AMREX_USE_OMP
295#pragma omp parallel for
296#endif
297 for (int i = 0; i < num_tags; ++i) {
298 const NeighborCopyTag& tag = tags[i];
299 const int global_who = this->ParticleDistributionMap(tag.level)[tag.grid];
300 const int who = ParallelContext::global_to_local_rank(global_who);
301 if (who == MyProc) {
302 PairIndex dst_index(tag.grid, tag.tile);
303 auto dst = neighbors[tag.level][dst_index].getParticleTileData();
304 copyParticle(dst, src, tag.src_index, tag.dst_index);
305 if (periodicity.isAnyPeriodic()) {
306 auto& aos = neighbors[tag.level][dst_index].GetArrayOfStructs();
307 ParticleType& p = aos[tag.dst_index];
308 for (int dir = 0; dir < AMREX_SPACEDIM; ++dir) {
309 if (! periodicity.isPeriodic(dir)) { continue; }
310 if (tag.periodic_shift[dir] < 0) {
311 p.pos(dir) += static_cast<ParticleReal> (prob_domain.length(dir));
312 } else if (tag.periodic_shift[dir] > 0) {
313 p.pos(dir) -= static_cast<ParticleReal> (prob_domain.length(dir));
314 }
315 }
316 }
317
318 if ( enableInverse() )
319 {
320 auto& itags = inverse_tags[tag.level][dst_index];
321 AMREX_ASSERT(tag.dst_index < itags.size());
322 itags[tag.dst_index].src_grid = src_index.first;
323 itags[tag.dst_index].src_tile = src_index.second;
324 itags[tag.dst_index].src_index = tag.src_index;
325 itags[tag.dst_index].src_level = lev;
326 }
327 } else {
328 auto& aos = pti.GetArrayOfStructs();
329 auto& soa = pti.GetStructOfArrays();
330 ParticleType p = aos[tag.src_index]; // copy
331 if (periodicity.isAnyPeriodic()) {
332 for (int dir = 0; dir < AMREX_SPACEDIM; ++dir) {
333 if (! periodicity.isPeriodic(dir)) { continue; }
334 if (tag.periodic_shift[dir] < 0) {
335 p.pos(dir) += static_cast<ParticleReal> (prob_domain.length(dir));
336 } else if (tag.periodic_shift[dir] > 0) {
337 p.pos(dir) -= static_cast<ParticleReal> (prob_domain.length(dir));
338 }
339 }
340 }
341
342 char* dst_ptr = &send_data[who][tag.dst_index];
343 char* src_ptr = (char *) &p;
344 for (int ii = 0; ii < AMREX_SPACEDIM + NStructReal; ++ii) {
345 if (ghost_real_comp[ii]) {
346 std::memcpy(dst_ptr, src_ptr, sizeof(typename ParticleType::RealType));
347 dst_ptr += sizeof(typename ParticleType::RealType);
348 }
349 src_ptr += sizeof(typename ParticleType::RealType);
350 }
351 for (int ii = 0; ii < this->NumRealComps(); ++ii) {
352 if (ghost_real_comp[ii+AMREX_SPACEDIM+NStructReal])
353 {
354 std::memcpy(dst_ptr, &(soa.GetRealData(ii)[tag.src_index]),
355 sizeof(typename ParticleType::RealType));
356 dst_ptr += sizeof(typename ParticleType::RealType);
357 }
358 }
359 for (int ii = 0; ii < 2 + NStructInt; ++ii) {
360 if (ghost_int_comp[ii]) {
361 std::memcpy(dst_ptr, src_ptr, sizeof(int));
362 dst_ptr += sizeof(int);
363 }
364 src_ptr += sizeof(int);
365 }
366 for (int ii = 0; ii < this->NumIntComps(); ++ii) {
367 if (ghost_int_comp[ii+2+NStructInt])
368 {
369 std::memcpy(dst_ptr, &(soa.GetIntData(ii)[tag.src_index]),
370 sizeof(int));
371 dst_ptr += sizeof(int);
372 }
373 }
374 if ( enableInverse() )
375 {
376 std::memcpy(dst_ptr,&(src_index.first),sizeof(int)); dst_ptr += sizeof(int);
377 std::memcpy(dst_ptr,&(src_index.second),sizeof(int)); dst_ptr += sizeof(int);
378 std::memcpy(dst_ptr,&(tag.src_index),sizeof(int)); dst_ptr += sizeof(int);
379 std::memcpy(dst_ptr,&(lev),sizeof(int)); dst_ptr += sizeof(int);
380 }
381 }
382 }
383 }
384 }
385
386#ifdef AMREX_USE_OMP
387#pragma omp parallel
388#endif
389 for (MFIter mfi = this->MakeMFIter(lev); mfi.isValid(); ++mfi) {
390 const int grid = mfi.index();
391 const int tile = mfi.LocalTileIndex();
392 PairIndex dst_index(grid, tile);
393 neighbors[lev][dst_index].resize(local_neighbor_sizes[lev][dst_index]);
394 if ( enableInverse() ) {
395 inverse_tags[lev][dst_index].resize(local_neighbor_sizes[lev][dst_index]);
396 }
397 }
398 }
399 BL_PROFILE_VAR_STOP(update);
400
401 fillNeighborsMPI(reuse_rcv_counts);
402
403 for (int lev = 0; lev < this->numLevels(); ++lev)
404 {
405 for(MFIter mfi = this->MakeMFIter(lev); mfi.isValid(); ++mfi)
406 {
407 int src_grid = mfi.index();
408 int src_tile = mfi.LocalTileIndex();
409 auto index = std::make_pair(src_grid, src_tile);
410 auto& ptile = this->GetParticles(lev)[index];
411 ptile.setNumNeighbors(neighbors[lev][index].size());
412 amrex::copyParticles(ptile, neighbors[lev][index], 0,
413 ptile.numRealParticles(), ptile.numNeighborParticles());
414 }
415 }
416
417}
418
419template <int NStructReal, int NStructInt, int NArrayReal, int NArrayInt>
420void
421NeighborParticleContainer<NStructReal, NStructInt, NArrayReal, NArrayInt>
422::clearNeighborsCPU ()
423{
424 BL_PROFILE("NeighborParticleContainer::clearNeighborsCPU");
425
426 resizeContainers(this->numLevels());
427 for (int lev = 0; lev < this->numLevels(); ++lev) {
428 neighbors[lev].clear();
429 if ( enableInverse() ) { inverse_tags[lev].clear(); }
430 buffer_tag_cache[lev].clear();
431
432 for(MFIter mfi = this->MakeMFIter(lev); mfi.isValid(); ++mfi)
433 {
434 int src_grid = mfi.index();
435 int src_tile = mfi.LocalTileIndex();
436 auto index = std::make_pair(src_grid, src_tile);
437 auto& ptile = this->GetParticles(lev)[index];
438 ptile.setNumNeighbors(0);
439 }
440 }
441
442 send_data.clear();
443}
444
445template <int NStructReal, int NStructInt, int NArrayReal, int NArrayInt>
446void
449
450 BL_PROFILE("NeighborParticleContainer::getRcvCountsMPI");
451
452#ifdef AMREX_USE_MPI
453 const int NProcs = ParallelContext::NProcsSub();
454
455 // each proc figures out how many bytes it will send, and how
456 // many it will receive
457 Vector<Long> snds(NProcs, 0);
458 rcvs.resize(NProcs);
459 for (int i = 0; i < NProcs; ++i) {
460 rcvs[i] = 0;
461 }
462
463 num_snds = 0;
464 for (const auto& kv : send_data) {
465 num_snds += kv.second.size();
466 snds[kv.first] = kv.second.size();
467 }
468
470
471 if (num_snds == 0) { return; }
472
473 const int num_rcvs = neighbor_procs.size();
474 Vector<MPI_Status> stats(num_rcvs);
475 Vector<MPI_Request> rreqs(num_rcvs);
476
477 const int SeqNum = ParallelDescriptor::SeqNum();
478
479 // Post receives
480 for (int i = 0; i < num_rcvs; ++i) {
481 const int Who = neighbor_procs[i];
482 const Long Cnt = 1;
483
484 AMREX_ASSERT(Who >= 0 && Who < NProcs);
485
486 rreqs[i] = ParallelDescriptor::Arecv(&rcvs[Who], Cnt, Who, SeqNum,
488 }
489
490 // Send.
491 for (int i = 0; i < num_rcvs; ++i) {
492 const int Who = neighbor_procs[i];
493 const Long Cnt = 1;
494
495 AMREX_ASSERT(Who >= 0 && Who < NProcs);
496
497 ParallelDescriptor::Send(&snds[Who], Cnt, Who, SeqNum,
499 }
500
501 if (num_rcvs > 0) { ParallelDescriptor::Waitall(rreqs, stats); }
502
503#endif // AMREX_USE_MPI
504}
505
506template <int NStructReal, int NStructInt, int NArrayReal, int NArrayInt>
507void
509fillNeighborsMPI (bool reuse_rcv_counts) {
510
511 BL_PROFILE("NeighborParticleContainer::fillNeighborsMPI");
512
513#ifdef AMREX_USE_MPI
514 const int NProcs = ParallelContext::NProcsSub();
515
516 // each proc figures out how many bytes it will send, and how
517 // many it will receive
518 if (!reuse_rcv_counts) { getRcvCountsMPI(); }
519 if (num_snds == 0) { return; }
520
521 Vector<int> RcvProc;
522 Vector<std::size_t> rOffset; // Offset (in bytes) in the receive buffer
523 std::size_t TotRcvBytes = 0;
524 for (int i = 0; i < NProcs; ++i) {
525 if (rcvs[i] > 0) {
526 RcvProc.push_back(i);
527 rOffset.push_back(TotRcvBytes);
528 TotRcvBytes += rcvs[i];
529 }
530 }
531
532 const auto nrcvs = int(RcvProc.size());
533 Vector<MPI_Status> stats(nrcvs);
534 Vector<MPI_Request> rreqs(nrcvs);
535
536 const int SeqNum = ParallelDescriptor::SeqNum();
537
538 // Allocate data for rcvs as one big chunk.
539 Vector<char> recvdata(TotRcvBytes);
540
541 // Post receives.
542 for (int i = 0; i < nrcvs; ++i) {
543 const auto Who = RcvProc[i];
544 const auto offset = rOffset[i];
545 const auto Cnt = rcvs[Who];
546
547 AMREX_ASSERT(Cnt > 0);
548 AMREX_ASSERT(Cnt < std::numeric_limits<int>::max());
549 AMREX_ASSERT(Who >= 0 && Who < NProcs);
550
551 rreqs[i] = ParallelDescriptor::Arecv(&recvdata[offset], Cnt, Who, SeqNum,
553 }
554
555 // Send.
556 for (const auto& kv : send_data) {
557 const auto Who = kv.first;
558 const auto Cnt = kv.second.size();
559
560 AMREX_ASSERT(Cnt > 0);
561 AMREX_ASSERT(Who >= 0 && Who < NProcs);
562 AMREX_ASSERT(Cnt < std::numeric_limits<int>::max());
563
564 ParallelDescriptor::Send(kv.second.data(), Cnt, Who, SeqNum);
565 }
566
567 // unpack the received data and put them into the proper neighbor buffers
568 if (nrcvs > 0) {
569 ParallelDescriptor::Waitall(rreqs, stats);
570 for (int i = 0; i < nrcvs; ++i) {
571 const auto offset = int(rOffset[i]);
572 char* buffer = &recvdata[offset];
573 int num_tiles, lev, gid, tid, size, np;
574 std::memcpy(&num_tiles, buffer, sizeof(int)); buffer += sizeof(int);
575 for (int j = 0; j < num_tiles; ++j) {
576 std::memcpy(&lev, buffer, sizeof(int)); buffer += sizeof(int);
577 std::memcpy(&gid, buffer, sizeof(int)); buffer += sizeof(int);
578 std::memcpy(&tid, buffer, sizeof(int)); buffer += sizeof(int);
579 std::memcpy(&size, buffer, sizeof(int)); buffer += sizeof(int);
580
581 if (size == 0) { continue; }
582
583 np = size / cdata_size;
584
585 AMREX_ASSERT(size % cdata_size == 0);
586
587 PairIndex dst_index(gid, tid);
588 size_t old_size = neighbors[lev][dst_index].size();
589 size_t new_size = neighbors[lev][dst_index].size() + np;
590 if ( enableInverse() )
591 {
592 AMREX_ASSERT(neighbors[lev][dst_index].size() ==
593 size_t(inverse_tags[lev][dst_index].size()));
594 inverse_tags[lev][dst_index].resize(new_size);
595 }
596 neighbors[lev][dst_index].resize(new_size);
597
598 char* src = buffer;
599 for (int n = 0; n < np; ++n) {
600 char* dst_aos = (char*) &neighbors[lev][dst_index].GetArrayOfStructs()[old_size+n];
601 auto& dst_soa = neighbors[lev][dst_index].GetStructOfArrays();
602 for (int ii = 0; ii < AMREX_SPACEDIM + NStructReal; ++ii) {
603 if (ghost_real_comp[ii]) {
604 std::memcpy(dst_aos, src, sizeof(typename ParticleType::RealType));
605 src += sizeof(typename ParticleType::RealType);
606 }
607 dst_aos += sizeof(typename ParticleType::RealType);
608 }
609 for (int ii = 0; ii < this->NumRealComps(); ++ii) {
610 if (ghost_real_comp[ii+AMREX_SPACEDIM+NStructReal])
611 {
612 std::memcpy(&(dst_soa.GetRealData(ii)[old_size+n]),
613 src, sizeof(typename ParticleType::RealType));
614 src += sizeof(typename ParticleType::RealType);
615 }
616 }
617 for (int ii = 0; ii < 2 + NStructInt; ++ii) {
618 if (ghost_int_comp[ii]) {
619 std::memcpy(dst_aos, src, sizeof(int));
620 src += sizeof(int);
621 }
622 dst_aos += sizeof(int);
623 }
624 for (int ii = 0; ii < this->NumIntComps(); ++ii) {
625 if (ghost_int_comp[ii+2+NStructInt])
626 {
627 std::memcpy(&(dst_soa.GetIntData(ii)[old_size+n]),
628 src, sizeof(int));
629 src += sizeof(int);
630 }
631 }
632
633 if ( enableInverse() )
634 {
635 auto& tag = inverse_tags[lev][dst_index][old_size+n];
636 std::memcpy(&(tag.src_grid),src,sizeof(int));
637 src += sizeof(int);
638
639 std::memcpy(&(tag.src_tile),src,sizeof(int));
640 src += sizeof(int);
641
642 std::memcpy(&(tag.src_index),src,sizeof(int));
643 src += sizeof(int);
644
645 std::memcpy(&(tag.src_level),src,sizeof(int));
646 src += sizeof(int);
647 }
648 }
649 buffer += size;
650 }
651 }
652 }
653#else
654 amrex::ignore_unused(reuse_rcv_counts);
655#endif
656}
657
658}
659
660#endif
#define BL_PROFILE(a)
Definition AMReX_BLProfiler.H:551
#define BL_PROFILE_VAR_STOP(vname)
Definition AMReX_BLProfiler.H:563
#define BL_PROFILE_VAR(fname, vname)
Definition AMReX_BLProfiler.H:560
#define AMREX_ASSERT(EX)
Definition AMReX_BLassert.H:38
Array4< int const > offset
Definition AMReX_HypreMLABecLap.cpp:1089
Print on all processors of the default communicator.
Definition AMReX_Print.H:117
Definition AMReX_NeighborParticles.H:35
std::pair< int, int > PairIndex
Definition AMReX_NeighborParticles.H:196
void getRcvCountsMPI()
Definition AMReX_NeighborParticlesCPUImpl.H:448
void sumNeighborsMPI(std::map< int, Vector< char > > &not_ours, int real_start_comp, int real_num_comp, int int_start_comp, int int_num_comp)
Definition AMReX_NeighborParticlesCPUImpl.H:110
void fillNeighborsMPI(bool reuse_rcv_counts)
Definition AMReX_NeighborParticlesCPUImpl.H:509
MPI_Request req() const
Definition AMReX_ParallelDescriptor.H:74
This provides length of period for periodic domains. 0 means it is not periodic in that direction....
Definition AMReX_Periodicity.H:17
bool isAnyPeriodic() const noexcept
Definition AMReX_Periodicity.H:22
bool isPeriodic(int dir) const noexcept
Definition AMReX_Periodicity.H:26
This class provides the user with a few print options.
Definition AMReX_Print.H:35
A Box with real dimensions. A RealBox is OK iff volume >= 0.
Definition AMReX_RealBox.H:21
AMREX_GPU_HOST_DEVICE Real length(int dir) const noexcept
Returns length in specified direction.
Definition AMReX_RealBox.H:62
This class is a thin wrapper around std::vector. Unlike vector, Vector::operator[] provides bound che...
Definition AMReX_Vector.H:27
Long size() const noexcept
Definition AMReX_Vector.H:50
AMREX_GPU_HOST_DEVICE Long size(T const &b) noexcept
integer version
Definition AMReX_GpuRange.H:26
int MyProc()
Definition AMReX_MPMD.cpp:117
constexpr int get_max_threads()
Definition AMReX_OpenMP.H:36
void Max(KeyValuePair< K, V > &vi, MPI_Comm comm)
Definition AMReX_ParallelReduce.H:126
MPI_Comm CommunicatorSub() noexcept
sub-communicator for current frame
Definition AMReX_ParallelContext.H:70
int MyProcSub() noexcept
my sub-rank in current frame
Definition AMReX_ParallelContext.H:76
int global_to_local_rank(int rank) noexcept
Definition AMReX_ParallelContext.H:98
int NProcsSub() noexcept
number of ranks in current frame
Definition AMReX_ParallelContext.H:74
void Waitall(Vector< MPI_Request > &, Vector< MPI_Status > &)
Definition AMReX_ParallelDescriptor.cpp:1298
Message Send(const T *buf, size_t n, int dst_pid, int tag)
Definition AMReX_ParallelDescriptor.H:1109
int SeqNum() noexcept
Returns sequential message sequence numbers, usually used as tags for send/recv.
Definition AMReX_ParallelDescriptor.H:613
Message Arecv(T *, size_t n, int pid, int tag)
Definition AMReX_ParallelDescriptor.H:1130
Definition AMReX_Amr.cpp:49
void copyParticles(DstTile &dst, const SrcTile &src) noexcept
Copy particles from src to dst. This version copies all the particles, writing them to the beginning ...
Definition AMReX_ParticleTransformation.H:158
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void ignore_unused(const Ts &...)
This shuts up the compiler about unused variables.
Definition AMReX.H:127
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
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void copyParticle(const ParticleTileData< T_ParticleType, NAR, NAI > &dst, const ConstParticleTileData< T_ParticleType, NAR, NAI > &src, int src_i, int dst_i) noexcept
A general single particle copying routine that can run on the GPU.
Definition AMReX_ParticleTransformation.H:31