Block-Structured AMR Software Framework
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_TypeTraits.H>
5 #include <AMReX_FabArray.H>
6 #include <AMReX_FArrayBox.H>
7 
8 namespace amrex::NonLocalBC {
9 
11 // [concept.IndexMapping]
12 //
13 
15 template <typename T, typename... Args>
16 using Inverse_t = decltype(std::declval<T>().Inverse(std::declval<Args>()...));
17 
19 template <typename T>
20 struct HasInverseMemFn : IsDetectedExact<Dim3, Inverse_t, T, Dim3> {};
21 
24 template <class IndexMap>
26  : Conjunction<IsCallableR<Dim3, IndexMap&, const Dim3&>,
27  HasInverseMemFn<const IndexMap&>> {};
28 
30 // [IndexMapping.MultiBlockIndexMapping]
31 //
32 
44 
51  [[nodiscard]] AMREX_GPU_HOST_DEVICE Dim3 operator()(Dim3 i) const noexcept {
52  int iv[3]{i.x, i.y, i.z};
53  int iv_new[3]{};
54  for (int d = 0; d < AMREX_SPACEDIM; ++d) {
55  iv_new[d] = sign[d] * (iv[permutation[d]] - offset[d]);
56  }
57  return {iv_new[0], iv_new[1], iv_new[2]};
58  }
59 
66  [[nodiscard]] AMREX_GPU_HOST_DEVICE Dim3 Inverse(Dim3 i) const noexcept {
67  int iv_new[3]{i.x, i.y, i.z};
68  int iv[3]{};
69  for (int d = 0; d < AMREX_SPACEDIM; ++d) {
70  AMREX_ASSERT(sign[d] == 1 || sign[d] == -1);
71  iv[permutation[d]] = iv_new[d] * sign[d] + offset[d];
72  }
73  return {iv[0], iv[1], iv[2]};
74  }
75 
76  [[nodiscard]] IndexType operator()(IndexType it) const noexcept {
77  return IndexType{IntVect{AMREX_D_DECL(it[permutation[0]], it[permutation[1]], it[permutation[2]])}};
78  }
79 
80  [[nodiscard]] IndexType Inverse(IndexType it) const noexcept {
81  IntVect inverse_permutation;
82  for (int i = 0; i < AMREX_SPACEDIM; ++i) {
83  inverse_permutation[permutation[i]] = i;
84  }
85  return IndexType{IntVect{AMREX_D_DECL(it[inverse_permutation[0]], it[inverse_permutation[1]], it[inverse_permutation[2]])}};
86  }
87 };
88 
100 template <typename DTOS>
101 std::enable_if_t<IsCallableR<Dim3, DTOS, Dim3>::value, IntVect>
102 Apply(DTOS const& dtos, const IntVect& iv)
103 {
104  Dim3 i = dtos(iv.dim3());
105  return IntVect{AMREX_D_DECL(i.x, i.y, i.z)};
106 }
107 
116 template <typename DTOS>
117 std::enable_if_t<IsCallableR<Dim3, DTOS, Dim3>::value && !IsCallableR<IndexType, DTOS, IndexType>::value, Box>
118 Image (DTOS const& dtos, const Box& box)
119 {
120  IntVect mapped_smallEnd = Apply(dtos, box.smallEnd());
121  IntVect mapped_bigEnd = Apply(dtos, box.bigEnd());
122  IntVect smallEnd;
123  IntVect bigEnd;
124  for (int d = 0; d < AMREX_SPACEDIM; ++d) {
125  smallEnd[d] = std::min(mapped_smallEnd[d], mapped_bigEnd[d]);
126  bigEnd[d] = std::max(mapped_smallEnd[d], mapped_bigEnd[d]);
127  }
128  return Box{smallEnd, bigEnd, box.ixType()};
129 }
130 
139 template <typename DTOS>
140 std::enable_if_t<IsCallableR<Dim3, DTOS, Dim3>::value && IsCallableR<IndexType, DTOS, IndexType>::value, Box>
141 Image (DTOS const& dtos, const Box& box)
142 {
143  // "Forget" the index type mapping and invoke Image without changing the index type.
144  Box srcbox = Image([&dtos](Dim3 d) { return dtos(d); }, box);
145  // Fix the index type of the resulting box
146  srcbox.setType(dtos(box.ixType()));
147  return srcbox;
148 }
149 
161 template <typename DTOS>
162 std::enable_if_t<HasInverseMemFn<DTOS>::value, IntVect>
163 ApplyInverse(DTOS const& dtos, const IntVect& iv)
164 {
165  return Apply([&dtos](Dim3 i) { return dtos.Inverse(i); }, iv);
166 }
167 
176 template <typename DTOS>
177 std::enable_if_t<HasInverseMemFn<DTOS>::value && !IsCallableR<IndexType, DTOS, IndexType>::value, Box>
178 InverseImage (DTOS const& dtos, const Box& box)
179 {
180  return Image([&dtos](Dim3 i) { return dtos.Inverse(i); }, box);
181 }
182 
191 template <typename DTOS>
192 std::enable_if_t<HasInverseMemFn<DTOS>::value && IsCallableR<IndexType, DTOS, IndexType>::value, Box>
193 InverseImage (DTOS const& dtos, const Box& box)
194 {
195  return Image([&dtos](auto&& i) { return dtos.Inverse(i); }, box);
196 }
197 
199 static_assert(IsIndexMapping<MultiBlockIndexMapping>(), // NOLINT(bugprone-throw-keyword-missing)
200  "MultiBlockIndexMapping is expected to satisfy IndexMapping");
201 
203 // [class.MultiBlockCommMetaData]
204 //
205 
212 
216  template <typename DTOS,
217  typename = std::enable_if_t<IsIndexMapping<DTOS>::value>>
218  MultiBlockCommMetaData(const FabArrayBase& dst, const Box& dstbox, const FabArrayBase& src,
219  const IntVect& ngrow, DTOS const& dtos);
220 
224  template <typename DTOS,
225  typename = std::enable_if_t<IsIndexMapping<DTOS>::value>>
227  const Box& dstbox, const BoxArray& srcba,
228  const DistributionMapping& srcdm, const IntVect& ngrow, DTOS const& dtos);
229 
231 
256  template <typename DTOS>
257  std::enable_if_t<IsIndexMapping<DTOS>::value>
258  define(const BoxArray& dstba, const DistributionMapping& dstdm, const Box& dstbox,
259  const BoxArray& srcba, const DistributionMapping& srcdm, const IntVect& ngrow,
260  DTOS const& dtos);
261 };
262 
264 // [concept.FabProjection]
265 //
266 
268 template <typename P, typename FAB>
270  : IsCallableR<typename FAB::value_type, P, Array4<const typename FAB::value_type>, Dim3, int>
271 {};
272 
274 // [FabProjection.Identity]
275 // [IndexMapping.Identity]
276 
280 struct Identity {
282  constexpr Dim3 operator()(Dim3 i) const noexcept { return i; }
284  [[nodiscard]] static constexpr Dim3 Inverse(Dim3 i) noexcept { return i; }
285 
287  template <typename T>
288  constexpr T operator()(Array4<const T> array, Dim3 i, int comp = 0) const
289  noexcept(noexcept(array(i.x, i.y, i.z, comp))) {
290  return array(i.x, i.y, i.z, comp);
291  }
292 
294  constexpr int operator()(int i) const noexcept { return i; }
295 };
296 static constexpr Identity identity{};
297 
298 static_assert(sizeof(Identity) == 1 );
299 static_assert(std::is_trivially_default_constructible_v<Identity> );
300 static_assert(std::is_trivially_copy_assignable_v<Identity> );
301 static_assert(std::is_trivially_copy_constructible_v<Identity> );
302 static_assert(IsIndexMapping<Identity>() ); // NOLINT(bugprone-throw-keyword-missing)
303 static_assert(IsFabProjection<Identity, FArrayBox>() ); // NOLINT(bugprone-throw-keyword-missing)
304 
306 // [FabProjection.MapComponents]
307 
314 template <typename Base, typename Map = Identity> struct MapComponents {
315  static_assert(IsCallable<Base, Array4<const Real>, Dim3, int>::value,
316  "Base needs to be a callable function: (Array4<const T>, Dim3, i) -> auto.");
317 
318  static_assert(IsCallableR<int, Map, int>::value,
319  "Map needs to be a callable function: int -> int.");
320 
321  Base base;
322  Map map;
323 
324  template <typename T,
325  typename = std::enable_if_t<IsCallable<Base, Array4<const T>, Dim3, int>::value>,
326  typename = std::enable_if_t<IsCallableR<int, Map, int>::value>>
327  constexpr decltype(auto) operator()(Array4<const T> array, Dim3 i, int comp) const
328  noexcept(noexcept(base(array, i, map(comp)))) {
329  return base(array, i, map(comp));
330  }
331 };
332 
333 static_assert(std::is_trivially_copy_assignable<MapComponents<Identity>>() ); // NOLINT(bugprone-throw-keyword-missing)
334 static_assert(std::is_trivially_copy_constructible<MapComponents<Identity>>() ); // NOLINT(bugprone-throw-keyword-missing)
335 static_assert(IsFabProjection<MapComponents<Identity>, FArrayBox>() ); // NOLINT(bugprone-throw-keyword-missing)
336 
338 // [FabProjection.MapComponents.SwapComponents]
339 
345 template <int I, int J> struct SwapComponents {
346  static_assert(I >= 0 && J >= 0, "I >= 0 && J >= 0");
347 
351  constexpr int operator()(int i) const noexcept {
352  const int map[2] = {I, J};
353  return i == I || i == J ? map[std::size_t(i == I)] : i;
354  }
355 };
356 
357 template <int I> struct SwapComponents<I, -1> {
358  static_assert(I >= 0, "I >= 0");
359 
360  int J;
361  constexpr int operator()(int i) const noexcept {
362  const int map[2] = {I, J};
363  return i == I || i == J ? map[std::size_t(i == I)] : i;
364  }
365 };
366 
367 template <int J> struct SwapComponents<-1, J> {
368  static_assert(J >= 0, "J >= 0");
369 
370  int I;
371  constexpr int operator()(int i) const noexcept {
372  const int map[2] = {I, J};
373  return i == I || i == J ? map[std::size_t(i == I)] : i;
374  }
375 };
376 
377 template <> struct SwapComponents<-1, -1> {
378  int I;
379  int J;
380  constexpr int operator()(int i) const noexcept {
381  const int map[2] = {I, J};
382  return i == I || i == J ? map[std::size_t(i == I)] : i;
383  }
384 };
385 
387 
388 template <int I, int J> static constexpr SwapComponents<I, J> swap_indices{};
389 
390 static_assert(sizeof(SwapComponents<0, 1>) == 1 );
391 static_assert(sizeof(DynamicSwapComponents) == 2 * sizeof(int) );
392 static_assert(sizeof(SwapComponents<0, -1>) == sizeof(int) );
393 static_assert(sizeof(SwapComponents<-1, 1>) == sizeof(int) );
394 static_assert(std::is_trivially_default_constructible<MapComponents<Identity, SwapComponents<0, 1>>>() ); // NOLINT(bugprone-throw-keyword-missing)
395 static_assert(std::is_trivially_copy_assignable<MapComponents<Identity, SwapComponents<0, 1>>>() ); // NOLINT(bugprone-throw-keyword-missing)
396 static_assert(std::is_trivially_copy_constructible<MapComponents<Identity, SwapComponents<0, 1>>>() ); // NOLINT(bugprone-throw-keyword-missing)
397 static_assert(IsFabProjection<MapComponents<Identity, SwapComponents<0, 1>>, FArrayBox>() ); // NOLINT(bugprone-throw-keyword-missing)
398 
399 static_assert(swap_indices<0, 1>(0) == 1 );
400 static_assert(swap_indices<0, 1>(1) == 0 );
401 static_assert(swap_indices<0, 1>(2) == 2 );
402 static_assert(DynamicSwapComponents{0, 1}(0) == 1 );
403 static_assert(DynamicSwapComponents{0, 1}(1) == 0 );
404 static_assert(DynamicSwapComponents{0, 1}(2) == 2 );
405 
407 // [class.CommData]
408 // [class.CommHandler]
409 
415 struct CommData {
416 #ifdef AMREX_USE_MPI
433 #endif
434 };
435 
436 #ifdef AMREX_USE_MPI
438 void PrepareCommBuffers(CommData& comm, const FabArrayBase::MapOfCopyComTagContainers& cctc,
439  int n_components, std::size_t object_size, std::size_t align);
440 
442 void PostRecvs(CommData& recv, int mpi_tag);
443 
445 void PostSends(CommData& send, int mpi_tag);
446 #endif
447 
448 
452 struct CommHandler {
453 #ifdef AMREX_USE_MPI
454  int mpi_tag{};
457 #endif
458 };
459 
461 // [concept.DataPacking]
462 //
463 template <typename... Args>
464 using PrepareSendBuffers_t = decltype(PrepareSendBuffers(std::declval<Args>()...));
465 
466 template <typename... Args>
467 using PrepareRecvBuffers_t = decltype(PrepareRecvBuffers(std::declval<Args>()...));
468 
469 template <typename... Args>
470 using PackSendBuffers_t = decltype(PackSendBuffers(std::declval<Args>()...));
471 
472 template <typename... Args>
473 using UnpackRecvBuffers_t = decltype(UnpackRecvBuffers(std::declval<Args>()...));
474 
475 template <typename... Args>
476 using LocalCopy_t = decltype(LocalCopy(std::declval<Args>()...));
477 
479 template <typename DP, typename FAB>
481  Conjunction<
482  IsDetected<LocalCopy_t, DP&, FabArray<FAB>&, const FabArray<FAB>&, const FabArrayBase::CopyComTagsContainer&>
483 #ifdef AMREX_USE_MPI
484  ,IsDetected<PrepareSendBuffers_t, DP&, FabArray<FAB>&, const FabArray<FAB>&, CommData&, const FabArrayBase::MapOfCopyComTagContainers&>,
485  IsDetected<PrepareRecvBuffers_t, DP&, FabArray<FAB>&, const FabArray<FAB>&, CommData&, const FabArrayBase::MapOfCopyComTagContainers&>,
486  IsDetected<PackSendBuffers_t, DP&, const FabArray<FAB>&, CommData&>,
487  IsDetected<UnpackRecvBuffers_t, DP&, FabArray<FAB>&, CommData&>
488 #endif
489  > {};
490 
491 template <class FAB, class DTOS = Identity, class Proj = Identity>
492 std::enable_if_t<IsBaseFab<FAB>() && IsCallableR<Dim3, DTOS, Dim3>() && IsFabProjection<Proj, FAB>()>
493 local_copy_cpu (FabArray<FAB>& dest, const FabArray<FAB>& src, int dcomp, int scomp, int ncomp,
494  FabArrayBase::CopyComTagsContainer const& local_tags, DTOS const& dtos = DTOS{},
495  Proj const& proj = Proj{}) noexcept;
496 
497 template <class FAB, class DTOS = Identity, class Proj = Identity>
498 std::enable_if_t<IsBaseFab<FAB>() && IsCallableR<Dim3, DTOS, Dim3>() && IsFabProjection<Proj, FAB>()>
499 unpack_recv_buffer_cpu (FabArray<FAB>& mf, int dcomp, int ncomp, Vector<char*> const& recv_data,
500  Vector<std::size_t> const& recv_size,
502  DTOS const& dtos = DTOS{}, Proj const& proj = Proj{}) noexcept;
503 
504 #ifdef AMREX_USE_GPU
505 template <class FAB, class DTOS = Identity, class Proj = Identity>
506 std::enable_if_t<IsBaseFab<FAB>() && IsCallableR<Dim3, DTOS, Dim3>() && IsFabProjection<Proj, FAB>()>
507 local_copy_gpu (FabArray<FAB>& dest, const FabArray<FAB>& src, int dcomp, int scomp, int ncomp,
508  FabArrayBase::CopyComTagsContainer const& local_tags, DTOS const& dtos = DTOS{},
509  Proj const& proj = Proj{}) noexcept;
510 
511 template <class FAB, class DTOS = Identity, class Proj = Identity>
512 std::enable_if_t<IsBaseFab<FAB>() && IsCallableR<Dim3, DTOS, Dim3>() && IsFabProjection<Proj, FAB>()>
513 unpack_recv_buffer_gpu (FabArray<FAB>& mf, int scomp, int ncomp,
514  Vector<char*> const& recv_data,
515  Vector<std::size_t> const& recv_size,
517  DTOS const& dtos = DTOS{}, Proj const& proj = Proj{});
518 #endif
519 
521 // [DataPacking.PackComponents]
522 //
523 // PackComponents is the simplest data packing policy.
524 // This provides us with sane default behaviour that we can use when defining new
525 // data packing policies.
526 
531  int n_components{0};
532 };
533 
535 template <typename FAB>
536 std::enable_if_t<IsBaseFab<FAB>::value>
537 LocalCopy (const PackComponents& components, FabArray<FAB>& dest, const FabArray<FAB>& src,
538  const FabArrayBase::CopyComTagsContainer& local_tags) {
539 #ifdef AMREX_USE_GPU
540  if (Gpu::inLaunchRegion()) {
541  local_copy_gpu(dest, src, components.dest_component, components.src_component,
542  components.n_components, local_tags);
543  } else
544 #endif
545  {
546  local_copy_cpu(dest, src, components.dest_component, components.src_component,
547  components.n_components, local_tags);
548  }
549 }
550 
551 #ifdef AMREX_USE_MPI
553 template <typename FAB>
554 std::enable_if_t<IsBaseFab<FAB>::value>
555 PrepareSendBuffers (const PackComponents& components, FabArray<FAB>& dest, const FabArray<FAB>& src,
557  using T = typename FAB::value_type;
558  ignore_unused(dest, src);
559  PrepareCommBuffers(comm, cctc, components.n_components, sizeof(T), alignof(T));
560 }
561 
563 template <typename FAB>
564 std::enable_if_t<IsBaseFab<FAB>::value>
565 PrepareRecvBuffers (const PackComponents& components, FabArray<FAB>& dest, const FabArray<FAB>& src,
567  using T = typename FAB::value_type;
568  ignore_unused(dest, src);
569  PrepareCommBuffers(comm, cctc, components.n_components, sizeof(T), alignof(T));
570 }
571 
573 template <typename FAB>
574 std::enable_if_t<IsBaseFab<FAB>::value>
575 PackSendBuffers (const PackComponents& components, const FabArray<FAB>& src, CommData& send) {
576 #ifdef AMREX_USE_GPU
577  if (Gpu::inLaunchRegion()) {
579  send.data, send.size, send.cctc);
580  } else
581 #endif // AMREX_USE_GPU
582  {
584  send.data, send.size, send.cctc);
585  }
586 }
587 
589 template <typename FAB>
590 std::enable_if_t<IsBaseFab<FAB>::value>
591 UnpackRecvBuffers (const PackComponents& components, FabArray<FAB>& dest, const CommData& recv) {
592 #ifdef AMREX_USE_GPU
593  if (Gpu::inLaunchRegion()) {
594  unpack_recv_buffer_gpu(dest, components.dest_component, components.n_components, recv.data,
595  recv.size, recv.cctc);
596  } else
597 #endif // AMREX_USE_GPU
598  {
599  unpack_recv_buffer_cpu(dest, components.dest_component, components.n_components, recv.data,
600  recv.size, recv.cctc);
601  }
602 }
603 #endif // AMREX_USE_MPI
604 
605 static_assert(IsDataPacking<PackComponents, FArrayBox>(), // NOLINT(bugprone-throw-keyword-missing)
606  "PackComponents is expected to satisfy the concept DataPacking.");
607 
609 // [DataPacking.ApplyDtosAndProjectionOnReciever]
610 //
614 template <typename DTOS = Identity, typename FabProj = Identity>
616  constexpr ApplyDtosAndProjectionOnReciever() = default;
617  constexpr ApplyDtosAndProjectionOnReciever(const PackComponents& components, DTOS dtos_ = DTOS{}, FabProj proj_ = FabProj{})
618  : PackComponents(components), dtos(std::move(dtos_)), proj(std::move(proj_)) {}
619 
620  DTOS dtos;
621  FabProj proj;
622 
623  static_assert(IsCallableR<Dim3, DTOS, Dim3>(), "DTOS needs to be a callable: Dim3 -> Dim3");
624  static_assert(IsFabProjection<FabProj, FArrayBox>(), "FabProj needs to be at least a projection on FArrayBox.");
625 };
626 
628 template <typename FAB, typename DTOS, typename FabProj>
629 std::enable_if_t<IsBaseFab<FAB>::value>
631  const FabArray<FAB>& src, const FabArrayBase::CopyComTagsContainer& local_tags) {
632  static_assert(IsFabProjection<FabProj, FAB>(), "FabProj needs to be a projection for given FAB type.");
633 #ifdef AMREX_USE_GPU
634  if (Gpu::inLaunchRegion()) {
635  local_copy_gpu(dest, src, packing.dest_component, packing.src_component,
636  packing.n_components, local_tags, packing.dtos, packing.proj);
637  } else
638 #endif
639  {
640  local_copy_cpu(dest, src, packing.dest_component, packing.src_component,
641  packing.n_components, local_tags, packing.dtos, packing.proj);
642  }
643 }
644 
645 #ifdef AMREX_USE_MPI
647 template <typename FAB, typename DTOS, typename FabProj>
648 std::enable_if_t<IsBaseFab<FAB>::value>
650  FabArray<FAB>& dest, const CommData& recv) {
651  // If FAB is not FArrayBox we have not checked for the correct types yet.
652  static_assert(IsFabProjection<FabProj, FAB>(), "FabProj needs to be a projection for given FAB type.");
653 #ifdef AMREX_USE_GPU
654  if (Gpu::inLaunchRegion()) {
655  unpack_recv_buffer_gpu(dest, packing.dest_component, packing.n_components, recv.data,
656  recv.size, recv.cctc, packing.dtos, packing.proj);
657  } else
658 #endif // AMREX_USE_GPU
659  {
660  unpack_recv_buffer_cpu(dest, packing.dest_component, packing.n_components, recv.data,
661  recv.size, recv.cctc, packing.dtos, packing.proj);
662  }
663 }
664 #endif // AMREX_USE_MPI
665 
666 static_assert(IsDataPacking<ApplyDtosAndProjectionOnReciever<>, FArrayBox>(), // NOLINT(bugprone-throw-keyword-missing)
667  "ApplyDtosAndProjectionOnReciever<> is expected to satisfy the DataPacking concept.");
668 
670 // [ParallelCopy_nowait]
671 
672 static constexpr struct NoLocalCopy {} no_local_copy{};
673 static constexpr struct DoLocalCopy {} do_local_copy{};
674 
696 template <typename FAB, typename DataPacking,
697  typename = std::enable_if_t<IsBaseFab<FAB>::value>,
698  typename = std::enable_if_t<IsDataPacking<DataPacking, FAB>::value>>
699 #ifdef AMREX_USE_MPI
702  const FabArrayBase::CommMetaData& cmd, const DataPacking& data_packing) {
703  CommHandler handler{};
704  if (ParallelContext::NProcsSub() == 1) {
705  return handler;
706  }
707  //
708  // Do this before prematurely exiting if running in parallel.
709  // Otherwise sequence numbers will not match across MPI processes.
710  //
712 
713  if (cmd.m_RcvTags && !(cmd.m_RcvTags->empty())) {
714  PrepareRecvBuffers(data_packing, dest, src, handler.recv, *cmd.m_RcvTags);
715  PostRecvs(handler.recv, handler.mpi_tag);
716  }
717 
718  if (cmd.m_SndTags && !(cmd.m_SndTags->empty())) {
719  PrepareSendBuffers(data_packing, dest, src, handler.send, *cmd.m_SndTags);
720  PackSendBuffers(data_packing, src, handler.send);
721  PostSends(handler.send, handler.mpi_tag);
722  }
723  return handler;
724 }
725 #else
727  const FabArrayBase::CommMetaData&, const DataPacking&) {
728  return CommHandler{};
729 }
730 #endif
731 
753 template <typename FAB, typename DataPacking,
754  typename = std::enable_if_t<IsBaseFab<FAB>::value>,
755  typename = std::enable_if_t<IsDataPacking<DataPacking, FAB>::value>>
756 #ifdef AMREX_USE_MPI
758 #endif
759 CommHandler
761  const FabArrayBase::CommMetaData& cmd, const DataPacking& data_packing) {
762  CommHandler comm = ParallelCopy_nowait(no_local_copy, dest, src, cmd, data_packing);
763  // Eagerly do the local work and hope for some overlap with communication
764  if (cmd.m_LocTags && !cmd.m_LocTags->empty()) {
765  LocalCopy(data_packing, dest, src, *cmd.m_LocTags);
766  }
767  return comm;
768 }
770 // [ParallelCopy_finish]
771 
790 template <typename FAB, typename DataPacking>
791 std::enable_if_t<IsBaseFab<FAB>() && IsDataPacking<DataPacking, FAB>()>
792 #ifdef AMREX_USE_MPI
794  const FabArrayBase::CommMetaData& cmd, const DataPacking& data_packing) {
795  // If any FabArray is empty we have nothing to do.
796  if (dest.empty()) {
797  return;
798  }
799  // Return if nothing do
800  if (ParallelContext::NProcsSub() == 1) {
801  return;
802  }
803  // Unpack receives
804  if (cmd.m_RcvTags && !(cmd.m_RcvTags->empty())) {
806 #ifdef AMREX_DEBUG
807  if (!CheckRcvStats(handler.recv.stats, handler.recv.size, handler.mpi_tag)) {
808  amrex::Abort("NonLocalPC::ParallelCopy_finish failed with wrong message size");
809  }
810 #endif
811  UnpackRecvBuffers(data_packing, dest, handler.recv);
812  }
813 
814  // Wait for all sends to be done
815  if (cmd.m_SndTags && !(cmd.m_SndTags->empty())) {
817  }
818 }
819 #else
821 #endif
822 
842 template <typename FAB, typename DataPacking>
843 std::enable_if_t<IsBaseFab<FAB>() && IsDataPacking<DataPacking, FAB>()>
845  const FabArrayBase::CommMetaData& cmd, const DataPacking& data_packing) {
846  // Eagerly do the local work and hope for some overlap with communication
847  if (cmd.m_LocTags && !cmd.m_LocTags->empty()) {
848  LocalCopy(data_packing, dest, src, *cmd.m_LocTags);
849  }
850  ParallelCopy_finish(dest, std::move(handler), cmd, data_packing); // NOLINT
851 }
852 
877 template <typename FAB, typename DTOS = Identity, typename Proj = Identity>
878 std::enable_if_t<IsBaseFab<FAB>() && IsCallableR<Dim3, DTOS, Dim3>() && IsFabProjection<Proj, FAB>()>
880  SrcComp srccomp, DestComp destcomp, NumComps numcomp, DTOS const& dtos = DTOS{}, Proj const& proj = Proj{}) {
881  PackComponents components{};
882  components.dest_component = destcomp.i;
883  components.src_component = srccomp.i;
884  components.n_components = numcomp.n;
885  ApplyDtosAndProjectionOnReciever<DTOS, Proj> packing{components, dtos, proj};
886  CommHandler handler = ParallelCopy_nowait(dest, src, cmd, packing);
887  ParallelCopy_finish(dest, std::move(handler), cmd, packing); // NOLINT
888 }
889 
914 template <typename FAB, typename DTOS = Identity, typename Proj = Identity>
915 std::enable_if_t<IsBaseFab<FAB>() && IsCallableR<Dim3, DTOS, Dim3>() && IsFabProjection<Proj, FAB>()>
917  int srccomp, int destcomp, int numcomp, DTOS const& dtos = DTOS{}, Proj const& proj = Proj{}) {
918  ParallelCopy(dest, src, cmd, SrcComp(srccomp), DestComp(destcomp), NumComps(numcomp), dtos, proj);
919 }
920 
950 template <typename FAB, typename DTOS = Identity, typename Proj = Identity>
951 std::enable_if_t<IsBaseFab<FAB>() && IsIndexMapping<DTOS>() && IsFabProjection<Proj, FAB>(),
952 MultiBlockCommMetaData>
953 ParallelCopy (FabArray<FAB>& dest, const Box& destbox, const FabArray<FAB>& src, SrcComp srccomp,
954  DestComp destcomp, NumComps numcomp, const IntVect& ngrow, DTOS const& dtos = DTOS{}, Proj const& proj = Proj{}) {
955  MultiBlockCommMetaData cmd(dest, destbox, src, ngrow, dtos);
956  ParallelCopy(dest, src, cmd, srccomp, destcomp, numcomp, dtos, proj);
957  return cmd;
958 }
959 
989 template <typename FAB, typename DTOS = Identity, typename Proj = Identity>
990 std::enable_if_t<IsBaseFab<FAB>() && IsIndexMapping<DTOS>() && IsFabProjection<Proj, FAB>(),
991 MultiBlockCommMetaData>
992 ParallelCopy (FabArray<FAB>& dest, const Box& destbox, const FabArray<FAB>& src, int srccomp,
993  int destcomp, int numcomp, const IntVect& ngrow, DTOS const& dtos = DTOS{}, Proj const& proj = Proj{}) {
994  return ParallelCopy(dest, destbox, src, SrcComp(srccomp), DestComp(destcomp), NumComps(numcomp), ngrow, dtos, proj);
995 }
996 
997 // Rotate90 fills the lo-x and lo-y boundary regions by rotating the data
998 // around (x=0,y=0) by 90 degrees in either direction. It also fills the
999 // corner of lo-x and lo-y boundary region by rotating the data by 180
1000 // degrees.
1001 
1002 template <class FAB>
1003 std::enable_if_t<IsBaseFab<FAB>::value>
1004 Rotate90 (FabArray<FAB>& mf, int scomp, int ncomp, IntVect const& nghost, Box const& domain);
1005 
1006 template <class FAB>
1007 std::enable_if_t<IsBaseFab<FAB>::value>
1008 Rotate90 (FabArray<FAB>& mf, Box const& domain);
1009 
1010 // Rotate180 fills the lo-x boundary by rotating the data around
1011 // (x=0,y=L_y/2) by 180 degrees.
1012 
1013 template <class FAB>
1014 std::enable_if_t<IsBaseFab<FAB>::value>
1015 Rotate180 (FabArray<FAB>& mf, int scomp, int ncomp, IntVect const& nghost, Box const& domain);
1016 
1017 template <class FAB>
1018 std::enable_if_t<IsBaseFab<FAB>::value>
1019 Rotate180 (FabArray<FAB>& mf, Box const& domain);
1020 
1021 // Fill the polar boundaries of the spherical coordinates (theta, phi, r).
1022 // The lo-x boundary is filled with f(-x,y) = f(x,mod(y+pi,2*pi)), and
1023 // the hi-x boundary is filled with f(pi+x,y) = f(pi-x,mod(y+pi,2*pi)).
1024 
1025 template <class FAB>
1026 std::enable_if_t<IsBaseFab<FAB>::value>
1027 FillPolar (FabArray<FAB>& mf, int scomp, int ncomp, IntVect const& nghost, Box const& domain);
1028 
1029 template <class FAB>
1030 std::enable_if_t<IsBaseFab<FAB>::value>
1031 FillPolar (FabArray<FAB>& mf, Box const& domain);
1032 
1069 template <typename FAB, typename DTOS, typename Proj = Identity>
1070 [[nodiscard]]
1071 std::enable_if_t<IsBaseFab<FAB>() &&
1074  CommHandler>
1076  int scomp, int ncomp, DTOS const& dtos,
1077  Proj const& proj = Proj{});
1078 
1114 template <typename FAB, typename DTOS, typename Proj = Identity>
1115 std::enable_if_t<IsBaseFab<FAB>() &&
1117  IsFabProjection<Proj,FAB>()>
1119  FabArray<FAB>& mf, const FabArrayBase::CommMetaData& cmd,
1120  int scomp, int ncomp, DTOS const& dtos,
1121  Proj const& proj = Proj{});
1122 
1154 template <typename FAB, typename DTOS, typename Proj = Identity>
1155 std::enable_if_t<IsBaseFab<FAB>() &&
1157  IsFabProjection<Proj,FAB>()>
1159  int scomp, int ncomp, DTOS const& dtos, Proj const& proj = Proj{})
1160 {
1161  BL_PROFILE("FillBoundary(cmd)");
1162  auto handler = FillBoundary_nowait(mf, cmd, scomp, ncomp, dtos, proj);
1163  FillBoundary_finish(std::move(handler), mf, cmd, scomp, ncomp, dtos, proj);
1164 }
1165 
1180 template <typename FAB, typename DTOS>
1181 [[nodiscard]]
1182 std::enable_if_t<IsBaseFab<FAB>() && IsCallableR<Dim3,DTOS,Dim3>(),
1183  FabArrayBase::CommMetaData>
1185  Geometry const& geom, DTOS const& dtos);
1186 
1187 }
1188 
1189 #include <AMReX_NonLocalBCImpl.H>
1190 
1191 namespace amrex {
1196  using NonLocalBC::SphThetaPhiRIndexMapping;
1197  using NonLocalBC::SphThetaPhiRComponentMapping;
1204 }
1205 
1206 #endif
#define BL_PROFILE(a)
Definition: AMReX_BLProfiler.H:551
#define AMREX_ASSERT(EX)
Definition: AMReX_BLassert.H:38
#define AMREX_NODISCARD
Definition: AMReX_Extension.H:251
#define AMREX_GPU_HOST_DEVICE
Definition: AMReX_GpuQualifiers.H:20
#define AMREX_D_DECL(a, b, c)
Definition: AMReX_SPACE.H:104
A collection of Boxes stored in an Array.
Definition: AMReX_BoxArray.H:530
AMREX_GPU_HOST_DEVICE const IntVectND< dim > & smallEnd() const &noexcept
Get the smallend of the BoxND.
Definition: AMReX_Box.H:105
AMREX_GPU_HOST_DEVICE IndexTypeND< dim > ixType() const noexcept
Returns the indexing type.
Definition: AMReX_Box.H:127
AMREX_GPU_HOST_DEVICE const IntVectND< dim > & bigEnd() const &noexcept
Get the bigend.
Definition: AMReX_Box.H:116
AMREX_GPU_HOST_DEVICE BoxND & setType(const IndexTypeND< dim > &t) noexcept
Set indexing type.
Definition: AMReX_Box.H:492
Calculates the distribution of FABs to MPI processes.
Definition: AMReX_DistributionMapping.H:41
A Fortran Array of REALs.
Definition: AMReX_FArrayBox.H:229
Base class for FabArray.
Definition: AMReX_FabArrayBase.H:41
CopyComTag::CopyComTagsContainer CopyComTagsContainer
Definition: AMReX_FabArrayBase.H:219
CopyComTag::MapOfCopyComTagContainers MapOfCopyComTagContainers
Definition: AMReX_FabArrayBase.H:220
bool empty() const noexcept
Definition: AMReX_FabArrayBase.H:88
An Array of FortranArrayBox(FAB)-like Objects.
Definition: AMReX_FabArray.H:343
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)
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:73
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE Dim3 dim3() const noexcept
Definition: AMReX_IntVect.H:163
@ FAB
Definition: AMReX_AmrvisConstants.H:86
bool inLaunchRegion() noexcept
Definition: AMReX_GpuControl.H:86
Definition: AMReX_NonLocalBC.cpp:3
decltype(UnpackRecvBuffers(std::declval< Args >()...)) UnpackRecvBuffers_t
Definition: AMReX_NonLocalBC.H:473
std::enable_if_t< IsBaseFab< FAB >::value > PrepareRecvBuffers(const PackComponents &components, FabArray< FAB > &dest, const FabArray< FAB > &src, CommData &comm, const FabArrayBase::MapOfCopyComTagContainers &cctc)
Calls PrepareComBuffers.
Definition: AMReX_NonLocalBC.H:565
decltype(std::declval< T >().Inverse(std::declval< Args >()...)) Inverse_t
Return type of an InverseImage class member function.
Definition: AMReX_NonLocalBC.H:16
std::enable_if_t< IsBaseFab< FAB >::value > FillPolar(FabArray< FAB > &mf, int scomp, int ncomp, IntVect const &nghost, Box const &domain)
decltype(PackSendBuffers(std::declval< Args >()...)) PackSendBuffers_t
Definition: AMReX_NonLocalBC.H:470
std::enable_if_t< IsBaseFab< FAB >) &&IsCallableR< Dim3, DTOS, Dim3 >), FabArrayBase::CommMetaData > makeFillBoundaryMetaData(FabArray< FAB > &mf, IntVect const &nghost, Geometry const &geom, DTOS const &dtos)
Make metadata for FillBoundary.
std::enable_if_t< IsBaseFab< FAB >::value > 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:575
std::enable_if_t< IsBaseFab< FAB >::value > Rotate90(FabArray< FAB > &mf, int scomp, int ncomp, IntVect const &nghost, Box const &domain)
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:41
std::enable_if_t< IsBaseFab< FAB >::value > Rotate180(FabArray< FAB > &mf, int scomp, int ncomp, IntVect const &nghost, Box const &domain)
std::enable_if_t< IsBaseFab< FAB >) &&IsCallableR< Dim3, DTOS, Dim3 >) &&IsFabProjection< Proj, FAB >)> 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
std::enable_if_t< IsBaseFab< FAB >) &&IsCallableR< Dim3, DTOS, Dim3 >) &&IsFabProjection< Proj, FAB >)> 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
decltype(LocalCopy(std::declval< Args >()...)) LocalCopy_t
Definition: AMReX_NonLocalBC.H:476
std::enable_if_t< IsBaseFab< FAB >) &&IsCallableR< Dim3, DTOS, Dim3 >) &&IsFabProjection< Proj, FAB >)> 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
std::enable_if_t< IsBaseFab< FAB >) &&IsDataPacking< DataPacking, FAB >)> ParallelCopy_finish(FabArray< FAB > &dest, CommHandler handler, const FabArrayBase::CommMetaData &cmd, const DataPacking &data_packing)
Definition: AMReX_NonLocalBC.H:793
std::enable_if_t< IsCallableR< Dim3, DTOS, Dim3 >::value, IntVect > Apply(DTOS const &dtos, const IntVect &iv)
Applies the Dim3 to Dim3 mapping onto IntVects.
Definition: AMReX_NonLocalBC.H:102
void PostSends(CommData &send, int mpi_tag)
Initiate all sends with MPI_Isend calls associated with tag mpi_tag.
Definition: AMReX_NonLocalBC.cpp:121
std::enable_if_t< IsBaseFab< FAB >::value > PrepareSendBuffers(const PackComponents &components, FabArray< FAB > &dest, const FabArray< FAB > &src, CommData &comm, const FabArrayBase::MapOfCopyComTagContainers &cctc)
Calls PrepareComBuffers.
Definition: AMReX_NonLocalBC.H:555
static constexpr SwapComponents< I, J > swap_indices
Definition: AMReX_NonLocalBC.H:388
void PostRecvs(CommData &recv, int mpi_tag)
Initiate all recvieves with MPI_Irecv calls associated with tag mpi_tag.
Definition: AMReX_NonLocalBC.cpp:105
std::enable_if_t< HasInverseMemFn< DTOS >::value, IntVect > ApplyInverse(DTOS const &dtos, const IntVect &iv)
Applies the Dim3 to Dim3 invserse mapping onto IntVects.
Definition: AMReX_NonLocalBC.H:163
AMREX_NODISCARD CommHandler ParallelCopy_nowait(NoLocalCopy, FabArray< FAB > &dest, const FabArray< FAB > &src, const FabArrayBase::CommMetaData &cmd, const DataPacking &data_packing)
Definition: AMReX_NonLocalBC.H:701
std::enable_if_t< IsCallableR< Dim3, DTOS, Dim3 >::value &&!IsCallableR< IndexType, DTOS, IndexType >::value, 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:118
std::enable_if_t< IsBaseFab< FAB >::value > 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:591
static constexpr struct amrex::NonLocalBC::DoLocalCopy do_local_copy
decltype(PrepareSendBuffers(std::declval< Args >()...)) PrepareSendBuffers_t
Definition: AMReX_NonLocalBC.H:464
std::enable_if_t< IsBaseFab< FAB >) &&IsCallableR< Dim3, DTOS, Dim3 >) &&IsFabProjection< Proj, FAB >), 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.
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 &)
std::enable_if_t< HasInverseMemFn< DTOS >::value &&!IsCallableR< IndexType, DTOS, IndexType >::value, 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:178
std::enable_if_t< IsBaseFab< FAB >) &&IsCallableR< Dim3, DTOS, Dim3 >) &&IsFabProjection< Proj, FAB >)> 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{})
std::enable_if_t< IsBaseFab< FAB >::value > 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:537
static constexpr Identity identity
Definition: AMReX_NonLocalBC.H:296
decltype(PrepareRecvBuffers(std::declval< Args >()...)) PrepareRecvBuffers_t
Definition: AMReX_NonLocalBC.H:467
static constexpr struct amrex::NonLocalBC::NoLocalCopy no_local_copy
SwapComponents<-1, -1 > DynamicSwapComponents
Definition: AMReX_NonLocalBC.H:386
std::enable_if_t< IsBaseFab< FAB >) &&IsCallableR< Dim3, DTOS, Dim3 >) &&IsFabProjection< Proj, FAB >)> 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:1158
std::enable_if_t< IsBaseFab< FAB >) &&IsCallableR< Dim3, DTOS, Dim3 >) &&IsFabProjection< Proj, FAB >)> 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.
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:1295
int SeqNum() noexcept
Returns sequential message sequence numbers, usually used as tags for send/recv.
Definition: AMReX_ParallelDescriptor.H:613
@ min
Definition: AMReX_ParallelReduce.H:18
@ max
Definition: AMReX_ParallelReduce.H:17
Definition: AMReX_Amr.cpp:49
std::unique_ptr< char, TheFaArenaDeleter > TheFaArenaPointer
Definition: AMReX_FabArray.H:103
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void ignore_unused(const Ts &...)
This shuts up the compiler about unused variables.
Definition: AMReX.H:111
void Abort(const std::string &msg)
Print out message to cerr and exit via abort().
Definition: AMReX.cpp:221
std::is_same< Expected, Detected_t< Op, Args... > > IsDetectedExact
Definition: AMReX_TypeTraits.H:181
Definition: AMReX_Array4.H:61
Logical traits let us combine multiple type requirements in one enable_if_t clause.
Definition: AMReX_TypeTraits.H:225
Definition: AMReX_BaseFab.H:72
int i
Definition: AMReX_BaseFab.H:75
Definition: AMReX_Dim3.H:12
int x
Definition: AMReX_Dim3.H:12
int z
Definition: AMReX_Dim3.H:12
int y
Definition: AMReX_Dim3.H:12
Definition: AMReX_FabArrayBase.H:471
std::unique_ptr< MapOfCopyComTagContainers > m_RcvTags
Definition: AMReX_FabArrayBase.H:477
std::unique_ptr< MapOfCopyComTagContainers > m_SndTags
Definition: AMReX_FabArrayBase.H:476
std::unique_ptr< CopyComTagsContainer > m_LocTags
Definition: AMReX_FabArrayBase.H:475
Test if a given type T is callable with arguments of type Args...
Definition: AMReX_TypeTraits.H:207
Test if a given type T is callable with arguments of type Args...
Definition: AMReX_TypeTraits.H:201
This class specializes behaviour on local copies and unpacking receive buffers.
Definition: AMReX_NonLocalBC.H:615
constexpr ApplyDtosAndProjectionOnReciever(const PackComponents &components, DTOS dtos_=DTOS{}, FabProj proj_=FabProj{})
Definition: AMReX_NonLocalBC.H:617
FabProj proj
Definition: AMReX_NonLocalBC.H:621
DTOS dtos
Definition: AMReX_NonLocalBC.H:620
This class holds data buffers for either immediate MPI send or recv calls.
Definition: AMReX_NonLocalBC.H:415
Vector< std::size_t > size
The size in bytes for each data transaction.
Definition: AMReX_NonLocalBC.H:426
Vector< char * > data
Pointers to the_data that can be used for each single data transaction.
Definition: AMReX_NonLocalBC.H:422
Vector< const FabArrayBase::CopyComTagsContainer * > cctc
For each request the copy comm tags for the corresponding data FABs.
Definition: AMReX_NonLocalBC.H:432
Vector< MPI_Status > stats
For each request the corresponding MPI_status, used for debugging.
Definition: AMReX_NonLocalBC.H:430
Vector< MPI_Request > request
The associated MPI_Request for each data transaction.
Definition: AMReX_NonLocalBC.H:428
TheFaArenaPointer the_data
Holds 'em all in one data pointer.
Definition: AMReX_NonLocalBC.H:418
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:420
Vector< std::size_t > offset
All offsets of data in the_data.
Definition: AMReX_NonLocalBC.H:424
This class stores both recv and send buffers with an associated MPI tag.
Definition: AMReX_NonLocalBC.H:452
CommData send
Definition: AMReX_NonLocalBC.H:456
int mpi_tag
Definition: AMReX_NonLocalBC.H:454
CommData recv
Definition: AMReX_NonLocalBC.H:455
Definition: AMReX_NonLocalBC.H:673
Type trait that tests if T has an InverseImage class member function.
Definition: AMReX_NonLocalBC.H:20
This class acts as a default no-op operator.
Definition: AMReX_NonLocalBC.H:280
constexpr Dim3 operator()(Dim3 i) const noexcept
The identity function for Dim3.
Definition: AMReX_NonLocalBC.H:282
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:288
constexpr int operator()(int i) const noexcept
The identity for int.
Definition: AMReX_NonLocalBC.H:294
static constexpr Dim3 Inverse(Dim3 i) noexcept
The identity function for Dim3.
Definition: AMReX_NonLocalBC.H:284
This type trait tests if a given type DP satisfies the DataPacking concept for type FAB.
Definition: AMReX_NonLocalBC.H:489
This type trait tests if a type P is a projection for FAB.
Definition: AMReX_NonLocalBC.H:271
Tests if a given type IndexMap is usable as an index mapping between two index based coordinate syste...
Definition: AMReX_NonLocalBC.H:27
This class takes a projection and a component map and combines them to form a new projection.
Definition: AMReX_NonLocalBC.H:314
Base base
Definition: AMReX_NonLocalBC.H:316
Map map
Definition: AMReX_NonLocalBC.H:322
This is the index mapping based on the DTOS MultiBlockDestToSrc.
Definition: AMReX_NonLocalBC.H:210
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.
std::enable_if_t< IsIndexMapping< DTOS >::value > 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...
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.
This struct describes an affine index transformation for two coordinate systems.
Definition: AMReX_NonLocalBC.H:37
IndexType operator()(IndexType it) const noexcept
Definition: AMReX_NonLocalBC.H:76
IntVect sign
A vector of 1 and -1 describing the orientation in each component.
Definition: AMReX_NonLocalBC.H:43
IntVect offset
The offset in the source index space.
Definition: AMReX_NonLocalBC.H:41
AMREX_GPU_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:51
IntVect permutation
This vector needs to be a valid permutation.
Definition: AMReX_NonLocalBC.H:39
IndexType Inverse(IndexType it) const noexcept
Definition: AMReX_NonLocalBC.H:80
AMREX_GPU_HOST_DEVICE Dim3 Inverse(Dim3 i) const noexcept
The inverse function is given by rearringing all above terms.
Definition: AMReX_NonLocalBC.H:66
Definition: AMReX_NonLocalBC.H:672
Contains information about which components take part of the data transaction.
Definition: AMReX_NonLocalBC.H:528
int dest_component
Definition: AMReX_NonLocalBC.H:529
int src_component
Definition: AMReX_NonLocalBC.H:530
int n_components
Definition: AMReX_NonLocalBC.H:531
Definition: AMReX_NonLocalBC.H:377
int J
Definition: AMReX_NonLocalBC.H:379
int I
Definition: AMReX_NonLocalBC.H:378
constexpr int operator()(int i) const noexcept
Definition: AMReX_NonLocalBC.H:380
constexpr int operator()(int i) const noexcept
Definition: AMReX_NonLocalBC.H:371
int I
Definition: AMReX_NonLocalBC.H:368
int J
Definition: AMReX_NonLocalBC.H:358
constexpr int operator()(int i) const noexcept
Definition: AMReX_NonLocalBC.H:361
This is a permutation where only two components are swapped.
Definition: AMReX_NonLocalBC.H:345
constexpr int operator()(int i) const noexcept
Swaps indices I and J.
Definition: AMReX_NonLocalBC.H:351
Definition: AMReX_BaseFab.H:78
int n
Definition: AMReX_BaseFab.H:81
Definition: AMReX_BaseFab.H:66
int i
Definition: AMReX_BaseFab.H:69