Block-Structured AMR Software Framework
Loading...
Searching...
No Matches
AMReX_NonLocalBC.H
Go to the documentation of this file.
1#ifndef AMREX_NONLOCAL_BC_H_
2#define AMREX_NONLOCAL_BC_H_
3#include <AMReX_Config.H>
4#include <AMReX_Concepts.H>
5#include <AMReX_TypeTraits.H>
6#include <AMReX_FabArray.H>
7#include <AMReX_FArrayBox.H>
8
9namespace amrex::NonLocalBC {
10
12// [concept.IndexMapping]
13//
14
16template <typename T, typename... Args>
17using Inverse_t = decltype(std::declval<T>().Inverse(std::declval<Args>()...));
18
20template <typename T>
21struct HasInverseMemFn : IsDetectedExact<Dim3, Inverse_t, T, Dim3> {};
22
25template <class IndexMap>
27 : Conjunction<IsCallableR<Dim3, IndexMap&, const Dim3&>,
28 HasInverseMemFn<const IndexMap&>> {};
29
31// [IndexMapping.MultiBlockIndexMapping]
32//
33
45
52 [[nodiscard]] AMREX_GPU_HOST_DEVICE Dim3 operator()(Dim3 i) const noexcept {
53 int iv[3]{i.x, i.y, i.z};
54 int iv_new[3]{};
55 for (int d = 0; d < AMREX_SPACEDIM; ++d) {
56 iv_new[d] = sign[d] * (iv[permutation[d]] - offset[d]);
57 }
58 return Dim3{.x = iv_new[0], .y = iv_new[1], .z = iv_new[2]};
59 }
60
67 [[nodiscard]] AMREX_GPU_HOST_DEVICE Dim3 Inverse(Dim3 i) const noexcept {
68 int iv_new[3]{i.x, i.y, i.z};
69 int iv[3]{};
70 for (int d = 0; d < AMREX_SPACEDIM; ++d) {
71 AMREX_ASSERT(sign[d] == 1 || sign[d] == -1);
72 iv[permutation[d]] = iv_new[d] * sign[d] + offset[d];
73 }
74 return Dim3{.x = iv[0], .y = iv[1], .z = iv[2]};
75 }
76
77 [[nodiscard]] IndexType operator()(IndexType it) const noexcept {
78 return IndexType{IntVect{AMREX_D_DECL(it[permutation[0]], it[permutation[1]], it[permutation[2]])}};
79 }
80
81 [[nodiscard]] IndexType Inverse(IndexType it) const noexcept {
82 IntVect inverse_permutation;
83 for (int i = 0; i < AMREX_SPACEDIM; ++i) {
84 inverse_permutation[permutation[i]] = i;
85 }
86 return IndexType{IntVect{AMREX_D_DECL(it[inverse_permutation[0]], it[inverse_permutation[1]], it[inverse_permutation[2]])}};
87 }
88};
89
102template <typename DTOS>
105Apply(DTOS const& dtos, const IntVect& iv)
106{
107 Dim3 i = dtos(iv.dim3());
108 return IntVect{AMREX_D_DECL(i.x, i.y, i.z)};
109}
110
120template <typename DTOS>
122Box
123Image (DTOS const& dtos, const Box& box)
124{
125 IntVect mapped_smallEnd = Apply(dtos, box.smallEnd());
126 IntVect mapped_bigEnd = Apply(dtos, box.bigEnd());
127 IntVect smallEnd;
128 IntVect bigEnd;
129 for (int d = 0; d < AMREX_SPACEDIM; ++d) {
130 smallEnd[d] = std::min(mapped_smallEnd[d], mapped_bigEnd[d]);
131 bigEnd[d] = std::max(mapped_smallEnd[d], mapped_bigEnd[d]);
132 }
133 return Box{smallEnd, bigEnd, box.ixType()};
134}
135
145template <typename DTOS>
147Box
148Image (DTOS const& dtos, const Box& box)
149{
150 // "Forget" the index type mapping and invoke Image without changing the index type.
151 Box srcbox = Image([&dtos](Dim3 d) { return dtos(d); }, box);
152 // Fix the index type of the resulting box
153 srcbox.setType(dtos(box.ixType()));
154 return srcbox;
155}
156
169template <typename DTOS>
170requires (HasInverseMemFn<DTOS>::value)
172ApplyInverse(DTOS const& dtos, const IntVect& iv)
173{
174 return Apply([&dtos](Dim3 i) { return dtos.Inverse(i); }, iv);
175}
176
186template <typename DTOS>
187requires (HasInverseMemFn<DTOS>::value && !IsCallableR<IndexType, DTOS, IndexType>::value)
188Box
189InverseImage (DTOS const& dtos, const Box& box)
190{
191 return Image([&dtos](Dim3 i) { return dtos.Inverse(i); }, box);
192}
193
203template <typename DTOS>
204requires (HasInverseMemFn<DTOS>::value && IsCallableR<IndexType, DTOS, IndexType>::value)
205Box
206InverseImage (DTOS const& dtos, const Box& box)
207{
208 return Image([&dtos](auto&& i) { return dtos.Inverse(i); }, box);
209}
210
212static_assert(IsIndexMapping<MultiBlockIndexMapping>(), // NOLINT(bugprone-throw-keyword-missing)
213 "MultiBlockIndexMapping is expected to satisfy IndexMapping");
214
216// [class.MultiBlockCommMetaData]
217//
218
225
229 template <typename DTOS>
230 requires (IsIndexMapping<DTOS>::value)
231 MultiBlockCommMetaData(const FabArrayBase& dst, const Box& dstbox, const FabArrayBase& src,
232 const IntVect& ngrow, DTOS const& dtos);
233
237 template <typename DTOS>
240 const Box& dstbox, const BoxArray& srcba,
241 const DistributionMapping& srcdm, const IntVect& ngrow, DTOS const& dtos);
242
244
267 template <typename DTOS>
269 void define(const BoxArray& dstba, const DistributionMapping& dstdm, const Box& dstbox,
270 const BoxArray& srcba, const DistributionMapping& srcdm, const IntVect& ngrow,
271 DTOS const& dtos);
272};
273
275// [concept.FabProjection]
276//
277
279template <typename P, BaseFabType FAB>
281 : IsCallableR<typename FAB::value_type, P, Array4<const typename FAB::value_type>, Dim3, int>
282{};
283
285// [FabProjection.Identity]
286// [IndexMapping.Identity]
287
291struct Identity {
293 constexpr Dim3 operator()(Dim3 i) const noexcept { return i; }
295 [[nodiscard]] static constexpr Dim3 Inverse(Dim3 i) noexcept { return i; }
296
298 template <typename T>
299 constexpr T operator()(Array4<const T> array, Dim3 i, int comp = 0) const
300 noexcept(noexcept(array(i.x, i.y, i.z, comp))) {
301 return array(i.x, i.y, i.z, comp);
302 }
303
305 constexpr int operator()(int i) const noexcept { return i; }
306};
307static constexpr Identity identity{};
308
309static_assert(sizeof(Identity) == 1 );
310static_assert(std::is_trivially_default_constructible_v<Identity> );
311static_assert(std::is_trivially_copy_assignable_v<Identity> );
312static_assert(std::is_trivially_copy_constructible_v<Identity> );
313static_assert(IsIndexMapping<Identity>() ); // NOLINT(bugprone-throw-keyword-missing)
314static_assert(IsFabProjection<Identity, FArrayBox>() ); // NOLINT(bugprone-throw-keyword-missing)
315
317// [FabProjection.MapComponents]
318
325template <typename Base, typename Map = Identity> struct MapComponents {
326 static_assert(IsCallable<Base, Array4<const Real>, Dim3, int>::value,
327 "Base needs to be a callable function: (Array4<const T>, Dim3, i) -> auto.");
328
330 "Map needs to be a callable function: int -> int.");
331
332 Base base;
333 Map map;
334
335 template <typename T>
337 constexpr decltype(auto) operator()(Array4<const T> array, Dim3 i, int comp) const
338 noexcept(noexcept(base(array, i, map(comp))))
339 {
340 return base(array, i, map(comp));
341 }
342};
343
344static_assert(std::is_trivially_copy_assignable<MapComponents<Identity>>() ); // NOLINT(bugprone-throw-keyword-missing)
345static_assert(std::is_trivially_copy_constructible<MapComponents<Identity>>() ); // NOLINT(bugprone-throw-keyword-missing)
346static_assert(IsFabProjection<MapComponents<Identity>, FArrayBox>() ); // NOLINT(bugprone-throw-keyword-missing)
347
349// [FabProjection.MapComponents.SwapComponents]
350
356template <int CompI, int CompJ> struct SwapComponents {
357 static_assert(CompI >= 0 && CompJ >= 0, "CompI >= 0 && CompJ >= 0");
358
362 constexpr int operator()(int i) const noexcept {
363 const int map[2] = {CompI, CompJ};
364 return i == CompI || i == CompJ ? map[std::size_t(i == CompI)] : i;
365 }
366};
367
368template <int CompI> struct SwapComponents<CompI, -1> {
369 static_assert(CompI >= 0, "CompI >= 0");
370
371 int J;
372 constexpr int operator()(int i) const noexcept {
373 const int map[2] = {CompI, J};
374 return i == CompI || i == J ? map[std::size_t(i == CompI)] : i;
375 }
376};
377
378template <int CompJ> struct SwapComponents<-1, CompJ> {
379 static_assert(CompJ >= 0, "CompJ >= 0");
380
381 int I;
382 constexpr int operator()(int i) const noexcept {
383 const int map[2] = {I, CompJ};
384 return i == I || i == CompJ ? map[std::size_t(i == I)] : i;
385 }
386};
387
388template <> struct SwapComponents<-1, -1> {
389 int I;
390 int J;
391 constexpr int operator()(int i) const noexcept {
392 const int map[2] = {I, J};
393 return i == I || i == J ? map[std::size_t(i == I)] : i;
394 }
395};
396
398
399template <int CompI, int CompJ> static constexpr SwapComponents<CompI, CompJ> swap_indices{};
400
401static_assert(sizeof(SwapComponents<0, 1>) == 1 );
402static_assert(sizeof(DynamicSwapComponents) == 2 * sizeof(int) );
403static_assert(sizeof(SwapComponents<0, -1>) == sizeof(int) );
404static_assert(sizeof(SwapComponents<-1, 1>) == sizeof(int) );
405static_assert(std::is_trivially_default_constructible<MapComponents<Identity, SwapComponents<0, 1>>>() ); // NOLINT(bugprone-throw-keyword-missing)
406static_assert(std::is_trivially_copy_assignable<MapComponents<Identity, SwapComponents<0, 1>>>() ); // NOLINT(bugprone-throw-keyword-missing)
407static_assert(std::is_trivially_copy_constructible<MapComponents<Identity, SwapComponents<0, 1>>>() ); // NOLINT(bugprone-throw-keyword-missing)
408static_assert(IsFabProjection<MapComponents<Identity, SwapComponents<0, 1>>, FArrayBox>() ); // NOLINT(bugprone-throw-keyword-missing)
409
410static_assert(swap_indices<0, 1>(0) == 1 );
411static_assert(swap_indices<0, 1>(1) == 0 );
412static_assert(swap_indices<0, 1>(2) == 2 );
413static_assert(DynamicSwapComponents{0, 1}(0) == 1 );
414static_assert(DynamicSwapComponents{0, 1}(1) == 0 );
415static_assert(DynamicSwapComponents{0, 1}(2) == 2 );
416
418// [class.CommData]
419// [class.CommHandler]
420
454
455#ifdef AMREX_USE_MPI
458 int n_components, std::size_t object_size, std::size_t align);
459
461void PostRecvs(CommData& recv, int mpi_tag);
462
464void PostSends(CommData& send, int mpi_tag);
465
470void TranslateRanks(CommData& comm, MPI_Comm c);
471
477
483void Alltoallv(CommData const& send, CommData& recv, MPI_Comm c);
484
489 int n_components, std::size_t object_size, std::size_t block_size,
490 MPI_Comm c);
491
496void Alltoall(CommData const& send, CommData& recv, std::size_t block_size, MPI_Comm c);
497
499void ReleaseCommBuffer(CommData& comm);
500
502void AcquireCommBuffer(CommData& comm);
503#endif
504
509#ifdef AMREX_USE_MPI
510 int mpi_tag{};
513#endif
514};
515
517// [concept.DataPacking]
518//
519template <typename... Args>
520using PrepareSendBuffers_t = decltype(PrepareSendBuffers(std::declval<Args>()...));
521
522template <typename... Args>
523using PrepareRecvBuffers_t = decltype(PrepareRecvBuffers(std::declval<Args>()...));
524
525template <typename... Args>
526using PackSendBuffers_t = decltype(PackSendBuffers(std::declval<Args>()...));
527
528template <typename... Args>
529using UnpackRecvBuffers_t = decltype(UnpackRecvBuffers(std::declval<Args>()...));
530
531template <typename... Args>
532using LocalCopy_t = decltype(LocalCopy(std::declval<Args>()...));
533
535#if defined(AMREX_USE_CUDA) && defined(_WIN32)
536template <typename DP, BaseFabType FAB> struct IsDataPacking : std::true_type {};
537#else
538template <typename DP, BaseFabType FAB>
541 IsDetected<LocalCopy_t, DP&, FabArray<FAB>&, const FabArray<FAB>&, const FabArrayBase::CopyComTagsContainer&>
542#ifdef AMREX_USE_MPI
543 ,IsDetected<PrepareSendBuffers_t, DP&, FabArray<FAB>&, const FabArray<FAB>&, CommData&, const FabArrayBase::MapOfCopyComTagContainers&>,
544 IsDetected<PrepareRecvBuffers_t, DP&, FabArray<FAB>&, const FabArray<FAB>&, CommData&, const FabArrayBase::MapOfCopyComTagContainers&>,
545 IsDetected<PackSendBuffers_t, DP&, const FabArray<FAB>&, CommData&>,
546 IsDetected<UnpackRecvBuffers_t, DP&, FabArray<FAB>&, CommData&>
547#endif
548 > {};
549#endif
550
551template <BaseFabType FAB, class DTOS = Identity, class Proj = Identity>
553void
554local_copy_cpu (FabArray<FAB>& dest, const FabArray<FAB>& src, int dcomp, int scomp, int ncomp,
555 FabArrayBase::CopyComTagsContainer const& local_tags, DTOS const& dtos = DTOS{},
556 Proj const& proj = Proj{}) noexcept;
557
558
559template <BaseFabType FAB, class DTOS = Identity, class Proj = Identity>
560requires (IsCallableR<Dim3, DTOS, Dim3>::value && IsFabProjection<Proj, FAB>::value)
561void
562unpack_recv_buffer_cpu (FabArray<FAB>& mf, int dcomp, int ncomp, Vector<char*> const& recv_data,
563 Vector<std::size_t> const& recv_size,
565 DTOS const& dtos = DTOS{}, Proj const& proj = Proj{}) noexcept;
566
567
568#ifdef AMREX_USE_GPU
569template <BaseFabType FAB, class DTOS = Identity, class Proj = Identity>
570requires (IsCallableR<Dim3, DTOS, Dim3>::value && IsFabProjection<Proj, FAB>::value)
571void
572local_copy_gpu (FabArray<FAB>& dest, const FabArray<FAB>& src, int dcomp, int scomp, int ncomp,
573 FabArrayBase::CopyComTagsContainer const& local_tags, DTOS const& dtos = DTOS{},
574 Proj const& proj = Proj{}) noexcept;
575
576
577template <BaseFabType FAB, class DTOS = Identity, class Proj = Identity>
578requires (IsCallableR<Dim3, DTOS, Dim3>::value && IsFabProjection<Proj, FAB>::value)
579void
580unpack_recv_buffer_gpu (FabArray<FAB>& mf, int scomp, int ncomp,
581 Vector<char*> const& recv_data,
582 Vector<std::size_t> const& recv_size,
584 DTOS const& dtos = DTOS{}, Proj const& proj = Proj{});
585#endif
586
588// [DataPacking.PackComponents]
589//
590// PackComponents is the simplest data packing policy.
591// This provides us with sane default behaviour that we can use when defining new
592// data packing policies.
593
600
602template <BaseFabType FAB>
603void
604LocalCopy (const PackComponents& components, FabArray<FAB>& dest, const FabArray<FAB>& src,
605 const FabArrayBase::CopyComTagsContainer& local_tags)
606{
607#ifdef AMREX_USE_GPU
608 if (Gpu::inLaunchRegion()) {
609 local_copy_gpu(dest, src, components.dest_component, components.src_component,
610 components.n_components, local_tags);
611 } else
612#endif
613 {
614 local_copy_cpu(dest, src, components.dest_component, components.src_component,
615 components.n_components, local_tags);
616 }
617}
618
619#ifdef AMREX_USE_MPI
621template <BaseFabType FAB>
622void
623PrepareSendBuffers (const PackComponents& components, FabArray<FAB>& dest, const FabArray<FAB>& src,
625{
626 using T = typename FAB::value_type;
627 ignore_unused(dest, src);
628 PrepareCommBuffers(comm, cctc, components.n_components, sizeof(T), alignof(T));
629}
630
632template <BaseFabType FAB>
633void
634PrepareRecvBuffers (const PackComponents& components, FabArray<FAB>& dest, const FabArray<FAB>& src,
636{
637 using T = typename FAB::value_type;
638 ignore_unused(dest, src);
639 PrepareCommBuffers(comm, cctc, components.n_components, sizeof(T), alignof(T));
640}
641
643template <BaseFabType FAB>
644void
645PackSendBuffers (const PackComponents& components, const FabArray<FAB>& src, CommData& send)
646{
647#ifdef AMREX_USE_GPU
648 if (Gpu::inLaunchRegion()) {
650 send.data, send.size, send.cctc, send.id);
651 } else
652#endif // AMREX_USE_GPU
653 {
655 send.data, send.size, send.cctc);
656 }
657}
658
660template <BaseFabType FAB>
661void
662UnpackRecvBuffers (const PackComponents& components, FabArray<FAB>& dest, const CommData& recv)
663{
664#ifdef AMREX_USE_GPU
665 if (Gpu::inLaunchRegion()) {
666 unpack_recv_buffer_gpu(dest, components.dest_component, components.n_components, recv.data,
667 recv.size, recv.cctc);
668 } else
669#endif // AMREX_USE_GPU
670 {
671 unpack_recv_buffer_cpu(dest, components.dest_component, components.n_components, recv.data,
672 recv.size, recv.cctc);
673 }
674}
675#endif // AMREX_USE_MPI
676
677static_assert(IsDataPacking<PackComponents, FArrayBox>(), // NOLINT(bugprone-throw-keyword-missing)
678 "PackComponents is expected to satisfy the concept DataPacking.");
679
681// [DataPacking.ApplyDtosAndProjectionOnReciever]
682//
686template <typename DTOS = Identity, typename FabProj = Identity>
688 constexpr ApplyDtosAndProjectionOnReciever() = default;
689 constexpr ApplyDtosAndProjectionOnReciever(const PackComponents& components, DTOS dtos_ = DTOS{}, FabProj proj_ = FabProj{})
690 : PackComponents(components), dtos(std::move(dtos_)), proj(std::move(proj_)) {}
691
692 DTOS dtos;
693 FabProj proj;
694
695 static_assert(IsCallableR<Dim3, DTOS, Dim3>::value, "DTOS needs to be a callable: Dim3 -> Dim3");
696 static_assert(IsFabProjection<FabProj, FArrayBox>(), "FabProj needs to be at least a projection on FArrayBox.");
697};
698
700template <BaseFabType FAB, typename DTOS, typename FabProj>
701void
703 const FabArray<FAB>& src, const FabArrayBase::CopyComTagsContainer& local_tags)
704{
705 static_assert(IsFabProjection<FabProj, FAB>(), "FabProj needs to be a projection for given FAB type.");
706#ifdef AMREX_USE_GPU
707 if (Gpu::inLaunchRegion()) {
708 local_copy_gpu(dest, src, packing.dest_component, packing.src_component,
709 packing.n_components, local_tags, packing.dtos, packing.proj);
710 } else
711#endif
712 {
713 local_copy_cpu(dest, src, packing.dest_component, packing.src_component,
714 packing.n_components, local_tags, packing.dtos, packing.proj);
715 }
716}
717
718#ifdef AMREX_USE_MPI
720template <BaseFabType FAB, typename DTOS, typename FabProj>
721void
723 FabArray<FAB>& dest, const CommData& recv)
724{
725 // If FAB is not FArrayBox we have not checked for the correct types yet.
726 static_assert(IsFabProjection<FabProj, FAB>(), "FabProj needs to be a projection for given FAB type.");
727#ifdef AMREX_USE_GPU
728 if (Gpu::inLaunchRegion()) {
729 unpack_recv_buffer_gpu(dest, packing.dest_component, packing.n_components, recv.data,
730 recv.size, recv.cctc, packing.dtos, packing.proj);
731 } else
732#endif // AMREX_USE_GPU
733 {
734 unpack_recv_buffer_cpu(dest, packing.dest_component, packing.n_components, recv.data,
735 recv.size, recv.cctc, packing.dtos, packing.proj);
736 }
737}
738#endif // AMREX_USE_MPI
739
740static_assert(IsDataPacking<ApplyDtosAndProjectionOnReciever<>, FArrayBox>(), // NOLINT(bugprone-throw-keyword-missing)
741 "ApplyDtosAndProjectionOnReciever<> is expected to satisfy the DataPacking concept.");
742
744// [ParallelCopy_nowait]
745
746static constexpr struct NoLocalCopy {} no_local_copy{};
747static constexpr struct DoLocalCopy {} do_local_copy{};
748
770template <BaseFabType FAB, typename DataPacking>
771requires (IsDataPacking<DataPacking, FAB>::value)
772#ifdef AMREX_USE_MPI
773[[nodiscard]] CommHandler
775 const FabArrayBase::CommMetaData& cmd, const DataPacking& data_packing)
776{
777 CommHandler handler{};
778 if (ParallelContext::NProcsSub() == 1) {
779 return handler;
780 }
781 //
782 // Do this before prematurely exiting if running in parallel.
783 // Otherwise sequence numbers will not match across MPI processes.
784 //
786
787 if (cmd.m_RcvTags && !(cmd.m_RcvTags->empty())) {
788 PrepareRecvBuffers(data_packing, dest, src, handler.recv, *cmd.m_RcvTags);
789 PostRecvs(handler.recv, handler.mpi_tag);
790 }
791
792 if (cmd.m_SndTags && !(cmd.m_SndTags->empty())) {
793 PrepareSendBuffers(data_packing, dest, src, handler.send, *cmd.m_SndTags);
794 PackSendBuffers(data_packing, src, handler.send);
795 PostSends(handler.send, handler.mpi_tag);
796 }
797 return handler;
798}
799#else
801 const FabArrayBase::CommMetaData&, const DataPacking&) {
802 return CommHandler{};
803}
804#endif
805
827template <BaseFabType FAB, typename DataPacking>
829#ifdef AMREX_USE_MPI
830[[nodiscard]]
831#endif
834 const FabArrayBase::CommMetaData& cmd, const DataPacking& data_packing)
835{
836 CommHandler comm = ParallelCopy_nowait(no_local_copy, dest, src, cmd, data_packing);
837 // Eagerly do the local work and hope for some overlap with communication
838 if (cmd.m_LocTags && !cmd.m_LocTags->empty()) {
839 LocalCopy(data_packing, dest, src, *cmd.m_LocTags);
840 }
841 return comm;
842}
843
844// [ParallelCopy_finish]
845
862template <BaseFabType FAB, typename DataPacking>
863requires (IsDataPacking<DataPacking, FAB>::value)
864void
865#ifdef AMREX_USE_MPI
867 const FabArrayBase::CommMetaData& cmd, const DataPacking& data_packing)
868{
869 // If any FabArray is empty we have nothing to do.
870 if (dest.empty()) {
871 return;
872 }
873 // Return if nothing do
874 if (ParallelContext::NProcsSub() == 1) {
875 return;
876 }
877 // Unpack receives
878 if (cmd.m_RcvTags && !(cmd.m_RcvTags->empty())) {
880#ifdef AMREX_DEBUG
881 if (!CheckRcvStats(handler.recv.stats, handler.recv.size, handler.mpi_tag)) {
882 amrex::Abort("NonLocalPC::ParallelCopy_finish failed with wrong message size");
883 }
884#endif
885 UnpackRecvBuffers(data_packing, dest, handler.recv);
886 }
887
888 // Wait for all sends to be done
889 if (cmd.m_SndTags && !(cmd.m_SndTags->empty())) {
891 }
892}
893#else
895#endif
896
914template <BaseFabType FAB, typename DataPacking>
915requires (IsDataPacking<DataPacking, FAB>::value)
916void
918 const FabArrayBase::CommMetaData& cmd, const DataPacking& data_packing)
919{
920 // Eagerly do the local work and hope for some overlap with communication
921 if (cmd.m_LocTags && !cmd.m_LocTags->empty()) {
922 LocalCopy(data_packing, dest, src, *cmd.m_LocTags);
923 }
924 ParallelCopy_finish(dest, std::move(handler), cmd, data_packing); // NOLINT
925}
926
928// [ParallelCopy_alltoallv]
929
954template <BaseFabType FAB, typename DataPacking>
955requires (IsDataPacking<DataPacking, FAB>::value)
956void
958 const FabArrayBase::CommMetaData& cmd, const DataPacking& data_packing,
959 CommHandler* cached = nullptr, MPI_Comm comm = MPI_COMM_NULL)
960{
961 if (dest.empty()) { return; }
962
963#ifdef AMREX_USE_MPI
964 if (comm == MPI_COMM_NULL) { comm = ParallelContext::CommunicatorSub(); }
965 int nprocs_comm;
966 MPI_Comm_size(comm, &nprocs_comm);
967 if (nprocs_comm > 1)
968 {
969 CommHandler local_handler{};
970 CommHandler& handler = cached ? *cached : local_handler;
971
972 static const FabArrayBase::MapOfCopyComTagContainers no_tags{};
973 auto const& rcv_tags = cmd.m_RcvTags ? *cmd.m_RcvTags : no_tags;
974 auto const& snd_tags = cmd.m_SndTags ? *cmd.m_SndTags : no_tags;
975
976 // PrepareCommBuffers sets the id even when there is nothing to communicate.
977 if (handler.send.id == std::numeric_limits<std::uint64_t>::max()) {
978 PrepareRecvBuffers(data_packing, dest, src, handler.recv, rcv_tags);
979 PrepareSendBuffers(data_packing, dest, src, handler.send, snd_tags);
980 TranslateRanks(handler.recv, comm);
981 TranslateRanks(handler.send, comm);
982 PrepareAlltoallvCounts(handler.recv, comm);
983 PrepareAlltoallvCounts(handler.send, comm);
984 } else {
985 AcquireCommBuffer(handler.recv);
986 AcquireCommBuffer(handler.send);
987 }
988
989 if (!snd_tags.empty()) {
990 PackSendBuffers(data_packing, src, handler.send);
991 }
992
993 // The local copy comes first. MPI_Ialltoallv would allow overlapping
994 // it, but it was slower than the blocking call on the systems tested.
995 if (cmd.m_LocTags && !cmd.m_LocTags->empty()) {
996 LocalCopy(data_packing, dest, src, *cmd.m_LocTags);
997 }
998
999 Alltoallv(handler.send, handler.recv, comm);
1000
1001 if (!rcv_tags.empty()) {
1002 UnpackRecvBuffers(data_packing, dest, handler.recv);
1003 }
1004 if (cached) {
1005 ReleaseCommBuffer(handler.send);
1006 ReleaseCommBuffer(handler.recv);
1007 }
1008 return;
1009 }
1010#else
1011 amrex::ignore_unused(cached, comm);
1012#endif
1013
1014 if (cmd.m_LocTags && !cmd.m_LocTags->empty()) {
1015 LocalCopy(data_packing, dest, src, *cmd.m_LocTags);
1016 }
1017}
1018
1023template <BaseFabType FAB, typename DTOS = Identity, typename Proj = Identity>
1024requires (IsCallableR<Dim3, DTOS, Dim3>::value && IsFabProjection<Proj, FAB>::value)
1025void
1027 const FabArrayBase::CommMetaData& cmd,
1028 int srccomp, int destcomp, int numcomp,
1029 DTOS const& dtos = DTOS{}, Proj const& proj = Proj{},
1030 CommHandler* cached = nullptr, MPI_Comm comm = MPI_COMM_NULL)
1031{
1032 PackComponents components{};
1033 components.dest_component = destcomp;
1034 components.src_component = srccomp;
1035 components.n_components = numcomp;
1036 ApplyDtosAndProjectionOnReciever<DTOS, Proj> packing{components, dtos, proj};
1037 ParallelCopy_alltoallv(dest, src, cmd, packing, cached, comm);
1038}
1039
1041// [ParallelCopy_alltoall]
1042
1050template <BaseFabType FAB, typename DataPacking>
1052void
1054 const FabArrayBase::CommMetaData& cmd, const DataPacking& data_packing,
1055 std::size_t block_size, CommHandler* cached = nullptr,
1056 MPI_Comm comm = MPI_COMM_NULL)
1057{
1058 if (dest.empty()) { return; }
1059
1060#ifdef AMREX_USE_MPI
1061 if (comm == MPI_COMM_NULL) { comm = ParallelContext::CommunicatorSub(); }
1062 int nprocs_comm;
1063 MPI_Comm_size(comm, &nprocs_comm);
1064 if (nprocs_comm > 1)
1065 {
1066 using T = typename FAB::value_type;
1067
1068 CommHandler local_handler{};
1069 CommHandler& handler = cached ? *cached : local_handler;
1070
1071 static const FabArrayBase::MapOfCopyComTagContainers no_tags{};
1072 auto const& rcv_tags = cmd.m_RcvTags ? *cmd.m_RcvTags : no_tags;
1073 auto const& snd_tags = cmd.m_SndTags ? *cmd.m_SndTags : no_tags;
1074
1075 if (handler.send.id == std::numeric_limits<std::uint64_t>::max()) {
1076 PrepareCommBuffersUniform(handler.recv, rcv_tags, data_packing.n_components,
1077 sizeof(T), block_size, comm);
1078 PrepareCommBuffersUniform(handler.send, snd_tags, data_packing.n_components,
1079 sizeof(T), block_size, comm);
1080 } else {
1081 AcquireCommBuffer(handler.recv);
1082 AcquireCommBuffer(handler.send);
1083 }
1084
1085 if (!snd_tags.empty()) {
1086 PackSendBuffers(data_packing, src, handler.send);
1087 }
1088
1089 if (cmd.m_LocTags && !cmd.m_LocTags->empty()) {
1090 LocalCopy(data_packing, dest, src, *cmd.m_LocTags);
1091 }
1092
1093 Alltoall(handler.send, handler.recv, block_size, comm);
1094
1095 if (!rcv_tags.empty()) {
1096 UnpackRecvBuffers(data_packing, dest, handler.recv);
1097 }
1098 if (cached) {
1099 ReleaseCommBuffer(handler.send);
1100 ReleaseCommBuffer(handler.recv);
1101 }
1102 return;
1103 }
1104#else
1105 amrex::ignore_unused(block_size, cached, comm);
1106#endif
1107
1108 if (cmd.m_LocTags && !cmd.m_LocTags->empty()) {
1109 LocalCopy(data_packing, dest, src, *cmd.m_LocTags);
1110 }
1111}
1112
1116template <BaseFabType FAB, typename DTOS = Identity, typename Proj = Identity>
1117requires (IsCallableR<Dim3, DTOS, Dim3>::value && IsFabProjection<Proj, FAB>::value)
1118void
1120 const FabArrayBase::CommMetaData& cmd,
1121 int srccomp, int destcomp, int numcomp,
1122 DTOS const& dtos, Proj const& proj,
1123 std::size_t block_size, CommHandler* cached = nullptr,
1124 MPI_Comm comm = MPI_COMM_NULL)
1125{
1126 PackComponents components{};
1127 components.dest_component = destcomp;
1128 components.src_component = srccomp;
1129 components.n_components = numcomp;
1130 ApplyDtosAndProjectionOnReciever<DTOS, Proj> packing{components, dtos, proj};
1131 ParallelCopy_alltoall(dest, src, cmd, packing, block_size, cached, comm);
1132}
1133
1156template <BaseFabType FAB, typename DTOS = Identity, typename Proj = Identity>
1157requires (IsCallableR<Dim3, DTOS, Dim3>::value && IsFabProjection<Proj, FAB>::value)
1158void
1160 SrcComp srccomp, DestComp destcomp, NumComps numcomp, DTOS const& dtos = DTOS{}, Proj const& proj = Proj{})
1161{
1162 PackComponents components{};
1163 components.dest_component = destcomp.i;
1164 components.src_component = srccomp.i;
1165 components.n_components = numcomp.n;
1166#if defined(__GNUC__) && !defined(__clang__)
1167#pragma GCC diagnostic push
1168#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
1169#endif
1170 ApplyDtosAndProjectionOnReciever<DTOS, Proj> packing{components, dtos, proj};
1171 CommHandler handler = ParallelCopy_nowait(dest, src, cmd, packing);
1172 ParallelCopy_finish(dest, std::move(handler), cmd, packing); // NOLINT
1173#if defined(__GNUC__) && !defined(__clang__)
1174#pragma GCC diagnostic pop
1175#endif
1176}
1177
1200template <BaseFabType FAB, typename DTOS = Identity, typename Proj = Identity>
1201requires (IsCallableR<Dim3, DTOS, Dim3>::value && IsFabProjection<Proj, FAB>::value)
1202void
1204 int srccomp, int destcomp, int numcomp, DTOS const& dtos = DTOS{}, Proj const& proj = Proj{})
1205{
1206 ParallelCopy(dest, src, cmd, SrcComp(srccomp), DestComp(destcomp), NumComps(numcomp), dtos, proj);
1207}
1208
1238template <BaseFabType FAB, typename DTOS = Identity, typename Proj = Identity>
1241ParallelCopy (FabArray<FAB>& dest, const Box& destbox, const FabArray<FAB>& src, SrcComp srccomp,
1242 DestComp destcomp, NumComps numcomp, const IntVect& ngrow, DTOS const& dtos = DTOS{}, Proj const& proj = Proj{})
1243{
1244 MultiBlockCommMetaData cmd(dest, destbox, src, ngrow, dtos);
1245 ParallelCopy(dest, src, cmd, srccomp, destcomp, numcomp, dtos, proj);
1246 return cmd;
1247}
1248
1278template <BaseFabType FAB, typename DTOS = Identity, typename Proj = Identity>
1281ParallelCopy (FabArray<FAB>& dest, const Box& destbox, const FabArray<FAB>& src, int srccomp,
1282 int destcomp, int numcomp, const IntVect& ngrow, DTOS const& dtos = DTOS{}, Proj const& proj = Proj{})
1283{
1284 return ParallelCopy(dest, destbox, src, SrcComp(srccomp), DestComp(destcomp), NumComps(numcomp), ngrow, dtos, proj);
1285}
1286
1287// Rotate90 fills the lo-x and lo-y boundary regions by rotating the data
1288// around (x=0,y=0) by 90 degrees in either direction. It also fills the
1289// corner of lo-x and lo-y boundary region by rotating the data by 180
1290// degrees.
1291
1292template <BaseFabType FAB>
1293void
1294Rotate90 (FabArray<FAB>& mf, int scomp, int ncomp, IntVect const& nghost, Box const& domain);
1295
1296template <BaseFabType FAB>
1297void
1298Rotate90 (FabArray<FAB>& mf, Box const& domain);
1299
1300// Rotate180 fills the lo-x boundary by rotating the data around
1301// (x=0,y=L_y/2) by 180 degrees.
1302
1303template <BaseFabType FAB>
1304void
1305Rotate180 (FabArray<FAB>& mf, int scomp, int ncomp, IntVect const& nghost, Box const& domain);
1306
1307template <BaseFabType FAB>
1308void
1309Rotate180 (FabArray<FAB>& mf, Box const& domain);
1310
1311// Fill the polar boundaries of the spherical coordinates (theta, phi, r).
1312// The lo-x boundary is filled with f(-x,y) = f(x,mod(y+pi,2*pi)), and
1313// the hi-x boundary is filled with f(pi+x,y) = f(pi-x,mod(y+pi,2*pi)).
1314
1315template <BaseFabType FAB>
1316void
1317FillPolar (FabArray<FAB>& mf, int scomp, int ncomp, IntVect const& nghost, Box const& domain);
1318
1319template <BaseFabType FAB>
1320void
1321FillPolar (FabArray<FAB>& mf, Box const& domain);
1322
1359template <BaseFabType FAB, typename DTOS, typename Proj = Identity>
1361[[nodiscard]]
1364 int scomp, int ncomp, DTOS const& dtos,
1365 Proj const& proj = Proj{});
1366
1402template <BaseFabType FAB, typename DTOS, typename Proj = Identity>
1403requires (IsCallableR<Dim3,DTOS,Dim3>::value && IsFabProjection<Proj,FAB>::value)
1404void
1407 int scomp, int ncomp, DTOS const& dtos,
1408 Proj const& proj = Proj{});
1409
1441template <BaseFabType FAB, typename DTOS, typename Proj = Identity>
1442requires (IsCallableR<Dim3,DTOS,Dim3>::value && IsFabProjection<Proj,FAB>::value)
1443void
1445 int scomp, int ncomp, DTOS const& dtos, Proj const& proj = Proj{})
1446{
1447 BL_PROFILE("FillBoundary(cmd)");
1448 auto handler = FillBoundary_nowait(mf, cmd, scomp, ncomp, dtos, proj);
1449 FillBoundary_finish(std::move(handler), mf, cmd, scomp, ncomp, dtos, proj);
1450}
1451
1466template <BaseFabType FAB, typename DTOS>
1467requires (IsCallableR<Dim3,DTOS,Dim3>::value)
1468[[nodiscard]]
1469FabArrayBase::CommMetaData
1471 Geometry const& geom, DTOS const& dtos);
1472
1473}
1474
1475#include <AMReX_NonLocalBCImpl.H>
1476
1477namespace amrex {
1482 using NonLocalBC::SphThetaPhiRIndexMapping;
1483 using NonLocalBC::SphThetaPhiRComponentMapping;
1492}
1493
1494#endif
#define BL_PROFILE(a)
Definition AMReX_BLProfiler.H:593
#define AMREX_ASSERT(EX)
Definition AMReX_BLassert.H:38
Floating-point specialization of BaseFab plus FAB I/O helpers.
Distributed container of FAB objects plus copy and fill utilities.
#define AMREX_GPU_HOST_DEVICE
Definition AMReX_GpuQualifiers.H:20
#define AMREX_D_DECL(a, b, c)
Definition AMReX_SPACE.H:171
Reference-counted collection of Boxes.
Definition AMReX_BoxArray.H:681
__host__ __device__ const IntVectND< dim > & bigEnd() const &noexcept
Return the inclusive upper bound of the box.
Definition AMReX_Box.H:136
__host__ __device__ IndexTypeND< dim > ixType() const noexcept
Return the indexing type.
Definition AMReX_Box.H:148
__host__ __device__ BoxND & setType(const IndexTypeND< dim > &t) noexcept
Set indexing type.
Definition AMReX_Box.H:534
__host__ __device__ const IntVectND< dim > & smallEnd() const &noexcept
Return the inclusive lower bound of the box.
Definition AMReX_Box.H:124
Calculates the distribution of FABs to MPI processes.
Definition AMReX_DistributionMapping.H:51
A Fortran Array of REALs.
Definition AMReX_FArrayBox.H:237
Base class for FabArray.
Definition AMReX_FabArrayBase.H:47
CopyComTag::CopyComTagsContainer CopyComTagsContainer
Definition AMReX_FabArrayBase.H:236
CopyComTag::MapOfCopyComTagContainers MapOfCopyComTagContainers
Definition AMReX_FabArrayBase.H:237
bool empty() const noexcept
Definition AMReX_FabArrayBase.H:94
An Array of FortranArrayBox(FAB)-like Objects.
Definition AMReX_FabArray.H:356
static void pack_send_buffer_gpu(FabArray< FAB > const &src, int scomp, int ncomp, Vector< char * > const &send_data, Vector< std::size_t > const &send_size, Vector< const CopyComTagsContainer * > const &send_cctc, std::uint64_t id)
static void pack_send_buffer_cpu(FabArray< FAB > const &src, int scomp, int ncomp, Vector< char * > const &send_data, Vector< std::size_t > const &send_size, Vector< const CopyComTagsContainer * > const &send_cctc)
Rectangular problem domain geometry.
Definition AMReX_Geometry.H:87
__host__ __device__ constexpr Dim3 dim3() const noexcept
Definition AMReX_IntVect.H:262
This class is a thin wrapper around std::vector. Unlike vector, Vector::operator[] provides bound che...
Definition AMReX_Vector.H:29
ArrayND< T, 4, true > Array4
Convenient alias for a 4D ArrayND with three spatial dimensions plus a component dimension.
Definition AMReX_Array4.H:1340
bool inLaunchRegion() noexcept
Definition AMReX_GpuControl.H:88
Definition AMReX_NonLocalBC.cpp:41
void AcquireCommBuffer(CommData &comm)
Allocate the_data of a prepared CommData again after ReleaseCommBuffer.
Definition AMReX_NonLocalBC.cpp:232
IntVect Apply(DTOS const &dtos, const IntVect &iv)
Applies the Dim3 to Dim3 mapping onto IntVects.
Definition AMReX_NonLocalBC.H:105
void Rotate90(FabArray< FAB > &mf, int scomp, int ncomp, IntVect const &nghost, Box const &domain)
decltype(PrepareRecvBuffers(std::declval< Args >()...)) PrepareRecvBuffers_t
Definition AMReX_NonLocalBC.H:523
void ReleaseCommBuffer(CommData &comm)
Free the_data of a prepared CommData, keeping the rest of the meta-data.
Definition AMReX_NonLocalBC.cpp:226
FabArrayBase::CommMetaData makeFillBoundaryMetaData(FabArray< FAB > &mf, IntVect const &nghost, Geometry const &geom, DTOS const &dtos)
Make metadata for FillBoundary.
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
void Alltoallv(CommData const &send, CommData &recv, MPI_Comm comm)
Exchange all send buffers for all recv buffers with one MPI_Alltoallv.
Definition AMReX_NonLocalBC.cpp:272
IntVect ApplyInverse(DTOS const &dtos, const IntVect &iv)
Applies the Dim3 to Dim3 invserse mapping onto IntVects.
Definition AMReX_NonLocalBC.H:172
void PrepareCommBuffers(CommData &comm, const FabArrayBase::MapOfCopyComTagContainers &cctc, int n_components, std::size_t object_size, std::size_t align)
Fill all class member variables of comm but the request and the stats vector.
Definition AMReX_NonLocalBC.cpp:45
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 PackSendBuffers(const PackComponents &components, const FabArray< FAB > &src, CommData &send)
Serializes FAB data without any knowledge of a DTOS nor a projection.
Definition AMReX_NonLocalBC.H:645
decltype(std::declval< T >().Inverse(std::declval< Args >()...)) Inverse_t
Return type of an InverseImage class member function.
Definition AMReX_NonLocalBC.H:17
CommHandler FillBoundary_nowait(FabArray< FAB > &mf, const FabArrayBase::CommMetaData &cmd, int scomp, int ncomp, DTOS const &dtos, Proj const &proj=Proj{})
Start communication to fill boundary.
void Alltoall(CommData const &send, CommData &recv, std::size_t block_size, MPI_Comm comm)
Exchange uniform blocks of block_size bytes with one MPI_Alltoall.
Definition AMReX_NonLocalBC.cpp:248
decltype(PrepareSendBuffers(std::declval< Args >()...)) PrepareSendBuffers_t
Definition AMReX_NonLocalBC.H:520
void ParallelCopy_finish(FabArray< FAB > &dest, CommHandler handler, const FabArrayBase::CommMetaData &cmd, const DataPacking &data_packing)
Definition AMReX_NonLocalBC.H:866
void Rotate180(FabArray< FAB > &mf, int scomp, int ncomp, IntVect const &nghost, Box const &domain)
void PrepareAlltoallvCounts(CommData &comm, MPI_Comm c)
Fill comm.counts and comm.displs for MPI_Alltoallv on communicator c.
Definition AMReX_NonLocalBC.cpp:159
void LocalCopy(const PackComponents &components, FabArray< FAB > &dest, const FabArray< FAB > &src, const FabArrayBase::CopyComTagsContainer &local_tags)
Dispatch local copies to the default behaviour that knows no DTOS nor projection.
Definition AMReX_NonLocalBC.H:604
static constexpr SwapComponents< CompI, CompJ > swap_indices
Definition AMReX_NonLocalBC.H:399
void PostSends(CommData &send, int mpi_tag)
Initiate all sends with MPI_Isend calls associated with tag mpi_tag.
Definition AMReX_NonLocalBC.cpp:123
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 PostRecvs(CommData &recv, int mpi_tag)
Initiate all recvieves with MPI_Irecv calls associated with tag mpi_tag.
Definition AMReX_NonLocalBC.cpp:107
SwapComponents<-1, -1 > DynamicSwapComponents
Definition AMReX_NonLocalBC.H:397
void FillBoundary_finish(CommHandler handler, FabArray< FAB > &mf, const FabArrayBase::CommMetaData &cmd, int scomp, int ncomp, DTOS const &dtos, Proj const &proj=Proj{})
Finish communication started by FillBoundary_nowait.
void FillPolar(FabArray< FAB > &mf, int scomp, int ncomp, IntVect const &nghost, Box const &domain)
void FillBoundary(FabArray< FAB > &mf, const FabArrayBase::CommMetaData &cmd, int scomp, int ncomp, DTOS const &dtos, Proj const &proj=Proj{})
Fill ghost cells for FabArray/MultiFab.
Definition AMReX_NonLocalBC.H:1444
void UnpackRecvBuffers(const PackComponents &components, FabArray< FAB > &dest, const CommData &recv)
De-serializes FAB data without any knowledge of a DTOS nor a projection.
Definition AMReX_NonLocalBC.H:662
static constexpr struct amrex::NonLocalBC::DoLocalCopy do_local_copy
decltype(LocalCopy(std::declval< Args >()...)) LocalCopy_t
Definition AMReX_NonLocalBC.H:532
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
template MultiBlockCommMetaData ParallelCopy(FabArray< FArrayBox > &dest, const Box &destbox, const FabArray< FArrayBox > &src, int destcomp, int srccomp, int numcomp, const IntVect &ngrow, MultiBlockIndexMapping const &, Identity const &)
CommHandler ParallelCopy_nowait(NoLocalCopy, FabArray< FAB > &dest, const FabArray< FAB > &src, const FabArrayBase::CommMetaData &cmd, const DataPacking &data_packing)
Definition AMReX_NonLocalBC.H:774
static constexpr Identity identity
Definition AMReX_NonLocalBC.H:307
decltype(PackSendBuffers(std::declval< Args >()...)) PackSendBuffers_t
Definition AMReX_NonLocalBC.H:526
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
decltype(UnpackRecvBuffers(std::declval< Args >()...)) UnpackRecvBuffers_t
Definition AMReX_NonLocalBC.H:529
void PrepareRecvBuffers(const PackComponents &components, FabArray< FAB > &dest, const FabArray< FAB > &src, CommData &comm, const FabArrayBase::MapOfCopyComTagContainers &cctc)
Calls PrepareComBuffers.
Definition AMReX_NonLocalBC.H:634
void ParallelCopy_alltoallv(FabArray< FAB > &dest, const FabArray< FAB > &src, const FabArrayBase::CommMetaData &cmd, const DataPacking &data_packing, CommHandler *cached=nullptr, MPI_Comm comm=MPI_COMM_NULL)
ParallelCopy that exchanges all messages with a single MPI_Alltoallv.
Definition AMReX_NonLocalBC.H:957
static constexpr struct amrex::NonLocalBC::NoLocalCopy no_local_copy
void PrepareSendBuffers(const PackComponents &components, FabArray< FAB > &dest, const FabArray< FAB > &src, CommData &comm, const FabArrayBase::MapOfCopyComTagContainers &cctc)
Calls PrepareComBuffers.
Definition AMReX_NonLocalBC.H:623
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{})
void ParallelCopy_alltoall(FabArray< FAB > &dest, const FabArray< FAB > &src, const FabArrayBase::CommMetaData &cmd, const DataPacking &data_packing, std::size_t block_size, CommHandler *cached=nullptr, MPI_Comm comm=MPI_COMM_NULL)
ParallelCopy that exchanges uniform blocks with a single MPI_Alltoall.
Definition AMReX_NonLocalBC.H:1053
void PrepareCommBuffersUniform(CommData &comm, const FabArrayBase::MapOfCopyComTagContainers &cctc, int n_components, std::size_t object_size, std::size_t block_size, MPI_Comm c)
Like PrepareCommBuffers, but every process in communicator c gets a block of block_size bytes in the ...
Definition AMReX_NonLocalBC.cpp:173
void TranslateRanks(CommData &comm, MPI_Comm c)
Fill comm.comm_rank with the ranks of comm.rank (global ranks) in communicator c.
Definition AMReX_NonLocalBC.cpp:139
MPI_Comm CommunicatorSub() noexcept
sub-communicator for current frame
Definition AMReX_ParallelContext.H:70
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:1312
int SeqNum() noexcept
Returns sequential message sequence numbers, usually used as tags for send/recv.
Definition AMReX_ParallelDescriptor.H:678
int MPI_Comm
Definition AMReX_ccse-mpi.H:51
static constexpr int MPI_COMM_NULL
Definition AMReX_ccse-mpi.H:59
Definition AMReX_Amr.cpp:50
__host__ __device__ void ignore_unused(const Ts &...)
No-op helper that marks variables as intentionally unused.
Definition AMReX.H:273
std::unique_ptr< char, TheFaArenaDeleter > TheFaArenaPointer
Definition AMReX_FabArray.H:118
BoxND< 3 > Box
Box is an alias for amrex::BoxND instantiated with AMREX_SPACEDIM.
Definition AMReX_BaseFwd.H:35
@ y
Definition AMReX_Orientation.H:14
@ x
Definition AMReX_Orientation.H:14
@ z
Definition AMReX_Orientation.H:14
IndexTypeND< 3 > IndexType
IndexType is an alias for amrex::IndexTypeND instantiated with AMREX_SPACEDIM.
Definition AMReX_BaseFwd.H:41
IntVectND< 3 > IntVect
IntVect is an alias for amrex::IntVectND instantiated with AMREX_SPACEDIM.
Definition AMReX_BaseFwd.H:38
void Abort(const std::string &msg)
Print a fatal-error message to stderr and abort execution.
Definition AMReX.cpp:244
const int[]
Definition AMReX_BLProfiler.cpp:1665
std::is_same< Expected, Detected_t< Op, Args... > > IsDetectedExact
Definition AMReX_TypeTraits.H:186
This class stores both recv and send buffers with an associated MPI tag.
Definition AMReX_NonLocalBC.H:508
Logical traits let us combine multiple type requirements.
Definition AMReX_TypeTraits.H:232
Destination-component descriptor.
Definition AMReX_BaseFab.H:107
int i
Definition AMReX_BaseFab.H:110
A simple struct holding 3 int values for a 3D index.
Definition AMReX_Dim3.H:24
int x
Definition AMReX_Dim3.H:24
int z
Definition AMReX_Dim3.H:24
int y
Definition AMReX_Dim3.H:24
Definition AMReX_FabArrayBase.H:555
std::unique_ptr< MapOfCopyComTagContainers > m_RcvTags
Definition AMReX_FabArrayBase.H:561
std::unique_ptr< MapOfCopyComTagContainers > m_SndTags
Definition AMReX_FabArrayBase.H:560
std::unique_ptr< CopyComTagsContainer > m_LocTags
Definition AMReX_FabArrayBase.H:559
Test if a given type T is callable with arguments of type Args...
Definition AMReX_TypeTraits.H:214
Test if a given type T is callable with arguments of type Args...
Definition AMReX_TypeTraits.H:208
This is the index mapping based on the DTOS MultiBlockDestToSrc.
Definition AMReX_NonLocalBC.H:223
MultiBlockCommMetaData(const FabArrayBase &dst, const Box &dstbox, const FabArrayBase &src, const IntVect &ngrow, DTOS const &dtos)
Build global meta data by calling the define() member function.
This class specializes behaviour on local copies and unpacking receive buffers.
Definition AMReX_NonLocalBC.H:687
constexpr ApplyDtosAndProjectionOnReciever(const PackComponents &components, DTOS dtos_=DTOS{}, FabProj proj_=FabProj{})
Definition AMReX_NonLocalBC.H:689
FabProj proj
Definition AMReX_NonLocalBC.H:693
DTOS dtos
Definition AMReX_NonLocalBC.H:692
This class holds data buffers for either immediate MPI send or recv calls.
Definition AMReX_NonLocalBC.H:426
Vector< std::size_t > size
The size in bytes for each data transaction.
Definition AMReX_NonLocalBC.H:437
Vector< char * > data
Pointers to the_data that can be used for each single data transaction.
Definition AMReX_NonLocalBC.H:433
Vector< const FabArrayBase::CopyComTagsContainer * > cctc
For each request the copy comm tags for the corresponding data FABs.
Definition AMReX_NonLocalBC.H:443
std::size_t total_bytes
Size of the_data in bytes, so that it can be released and reacquired.
Definition AMReX_NonLocalBC.H:450
Vector< MPI_Status > stats
For each request the corresponding MPI_status, used for debugging.
Definition AMReX_NonLocalBC.H:441
Vector< MPI_Request > request
The associated MPI_Request for each data transaction.
Definition AMReX_NonLocalBC.H:439
TheFaArenaPointer the_data
Holds 'em all in one data pointer.
Definition AMReX_NonLocalBC.H:429
std::uint64_t id
Definition AMReX_NonLocalBC.H:451
Vector< int > rank
Stores MPI ranks. For recvs it is the 'from' rank and for sends it is the 'to' rank.
Definition AMReX_NonLocalBC.H:431
Vector< int > displs
Definition AMReX_NonLocalBC.H:448
Vector< std::size_t > offset
All offsets of data in the_data.
Definition AMReX_NonLocalBC.H:435
Vector< int > counts
size and offset per rank of that communicator, as MPI_Alltoallv wants them.
Definition AMReX_NonLocalBC.H:447
Vector< int > comm_rank
rank translated into the communicator used by Alltoall and Alltoallv.
Definition AMReX_NonLocalBC.H:445
This class stores both recv and send buffers with an associated MPI tag.
Definition AMReX_NonLocalBC.H:508
CommData send
Definition AMReX_NonLocalBC.H:512
int mpi_tag
Definition AMReX_NonLocalBC.H:510
CommData recv
Definition AMReX_NonLocalBC.H:511
Definition AMReX_NonLocalBC.H:747
Type trait that tests if T has an InverseImage class member function.
Definition AMReX_NonLocalBC.H:21
This class acts as a default no-op operator.
Definition AMReX_NonLocalBC.H:291
constexpr Dim3 operator()(Dim3 i) const noexcept
The identity function for Dim3.
Definition AMReX_NonLocalBC.H:293
constexpr T operator()(Array4< const T > array, Dim3 i, int comp=0) const noexcept(noexcept(array(i.x, i.y, i.z, comp)))
Definition AMReX_NonLocalBC.H:299
constexpr int operator()(int i) const noexcept
The identity for int.
Definition AMReX_NonLocalBC.H:305
static constexpr Dim3 Inverse(Dim3 i) noexcept
The identity function for Dim3.
Definition AMReX_NonLocalBC.H:295
This type trait tests if a given type DP satisfies the DataPacking concept for type FAB.
Definition AMReX_NonLocalBC.H:548
This type trait tests if a type P is a projection for FAB.
Definition AMReX_NonLocalBC.H:282
Tests if a given type IndexMap is usable as an index mapping between two index based coordinate syste...
Definition AMReX_NonLocalBC.H:28
This class takes a projection and a component map and combines them to form a new projection.
Definition AMReX_NonLocalBC.H:325
Base base
Definition AMReX_NonLocalBC.H:332
Map map
Definition AMReX_NonLocalBC.H:333
constexpr decltype(auto) operator()(Array4< const T > array, Dim3 i, int comp) const noexcept(noexcept(base(array, i, map(comp))))
Definition AMReX_NonLocalBC.H:337
This is the index mapping based on the DTOS MultiBlockDestToSrc.
Definition AMReX_NonLocalBC.H:223
MultiBlockCommMetaData(const BoxArray &dstba, const DistributionMapping &dstdm, const Box &dstbox, const BoxArray &srcba, const DistributionMapping &srcdm, const IntVect &ngrow, DTOS const &dtos)
Build global meta data by calling the define() member function.
MultiBlockCommMetaData(const FabArrayBase &dst, const Box &dstbox, const FabArrayBase &src, const IntVect &ngrow, DTOS const &dtos)
Build global meta data by calling the define() member function.
void define(const BoxArray &dstba, const DistributionMapping &dstdm, const Box &dstbox, const BoxArray &srcba, const DistributionMapping &srcdm, const IntVect &ngrow, DTOS const &dtos)
Build global meta data that is being used to identify send and recv dependencies in communication rou...
This struct describes an affine index transformation for two coordinate systems.
Definition AMReX_NonLocalBC.H:38
IndexType operator()(IndexType it) const noexcept
Definition AMReX_NonLocalBC.H:77
IntVect sign
A vector of 1 and -1 describing the orientation in each component.
Definition AMReX_NonLocalBC.H:44
__host__ __device__ Dim3 operator()(Dim3 i) const noexcept
Applies this mapping on the index from destination space and returns an index in the source space.
Definition AMReX_NonLocalBC.H:52
__host__ __device__ Dim3 Inverse(Dim3 i) const noexcept
The inverse function is given by rearringing all above terms.
Definition AMReX_NonLocalBC.H:67
IntVect offset
The offset in the source index space.
Definition AMReX_NonLocalBC.H:42
IntVect permutation
This vector needs to be a valid permutation.
Definition AMReX_NonLocalBC.H:40
IndexType Inverse(IndexType it) const noexcept
Definition AMReX_NonLocalBC.H:81
Definition AMReX_NonLocalBC.H:746
Contains information about which components take part of the data transaction.
Definition AMReX_NonLocalBC.H:595
int dest_component
Definition AMReX_NonLocalBC.H:596
int src_component
Definition AMReX_NonLocalBC.H:597
int n_components
Definition AMReX_NonLocalBC.H:598
int J
Definition AMReX_NonLocalBC.H:390
int I
Definition AMReX_NonLocalBC.H:389
constexpr int operator()(int i) const noexcept
Definition AMReX_NonLocalBC.H:391
constexpr int operator()(int i) const noexcept
Definition AMReX_NonLocalBC.H:382
int I
Definition AMReX_NonLocalBC.H:381
constexpr int operator()(int i) const noexcept
Definition AMReX_NonLocalBC.H:372
int J
Definition AMReX_NonLocalBC.H:371
This is a permutation where only two components are swapped.
Definition AMReX_NonLocalBC.H:356
constexpr int operator()(int i) const noexcept
Swaps indices CompI and CompJ.
Definition AMReX_NonLocalBC.H:362
Number-of-components descriptor.
Definition AMReX_BaseFab.H:114
int n
Definition AMReX_BaseFab.H:117
Source-component descriptor.
Definition AMReX_BaseFab.H:100
int i
Definition AMReX_BaseFab.H:103