16#ifndef CABANA_HALO_HPP
17#define CABANA_HALO_HPP
23#include <Kokkos_Core.hpp>
24#include <Kokkos_Profiling_ScopedRegion.hpp>
58template <
class MemorySpace>
102 template <
class IdViewType,
class RankViewType>
104 const IdViewType& element_export_ids,
105 const RankViewType& element_export_ranks,
106 const std::vector<int>& neighbor_ranks )
108 , _num_local( num_local )
110 if ( element_export_ids.size() != element_export_ranks.size() )
111 throw std::runtime_error(
112 "Cabana::Halo: Export ids and ranks different sizes!" );
114 auto neighbor_ids = this->createFromExportsAndTopology(
115 element_export_ranks, neighbor_ranks );
116 this->createExportSteering( neighbor_ids, element_export_ranks,
117 element_export_ids );
153 template <
class IdViewType,
class RankViewType>
155 const IdViewType& element_export_ids,
156 const RankViewType& element_export_ranks )
158 , _num_local( num_local )
160 if ( element_export_ids.size() != element_export_ranks.size() )
161 throw std::runtime_error(
162 "Cabana::Halo: Export ids and ranks different sizes!" );
164 auto neighbor_ids = this->createFromExportsOnly( element_export_ranks );
165 this->createExportSteering( neighbor_ids, element_export_ranks,
166 element_export_ids );
174 std::size_t
numLocal()
const {
return _num_local; }
186 std::size_t _num_local;
192struct is_halo_impl :
public std::false_type
196template <
typename MemorySpace>
197struct is_halo_impl<
Halo<MemorySpace>> :
public std::true_type
204struct is_halo :
public is_halo_impl<typename std::remove_cv<T>::type>::type
217template <
class Halo,
class ParticleData>
219 const Halo& halo,
const ParticleData& particles,
226template <
class HaloType,
class AoSoAType,
class SFINAE =
void>
241template <
class HaloType,
class AoSoAType>
243 typename std::enable_if<is_aosoa<AoSoAType>::value>::type>
275 Gather( HaloType halo, AoSoAType aosoa,
const double overallocation = 1.0 )
276 :
base_type( halo, aosoa, overallocation )
289 template <
class ExecutionSpace>
292 Kokkos::Profiling::ScopedRegion region(
"Cabana::Gather::apply" );
300 auto steering = _halo.getExportSteering();
302 auto gather_send_buffer_func = KOKKOS_LAMBDA(
const std::size_t i )
304 send_buffer( i ) = aosoa.getTuple( steering( i ) );
306 Kokkos::RangePolicy<ExecutionSpace> send_policy( 0, _send_size );
307 Kokkos::parallel_for(
"Cabana::Gather::gather_send_buffer", send_policy,
308 gather_send_buffer_func );
312 const int mpi_tag = 2345;
315 int num_n = _halo.numNeighbor();
316 std::vector<MPI_Request> requests( num_n );
317 std::pair<std::size_t, std::size_t> recv_range = { 0, 0 };
318 for (
int n = 0; n < num_n; ++n )
320 recv_range.second = recv_range.first + _halo.numImport( n );
322 auto recv_subview = Kokkos::subview( recv_buffer, recv_range );
324 MPI_Irecv( recv_subview.data(),
325 recv_subview.size() *
sizeof(
data_type ), MPI_BYTE,
326 _halo.neighborRank( n ), mpi_tag, _halo.comm(),
329 recv_range.first = recv_range.second;
333 std::pair<std::size_t, std::size_t> send_range = { 0, 0 };
334 for (
int n = 0; n < num_n; ++n )
336 send_range.second = send_range.first + _halo.numExport( n );
338 auto send_subview = Kokkos::subview( send_buffer, send_range );
340 MPI_Send( send_subview.data(),
341 send_subview.size() *
sizeof(
data_type ), MPI_BYTE,
342 _halo.neighborRank( n ), mpi_tag, _halo.comm() );
344 send_range.first = send_range.second;
348 std::vector<MPI_Status> status( num_n );
350 MPI_Waitall( requests.size(), requests.data(), status.data() );
351 if ( MPI_SUCCESS != ec )
352 throw std::logic_error(
353 "Cabana::Gather::apply (AoSoA): Failed MPI Communication" );
356 std::size_t num_local = _halo.numLocal();
357 auto extract_recv_buffer_func = KOKKOS_LAMBDA(
const std::size_t i )
359 std::size_t ghost_idx = i + num_local;
360 aosoa.setTuple( ghost_idx, recv_buffer( i ) );
362 Kokkos::RangePolicy<ExecutionSpace> recv_policy( 0, _recv_size );
363 Kokkos::parallel_for(
"Cabana::Gather::apply::extract_recv_buffer",
364 recv_policy, extract_recv_buffer_func );
368 MPI_Barrier( _halo.comm() );
379 void reserve(
const HaloType& halo, AoSoAType& aosoa )
382 throw std::runtime_error(
383 "Cabana::Gather:reserve: "
384 "AoSoA is the wrong size for gather! (Label: " +
385 aosoa.label() +
")" );
397 void reserve(
const HaloType& halo, AoSoAType& aosoa,
398 const double overallocation )
401 throw std::runtime_error(
402 "Cabana::Gather:reserve: "
403 "AoSoA is the wrong size for gather! (Label: " +
404 aosoa.label() +
")" );
411 plan_type _halo = base_type::_comm_plan;
412 using base_type::_recv_size;
413 using base_type::_send_size;
427template <
class HaloType,
class SliceType>
429 typename std::enable_if<is_slice<SliceType>::value>::type>
461 Gather( HaloType halo, SliceType
slice,
const double overallocation = 1.0 )
475 template <
class ExecutionSpace>
478 Kokkos::Profiling::ScopedRegion region(
"Cabana::Gather::apply" );
489 auto slice_data =
slice.data();
492 auto steering = _halo.getExportSteering();
495 auto gather_send_buffer_func = KOKKOS_LAMBDA(
const std::size_t i )
497 auto s = SliceType::index_type::s( steering( i ) );
498 auto a = SliceType::index_type::a( steering( i ) );
499 std::size_t slice_offset = s *
slice.stride( 0 ) + a;
500 for ( std::size_t n = 0; n < num_comp; ++n )
501 send_buffer( i, n ) =
502 slice_data[slice_offset + n * SliceType::vector_length];
504 Kokkos::RangePolicy<ExecutionSpace> send_policy( 0, _send_size );
505 Kokkos::parallel_for(
"Cabana::Gather::gather_send_buffer", send_policy,
506 gather_send_buffer_func );
510 const int mpi_tag = 2345;
513 int num_n = _halo.numNeighbor();
514 std::vector<MPI_Request> requests( num_n );
515 std::pair<std::size_t, std::size_t> recv_range = { 0, 0 };
516 for (
int n = 0; n < num_n; ++n )
518 recv_range.second = recv_range.first + _halo.numImport( n );
521 Kokkos::subview( recv_buffer, recv_range, Kokkos::ALL );
523 MPI_Irecv( recv_subview.data(),
524 recv_subview.size() *
sizeof(
data_type ), MPI_BYTE,
525 _halo.neighborRank( n ), mpi_tag, _halo.comm(),
528 recv_range.first = recv_range.second;
532 std::pair<std::size_t, std::size_t> send_range = { 0, 0 };
533 for (
int n = 0; n < num_n; ++n )
535 send_range.second = send_range.first + _halo.numExport( n );
538 Kokkos::subview( send_buffer, send_range, Kokkos::ALL );
540 MPI_Send( send_subview.data(),
541 send_subview.size() *
sizeof(
data_type ), MPI_BYTE,
542 _halo.neighborRank( n ), mpi_tag, _halo.comm() );
544 send_range.first = send_range.second;
548 std::vector<MPI_Status> status( num_n );
550 MPI_Waitall( requests.size(), requests.data(), status.data() );
551 if ( MPI_SUCCESS != ec )
552 throw std::logic_error(
553 "Cabana::Gather::apply (Slice): Failed MPI Communication" );
556 std::size_t num_local = _halo.numLocal();
557 auto extract_recv_buffer_func = KOKKOS_LAMBDA(
const std::size_t i )
559 std::size_t ghost_idx = i + num_local;
560 auto s = SliceType::index_type::s( ghost_idx );
561 auto a = SliceType::index_type::a( ghost_idx );
562 std::size_t slice_offset = s *
slice.stride( 0 ) + a;
563 for ( std::size_t n = 0; n < num_comp; ++n )
564 slice_data[slice_offset + SliceType::vector_length * n] =
567 Kokkos::RangePolicy<ExecutionSpace> recv_policy( 0, _recv_size );
568 Kokkos::parallel_for(
"Cabana::Gather::extract_recv_buffer",
569 recv_policy, extract_recv_buffer_func );
573 MPI_Barrier( _halo.comm() );
587 const double overallocation )
590 throw std::runtime_error(
591 "Cabana::Gather:reserve: "
592 "Slice is the wrong size for gather! (Label: " +
593 slice.label() +
")" );
607 throw std::runtime_error(
608 "Cabana::Gather:reserve: "
609 "Slice is the wrong size for gather! (Label: " +
610 slice.label() +
")" );
616 plan_type _halo = base_type::_comm_plan;
617 using base_type::_recv_size;
618 using base_type::_send_size;
635template <
class HaloType,
class ParticleDataType>
637 const double overallocation = 1.0 )
660template <
class HaloType,
class ParticleDataType>
661void gather(
const HaloType& halo, ParticleDataType& data )
683template <
class HaloType,
class SliceType>
716 Scatter( HaloType halo, SliceType
slice,
const double overallocation = 1.0 )
730 template <
class ExecutionSpace>
733 Kokkos::Profiling::ScopedRegion region(
"Cabana::Scatter::apply" );
746 Kokkos::MemoryTraits<Kokkos::Unmanaged>>
750 std::size_t num_local = _halo.numLocal();
751 auto extract_send_buffer_func = KOKKOS_LAMBDA(
const std::size_t i )
753 std::size_t ghost_idx = i + num_local;
754 auto s = SliceType::index_type::s( ghost_idx );
755 auto a = SliceType::index_type::a( ghost_idx );
756 std::size_t slice_offset = s *
slice.stride( 0 ) + a;
757 for ( std::size_t n = 0; n < num_comp; ++n )
758 send_buffer( i, n ) =
759 slice_data( slice_offset + SliceType::vector_length * n );
761 Kokkos::RangePolicy<ExecutionSpace> send_policy( 0, _send_size );
762 Kokkos::parallel_for(
"Cabana::Scatter::apply::extract_send_buffer",
763 send_policy, extract_send_buffer_func );
767 const int mpi_tag = 2345;
770 int num_n = _halo.numNeighbor();
771 std::vector<MPI_Request> requests( num_n );
772 std::pair<std::size_t, std::size_t> recv_range = { 0, 0 };
773 for (
int n = 0; n < num_n; ++n )
775 recv_range.second = recv_range.first + _halo.numExport( n );
778 Kokkos::subview( recv_buffer, recv_range, Kokkos::ALL );
780 MPI_Irecv( recv_subview.data(),
781 recv_subview.size() *
sizeof(
data_type ), MPI_BYTE,
782 _halo.neighborRank( n ), mpi_tag, _halo.comm(),
785 recv_range.first = recv_range.second;
789 std::pair<std::size_t, std::size_t> send_range = { 0, 0 };
790 for (
int n = 0; n < num_n; ++n )
792 send_range.second = send_range.first + _halo.numImport( n );
795 Kokkos::subview( send_buffer, send_range, Kokkos::ALL );
797 MPI_Send( send_subview.data(),
798 send_subview.size() *
sizeof(
data_type ), MPI_BYTE,
799 _halo.neighborRank( n ), mpi_tag, _halo.comm() );
801 send_range.first = send_range.second;
805 std::vector<MPI_Status> status( num_n );
807 MPI_Waitall( requests.size(), requests.data(), status.data() );
808 if ( MPI_SUCCESS != ec )
809 throw std::logic_error(
"Cabana::Scatter::apply (Slice): "
810 "Failed MPI Communication" );
813 auto steering = _halo.getExportSteering();
816 auto scatter_recv_buffer_func = KOKKOS_LAMBDA(
const std::size_t i )
818 auto s = SliceType::index_type::s( steering( i ) );
819 auto a = SliceType::index_type::a( steering( i ) );
820 std::size_t slice_offset = s *
slice.stride( 0 ) + a;
821 for ( std::size_t n = 0; n < num_comp; ++n )
823 &slice_data( slice_offset + SliceType::vector_length * n ),
824 recv_buffer( i, n ) );
826 Kokkos::RangePolicy<ExecutionSpace> recv_policy( 0, _recv_size );
827 Kokkos::parallel_for(
"Cabana::Scatter::apply::scatter_recv_buffer",
828 recv_policy, scatter_recv_buffer_func );
832 MPI_Barrier( _halo.comm() );
847 const double overallocation )
850 throw std::runtime_error(
851 "Cabana::Scatter::reserve: "
852 "Slice is the wrong size for scatter! (Label: " +
853 slice.label() +
")" );
867 throw std::runtime_error(
868 "Cabana::Scatter::reserve: "
869 "Slice is the wrong size for scatter! (Label: " +
870 slice.label() +
")" );
894template <
class HaloType,
class SliceType>
896 const double overallocation = 1.0,
922template <
class HaloType,
class SliceType>
Array-of-Struct-of-Arrays particle data structure.
Multi-node communication patterns.
Slice a single particle property from an AoSoA.
typename plan_type::execution_space execution_space
Definition Cabana_CommunicationPlan.hpp:1184
buffer_type getSendBuffer() const
Definition Cabana_CommunicationPlan.hpp:1214
particle_data_type getData() const
Definition Cabana_CommunicationPlan.hpp:1219
plan_type _comm_plan
Definition Cabana_CommunicationPlan.hpp:1312
std::size_t _recv_size
Definition Cabana_CommunicationPlan.hpp:1320
typename comm_data_type::data_type data_type
Definition Cabana_CommunicationPlan.hpp:1194
typename comm_data_type::buffer_type buffer_type
Definition Cabana_CommunicationPlan.hpp:1196
auto getSliceComponents()
Definition Cabana_CommunicationPlan.hpp:1309
HaloType plan_type
Definition Cabana_CommunicationPlan.hpp:1182
CommunicationData(const HaloType &comm_plan, const particle_data_type &particles, const double overallocation=1.0)
Definition Cabana_CommunicationPlan.hpp:1204
typename comm_data_type::memory_space memory_space
Definition Cabana_CommunicationPlan.hpp:1192
buffer_type getReceiveBuffer() const
Definition Cabana_CommunicationPlan.hpp:1216
std::size_t _send_size
Definition Cabana_CommunicationPlan.hpp:1318
MPI_Comm comm() const
Get the MPI communicator.
Definition Cabana_CommunicationPlan.hpp:468
std::size_t totalNumImport() const
Get the total number of imports this rank will do.
Definition Cabana_CommunicationPlan.hpp:525
CommunicationPlan(MPI_Comm comm)
Constructor.
Definition Cabana_CommunicationPlan.hpp:446
typename base_type::memory_space memory_space
Kokkos memory space.
Definition Cabana_Halo.hpp:257
void apply() override
Perform the communication (migrate, gather, scatter).
Definition Cabana_Halo.hpp:371
void reserve(const HaloType &halo, AoSoAType &aosoa, const double overallocation)
Reserve new buffers as needed and update the halo and AoSoA data.
Definition Cabana_Halo.hpp:397
auto totalSend()
Total gather send size for this rank.
Definition Cabana_Halo.hpp:282
typename base_type::data_type data_type
Communication data type.
Definition Cabana_Halo.hpp:259
Gather(HaloType halo, AoSoAType aosoa, const double overallocation=1.0)
Definition Cabana_Halo.hpp:275
auto totalReceive()
Total gather receive size for this rank.
Definition Cabana_Halo.hpp:284
void apply(ExecutionSpace)
Perform the gather operation.
Definition Cabana_Halo.hpp:290
typename base_type::buffer_type buffer_type
Communication buffer type.
Definition Cabana_Halo.hpp:261
typename base_type::plan_type plan_type
Communication plan type (Halo)
Definition Cabana_Halo.hpp:253
typename base_type::execution_space execution_space
Kokkos execution space.
Definition Cabana_Halo.hpp:255
void reserve(const HaloType &halo, AoSoAType &aosoa)
Reserve new buffers as needed and update the halo and AoSoA data.
Definition Cabana_Halo.hpp:379
CommunicationData< HaloType, CommunicationDataAoSoA< AoSoAType > > base_type
Base type.
Definition Cabana_Halo.hpp:250
typename base_type::memory_space memory_space
Kokkos memory space.
Definition Cabana_Halo.hpp:443
typename base_type::buffer_type buffer_type
Communication buffer type.
Definition Cabana_Halo.hpp:447
CommunicationData< HaloType, CommunicationDataSlice< SliceType > > base_type
Base type.
Definition Cabana_Halo.hpp:436
void apply(ExecutionSpace)
Perform the gather operation.
Definition Cabana_Halo.hpp:476
void apply() override
Perform the communication (migrate, gather, scatter).
Definition Cabana_Halo.hpp:576
auto totalReceive()
Total gather receive size for this rank.
Definition Cabana_Halo.hpp:470
Gather(HaloType halo, SliceType slice, const double overallocation=1.0)
Definition Cabana_Halo.hpp:461
void reserve(const HaloType &halo, const SliceType &slice, const double overallocation)
Reserve new buffers as needed and update the halo and slice data.
Definition Cabana_Halo.hpp:586
typename base_type::execution_space execution_space
Kokkos execution space.
Definition Cabana_Halo.hpp:441
typename base_type::plan_type plan_type
Communication plan type (Halo)
Definition Cabana_Halo.hpp:439
auto totalSend()
Total gather send size for this rank.
Definition Cabana_Halo.hpp:468
void reserve(const HaloType &halo, const SliceType &slice)
Reserve new buffers as needed and update the halo and slice data.
Definition Cabana_Halo.hpp:604
typename base_type::data_type data_type
Communication data type.
Definition Cabana_Halo.hpp:445
Definition Cabana_Halo.hpp:227
A communication plan for scattering and gathering of ghosted data.
Definition Cabana_Halo.hpp:60
std::size_t numLocal() const
Get the number of elements locally owned by this rank.
Definition Cabana_Halo.hpp:174
std::size_t numGhost() const
Get the number of ghost elements this rank. Use this to resize a data structure for scatter/gather op...
Definition Cabana_Halo.hpp:183
Halo(MPI_Comm comm, const std::size_t num_local, const IdViewType &element_export_ids, const RankViewType &element_export_ranks)
Export rank constructor. Use this when you don't know who you will receiving from - only who you are ...
Definition Cabana_Halo.hpp:154
Halo(MPI_Comm comm, const std::size_t num_local, const IdViewType &element_export_ids, const RankViewType &element_export_ranks, const std::vector< int > &neighbor_ranks)
Neighbor and export rank constructor. Use this when you already know which ranks neighbor each other ...
Definition Cabana_Halo.hpp:103
Synchronously scatter data from the ghosts to the local decomposition of a slice using the halo rever...
Definition Cabana_Halo.hpp:686
void reserve(const HaloType &halo, const SliceType &slice)
Reserve new buffers as needed and update the halo and slice data.
Definition Cabana_Halo.hpp:864
CommunicationData< HaloType, CommunicationDataSlice< SliceType > > base_type
Base type.
Definition Cabana_Halo.hpp:691
typename base_type::memory_space memory_space
Kokkos memory space.
Definition Cabana_Halo.hpp:698
void apply(ExecutionSpace)
Perform the scatter operation.
Definition Cabana_Halo.hpp:731
typename base_type::data_type data_type
Communication data type.
Definition Cabana_Halo.hpp:700
void reserve(const HaloType &halo, const SliceType &slice, const double overallocation)
Reserve new buffers as needed and update the halo and slice data. Reallocation only occurs if there i...
Definition Cabana_Halo.hpp:846
typename base_type::plan_type plan_type
Communication plan type (Halo).
Definition Cabana_Halo.hpp:694
auto totalReceive()
Total scatter receive size for this rank.
Definition Cabana_Halo.hpp:725
void apply() override
Perform the communication (migrate, gather, scatter).
Definition Cabana_Halo.hpp:835
typename base_type::buffer_type buffer_type
Communication buffer type.
Definition Cabana_Halo.hpp:702
typename base_type::execution_space execution_space
Kokkos execution space.
Definition Cabana_Halo.hpp:696
Scatter(HaloType halo, SliceType slice, const double overallocation=1.0)
Definition Cabana_Halo.hpp:716
auto totalSend()
Total scatter send size for this rank.
Definition Cabana_Halo.hpp:723
Core: particle data structures and algorithms.
Definition Cabana_AoSoA.hpp:36
void gather(const HaloType &halo, ParticleDataType &data)
Synchronously gather data from the local decomposition to the ghosts using the halo forward communica...
Definition Cabana_Halo.hpp:661
AoSoA_t::template member_slice_type< M > slice(const AoSoA_t &aosoa, const std::string &slice_label="")
Create a slice from an AoSoA.
Definition Cabana_AoSoA.hpp:77
void scatter(const HaloType &halo, SliceType &slice, typename std::enable_if<(is_halo< HaloType >::value &&is_slice< SliceType >::value), int >::type *=0)
Synchronously scatter data from the ghosts to the local decomposition of a slice using the halo rever...
Definition Cabana_Halo.hpp:923
auto createScatter(const HaloType &halo, const SliceType &slice, const double overallocation=1.0, typename std::enable_if<(is_halo< HaloType >::value &&is_slice< SliceType >::value), int >::type *=0)
Create the scatter.
Definition Cabana_Halo.hpp:895
auto createGather(const HaloType &halo, const ParticleDataType &data, const double overallocation=1.0)
Create the gather.
Definition Cabana_Halo.hpp:636
bool haloCheckValidSize(const Halo &halo, const ParticleData &particles, typename std::enable_if<(is_halo< Halo >::value), int >::type *=0)
Ensure the particle size matches the total halo (local and ghost) size.
Definition Cabana_Halo.hpp:218
Halo static type checker.
Definition Cabana_Halo.hpp:205
Slice static type checker.
Definition Cabana_Slice.hpp:861