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