2#ifndef BL_FACOPYDESCRIPTOR_H_
3#define BL_FACOPYDESCRIPTOR_H_
4#include <AMReX_Config.H>
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; }
69 [[nodiscard]]
int Id ()
const {
return fabArrayId; }
73 return fabArrayId == rhs.fabArrayId;
114 localFabSource(nullptr)
121 if (cacheDataAllocated) {
122 delete localFabSource;
135 using FCDMap = std::multimap<int,FabCopyDescriptor<FAB>*>;
137 using FCDMapValueType =
typename FCDMap::value_type;
138 using FCDMapIter =
typename FCDMap::iterator;
139 using FCDMapConstIter =
typename FCDMap::const_iterator;
165 const Box& destFabBox,
172 const Box& destFabBox,
189 const Box& destFabBox,
195 bool bUseValidBox =
true);
224 [[nodiscard]]
int nFabComTags ()
const {
return fabComTagList.size(); }
234 const Box& destFabBox,
235 BoxList* returnedUnfilledBoxes,
245 using FabComTagContainer = std::vector<FabArrayBase::FabComTag>;
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};
262 BL_ASSERT(fabArrays.size() == fabCopyDescList.size());
266 fabArrays.push_back(fabarray);
268 fabCopyDescList.push_back(FCDMap());
276 const Box& destFabBox,
277 BoxList* returnedUnfilledBoxes,
289 BL_ASSERT(faindex >= 0 && faindex < fabArray->size());
304 auto* fcd =
new FabCopyDescriptor<FAB>;
310 +
":: _in AddBoxDoIt: nProcs remoteProc = "
312 +
" " + std::to_string(remoteProc) +
"\n");
314 fcd->fillBoxId = nextFillBoxId;
316 fcd->myProc = myProc;
317 fcd->copyFromProc = remoteProc;
318 fcd->copyFromIndex = faindex;
319 fcd->srcComp = srccomp;
320 fcd->destComp = destcomp;
321 fcd->nComp = numcomp;
329 fcd->localFabSource = &(*fabArray)[faindex];
336 FabArrayBase::FabComTag fabComTag;
338 dataAvailable =
false;
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;
348 fabComTag.srcComp = srccomp;
349 fabComTag.destComp = destcomp;
350 fabComTag.nComp = numcomp;
354 fabComTagList.push_back(fabComTag);
357 fabCopyDescList[fabarrayid.
Id()].insert(FCDMapValueType(fcd->fillBoxId,fcd));
359 if (returnedUnfilledBoxes !=
nullptr)
369 const Box& destFabBox,
370 BoxList* returnedUnfilledBoxes,
377 if (returnedUnfilledBoxes !=
nullptr)
379 unfilledBoxDomain.
add(destFabBox);
382 std::vector< std::pair<int,Box> > isects;
384 fabArrays[fabarrayid.
Id()]->boxArray().intersections(destFabBox,isects);
386 for (
auto & isect : isects)
388 AddBoxDoIt(fabarrayid,
390 returnedUnfilledBoxes,
399 if (returnedUnfilledBoxes !=
nullptr)
401 returnedUnfilledBoxes->
clear();
402 (*returnedUnfilledBoxes) = unfilledBoxDomain.
boxList();
405 return FillBoxId(nextFillBoxId++, destFabBox);
411 const Box& destFabBox,
412 BoxList* returnedUnfilledBoxes,
421 if (returnedUnfilledBoxes !=
nullptr)
423 unfilledBoxDomain.
add(destFabBox);
426 AddBoxDoIt(fabarrayid,
428 returnedUnfilledBoxes,
436 if (returnedUnfilledBoxes !=
nullptr)
438 returnedUnfilledBoxes->
clear();
439 (*returnedUnfilledBoxes) = unfilledBoxDomain.
boxList();
442 return FillBoxId(nextFillBoxId++, destFabBox);
448 const Box& destFabBox,
449 BoxList* returnedUnfilledBoxes)
451 return AddBox(fabarrayid,
453 returnedUnfilledBoxes,
456 fabArrays[fabarrayid.
Id()]->nComp());
469 for (
unsigned int i = 0, N = fabCopyDescList.size(); i < N; ++i)
471 for (
auto fmi = fabCopyDescList[i].
begin(), End = fabCopyDescList[i].end();
475 delete (*fmi).second;
480 fabCopyDescList.clear();
481 fabComTagList.clear();
484 dataAvailable =
false;
491 dataAvailable =
true;
496 using value_type =
typename FAB::value_type;
498 BL_PROFILE(
"FabArrayCopyDescriptor::CollectData()");
503 int Total_Rcvs_Size = 0;
507 std::map< int,FabComTagIterContainer > RcvTags;
509 std::map<int,int> Snds, Rcvs, Npts;
513 for (
auto it = fabComTagList.begin(),
514 End = fabComTagList.end();
519 BL_ASSERT(it->procThatNeedsData == MyProc);
520 BL_ASSERT(it->procThatHasData != MyProc);
522 const int Who = it->procThatHasData;
523 const Long cnt_long = it->box.numPts() *
Long(it->nComp);
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);
529 RcvTags[Who].emplace_back(it);
531 Total_Rcvs_Size += Cnt;
533 if (Rcvs.contains(Who))
542 if (Npts.contains(Who))
553 BL_ASSERT((Total_Rcvs_Size*
sizeof(value_type))
554 <
static_cast<std::size_t
>(std::numeric_limits<int>::max()));
559 Vector<int> SndsArray(NProcs,0), RcvsArray(NProcs,0);
561 for (
auto const& Rcv : Rcvs)
563 RcvsArray[Rcv.first] = Rcv.second;
569 BLProfiler::BeforeCall());
571 BL_MPI_REQUIRE( MPI_Alltoall(RcvsArray.
dataPtr(),
580 BLProfiler::AfterCall());
586 for (
int i = 0; i < NProcs; i++) {
587 if (SndsArray[i] > 0) {
588 Snds[i] = SndsArray[i];
599 const auto N_snds =
static_cast<int>(Snds.size());
600 const auto N_rcvs =
static_cast<int>(Rcvs.size());
602 if ( N_snds == 0 && N_rcvs == 0 ) {
return; }
604 const int Nints = 4 + 3*AMREX_SPACEDIM;
607 Vector<int> md_sender, md_offset, md_icnts, md_bcnts;
608 int* md_recv_data =
nullptr;
614 value_type* recv_data =
nullptr;
623 for (
auto const& Snd : Snds)
625 md_sender.push_back(Snd.first);
626 md_bcnts.push_back(Snd.second);
627 int cnt = Snd.second * Nints;
628 md_icnts.push_back(cnt);
629 md_offset.push_back(N);
635 for (
int i = 0; i < N_snds; ++i)
638 md_icnts[i], md_sender[i],
646 for (
auto const& Rcv : Rcvs)
648 int rank = Rcv.first;
649 int Nmds = Rcv.second;
650 int cnt = Nmds * Nints;
653 md_send_data.push_back(p);
655 const FabComTagIterContainer& tags = RcvTags[rank];
659 for (
int i = 0; i < Nmds; ++i, md += Nints)
661 md[0] = tags[i]->fabArrayId;
662 md[1] = tags[i]->fabIndex;
663 md[2] = tags[i]->srcComp;
664 md[3] = tags[i]->nComp;
665 const int* lo = tags[i]->box.loVect();
666 const int* hi = tags[i]->box.hiVect();
667 const IntVect& bxtyp = tags[i]->box.type();
668 const int* tp = bxtyp.
getVect();
673 md[5+ AMREX_SPACEDIM] = hi[1],
674 md[6+ AMREX_SPACEDIM] = hi[2]);
676 md[5+2*AMREX_SPACEDIM] = tp[1],
677 md[6+2*AMREX_SPACEDIM] = tp[2]);
690 for (
auto & Npt : Npts)
693 int Cnt = Npt.second;
695 BL_ASSERT(Cnt < std::numeric_limits<int>::max());
696 data_sender.push_back(Who);
698 Cnt,Who,SeqNum_data).req());
699 data_offset.push_back(Idx);
707 int send_counter = 0;
708 while (send_counter++ < N_snds)
714 int rank = status.MPI_SOURCE;
718 const int* p = &md_recv_data[md_offset[index]];
719 int numboxes = md_bcnts[index];
728 for (
int i = 0; i < numboxes; ++i, md += Nints)
735 IntVect(&md[4+AMREX_SPACEDIM]),
736 IntVect(&md[4+AMREX_SPACEDIM*2])));
737 const Long np_long = bxs.back().numPts() *
Long(ncomp[i]);
739 npts[i] =
static_cast<int>(np_long);
743 BL_ASSERT(N < std::numeric_limits<int>::max());
746 value_type* dptr = data;
747 send_data.push_back(data);
749 for (
int i = 0; i < numboxes; ++i)
751 (*fabArrays[faid[i]])[fidx[i]].
template copyToMem<RunOn::Host>(bxs[i],scomp[i],ncomp[i],dptr);
767 for (
int i = 0; i < N_rcvs; ++i) {
773 std::pair<FCDMapIter,FCDMapIter>
match;
774 std::map< int,FabComTagIterContainer >::const_iterator found;
776 for (
int k = 0; k < N_rcvs; k++)
778 const int Who = data_sender[k];
779 const value_type* dptr = &recv_data[data_offset[k]];
783 found = RcvTags.find(Who);
787 const FabComTagIterContainer& tags = found->second;
789 for (
auto const& it : tags)
797 for (
auto fmi =
match.first; fmi !=
match.second; ++fmi)
809 auto Cnt =
static_cast<int>(cnt_long);
827 for (
int i = 0; i < N_snds; ++i) {
844 std::pair<FCDMapIter,FCDMapIter>
match = fabCopyDescList[faid.
Id()].equal_range(fillboxid.
Id());
846 for (
auto fmi =
match.first; fmi !=
match.second; ++fmi)
852 destFab.template copy<RunOn::Host>
871 FCDMapIter fmi = fabCopyDescList[faid.
Id()].lower_bound(fillboxid.
Id());
873 BL_ASSERT(fmi != fabCopyDescList[faid.
Id()].end());
888 BL_ASSERT(++fmi == fabCopyDescList[faid.
Id()].upper_bound(fillboxid.
Id()));
899 <<
": Parallel stats for FabArrayCopyDescriptor:" <<
'\n';
901 for (
int fa = 0; fa < fabArrays.size(); ++fa)
905 <<
"]->boxArray() = "
906 << fabArrays[fa]->boxArray()
#define BL_PROFILE(a)
Definition AMReX_BLProfiler.H:551
#define BL_COMM_PROFILE(cft, size, pid, tag)
Definition AMReX_BLProfiler.H:587
#define BL_PROFILE_VAR_STOP(vname)
Definition AMReX_BLProfiler.H:563
#define BL_PROFILE_VAR(fname, vname)
Definition AMReX_BLProfiler.H:560
#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
#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:894
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:65
__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:130
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:101
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:893
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:838
FabArrayCopyDescriptor< FAB > & operator=(const FabArrayCopyDescriptor< FAB > &)=delete
FabArrayCopyDescriptor()=default
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:864
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:344
Tracks metadata about a pending fill region (box and identifiers).
Definition AMReX_FACopyDescriptor.H:30
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:820
int MyProc() noexcept
Definition AMReX_ParallelDescriptor.H:128
int NProcs() noexcept
Definition AMReX_ParallelDescriptor.H:255
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:1154
MPI_Comm Communicator() noexcept
Definition AMReX_ParallelDescriptor.H:223
void Waitany(Vector< MPI_Request > &, int &, MPI_Status &)
Definition AMReX_ParallelDescriptor.cpp:1312
void Waitall(Vector< MPI_Request > &, Vector< MPI_Status > &)
Definition AMReX_ParallelDescriptor.cpp:1308
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:1196
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:1717
__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:1930
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:241
Used for collecting information used in communicating FABs.
Definition AMReX_FabArrayBase.H:271
int fabArrayId
Definition AMReX_FabArrayBase.H:280
int procThatHasData
Definition AMReX_FabArrayBase.H:283
Box box
Definition AMReX_FabArrayBase.H:284
int nComp
Definition AMReX_FabArrayBase.H:278
int fillBoxId
Definition AMReX_FabArrayBase.H:281
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