1#ifndef AMREX_NONLOCAL_BC_H_
5#ifndef AMREX_NONLOCAL_BC_IMPL_H_
6#define AMREX_NONLOCAL_BC_IMPL_H_
7#include <AMReX_Config.H>
11struct Rotate90ClockWise {
13 IntVect operator() (IntVect
const& iv)
const noexcept {
18 Dim3 operator() (Dim3
const& a)
const noexcept {
19 return Dim3{.x = a.y, .y = -1-a.x, .z = a.z};
22 Box operator() (Box
const& box)
const noexcept {
32struct Rotate90CounterClockWise {
34 IntVect operator() (IntVect
const& iv)
const noexcept {
39 Dim3 operator() (Dim3
const& a)
const noexcept {
40 return Dim3{.x = -1-a.y, .y = a.x, .z = a.z};
43 Box operator() (Box
const& box)
const noexcept {
53struct Rotate90DstToSrc
56 Dim3 operator() (Dim3
const& a)
const noexcept {
58 return Rotate90ClockWise()(a);
60 return Rotate90CounterClockWise()(a);
69 IntVect operator() (IntVect
const& iv)
const noexcept {
74 Dim3 operator() (Dim3
const& a)
const noexcept {
75 return Dim3{.x = -1-a.x, .y = Ly-1-a.y, .z = a.z};
78 Box operator() (Box
const& box)
const noexcept {
92 int i_index (
int i)
const noexcept {
93 return (i < Lx/2) ? -1-i : 2*Lx-1-i;
97 int j_index (
int j)
const noexcept {
98 return (j < Ly/2) ? j+Ly/2 : j-Ly/2;
102 IntVect operator() (IntVect
const& iv)
const noexcept {
107 Dim3 operator() (Dim3
const& a)
const noexcept {
108 return Dim3{.x = i_index(a.x), .y = j_index(a.y), .z = a.z};
111 [[nodiscard]]
Box operator() (Box
const& box)
const noexcept {
125 int i_index (
int i)
const noexcept {
126 return (i < Lx/2) ? -1-i : 2*Lx-1-i;
130 int j_index (
int j)
const noexcept {
133 }
else if (j >= Ly) {
135 }
else if (j < Ly/2) {
143 IntVect operator() (IntVect
const& iv)
const noexcept {
148 Dim3 operator() (Dim3
const& a)
const noexcept {
149 return Dim3{.x = i_index(a.x), .y = j_index(a.y), .z = a.z};
152 [[nodiscard]]
Box operator() (Box
const& box)
const noexcept {
185template <BaseFabType FAB,
class DTOS,
class Proj>
186requires (IsCallableR<Dim3, DTOS, Dim3>::value && IsFabProjection<Proj, FAB>::value)
188local_copy_cpu (FabArray<FAB>& dest,
const FabArray<FAB>& src,
int dcomp,
int scomp,
int ncomp,
191 const auto N_locs =
static_cast<int>(local_tags.size());
192 if (N_locs == 0) {
return; }
194#pragma omp parallel for
196 for (
int itag = 0; itag < N_locs; ++itag) {
197 const auto& tag = local_tags[itag];
198 auto const& sfab = src.const_array(tag.srcIndex);
199 auto const& dfab = dest.array (tag.dstIndex);
202 auto const si = dtos(Dim3{.x = i, .y = j, .z = k});
203 dfab(i,j,k,dcomp+n) = proj(sfab,si,scomp+n);
213template <BaseFabType FAB,
class DTOS,
class Proj>
214requires (IsCallableR<Dim3, DTOS, Dim3>::value && IsFabProjection<Proj, FAB>::value)
216unpack_recv_buffer_cpu (FabArray<FAB>& mf,
int dcomp,
int ncomp, Vector<char*>
const& recv_data,
217 Vector<std::size_t>
const& recv_size,
218 Vector<FabArrayBase::CopyComTagsContainer const*>
const& recv_cctc,
219 DTOS
const& dtos, Proj
const& proj)
noexcept
223 const auto N_rcvs =
static_cast<int>(recv_cctc.size());
224 if (N_rcvs == 0) {
return; }
226 using T =
typename FAB::value_type;
228#pragma omp parallel for
230 for (
int ircv = 0; ircv < N_rcvs; ++ircv) {
231 const char* dptr = recv_data[ircv];
232 auto const& cctc = *recv_cctc[ircv];
233 for (
auto const& tag : cctc) {
234 auto const& dfab = mf.array(tag.dstIndex);
237 auto const si = dtos(Dim3{.x = i, .y = j, .z = k});
238 dfab(i, j, k, dcomp + n) = proj(sfab, si, n);
240 dptr += tag.sbox.numPts() * ncomp *
sizeof(T);
241 AMREX_ASSERT(dptr <= recv_data[ircv] + recv_size[ircv]);
248struct Array4Array4Box {
250 Array4<T const> sfab;
254 Box const& box () const noexcept {
return dbox; }
257template <BaseFabType FAB,
class DTOS,
class Proj>
258requires (IsCallableR<Dim3, DTOS, Dim3>::value && IsFabProjection<Proj, FAB>::value)
260local_copy_gpu (FabArray<FAB>& dest,
const FabArray<FAB>& src,
int dcomp,
int scomp,
int ncomp,
261 FabArrayBase::CopyComTagsContainer
const& local_tags, DTOS
const& dtos, Proj
const& proj)
noexcept
263 int N_locs = local_tags.
size();
264 if (N_locs == 0) {
return; }
266 using T =
typename FAB::value_type;
267 Vector<Array4Array4Box<T> > loc_copy_tags;
268 loc_copy_tags.reserve(N_locs);
269 for (
auto const& tag : local_tags) {
270 loc_copy_tags.push_back(Array4Array4Box<T>{.dfab = dest.array(tag.dstIndex),
271 .sfab = src.const_array(tag.srcIndex),
276 Array4Array4Box<T>
const& tag)
noexcept
278 auto const si = dtos(Dim3{.x = i, .y = j, .z = k});
279 tag.dfab(i,j,k,dcomp+n) = proj(tag.sfab, si, scomp+n);
283template <BaseFabType FAB,
class DTOS,
class Proj>
284requires (IsCallableR<Dim3, DTOS, Dim3>::value && IsFabProjection<Proj, FAB>::value)
286unpack_recv_buffer_gpu (FabArray<FAB>& mf,
int scomp,
int ncomp,
287 Vector<char*>
const& recv_data,
288 Vector<std::size_t>
const& recv_size,
289 Vector<FabArrayBase::CopyComTagsContainer const*>
const& recv_cctc,
290 DTOS
const& dtos, Proj
const& proj)
294 const int N_rcvs = recv_cctc.size();
295 if (N_rcvs == 0) {
return; }
297 char* pbuffer = recv_data[0];
299 std::size_t szbuffer = 0;
302 if (not ParallelDescriptor::UseGpuAwareMpi()) {
304 szbuffer = (recv_data[N_rcvs-1]-recv_data[0]) + recv_size[N_rcvs-1];
306 Gpu::copyAsync(Gpu::hostToDevice,recv_data[0],recv_data[0]+szbuffer,pbuffer);
307 Gpu::streamSynchronize();
311 using T =
typename FAB::value_type;
312 using TagType = Array4Array4Box<T>;
313 Vector<TagType> tags;
314 tags.reserve(N_rcvs);
316 for (
int k = 0; k < N_rcvs; ++k)
318 std::size_t
offset = recv_data[k]-recv_data[0];
319 const char* dptr = pbuffer +
offset;
320 auto const& cctc = *recv_cctc[k];
321 for (
auto const& tag : cctc)
323 tags.emplace_back(TagType{mf.array(tag.dstIndex),
326 dptr += tag.dbox.numPts() * ncomp *
sizeof(T);
332 Array4Array4Box<T>
const& tag)
noexcept
334 auto const si = dtos(Dim3{.x = i, .y = j, .z = k});
335 tag.dfab(i,j,k,scomp+n) = proj(tag.sfab, si ,n);
340 if (pbuffer != recv_data[0]) {
346template <
typename DTOS>
347requires (IsIndexMapping<DTOS>::value)
348MultiBlockCommMetaData::MultiBlockCommMetaData (
const FabArrayBase& dst,
const Box& dstbox,
const FabArrayBase& src,
349 const IntVect& ngrow, DTOS
const& dtos)
350 : MultiBlockCommMetaData(dst.boxArray(), dst.DistributionMap(), dstbox, src.boxArray(),
351 src.DistributionMap(), ngrow, dtos) {}
353template <
typename DTOS>
354requires (IsIndexMapping<DTOS>::value)
355MultiBlockCommMetaData::MultiBlockCommMetaData (
const BoxArray& dstba,
const DistributionMapping& dstdm,
356 const Box& dstbox,
const BoxArray& srcba,
357 const DistributionMapping& srcdm,
const IntVect& ngrow, DTOS
const& dtos)
359 define(dstba, dstdm, dstbox, srcba, srcdm, ngrow, dtos);
362template <
typename DTOS>
363requires (IsIndexMapping<DTOS>::value)
365MultiBlockCommMetaData::define (
const BoxArray& dstba,
const DistributionMapping& dstdm,
const Box& dstbox,
366 const BoxArray& srcba,
const DistributionMapping& srcdm,
const IntVect& ngrow,
369 m_LocTags = std::make_unique<FabArrayBase::CopyComTagsContainer>();
370 m_SndTags = std::make_unique<FabArrayBase::MapOfCopyComTagContainers>();
371 m_RcvTags = std::make_unique<FabArrayBase::MapOfCopyComTagContainers>();
372 const int myproc = ParallelDescriptor::MyProc();
373 for (
int i = 0, N =
static_cast<int>(dstba.size()); i < N; ++i) {
374 const int dest_owner = dstdm[i];
375 const Box partial_dstbox =
grow(dstba[i], ngrow) & dstbox;
376 if (partial_dstbox.isEmpty()) {
379 const Box partial_dstbox_mapped_in_src =
Image(dtos, partial_dstbox).
setType(srcba.ixType());
380 enum { not_first_only = 0, first_only = 1 };
381 std::vector<std::pair<int, Box>> boxes_from_src =
382 srcba.intersections(partial_dstbox_mapped_in_src, not_first_only, ngrow);
383 for (std::pair<int, Box> counted_box : boxes_from_src) {
384 const int k = counted_box.first;
385 const Box src_box = counted_box.second;
387 const int src_owner = srcdm[k];
388 if (dest_owner == myproc || src_owner == myproc) {
389 if (src_owner == dest_owner) {
390 const BoxList tilelist(src_box, FabArrayBase::comm_tile_size);
391 for (
const Box& tilebox : tilelist) {
393 if ((inverse_image & partial_dstbox).ok()) {
394 m_LocTags->emplace_back(inverse_image, tilebox, i, k);
399 if ((inverse_image & partial_dstbox).ok()) {
400 FabArrayBase::CopyComTagsContainer& copy_tags =
401 (src_owner == myproc) ? (*m_SndTags)[dest_owner]
402 : (*m_RcvTags)[src_owner];
403 copy_tags.emplace_back(inverse_image, src_box, i, k);
411template <BaseFabType FAB,
class DTOS,
class Proj>
416Comm_nowait (FabArray<FAB>& mf,
int scomp,
int ncomp, FabArrayBase::CommMetaData
const& cmd,
417 DTOS
const& dtos, Proj
const& proj)
420 if (ParallelContext::NProcsSub() == 1)
423 if (cmd.m_LocTags->empty()) {
return CommHandler{}; }
425 if (Gpu::inLaunchRegion()) {
426 local_copy_gpu(mf, mf, scomp, scomp, ncomp, *cmd.m_LocTags, dtos, proj);
430 local_copy_cpu(mf, mf, scomp, scomp, ncomp, *cmd.m_LocTags, dtos, proj);
432 return CommHandler{};
440 int SeqNum = ParallelDescriptor::SeqNum();
442 const auto N_locs = cmd.m_LocTags->size();
443 const auto N_rcvs = cmd.m_RcvTags->size();
444 const auto N_snds = cmd.m_SndTags->size();
446 if (N_locs == 0 && N_rcvs == 0 && N_snds == 0) {
448 return CommHandler{};
451 CommHandler handler{};
455 handler.recv.the_data = FabArray<FAB>::PostRcvs(*cmd.m_RcvTags, handler.recv.data, handler.recv.size,
456 handler.recv.rank, handler.recv.request, ncomp, SeqNum);
460 handler.send.the_data =
461 FabArray<FAB>::PrepareSendBuffers(*cmd.m_SndTags, handler.send.data, handler.send.size,
462 handler.send.rank, handler.send.request, handler.send.cctc, ncomp);
463 handler.send.id = FabArrayBase::getNextCommMetaDataId();
466 if (Gpu::inLaunchRegion()) {
467 FabArray<FAB>::pack_send_buffer_gpu(mf, scomp, ncomp, handler.send.data,
468 handler.send.size, handler.send.cctc, handler.send.id);
472 FabArray<FAB>::pack_send_buffer_cpu(mf, scomp, ncomp, handler.send.data,
473 handler.send.size, handler.send.cctc);
476 FabArray<FAB>::PostSnds(handler.send.data, handler.send.size, handler.send.rank, handler.send.request, SeqNum);
482 if (Gpu::inLaunchRegion()) {
483 local_copy_gpu(mf, mf, scomp, scomp, ncomp, *cmd.m_LocTags, dtos, proj);
487 local_copy_cpu(mf, mf, scomp, scomp, ncomp, *cmd.m_LocTags, dtos, proj);
496template <BaseFabType FAB,
class DTOS,
class Proj>
498Comm_finish (FabArray<FAB>& mf,
int scomp,
int ncomp, FabArrayBase::CommMetaData
const& cmd,
499 CommHandler handler, DTOS
const& dtos, Proj
const& proj)
501 if (ParallelContext::NProcsSub() == 1) {
return; }
503 const auto N_rcvs =
static_cast<int>(cmd.m_RcvTags->size());
506 handler.recv.cctc.resize(N_rcvs,
nullptr);
507 for (
int k = 0; k < N_rcvs; ++k) {
508 auto const& cctc = cmd.m_RcvTags->at(handler.recv.rank[k]);
509 handler.recv.cctc[k] = &cctc;
511 handler.recv.stats.resize(handler.recv.request.size());
512 ParallelDescriptor::Waitall(handler.recv.request, handler.recv.stats);
514 if (!CheckRcvStats(handler.recv.stats, handler.recv.size, handler.mpi_tag)) {
515 amrex::Abort(
"NonLocalBC::Comm_finish failed with wrong message size");
520 if (Gpu::inLaunchRegion())
523 handler.recv.size, handler.recv.cctc, dtos, proj);
528 handler.recv.size, handler.recv.cctc, dtos, proj);
532 if ( ! cmd.m_SndTags->empty() ) {
533 handler.send.stats.resize(handler.send.request.size());
534 ParallelDescriptor::Waitall(handler.send.request, handler.send.stats);
539template <BaseFabType FAB>
541Rotate90 (FabArray<FAB>& mf,
int scomp,
int ncomp, IntVect
const& nghost, Box
const& domain)
549 AMREX_ASSERT(scomp < mf.nComp() && scomp+ncomp <= mf.nComp());
550 AMREX_ASSERT(nghost.allLE(mf.nGrowVect()) && nghost[0] == nghost[1]);
552 if (nghost[0] <= 0) {
return; }
554 const FabArrayBase::RB90& TheRB90 = mf.getRB90(nghost, domain);
556 auto handler = Comm_nowait(mf, scomp, ncomp, TheRB90,Rotate90DstToSrc{},
559 Box corner(-nghost, IntVect{
AMREX_D_DECL(-1,-1,domain.bigEnd(2)+nghost[2])});
561#pragma omp parallel if (Gpu::notInLaunchRegion())
563 for (MFIter mfi(mf); mfi.isValid(); ++mfi) {
564 Box const& bx = corner & mfi.fabbox();
566 auto const& fab = mf.array(mfi);
569 fab(i,j,k,scomp+n) = fab(-i-1,-j-1,k,scomp+n);
575 Comm_finish(mf, scomp, ncomp, TheRB90, std::move(handler), Rotate90DstToSrc{},
582template <BaseFabType FAB>
584Rotate90 (FabArray<FAB>& mf, Box
const& domain)
586 Rotate90(mf, 0, mf.nComp(), mf.nGrowVect(), domain);
589template <BaseFabType FAB>
591Rotate180 (FabArray<FAB>& mf,
int scomp,
int ncomp, IntVect
const& nghost, Box
const& domain)
599 AMREX_ASSERT(scomp < mf.nComp() && scomp+ncomp <= mf.nComp());
602 if (nghost[0] <= 0) {
return; }
604 const FabArrayBase::RB180& TheRB180 = mf.getRB180(nghost, domain);
606 auto handler = Comm_nowait(mf, scomp, ncomp, TheRB180,
607 Rotate180Fn{domain.length(1)}, Identity{});
610 Comm_finish(mf, scomp, ncomp, TheRB180, std::move(handler),
611 Rotate180Fn{domain.length(1)}, Identity{});
617template <BaseFabType FAB>
619Rotate180 (FabArray<FAB>& mf, Box
const& domain)
621 Rotate180(mf, 0, mf.nComp(), mf.nGrowVect(), domain);
624template <BaseFabType FAB>
626FillPolar (FabArray<FAB>& mf,
int scomp,
int ncomp, IntVect
const& nghost, Box
const& domain)
634 AMREX_ASSERT(scomp < mf.nComp() && scomp+ncomp <= mf.nComp());
637 if (nghost[0] <= 0) {
return; }
639 const FabArrayBase::PolarB& ThePolarB = mf.getPolarB(nghost, domain);
641 auto handler = Comm_nowait(mf, scomp, ncomp, ThePolarB,
642 PolarFn{.Lx = domain.length(0), .Ly = domain.length(1)},
646 Comm_finish(mf, scomp, ncomp, ThePolarB, std::move(handler),
647 PolarFn{.Lx = domain.length(0), .Ly = domain.length(1)}, Identity{});
653template <BaseFabType FAB>
655FillPolar (FabArray<FAB>& mf, Box
const& domain)
657 FillPolar(mf, 0, mf.nComp(), mf.nGrowVect(), domain);
660template <BaseFabType FAB,
typename DTOS,
typename Proj>
661requires (IsCallableR<Dim3,DTOS,Dim3>::value && IsFabProjection<Proj,FAB>::value)
663FillBoundary_nowait (FabArray<FAB>& mf,
const FabArrayBase::CommMetaData& cmd,
664 int scomp,
int ncomp, DTOS
const& dtos, Proj
const& proj)
667 AMREX_ASSERT(scomp < mf.nComp() && scomp+ncomp <= mf.nComp());
668 return Comm_nowait(mf, scomp, ncomp, cmd, dtos, proj);
671template <BaseFabType FAB,
typename DTOS,
typename Proj>
672requires (IsCallableR<Dim3,DTOS,Dim3>::value && IsFabProjection<Proj,FAB>::value)
674FillBoundary_finish (CommHandler handler,
675 FabArray<FAB>& mf,
const FabArrayBase::CommMetaData& cmd,
676 int scomp,
int ncomp, DTOS
const& dtos, Proj
const& proj)
680 Comm_finish(mf, scomp, ncomp, cmd, std::move(handler), dtos, proj);
686template <
typename DTOS>
687Vector<std::pair<Box,Box>>
688get_src_dst_boxes (DTOS
const& dtos, Box
const& dstbox, Box
const& domain)
690 Vector<std::pair<Box,Box>> r;
693 if (!domain.contains(mapped_smallend) || !domain.contains(mapped_bigend)) {
699 auto dtype = dstbox.type();
703 Array<Array<std::pair<int,int>,2>,AMREX_SPACEDIM> ends;
704 Array<Array<std::pair<int,int>,2>,AMREX_SPACEDIM> dst_ends;
705 Array<int,AMREX_SPACEDIM> nboxes;
706 for (
int ddim = 0; ddim < AMREX_SPACEDIM; ++ddim) {
707 int sdim = perm[ddim];
708 auto mm = std::minmax(mapped_smallend[sdim],mapped_bigend[sdim]);
709 if (((sign[ddim] > 0) && (mapped_smallend[sdim] <= mapped_bigend[sdim])) ||
710 ((sign[ddim] < 0) && (mapped_bigend[sdim] <= mapped_smallend[sdim])))
714 dst_ends[ddim][0] = std::make_pair(dstbox.smallEnd(ddim),
715 dstbox.bigEnd(ddim));
718 ends[sdim][0].first = domain.smallEnd(sdim);
719 ends[sdim][0].second = mm.first;
720 ends[sdim][1].first = mm.second;
721 ends[sdim][1].second = domain.bigEnd(sdim);
722 int n0 = ends[sdim][0].second - ends[sdim][0].first;
723 int n1 = ends[sdim][1].second - ends[sdim][1].first;
724 if (mm.first == mapped_smallend[sdim]) {
725 dst_ends[ddim][0] = std::make_pair(dstbox.smallEnd(ddim),
726 dstbox.smallEnd(ddim)+n0);
727 dst_ends[ddim][1] = std::make_pair(dstbox.bigEnd(ddim)-n1,
728 dstbox.bigEnd(ddim));
730 dst_ends[ddim][0] = std::make_pair(dstbox.bigEnd(ddim)-n0,
731 dstbox.bigEnd(ddim));
732 dst_ends[ddim][1] = std::make_pair(dstbox.smallEnd(ddim),
733 dstbox.smallEnd(ddim)+n1);
738 r.reserve(
AMREX_D_TERM(nboxes[0],*nboxes[1],*nboxes[2]));
740#if (AMREX_SPACEDIM == 3)
741 for (
int kbox = 0; kbox < nboxes[2]; ++kbox) {
743#if (AMREX_SPACEDIM >=2 )
744 for (
int jbox = 0; jbox < nboxes[1]; ++jbox) {
746 for (
int ibox = 0; ibox < nboxes[0]; ++ibox)
752 ends[2][kbox].first)),
754 ends[1][jbox].second,
755 ends[2][kbox].second)),
758 dst_ends[1][div[1]].first,
759 dst_ends[2][div[2]].first)),
761 dst_ends[1][div[1]].second,
762 dst_ends[2][div[2]].second)),
769template <
typename DTOS>
770Box get_dst_subbox (DTOS
const& dtos, std::pair<Box,Box>
const& sdboxes,
771 Box
const& srcsubbox)
773 Box const& srcbox = sdboxes.first;
774 Box const& dstbox = sdboxes.second;
775 if (srcbox == srcsubbox) {
780 Box dstsubbox = dstbox;
781 for (
int ddim = 0; ddim < AMREX_SPACEDIM; ++ddim) {
782 int sdim = perm[ddim];
783 if (sign[ddim] > 0) {
784 dstsubbox.
growLo(ddim, srcbox.smallEnd(sdim)-srcsubbox.smallEnd(sdim));
785 dstsubbox.
growHi(ddim, srcsubbox.bigEnd(sdim)-srcbox.bigEnd(sdim));
787 dstsubbox.
growLo(ddim, srcsubbox.bigEnd(sdim)-srcbox.bigEnd(sdim));
788 dstsubbox.
growHi(ddim, srcbox.smallEnd(sdim)-srcsubbox.smallEnd(sdim));
797 void split_boxes (BoxList& bl, Box
const& domain);
801template <BaseFabType FAB,
typename DTOS>
802requires (IsCallableR<Dim3,DTOS,Dim3>::value)
803FabArrayBase::CommMetaData
804makeFillBoundaryMetaData (FabArray<FAB>& mf, IntVect
const& nghost,
805 Geometry
const& geom, DTOS
const& dtos)
807 FabArrayBase::CommMetaData cmd;
808 cmd.m_LocTags = std::make_unique<FabArrayBase::CopyComTagsContainer>();
809 cmd.m_SndTags = std::make_unique<FabArrayBase::MapOfCopyComTagContainers>();
810 cmd.m_RcvTags = std::make_unique<FabArrayBase::MapOfCopyComTagContainers>();
813 mf.define_fb_metadata(cmd, nghost,
false, geom.periodicity(),
false);
815 BoxArray
const& ba = mf.boxArray();
816 DistributionMapping
const& dm = mf.DistributionMap();
820 const int myproc = ParallelDescriptor::MyProc();
821 const auto nboxes =
static_cast<int>(ba.size());
822 std::vector<std::pair<int,Box> > isects;
824 for (
int i = 0; i < nboxes; ++i) {
827 if (bl.isEmpty()) {
continue; }
829 detail::split_boxes(bl, dombox);
831 const int dst_owner = dm[i];
832 for (
auto const& dst_box : bl) {
833 auto const& src_dst_boxes = get_src_dst_boxes(dtos, dst_box, dombox);
834 for (
auto const& sd_box_pair : src_dst_boxes) {
835 ba.intersections(sd_box_pair.first, isects);
836 for (
auto const& is : isects) {
837 int const k = is.first;
838 Box const src_b = is.second;
839 int const src_owner = dm[k];
840 if (dst_owner == myproc || src_owner == myproc) {
841 Box const& dst_b = get_dst_subbox(dtos, sd_box_pair, src_b);
842 if (src_owner == dst_owner) {
843 cmd.m_LocTags->emplace_back(dst_b, src_b, i, k);
845 auto& tags = (dst_owner == myproc) ?
846 (*cmd.m_RcvTags)[src_owner] :
847 (*cmd.m_SndTags)[dst_owner];
848 tags.emplace_back(dst_b, src_b, i, k);
859struct SphThetaPhiRIndexMapping
861 SphThetaPhiRIndexMapping (Box
const& a_domain)
870 Dim3 operator() (Dim3
const& ijk)
const noexcept
877 bool imd = i >= 0 && i < nx;
880 bool jmd = j >= 0 && j < ny;
882 bool kmd = k >= 0 && k < nz;
885 if (ilo && jmd && kmd)
887 return Dim3{.x = -1-i, .y = (j+ny/2)%ny, .z = k};
889 else if (ihi && jmd && kmd)
891 return Dim3{.x = 2*nx-1-i, .y = (j+ny/2)%ny, .z = k};
893 else if (imd && jlo && kmd)
895 return Dim3{.x = i, .y = j+ny, .z = k};
897 else if (imd && jhi && kmd)
899 return Dim3{.x = i, .y = j-ny, .z = k};
901 else if (imd && jmd && klo)
903 return Dim3{.x = nx-1-i, .y = (j+ny/2)%ny, .z = -1-k};
905 else if (ilo && jlo && kmd)
907 return Dim3{.x = -1-i, .y = (j+ny/2)%ny, .z = k};
909 else if (ihi && jlo && kmd)
911 return Dim3{.x = 2*nx-1-i, .y = (j+ny/2)%ny, .z = k};
913 else if (ilo && jhi && kmd)
915 return Dim3{.x = -1-i, .y = (j+ny/2)%ny, .z = k};
917 else if (ihi && jhi && kmd)
919 return Dim3{.x = 2*nx-1-i, .y = (j+ny/2)%ny, .z = k};
921 else if (imd && jlo && klo)
923 return Dim3{.x = nx-1-i, .y = (j+ny/2)%ny, .z = -1-k};
925 else if (imd && jhi && klo)
927 return Dim3{.x = nx-1-i, .y = (j+ny/2)%ny, .z = -1-k};
935 [[nodiscard]]
IntVect sign (Dim3
const& ijk)
const noexcept
939 }
else if (ijk.z >=0 && ijk.z < nz &&
940 (ijk.x < 0 || ijk.x >= nx)) {
947 [[nodiscard]]
IntVect permutation (Dim3
const& )
const noexcept
956struct SphThetaPhiRComponentMapping
958 SphThetaPhiRComponentMapping (Box
const& a_domain,
int a_start_index)
962 scomp(a_start_index) {}
964 template <
typename T>
966 T operator()(Array4<const T>
const& a, Dim3
const& ijk,
int n)
const noexcept
973 if ((i >= 0 && i < nx) &&
974 (j < 0 || j >= ny) &&
975 (k >= 0 && k < nz)) {
982 }
else if (n == scomp+2) {
997extern template MultiBlockCommMetaData
ParallelCopy(FabArray<FArrayBox>& dest,
const Box& destbox,
998 const FabArray<FArrayBox>& src,
int destcomp,
999 int srccomp,
int numcomp,
const IntVect& ngrow,
1000 MultiBlockIndexMapping
const&, Identity
const&);
#define BL_PROFILE(a)
Definition AMReX_BLProfiler.H:562
#define BL_ASSERT(EX)
Definition AMReX_BLassert.H:39
#define AMREX_ASSERT(EX)
Definition AMReX_BLassert.H:38
#define AMREX_FORCE_INLINE
Definition AMReX_Extension.H:124
#define AMREX_HOST_DEVICE_PARALLEL_FOR_4D(...)
Definition AMReX_GpuLaunchMacrosC.nolint.H:111
#define AMREX_GPU_DEVICE
Definition AMReX_GpuQualifiers.H:18
#define AMREX_GPU_HOST_DEVICE
Definition AMReX_GpuQualifiers.H:20
Array4< int const > offset
Definition AMReX_HypreMLABecLap.cpp:1131
#define AMREX_D_TERM(a, b, c)
Definition AMReX_SPACE.H:172
#define AMREX_D_DECL(a, b, c)
Definition AMReX_SPACE.H:171
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.
__host__ __device__ IntVectND< dim > size() const noexcept
Return the length of the BoxND.
Definition AMReX_Box.H:160
__host__ __device__ BoxND & growLo(int idir, int n_cell=1) noexcept
Grow on the low end by n_cell cells in direction idir (negative shrinks).
Definition AMReX_Box.H:690
__host__ __device__ BoxND & growHi(int idir, int n_cell=1) noexcept
Grow on the high end by n_cell cells in direction idir (negative shrinks).
Definition AMReX_Box.H:702
__host__ __device__ BoxND & setType(const IndexTypeND< dim > &t) noexcept
Set indexing type.
Definition AMReX_Box.H:534
CopyComTag::CopyComTagsContainer CopyComTagsContainer
Definition AMReX_FabArrayBase.H:236
__host__ __device__ Dim3 ubound(Array4< T > const &a) noexcept
Return the inclusive upper bounds of an Array4 in Dim3 form.
Definition AMReX_Array4.H:1365
__host__ __device__ Dim3 length(Array4< T > const &a) noexcept
Return the spatial extents of an Array4 in Dim3 form.
Definition AMReX_Array4.H:1379
__host__ __device__ Dim3 lbound(Array4< T > const &a) noexcept
Return the inclusive lower bounds of an Array4 in Dim3 form.
Definition AMReX_Array4.H:1351
__host__ __device__ BoxND< dim > convert(const BoxND< dim > &b, const IntVectND< dim > &typ) noexcept
Return a copy of b converted to the nodal flags typ.
Definition AMReX_Box.H:1630
__host__ __device__ BoxND< dim > grow(const BoxND< dim > &b, int i) noexcept
Return a copy of b grown uniformly by i cells in every direction.
Definition AMReX_Box.H:1326
Arena * The_Arena()
Definition AMReX_Arena.cpp:815
Definition AMReX_NonLocalBC.cpp:39
void Rotate90(FabArray< FAB > &mf, int scomp, int ncomp, IntVect const &nghost, Box const &domain)
void unpack_recv_buffer_cpu(FabArray< FAB > &mf, int dcomp, int ncomp, Vector< char * > const &recv_data, Vector< std::size_t > const &recv_size, Vector< FabArrayBase::CopyComTagsContainer const * > const &recv_cctc, DTOS const &dtos=DTOS{}, Proj const &proj=Proj{}) noexcept
Box InverseImage(DTOS const &dtos, const Box &box)
Applies the inverse Dim3 to Dim3 mapping onto Boxes without changing the index type.
Definition AMReX_NonLocalBC.H:189
void Rotate180(FabArray< FAB > &mf, int scomp, int ncomp, IntVect const &nghost, Box const &domain)
void local_copy_cpu(FabArray< FAB > &dest, const FabArray< FAB > &src, int dcomp, int scomp, int ncomp, FabArrayBase::CopyComTagsContainer const &local_tags, DTOS const &dtos=DTOS{}, Proj const &proj=Proj{}) noexcept
void FillPolar(FabArray< FAB > &mf, int scomp, int ncomp, IntVect const &nghost, Box const &domain)
void local_copy_gpu(FabArray< FAB > &dest, const FabArray< FAB > &src, int dcomp, int scomp, int ncomp, FabArrayBase::CopyComTagsContainer const &local_tags, DTOS const &dtos=DTOS{}, Proj const &proj=Proj{}) noexcept
Box Image(DTOS const &dtos, const Box &box)
Applies the Dim3 to Dim3 mapping onto Boxes but does not change the index type.
Definition AMReX_NonLocalBC.H:123
void unpack_recv_buffer_gpu(FabArray< FAB > &mf, int scomp, int ncomp, Vector< char * > const &recv_data, Vector< std::size_t > const &recv_size, Vector< FabArrayBase::CopyComTagsContainer const * > const &recv_cctc, DTOS const &dtos=DTOS{}, Proj const &proj=Proj{})
int SeqNum() noexcept
Returns sequential message sequence numbers, usually used as tags for send/recv.
Definition AMReX_ParallelDescriptor.H:678
__host__ __device__ void ignore_unused(const Ts &...)
No-op helper that marks variables as intentionally unused.
Definition AMReX.H:259
__host__ __device__ Array4< T > makeArray4(T *p, Box const &bx, int ncomp) noexcept
Definition AMReX_BaseFab.H:123
void ParallelFor(TypeList< CTOs... > ctos, std::array< int, sizeof...(CTOs)> const &runtime_options, T N, F &&f)
Definition AMReX_CTOParallelForImpl.H:202
BoxND< 3 > Box
Box is an alias for amrex::BoxND instantiated with AMREX_SPACEDIM.
Definition AMReX_BaseFwd.H:35
BoxList boxDiff(const Box &b1in, const Box &b2)
Returns a BoxList defining the complement of b2 in b1in.
Definition AMReX_BoxList.cpp:599
void ParallelCopy(MF &dst, MF const &src, int scomp, int dcomp, int ncomp, IntVect const &ng_src=IntVect(0), IntVect const &ng_dst=IntVect(0), Periodicity const &period=Periodicity::NonPeriodic())
dst = src w/ MPI communication
Definition AMReX_FabArrayUtility.H:2251
IntVectND< 3 > IntVect
IntVect is an alias for amrex::IntVectND instantiated with AMREX_SPACEDIM.
Definition AMReX_BaseFwd.H:38
void LoopConcurrentOnCpu(Dim3 lo, Dim3 hi, F const &f) noexcept
Definition AMReX_Loop.H:388
void Abort(const std::string &msg)
Print a fatal-error message to stderr and abort execution.
Definition AMReX.cpp:242