Block-Structured AMR Software Framework
Loading...
Searching...
No Matches
AMReX_FACopyDescriptor.H
Go to the documentation of this file.
1
2#ifndef BL_FACOPYDESCRIPTOR_H_
3#define BL_FACOPYDESCRIPTOR_H_
4#include <AMReX_Config.H>
5
6#include <AMReX_FabArray.H>
7#include <string>
8
14namespace amrex {
15
24
30{
31 public:
32
33 FillBoxId () = default;
34
35 FillBoxId (int newid, const Box& fillbox)
36 :
37 m_fillBox(fillbox),
38 m_fillBoxId(newid)
39 {}
40
42 [[nodiscard]] int Id () const { return m_fillBoxId; }
44 [[nodiscard]] int FabIndex () const { return m_fabIndex; }
46 void FabIndex (int fabindex) { m_fabIndex = fabindex; }
48 [[nodiscard]] const Box& box () const { return m_fillBox; }
49
50private:
51
52 Box m_fillBox;
53 int m_fillBoxId{-1};
54 int m_fabIndex{-1};
55};
56
62{
63public:
64
65 explicit FabArrayId (int newid = -1)
66 :
67 fabArrayId(newid) {}
68
69 [[nodiscard]] int Id () const { return fabArrayId; }
70
71 bool operator== (const FabArrayId& rhs) const
72 {
73 return fabArrayId == rhs.fabArrayId;
74 }
75
76private:
77
78 int fabArrayId;
79};
80
86template <class FAB>
110
111template <class FAB>
113 :
114 localFabSource(nullptr)
115
116{}
117
118template <class FAB>
120{
121 if (cacheDataAllocated) {
122 delete localFabSource;
123 }
124}
125
132template <class FAB>
134{
135 using FCDMap = std::multimap<int,FabCopyDescriptor<FAB>*>;
136
137 using FCDMapValueType = typename FCDMap::value_type;
138 using FCDMapIter = typename FCDMap::iterator;
139 using FCDMapConstIter = typename FCDMap::const_iterator;
140
141public:
142
144
146
151
157
165 const Box& destFabBox,
166 BoxList* unfilledBoxes);
167
172 const Box& destFabBox,
173 BoxList* unfilledBoxes,
174 int srccomp,
175 int destcomp,
176 int numcomp);
189 const Box& destFabBox,
190 BoxList* unfilledBoxes,
191 int fabarrayindex,
192 int srccomp,
193 int destcomp,
194 int numcomp,
195 bool bUseValidBox = true);
196
198 void CollectData ();
199
201 void FillFab (FabArrayId faid,
202 const FillBoxId& fillboxid,
203 FAB& destFab);
204
206 void FillFab (FabArrayId faid,
207 const FillBoxId& fillboxid,
208 FAB& destFab,
209 const Box& destBox);
210
212 void PrintStats () const;
213
215 [[nodiscard]] bool DataAvailable () const { return dataAvailable; }
216
218 void clear ();
219
221 [[nodiscard]] int CurrentNFabArrays () const { return fabArrays.size(); }
222
224 [[nodiscard]] int nFabComTags () const { return fabComTagList.size(); }
225
227 [[nodiscard]] int nFabCopyDescs () const { return fabCopyDescList.size(); }
228
229private:
233 void AddBoxDoIt (FabArrayId fabarrayid,
234 const Box& destFabBox,
235 BoxList* returnedUnfilledBoxes,
236 int faindex,
237 int srccomp,
238 int destcomp,
239 int numcomp,
240 bool bUseValidBox,
241 BoxDomain& unfilledBoxDomain);
245 using FabComTagContainer = std::vector<FabArrayBase::FabComTag>;
246
247 using FabComTagIterContainer = std::vector<FabComTagContainer::const_iterator>;
251 std::vector<FabArray<FAB>*> fabArrays;
252 std::vector<FCDMap> fabCopyDescList;
253 FabComTagContainer fabComTagList;
254 int nextFillBoxId{0};
255 bool dataAvailable{false};
256};
257
258template <class FAB>
259FabArrayId
261{
262 BL_ASSERT(fabArrays.size() == fabCopyDescList.size());
263
264 FabArrayId result(fabArrays.size());
265
266 fabArrays.push_back(fabarray); /* Bump size() by one */
267
268 fabCopyDescList.push_back(FCDMap());
269
270 return result;
271}
272
273template <class FAB>
274void
276 const Box& destFabBox,
277 BoxList* returnedUnfilledBoxes,
278 int faindex,
279 int srccomp,
280 int destcomp,
281 int numcomp,
282 bool bUseValidBox,
283 BoxDomain& unfilledBoxDomain)
284{
285 const int myProc = ParallelDescriptor::MyProc();
286
287 FabArray<FAB>* fabArray = fabArrays[fabarrayid.Id()];
288
289 BL_ASSERT(faindex >= 0 && faindex < fabArray->size());
290
291 Box intersect = destFabBox;
292
293 if (bUseValidBox)
294 {
295 intersect &= fabArray->box(faindex);
296 }
297 else
298 {
299 intersect &= fabArray->fabbox(faindex);
300 }
301
302 if (intersect.ok())
303 {
304 auto* fcd = new FabCopyDescriptor<FAB>;
305
306 int remoteProc = fabArray->DistributionMap()[faindex];
307 if(remoteProc >= ParallelDescriptor::NProcs()) {
308 amrex::Abort("Bad remoteProc: "
309 + std::to_string(ParallelDescriptor::MyProc())
310 + ":: _in AddBoxDoIt: nProcs remoteProc = "
311 + std::to_string(ParallelDescriptor::NProcs())
312 + " " + std::to_string(remoteProc) + "\n");
313 }
314 fcd->fillBoxId = nextFillBoxId;
315 fcd->subBox = intersect;
316 fcd->myProc = myProc;
317 fcd->copyFromProc = remoteProc;
318 fcd->copyFromIndex = faindex;
319 fcd->srcComp = srccomp;
320 fcd->destComp = destcomp;
321 fcd->nComp = numcomp;
322
323 if (ParallelDescriptor::sameTeam(remoteProc))
324 {
325 //
326 // Data is local.
327 //
328 fcd->fillType = FillLocally;
329 fcd->localFabSource = &(*fabArray)[faindex];
330 }
331 else
332 {
333 //
334 // Data is remote.
335 //
336 FabArrayBase::FabComTag fabComTag;
337
338 dataAvailable = false;
339 fcd->fillType = FillRemotely;
340 fcd->localFabSource = new FAB(intersect, numcomp);
341 fcd->cacheDataAllocated = true;
342 fabComTag.fabArrayId = fabarrayid.Id();
343 fabComTag.fillBoxId = nextFillBoxId;
344 fabComTag.fabIndex = faindex;
345 fabComTag.procThatNeedsData = myProc;
346 fabComTag.procThatHasData = remoteProc;
347 fabComTag.box = intersect;
348 fabComTag.srcComp = srccomp;
349 fabComTag.destComp = destcomp;
350 fabComTag.nComp = numcomp;
351 //
352 // Do not send the data yet.
353 //
354 fabComTagList.push_back(fabComTag);
355 }
356
357 fabCopyDescList[fabarrayid.Id()].insert(FCDMapValueType(fcd->fillBoxId,fcd));
358
359 if (returnedUnfilledBoxes != nullptr)
360 {
361 unfilledBoxDomain.rmBox(intersect);
362 }
363 }
364}
365
366template <class FAB>
367FillBoxId
369 const Box& destFabBox,
370 BoxList* returnedUnfilledBoxes,
371 int srccomp,
372 int destcomp,
373 int numcomp)
374{
375 BoxDomain unfilledBoxDomain(destFabBox.ixType());
376
377 if (returnedUnfilledBoxes != nullptr)
378 {
379 unfilledBoxDomain.add(destFabBox);
380 }
381
382 std::vector< std::pair<int,Box> > isects;
383
384 fabArrays[fabarrayid.Id()]->boxArray().intersections(destFabBox,isects);
385
386 for (auto & isect : isects)
387 {
388 AddBoxDoIt(fabarrayid,
389 destFabBox,
390 returnedUnfilledBoxes,
391 isect.first,
392 srccomp,
393 destcomp,
394 numcomp,
395 true,
396 unfilledBoxDomain);
397 }
398
399 if (returnedUnfilledBoxes != nullptr)
400 {
401 returnedUnfilledBoxes->clear();
402 (*returnedUnfilledBoxes) = unfilledBoxDomain.boxList();
403 }
404
405 return FillBoxId(nextFillBoxId++, destFabBox);
406}
407
408template <class FAB>
411 const Box& destFabBox,
412 BoxList* returnedUnfilledBoxes,
413 int fabarrayindex,
414 int srccomp,
415 int destcomp,
416 int numcomp,
417 bool bUseValidBox)
418{
419 BoxDomain unfilledBoxDomain(destFabBox.ixType());
420
421 if (returnedUnfilledBoxes != nullptr)
422 {
423 unfilledBoxDomain.add(destFabBox);
424 }
425
426 AddBoxDoIt(fabarrayid,
427 destFabBox,
428 returnedUnfilledBoxes,
429 fabarrayindex,
430 srccomp,
431 destcomp,
432 numcomp,
433 bUseValidBox,
434 unfilledBoxDomain);
435
436 if (returnedUnfilledBoxes != nullptr)
437 {
438 returnedUnfilledBoxes->clear();
439 (*returnedUnfilledBoxes) = unfilledBoxDomain.boxList();
440 }
441
442 return FillBoxId(nextFillBoxId++, destFabBox);
443}
444
445template <class FAB>
448 const Box& destFabBox,
449 BoxList* returnedUnfilledBoxes)
450{
451 return AddBox(fabarrayid,
452 destFabBox,
453 returnedUnfilledBoxes,
454 0,
455 0,
456 fabArrays[fabarrayid.Id()]->nComp());
457}
458
459template <class FAB>
464
465template <class FAB>
466void
468{
469 for (unsigned int i = 0, N = fabCopyDescList.size(); i < N; ++i)
470 {
471 for (auto fmi = fabCopyDescList[i].begin(), End = fabCopyDescList[i].end();
472 fmi != End;
473 ++fmi)
474 {
475 delete (*fmi).second;
476 }
477 }
478
479 fabArrays.clear();
480 fabCopyDescList.clear();
481 fabComTagList.clear();
482
483 nextFillBoxId = 0;
484 dataAvailable = false;
485}
486
487template <class FAB>
488void
490{
491 dataAvailable = true;
492
493 if (ParallelContext::NProcsSub() == 1) { return; }
494
495#ifdef BL_USE_MPI
496 using value_type = typename FAB::value_type;
497
498 BL_PROFILE("FabArrayCopyDescriptor::CollectData()");
499
500 const int MyProc = ParallelDescriptor::MyProc();
501 amrex::ignore_unused(MyProc);
502
503 int Total_Rcvs_Size = 0;
504 //
505 // We use this to make finding matching FabComTags more efficient.
506 //
507 std::map< int,FabComTagIterContainer > RcvTags;
508
509 std::map<int,int> Snds, Rcvs, Npts;
510 //
511 // Set Rcvs[i] to # of blocks needed from CPU i
512 //
513 for (auto it = fabComTagList.begin(),
514 End = fabComTagList.end();
515 it != End;
516 ++it)
517 {
518 BL_ASSERT(it->box.ok());
519 BL_ASSERT(it->procThatNeedsData == MyProc);
520 BL_ASSERT(it->procThatHasData != MyProc);
521
522 const int Who = it->procThatHasData;
523 const Long cnt_long = it->box.numPts() * Long(it->nComp);
524 AMREX_ALWAYS_ASSERT_WITH_MESSAGE(cnt_long >= 0 &&
525 cnt_long <= Long(std::numeric_limits<int>::max()),
526 "CollectData: message chunk exceeds INT_MAX elements");
527 const int Cnt = static_cast<int>(cnt_long);
528
529 RcvTags[Who].emplace_back(it);
530
531 Total_Rcvs_Size += Cnt;
532
533 if (Rcvs.contains(Who))
534 {
535 Rcvs[Who] += 1;
536 }
537 else
538 {
539 Rcvs[Who] = 1;
540 }
541
542 if (Npts.contains(Who))
543 {
544 Npts[Who] += Cnt;
545 }
546 else
547 {
548 Npts[Who] = Cnt;
549 }
550 }
551 BL_ASSERT(!Rcvs.contains(MyProc));
552
553 BL_ASSERT((Total_Rcvs_Size*sizeof(value_type))
554 < static_cast<std::size_t>(std::numeric_limits<int>::max()));
555
556 const int NProcs = ParallelContext::NProcsSub();
558
559 {
560 Vector<int> SndsArray(NProcs,0), RcvsArray(NProcs,0);
561
562 for (auto const& Rcv : Rcvs)
563 {
564 RcvsArray[ParallelContext::global_to_local_rank(Rcv.first)] = Rcv.second;
565 }
566
567 {
568 BL_PROFILE_VAR("CollectData_Alltoall()", blpvCDATA);
569 BL_COMM_PROFILE(BLProfiler::Alltoall, sizeof(int), ParallelDescriptor::MyProc(),
570 BLProfiler::BeforeCall());
571
572 BL_MPI_REQUIRE( MPI_Alltoall(RcvsArray.dataPtr(),
573 1,
575 SndsArray.dataPtr(),
576 1,
578 comm) );
579
580 BL_COMM_PROFILE(BLProfiler::Alltoall, sizeof(int), ParallelDescriptor::MyProc(),
581 BLProfiler::AfterCall());
582
583 BL_PROFILE_VAR_STOP(blpvCDATA);
584 }
585 BL_ASSERT(SndsArray[ParallelContext::MyProcSub()] == 0);
586
587 for (int i = 0; i < NProcs; i++) {
588 if (SndsArray[i] > 0) {
589 Snds[i] = SndsArray[i];
590 }
591 }
592 }
593
594 // There are two rounds of send and recv.
595 // First, the data receivers need to send the data senders meta-data (e.g., boxes).
596 // Then, the senders know what data to send and perform send.
597 const int SeqNum_md = ParallelDescriptor::SeqNum();
598 const int SeqNum_data = ParallelDescriptor::SeqNum();
599
600 const auto N_snds = static_cast<int>(Snds.size());
601 const auto N_rcvs = static_cast<int>(Rcvs.size());
602
603 if ( N_snds == 0 && N_rcvs == 0 ) { return; }
604
605 const int Nints = 4 + 3*AMREX_SPACEDIM; // # of ints in a meta-data
606
607 // for meta-data
608 Vector<int> md_sender, md_offset, md_icnts, md_bcnts;
609 int* md_recv_data = nullptr;
610 Vector<int*> md_send_data;
611 Vector<MPI_Request> md_recv_reqs, md_send_reqs;
612
613 // for data
614 Vector<int> data_sender, data_offset;
615 value_type* recv_data = nullptr;
616 Vector<value_type*> send_data;
617 Vector<MPI_Request> data_recv_reqs, data_send_reqs;
618
619 if (N_snds > 0)
620 {
621 // Recv meta-data
622
623 int N = 0;
624 for (auto const& Snd : Snds)
625 {
626 md_sender.push_back(Snd.first);
627 md_bcnts.push_back(Snd.second);
628 int cnt = Snd.second * Nints;
629 md_icnts.push_back(cnt);
630 md_offset.push_back(N);
631 N += cnt;
632 }
633
634 md_recv_data = static_cast<int*>(amrex::The_Arena()->alloc(N*sizeof(int)));
635
636 for (int i = 0; i < N_snds; ++i)
637 {
638 md_recv_reqs.push_back(ParallelDescriptor::Arecv(&md_recv_data[md_offset[i]],
639 md_icnts[i], md_sender[i],
640 SeqNum_md, comm).req());
641 }
642 }
643
644 if (N_rcvs > 0)
645 {
646 // Send meta-data
647 for (auto const& Rcv : Rcvs)
648 {
649 int rank = Rcv.first;
650 int Nmds = Rcv.second;
651 int cnt = Nmds * Nints;
652
653 int* p = static_cast<int*>(amrex::The_Arena()->alloc(cnt*sizeof(int)));
654 md_send_data.push_back(p);
655
656 const FabComTagIterContainer& tags = RcvTags[rank];
657
658 // initialized the data
659 int * md = p;
660 for (int i = 0; i < Nmds; ++i, md += Nints)
661 {
662 md[0] = tags[i]->fabArrayId;
663 md[1] = tags[i]->fabIndex;
664 md[2] = tags[i]->srcComp;
665 md[3] = tags[i]->nComp;
666 const int* lo = tags[i]->box.loVect();
667 const int* hi = tags[i]->box.hiVect();
668 const IntVect& bxtyp = tags[i]->box.type();
669 const int* tp = bxtyp.getVect();
670 AMREX_D_EXPR(md[4] = lo[0],
671 md[5] = lo[1],
672 md[6] = lo[2]);
673 AMREX_D_EXPR(md[4+ AMREX_SPACEDIM] = hi[0],
674 md[5+ AMREX_SPACEDIM] = hi[1],
675 md[6+ AMREX_SPACEDIM] = hi[2]);
676 AMREX_D_EXPR(md[4+2*AMREX_SPACEDIM] = tp[0],
677 md[5+2*AMREX_SPACEDIM] = tp[1],
678 md[6+2*AMREX_SPACEDIM] = tp[2]);
679 }
680
681 md_send_reqs.push_back(ParallelDescriptor::Asend
682 (p,cnt,ParallelContext::global_to_local_rank(rank),SeqNum_md,comm).req());
683 }
684 }
685
686 if (N_rcvs > 0)
687 {
688 recv_data = static_cast<value_type*>(amrex::The_Arena()->alloc(Total_Rcvs_Size*sizeof(value_type)));
689
690 // Post receives for data
691 int Idx = 0;
692 for (auto & Npt : Npts)
693 {
694 int Who = Npt.first;
695 int Cnt = Npt.second;
696 BL_ASSERT(Cnt > 0);
697 BL_ASSERT(Cnt < std::numeric_limits<int>::max());
698 data_sender.push_back(Who);
699 data_recv_reqs.push_back(ParallelDescriptor::Arecv
700 (&recv_data[Idx], Cnt, ParallelContext::global_to_local_rank(Who),
701 SeqNum_data, comm).req());
702 data_offset.push_back(Idx);
703 Idx += Cnt;
704 }
705 }
706
707 // Wait on meta-data and do send
708 if (N_snds > 0)
709 {
710 int send_counter = 0;
711 while (send_counter++ < N_snds)
712 {
713 MPI_Status status;
714 int index;
715 ParallelDescriptor::Waitany(md_recv_reqs, index, status);
716
717 int rank = status.MPI_SOURCE;
718 BL_ASSERT(status.MPI_TAG == SeqNum_md);
719 BL_ASSERT(rank == md_sender[index]);
720
721 const int* p = &md_recv_data[md_offset[index]];
722 int numboxes = md_bcnts[index];
723 Vector<int> faid(numboxes);
724 Vector<int> fidx(numboxes);
725 Vector<int> scomp(numboxes);
726 Vector<int> ncomp(numboxes);
727 Vector<int> npts(numboxes);
728 Vector<Box> bxs;
729 int N = 0;
730 const int * md = p;
731 for (int i = 0; i < numboxes; ++i, md += Nints)
732 {
733 faid[i] = md[0];
734 fidx[i] = md[1];
735 scomp[i] = md[2];
736 ncomp[i] = md[3];
737 bxs.push_back(Box(IntVect(&md[4]),
738 IntVect(&md[4+AMREX_SPACEDIM]),
739 IntVect(&md[4+AMREX_SPACEDIM*2])));
740 const Long np_long = bxs.back().numPts() * Long(ncomp[i]);
741 AMREX_ALWAYS_ASSERT(np_long <= Long(std::numeric_limits<int>::max()));
742 npts[i] = static_cast<int>(np_long);
743 N += npts[i];
744 }
745
746 BL_ASSERT(N < std::numeric_limits<int>::max());
747
748 auto* data = static_cast<value_type*>(amrex::The_Arena()->alloc(N*sizeof(value_type)));
749 value_type* dptr = data;
750 send_data.push_back(data);
751
752 for (int i = 0; i < numboxes; ++i)
753 {
754 (*fabArrays[faid[i]])[fidx[i]].template copyToMem<RunOn::Host>(bxs[i],scomp[i],ncomp[i],dptr);
755 dptr += npts[i];
756 }
757
758 data_send_reqs.push_back(ParallelDescriptor::Asend(data,N,rank,SeqNum_data,comm).req());
759 }
760
761 amrex::The_Arena()->free(md_recv_data);
762 }
763
764 // Wait and unpack data
765 if (N_rcvs > 0)
766 {
767 Vector<MPI_Status> stats(N_rcvs);
768
769 ParallelDescriptor::Waitall(md_send_reqs, stats);
770 for (int i = 0; i < N_rcvs; ++i) {
771 amrex::The_Arena()->free(md_send_data[i]);
772 }
773
774 ParallelDescriptor::Waitall(data_recv_reqs, stats);
775
776 std::pair<FCDMapIter,FCDMapIter> match;
777 std::map< int,FabComTagIterContainer >::const_iterator found;
778
779 for (int k = 0; k < N_rcvs; k++)
780 {
781 const int Who = data_sender[k];
782 const value_type* dptr = &recv_data[data_offset[k]];
783
784 BL_ASSERT(dptr != nullptr);
785
786 found = RcvTags.find(Who);
787
788 BL_ASSERT(found != RcvTags.end());
789
790 const FabComTagIterContainer& tags = found->second;
791
792 for (auto const& it : tags)
793 {
794 const FabArrayBase::FabComTag& tag = *it;
795
796 BL_ASSERT(tag.procThatHasData == Who);
797
798 match = fabCopyDescList[tag.fabArrayId].equal_range(tag.fillBoxId);
799
800 for (auto fmi = match.first; fmi != match.second; ++fmi)
801 {
802 FabCopyDescriptor<FAB>* fcdp = (*fmi).second;
803
804 BL_ASSERT(fcdp->fillBoxId == tag.fillBoxId);
805
806 if (fcdp->subBox == tag.box)
807 {
808 BL_ASSERT(fcdp->localFabSource->dataPtr() != nullptr);
809 BL_ASSERT(fcdp->localFabSource->box() == tag.box);
810 const Long cnt_long = tag.box.numPts() * Long(tag.nComp);
811 AMREX_ALWAYS_ASSERT(cnt_long <= Long(std::numeric_limits<int>::max()));
812 auto Cnt = static_cast<int>(cnt_long);
813 fcdp->localFabSource->template copyFromMem<RunOn::Host>(tag.box,0,tag.nComp,dptr);
814 dptr += Cnt;
815 break;
816 }
817 }
818 }
819 }
820
821 amrex::The_Arena()->free(recv_data);
822 }
823
824 // Finished send
825 if (N_snds > 0)
826 {
827 Vector<MPI_Status> stats(N_snds);
828 ParallelDescriptor::Waitall(data_send_reqs, stats);
829
830 for (int i = 0; i < N_snds; ++i) {
831 amrex::The_Arena()->free(send_data[i]);
832 }
833 }
834
835#endif /*BL_USE_MPI*/
836}
837
838
839template <class FAB>
840void
842 const FillBoxId& fillboxid,
843 FAB& destFab)
844{
845 BL_ASSERT(dataAvailable);
846
847 std::pair<FCDMapIter,FCDMapIter> match = fabCopyDescList[faid.Id()].equal_range(fillboxid.Id());
848
849 for (auto fmi = match.first; fmi != match.second; ++fmi)
850 {
851 FabCopyDescriptor<FAB>* fcdp = (*fmi).second;
852
853 BL_ASSERT(fcdp->fillBoxId == fillboxid.Id());
854
855 destFab.template copy<RunOn::Host>
856 (*fcdp->localFabSource,
857 fcdp->subBox,
858 fcdp->fillType == FillLocally ? fcdp->srcComp : 0,
859 fcdp->subBox,
860 fcdp->destComp,
861 fcdp->nComp);
862 }
863}
864
865template <class FAB>
866void
868 const FillBoxId& fillboxid,
869 FAB& destFab,
870 const Box& destBox)
871{
872 BL_ASSERT(dataAvailable);
873
874 FCDMapIter fmi = fabCopyDescList[faid.Id()].lower_bound(fillboxid.Id());
875
876 BL_ASSERT(fmi != fabCopyDescList[faid.Id()].end());
877
878 FabCopyDescriptor<FAB>* fcdp = (*fmi).second;
879
880 BL_ASSERT(fcdp->fillBoxId == fillboxid.Id());
881
882 BL_ASSERT(fcdp->subBox.sameSize(destBox));
883
884 destFab.template copy<RunOn::Host>
885 (*fcdp->localFabSource,
886 fcdp->subBox,
887 fcdp->fillType == FillLocally ? fcdp->srcComp : 0,
888 destBox,
889 fcdp->destComp,
890 fcdp->nComp);
891
892 BL_ASSERT(++fmi == fabCopyDescList[faid.Id()].upper_bound(fillboxid.Id()));
893}
894
895template <class FAB>
896void
898{
899 const int MyProc = ParallelDescriptor::MyProc();
900
901 amrex::AllPrint() << "----- "
902 << MyProc
903 << ": Parallel stats for FabArrayCopyDescriptor:" << '\n';
904
905 for (int fa = 0; fa < fabArrays.size(); ++fa)
906 {
907 amrex::AllPrint() << "fabArrays["
908 << fa
909 << "]->boxArray() = "
910 << fabArrays[fa]->boxArray()
911 << '\n';
912 }
913}
914
915}
916
917#endif
#define BL_PROFILE(a)
Definition AMReX_BLProfiler.H:562
#define BL_COMM_PROFILE(cft, size, pid, tag)
Definition AMReX_BLProfiler.H:598
#define BL_PROFILE_VAR_STOP(vname)
Definition AMReX_BLProfiler.H:574
#define BL_PROFILE_VAR(fname, vname)
Definition AMReX_BLProfiler.H:571
#define AMREX_ALWAYS_ASSERT_WITH_MESSAGE(EX, MSG)
Definition AMReX_BLassert.H:49
#define BL_ASSERT(EX)
Definition AMReX_BLassert.H:39
#define AMREX_ALWAYS_ASSERT(EX)
Definition AMReX_BLassert.H:50
Distributed container of FAB objects plus copy and fill utilities.
#define AMREX_D_EXPR(a, b, c)
Definition AMReX_SPACE.H:170
Print on all processors of the default communicator.
Definition AMReX_Print.H:113
virtual void free(void *pt)=0
Free a previously allocated block pointed to by pt.
virtual void * alloc(std::size_t sz)=0
Allocate sz bytes from this arena.
bool ok() const
Return true if the BoxArray is empty or every Box reports ok().
Definition AMReX_BoxArray.cpp:910
A list of disjoint boxes built on top of BoxList.
Definition AMReX_BoxDomain.H:95
BoxDomain & rmBox(const Box &b)
Erase the intersection between this domain and b.
Definition AMReX_BoxDomain.cpp:157
const BoxList & boxList() const
Return a const reference to the underlying BoxList of this BoxDomain.
Definition AMReX_BoxDomain.cpp:82
void add(const Box &b)
Insert a box into the domain, clipping it so the stored boxes remain disjoint.
Definition AMReX_BoxDomain.cpp:121
A list of Boxes sharing a common IndexType.
Definition AMReX_BoxList.H:109
void clear()
Remove all Boxes from this BoxList.
Definition AMReX_BoxList.cpp:67
__host__ __device__ Long numPts() const noexcept
Return the number of points contained in the BoxND.
Definition AMReX_Box.H:385
__host__ __device__ bool sameSize(const BoxND &b) const noexcept
Return true is Boxes same size, ie translates of each other,. It is an error if they have different t...
Definition AMReX_Box.H:312
__host__ __device__ IndexTypeND< dim > ixType() const noexcept
Return the indexing type.
Definition AMReX_Box.H:148
const DistributionMapping & DistributionMap() const noexcept
Return constant reference to associated DistributionMapping.
Definition AMReX_FabArrayBase.H:135
Box box(int K) const noexcept
Return the Kth Box in the BoxArray. That is, the valid region of the Kth grid.
Definition AMReX_FabArrayBase.H:106
Box fabbox(int K) const noexcept
Return the Kth FABs Box in the FabArray. That is, the region the Kth fab is actually defined on.
Definition AMReX_FabArrayBase.cpp:217
Manages multi-component copy operations out of one or more FabArrays.
Definition AMReX_FACopyDescriptor.H:134
void PrintStats() const
Print per-rank box-array information for each registered FabArray.
Definition AMReX_FACopyDescriptor.H:897
int nFabCopyDescs() const
Number of per-FabArray FabCopyDescriptor maps held (one per registered FabArray).
Definition AMReX_FACopyDescriptor.H:227
FabArrayCopyDescriptor(const FabArrayCopyDescriptor< FAB > &)=delete
FabArrayCopyDescriptor(FabArrayCopyDescriptor< FAB > &&)=delete
int nFabComTags() const
Number of remote-transfer FabComTag entries currently stored.
Definition AMReX_FACopyDescriptor.H:224
void clear()
Reset the descriptor, unregistering all FabArrays and outstanding boxes.
Definition AMReX_FACopyDescriptor.H:467
void FillFab(FabArrayId faid, const FillBoxId &fillboxid, FAB &destFab)
Copy staged data into the requested fill region of the destination Fab.
Definition AMReX_FACopyDescriptor.H:841
FabArrayCopyDescriptor< FAB > & operator=(const FabArrayCopyDescriptor< FAB > &)=delete
void CollectData()
Exchange staged data for all FillBox entries.
Definition AMReX_FACopyDescriptor.H:489
FillBoxId AddBox(FabArrayId fabarrayid, const Box &destFabBox, BoxList *unfilledBoxes)
Describe a destination box that needs to be filled.
Definition AMReX_FACopyDescriptor.H:447
FabArrayId RegisterFabArray(FabArray< FAB > *fabarray)
Register a FabArray from which copies may be requested.
Definition AMReX_FACopyDescriptor.H:260
int CurrentNFabArrays() const
Number of FabArrays currently registered with this descriptor.
Definition AMReX_FACopyDescriptor.H:221
FillBoxId AddBox(FabArrayId fabarrayid, const Box &destFabBox, BoxList *unfilledBoxes, int srccomp, int destcomp, int numcomp)
Add a destination box specifying component ranges explicitly.
Definition AMReX_FACopyDescriptor.H:368
~FabArrayCopyDescriptor()
Definition AMReX_FACopyDescriptor.H:460
bool DataAvailable() const
Return true once all requested data have been staged locally.
Definition AMReX_FACopyDescriptor.H:215
FillBoxId AddBox(FabArrayId fabarrayid, const Box &destFabBox, BoxList *unfilledBoxes, int fabarrayindex, int srccomp, int destcomp, int numcomp, bool bUseValidBox=true)
Add a destination box but restrict fills to a specific Fab index.
Definition AMReX_FACopyDescriptor.H:410
void FillFab(FabArrayId faid, const FillBoxId &fillboxid, FAB &destFab, const Box &destBox)
Copy staged data into a user-specified sub-box of the destination Fab.
Definition AMReX_FACopyDescriptor.H:867
Lightweight handle returned when registering FabArrays with a descriptor.
Definition AMReX_FACopyDescriptor.H:62
int Id() const
Definition AMReX_FACopyDescriptor.H:69
bool operator==(const FabArrayId &rhs) const
Definition AMReX_FACopyDescriptor.H:71
FabArrayId(int newid=-1)
Definition AMReX_FACopyDescriptor.H:65
An Array of FortranArrayBox(FAB)-like Objects.
Definition AMReX_FabArray.H:356
Tracks metadata about a pending fill region (box and identifiers).
Definition AMReX_FACopyDescriptor.H:30
FillBoxId()=default
const Box & box() const
Geometric region requested.
Definition AMReX_FACopyDescriptor.H:48
int Id() const
Unique identifier assigned by the descriptor.
Definition AMReX_FACopyDescriptor.H:42
int FabIndex() const
Optional caller-managed Fab index associated with this fill; defaults to -1.
Definition AMReX_FACopyDescriptor.H:44
FillBoxId(int newid, const Box &fillbox)
Definition AMReX_FACopyDescriptor.H:35
void FabIndex(int fabindex)
Associate a caller-managed Fab index with this fill.
Definition AMReX_FACopyDescriptor.H:46
__host__ __device__ const int * getVect() const &noexcept
Returns a const pointer to an array of coordinates of the IntVectND. Useful for arguments to FORTRAN ...
Definition AMReX_IntVect.H:383
MPI_Request req() const
Definition AMReX_ParallelDescriptor.H:74
This class is a thin wrapper around std::vector. Unlike vector, Vector::operator[] provides bound che...
Definition AMReX_Vector.H:29
T * dataPtr() noexcept
get access to the underlying data pointer
Definition AMReX_Vector.H:50
amrex_long Long
Definition AMReX_INT.H:30
Arena * The_Arena()
Definition AMReX_Arena.cpp:815
int MyProc() noexcept
Definition AMReX_ParallelDescriptor.H:128
int NProcs() noexcept
Definition AMReX_ParallelDescriptor.H:255
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:101
int NProcsSub() noexcept
number of ranks in current frame
Definition AMReX_ParallelContext.H:74
bool sameTeam(int rank) noexcept
Definition AMReX_ParallelDescriptor.H:345
Message Asend(const T *, size_t n, int pid, int tag)
Definition AMReX_ParallelDescriptor.H:1163
void Waitany(Vector< MPI_Request > &, int &, MPI_Status &)
Definition AMReX_ParallelDescriptor.cpp:1316
void Waitall(Vector< MPI_Request > &, Vector< MPI_Status > &)
Definition AMReX_ParallelDescriptor.cpp:1312
int SeqNum() noexcept
Returns sequential message sequence numbers, usually used as tags for send/recv.
Definition AMReX_ParallelDescriptor.H:678
Message Arecv(T *, size_t n, int pid, int tag)
Definition AMReX_ParallelDescriptor.H:1205
int MPI_Comm
Definition AMReX_ccse-mpi.H:51
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
BoxArray intersect(const BoxArray &ba, const Box &b, int ng)
Make a BoxArray from the intersection of Box b and BoxArray(+ghostcells).
Definition AMReX_BoxArray.cpp:1735
__host__ __device__ Dim3 begin(BoxND< dim > const &box) noexcept
Return the iterator begin coordinate of box as Dim3.
Definition AMReX_Box.H:2239
BoxND< 3 > Box
Box is an alias for amrex::BoxND instantiated with AMREX_SPACEDIM.
Definition AMReX_BaseFwd.H:35
bool match(const BoxArray &x, const BoxArray &y)
Return true if two BoxArrays cover the same index space.
Definition AMReX_BoxArray.cpp:1948
IntVectND< 3 > IntVect
IntVect is an alias for amrex::IntVectND instantiated with AMREX_SPACEDIM.
Definition AMReX_BaseFwd.H:38
FillType
Categorizes how a requested fill box can be satisfied.
Definition AMReX_FACopyDescriptor.H:23
@ FillLocally
Definition AMReX_FACopyDescriptor.H:23
@ Unfillable
Definition AMReX_FACopyDescriptor.H:23
@ FillRemotely
Definition AMReX_FACopyDescriptor.H:23
void Abort(const std::string &msg)
Print a fatal-error message to stderr and abort execution.
Definition AMReX.cpp:242
Used for collecting information used in communicating FABs.
Definition AMReX_FabArrayBase.H:289
int fabArrayId
Definition AMReX_FabArrayBase.H:298
int procThatHasData
Definition AMReX_FabArrayBase.H:301
Box box
Definition AMReX_FabArrayBase.H:302
int nComp
Definition AMReX_FabArrayBase.H:296
int fillBoxId
Definition AMReX_FabArrayBase.H:299
Describes a single copy request originating from a registered FabArray.
Definition AMReX_FACopyDescriptor.H:88
int destComp
Definition AMReX_FACopyDescriptor.H:105
FabCopyDescriptor(const FabCopyDescriptor &)=delete
int copyFromIndex
Definition AMReX_FACopyDescriptor.H:102
FabCopyDescriptor()
Definition AMReX_FACopyDescriptor.H:112
int myProc
Definition AMReX_FACopyDescriptor.H:100
bool cacheDataAllocated
Definition AMReX_FACopyDescriptor.H:108
FAB * localFabSource
Definition AMReX_FACopyDescriptor.H:98
FabCopyDescriptor & operator=(const FabCopyDescriptor &)=delete
~FabCopyDescriptor()
Definition AMReX_FACopyDescriptor.H:119
Box subBox
Definition AMReX_FACopyDescriptor.H:99
int nComp
Definition AMReX_FACopyDescriptor.H:106
int fillBoxId
Definition AMReX_FACopyDescriptor.H:103
int srcComp
Definition AMReX_FACopyDescriptor.H:104
FillType fillType
Definition AMReX_FACopyDescriptor.H:107
FabCopyDescriptor(FabCopyDescriptor &&)=delete
int copyFromProc
Definition AMReX_FACopyDescriptor.H:101
Communication datatype (note: this structure also works without MPI)
Definition AMReX_ccse-mpi.H:78
Definition AMReX_ccse-mpi.H:55