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(
"Export ids and ranks different sizes!" );
113 auto neighbor_ids = this->createFromExportsAndTopology(
114 element_export_ranks, neighbor_ranks );
115 this->createExportSteering( neighbor_ids, element_export_ranks,
116 element_export_ids );
152 template <
class IdViewType,
class RankViewType>
154 const IdViewType& element_export_ids,
155 const RankViewType& element_export_ranks )
157 , _num_local( num_local )
159 if ( element_export_ids.size() != element_export_ranks.size() )
160 throw std::runtime_error(
"Export ids and ranks different sizes!" );
162 auto neighbor_ids = this->createFromExportsOnly( element_export_ranks );
163 this->createExportSteering( neighbor_ids, element_export_ranks,
164 element_export_ids );
172 std::size_t
numLocal()
const {
return _num_local; }
184 std::size_t _num_local;
190struct is_halo_impl :
public std::false_type
194template <
typename MemorySpace>
195struct is_halo_impl<
Halo<MemorySpace>> :
public std::true_type
202struct is_halo :
public is_halo_impl<typename std::remove_cv<T>::type>::type
215template <
class Halo,
class ParticleData>
217 const Halo& halo,
const ParticleData& particles,
224template <
class HaloType,
class AoSoAType,
class SFINAE =
void>
239template <
class HaloType,
class AoSoAType>
241 typename std::enable_if<is_aosoa<AoSoAType>::value>::type>
273 Gather( HaloType halo, AoSoAType aosoa,
const double overallocation = 1.0 )
274 :
base_type( halo, aosoa, overallocation )
287 template <
class ExecutionSpace>
290 Kokkos::Profiling::ScopedRegion region(
"Cabana::gather" );
298 auto steering = _halo.getExportSteering();
300 auto gather_send_buffer_func = KOKKOS_LAMBDA(
const std::size_t i )
302 send_buffer( i ) = aosoa.getTuple( steering( i ) );
304 Kokkos::RangePolicy<ExecutionSpace> send_policy( 0, _send_size );
305 Kokkos::parallel_for(
"Cabana::gather::gather_send_buffer", send_policy,
306 gather_send_buffer_func );
310 const int mpi_tag = 2345;
313 int num_n = _halo.numNeighbor();
314 std::vector<MPI_Request> requests( num_n );
315 std::pair<std::size_t, std::size_t> recv_range = { 0, 0 };
316 for (
int n = 0; n < num_n; ++n )
318 recv_range.second = recv_range.first + _halo.numImport( n );
320 auto recv_subview = Kokkos::subview( recv_buffer, recv_range );
322 MPI_Irecv( recv_subview.data(),
323 recv_subview.size() *
sizeof(
data_type ), MPI_BYTE,
324 _halo.neighborRank( n ), mpi_tag, _halo.comm(),
327 recv_range.first = recv_range.second;
331 std::pair<std::size_t, std::size_t> send_range = { 0, 0 };
332 for (
int n = 0; n < num_n; ++n )
334 send_range.second = send_range.first + _halo.numExport( n );
336 auto send_subview = Kokkos::subview( send_buffer, send_range );
338 MPI_Send( send_subview.data(),
339 send_subview.size() *
sizeof(
data_type ), MPI_BYTE,
340 _halo.neighborRank( n ), mpi_tag, _halo.comm() );
342 send_range.first = send_range.second;
346 std::vector<MPI_Status> status( num_n );
348 MPI_Waitall( requests.size(), requests.data(), status.data() );
349 if ( MPI_SUCCESS != ec )
350 throw std::logic_error(
"Failed MPI Communication" );
353 std::size_t num_local = _halo.numLocal();
354 auto extract_recv_buffer_func = KOKKOS_LAMBDA(
const std::size_t i )
356 std::size_t ghost_idx = i + num_local;
357 aosoa.setTuple( ghost_idx, recv_buffer( i ) );
359 Kokkos::RangePolicy<ExecutionSpace> recv_policy( 0, _recv_size );
360 Kokkos::parallel_for(
"Cabana::gather::extract_recv_buffer",
361 recv_policy, extract_recv_buffer_func );
365 MPI_Barrier( _halo.comm() );
376 void reserve(
const HaloType& halo, AoSoAType& aosoa )
379 throw std::runtime_error(
"AoSoA is the wrong size for gather!" );
391 void reserve(
const HaloType& halo, AoSoAType& aosoa,
392 const double overallocation )
395 throw std::runtime_error(
"AoSoA is the wrong size for gather!" );
402 plan_type _halo = base_type::_comm_plan;
403 using base_type::_recv_size;
404 using base_type::_send_size;
418template <
class HaloType,
class SliceType>
420 typename std::enable_if<is_slice<SliceType>::value>::type>
452 Gather( HaloType halo, SliceType
slice,
const double overallocation = 1.0 )
466 template <
class ExecutionSpace>
469 Kokkos::Profiling::ScopedRegion region(
"Cabana::gather" );
480 auto slice_data =
slice.data();
483 auto steering = _halo.getExportSteering();
486 auto gather_send_buffer_func = KOKKOS_LAMBDA(
const std::size_t i )
488 auto s = SliceType::index_type::s( steering( i ) );
489 auto a = SliceType::index_type::a( steering( i ) );
490 std::size_t slice_offset = s *
slice.stride( 0 ) + a;
491 for ( std::size_t n = 0; n < num_comp; ++n )
492 send_buffer( i, n ) =
493 slice_data[slice_offset + n * SliceType::vector_length];
495 Kokkos::RangePolicy<ExecutionSpace> send_policy( 0, _send_size );
496 Kokkos::parallel_for(
"Cabana::gather::gather_send_buffer", send_policy,
497 gather_send_buffer_func );
501 const int mpi_tag = 2345;
504 int num_n = _halo.numNeighbor();
505 std::vector<MPI_Request> requests( num_n );
506 std::pair<std::size_t, std::size_t> recv_range = { 0, 0 };
507 for (
int n = 0; n < num_n; ++n )
509 recv_range.second = recv_range.first + _halo.numImport( n );
512 Kokkos::subview( recv_buffer, recv_range, Kokkos::ALL );
514 MPI_Irecv( recv_subview.data(),
515 recv_subview.size() *
sizeof(
data_type ), MPI_BYTE,
516 _halo.neighborRank( n ), mpi_tag, _halo.comm(),
519 recv_range.first = recv_range.second;
523 std::pair<std::size_t, std::size_t> send_range = { 0, 0 };
524 for (
int n = 0; n < num_n; ++n )
526 send_range.second = send_range.first + _halo.numExport( n );
529 Kokkos::subview( send_buffer, send_range, Kokkos::ALL );
531 MPI_Send( send_subview.data(),
532 send_subview.size() *
sizeof(
data_type ), MPI_BYTE,
533 _halo.neighborRank( n ), mpi_tag, _halo.comm() );
535 send_range.first = send_range.second;
539 std::vector<MPI_Status> status( num_n );
541 MPI_Waitall( requests.size(), requests.data(), status.data() );
542 if ( MPI_SUCCESS != ec )
543 throw std::logic_error(
"Failed MPI Communication" );
546 std::size_t num_local = _halo.numLocal();
547 auto extract_recv_buffer_func = KOKKOS_LAMBDA(
const std::size_t i )
549 std::size_t ghost_idx = i + num_local;
550 auto s = SliceType::index_type::s( ghost_idx );
551 auto a = SliceType::index_type::a( ghost_idx );
552 std::size_t slice_offset = s *
slice.stride( 0 ) + a;
553 for ( std::size_t n = 0; n < num_comp; ++n )
554 slice_data[slice_offset + SliceType::vector_length * n] =
557 Kokkos::RangePolicy<ExecutionSpace> recv_policy( 0, _recv_size );
558 Kokkos::parallel_for(
"Cabana::gather::extract_recv_buffer",
559 recv_policy, extract_recv_buffer_func );
563 MPI_Barrier( _halo.comm() );
577 const double overallocation )
580 throw std::runtime_error(
"AoSoA is the wrong size for gather!" );
594 throw std::runtime_error(
"AoSoA is the wrong size for gather!" );
600 plan_type _halo = base_type::_comm_plan;
601 using base_type::_recv_size;
602 using base_type::_send_size;
619template <
class HaloType,
class ParticleDataType>
621 const double overallocation = 1.0 )
644template <
class HaloType,
class ParticleDataType>
645void gather(
const HaloType& halo, ParticleDataType& data )
667template <
class HaloType,
class SliceType>
700 Scatter( HaloType halo, SliceType
slice,
const double overallocation = 1.0 )
714 template <
class ExecutionSpace>
717 Kokkos::Profiling::ScopedRegion region(
"Cabana::scatter" );
730 Kokkos::MemoryTraits<Kokkos::Unmanaged>>
734 std::size_t num_local = _halo.numLocal();
735 auto extract_send_buffer_func = KOKKOS_LAMBDA(
const std::size_t i )
737 std::size_t ghost_idx = i + num_local;
738 auto s = SliceType::index_type::s( ghost_idx );
739 auto a = SliceType::index_type::a( ghost_idx );
740 std::size_t slice_offset = s *
slice.stride( 0 ) + a;
741 for ( std::size_t n = 0; n < num_comp; ++n )
742 send_buffer( i, n ) =
743 slice_data( slice_offset + SliceType::vector_length * n );
745 Kokkos::RangePolicy<ExecutionSpace> send_policy( 0, _send_size );
746 Kokkos::parallel_for(
"Cabana::scatter::extract_send_buffer",
747 send_policy, extract_send_buffer_func );
751 const int mpi_tag = 2345;
754 int num_n = _halo.numNeighbor();
755 std::vector<MPI_Request> requests( num_n );
756 std::pair<std::size_t, std::size_t> recv_range = { 0, 0 };
757 for (
int n = 0; n < num_n; ++n )
759 recv_range.second = recv_range.first + _halo.numExport( n );
762 Kokkos::subview( recv_buffer, recv_range, Kokkos::ALL );
764 MPI_Irecv( recv_subview.data(),
765 recv_subview.size() *
sizeof(
data_type ), MPI_BYTE,
766 _halo.neighborRank( n ), mpi_tag, _halo.comm(),
769 recv_range.first = recv_range.second;
773 std::pair<std::size_t, std::size_t> send_range = { 0, 0 };
774 for (
int n = 0; n < num_n; ++n )
776 send_range.second = send_range.first + _halo.numImport( n );
779 Kokkos::subview( send_buffer, send_range, Kokkos::ALL );
781 MPI_Send( send_subview.data(),
782 send_subview.size() *
sizeof(
data_type ), MPI_BYTE,
783 _halo.neighborRank( n ), mpi_tag, _halo.comm() );
785 send_range.first = send_range.second;
789 std::vector<MPI_Status> status( num_n );
791 MPI_Waitall( requests.size(), requests.data(), status.data() );
792 if ( MPI_SUCCESS != ec )
793 throw std::logic_error(
"Failed MPI Communication" );
796 auto steering = _halo.getExportSteering();
799 auto scatter_recv_buffer_func = KOKKOS_LAMBDA(
const std::size_t i )
801 auto s = SliceType::index_type::s( steering( i ) );
802 auto a = SliceType::index_type::a( steering( i ) );
803 std::size_t slice_offset = s *
slice.stride( 0 ) + a;
804 for ( std::size_t n = 0; n < num_comp; ++n )
806 &slice_data( slice_offset + SliceType::vector_length * n ),
807 recv_buffer( i, n ) );
809 Kokkos::RangePolicy<ExecutionSpace> recv_policy( 0, _recv_size );
810 Kokkos::parallel_for(
"Cabana::scatter::scatter_recv_buffer",
811 recv_policy, scatter_recv_buffer_func );
815 MPI_Barrier( _halo.comm() );
830 const double overallocation )
833 throw std::runtime_error(
"AoSoA is the wrong size for scatter!" );
847 throw std::runtime_error(
"AoSoA is the wrong size for scatter!" );
871template <
class HaloType,
class SliceType>
873 const double overallocation = 1.0,
899template <
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:1178
buffer_type getSendBuffer() const
Definition Cabana_CommunicationPlan.hpp:1208
particle_data_type getData() const
Definition Cabana_CommunicationPlan.hpp:1213
plan_type _comm_plan
Definition Cabana_CommunicationPlan.hpp:1303
std::size_t _recv_size
Definition Cabana_CommunicationPlan.hpp:1311
typename comm_data_type::data_type data_type
Definition Cabana_CommunicationPlan.hpp:1188
typename comm_data_type::buffer_type buffer_type
Definition Cabana_CommunicationPlan.hpp:1190
auto getSliceComponents()
Definition Cabana_CommunicationPlan.hpp:1300
HaloType plan_type
Definition Cabana_CommunicationPlan.hpp:1176
CommunicationData(const HaloType &comm_plan, const particle_data_type &particles, const double overallocation=1.0)
Definition Cabana_CommunicationPlan.hpp:1198
typename comm_data_type::memory_space memory_space
Definition Cabana_CommunicationPlan.hpp:1186
buffer_type getReceiveBuffer() const
Definition Cabana_CommunicationPlan.hpp:1210
std::size_t _send_size
Definition Cabana_CommunicationPlan.hpp:1309
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:255
void apply() override
Perform the communication (migrate, gather, scatter).
Definition Cabana_Halo.hpp:368
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:391
auto totalSend()
Total gather send size for this rank.
Definition Cabana_Halo.hpp:280
typename base_type::data_type data_type
Communication data type.
Definition Cabana_Halo.hpp:257
Gather(HaloType halo, AoSoAType aosoa, const double overallocation=1.0)
Definition Cabana_Halo.hpp:273
auto totalReceive()
Total gather receive size for this rank.
Definition Cabana_Halo.hpp:282
void apply(ExecutionSpace)
Perform the gather operation.
Definition Cabana_Halo.hpp:288
typename base_type::buffer_type buffer_type
Communication buffer type.
Definition Cabana_Halo.hpp:259
typename base_type::plan_type plan_type
Communication plan type (Halo)
Definition Cabana_Halo.hpp:251
typename base_type::execution_space execution_space
Kokkos execution space.
Definition Cabana_Halo.hpp:253
void reserve(const HaloType &halo, AoSoAType &aosoa)
Reserve new buffers as needed and update the halo and AoSoA data.
Definition Cabana_Halo.hpp:376
CommunicationData< HaloType, CommunicationDataAoSoA< AoSoAType > > base_type
Base type.
Definition Cabana_Halo.hpp:248
typename base_type::memory_space memory_space
Kokkos memory space.
Definition Cabana_Halo.hpp:434
typename base_type::buffer_type buffer_type
Communication buffer type.
Definition Cabana_Halo.hpp:438
CommunicationData< HaloType, CommunicationDataSlice< SliceType > > base_type
Base type.
Definition Cabana_Halo.hpp:427
void apply(ExecutionSpace)
Perform the gather operation.
Definition Cabana_Halo.hpp:467
void apply() override
Perform the communication (migrate, gather, scatter).
Definition Cabana_Halo.hpp:566
auto totalReceive()
Total gather receive size for this rank.
Definition Cabana_Halo.hpp:461
Gather(HaloType halo, SliceType slice, const double overallocation=1.0)
Definition Cabana_Halo.hpp:452
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:576
typename base_type::execution_space execution_space
Kokkos execution space.
Definition Cabana_Halo.hpp:432
typename base_type::plan_type plan_type
Communication plan type (Halo)
Definition Cabana_Halo.hpp:430
auto totalSend()
Total gather send size for this rank.
Definition Cabana_Halo.hpp:459
void reserve(const HaloType &halo, const SliceType &slice)
Reserve new buffers as needed and update the halo and slice data.
Definition Cabana_Halo.hpp:591
typename base_type::data_type data_type
Communication data type.
Definition Cabana_Halo.hpp:436
Definition Cabana_Halo.hpp:225
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:172
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:181
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:153
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:670
void reserve(const HaloType &halo, const SliceType &slice)
Reserve new buffers as needed and update the halo and slice data.
Definition Cabana_Halo.hpp:844
CommunicationData< HaloType, CommunicationDataSlice< SliceType > > base_type
Base type.
Definition Cabana_Halo.hpp:675
typename base_type::memory_space memory_space
Kokkos memory space.
Definition Cabana_Halo.hpp:682
void apply(ExecutionSpace)
Perform the scatter operation.
Definition Cabana_Halo.hpp:715
typename base_type::data_type data_type
Communication data type.
Definition Cabana_Halo.hpp:684
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:829
typename base_type::plan_type plan_type
Communication plan type (Halo).
Definition Cabana_Halo.hpp:678
auto totalReceive()
Total scatter receive size for this rank.
Definition Cabana_Halo.hpp:709
void apply() override
Perform the communication (migrate, gather, scatter).
Definition Cabana_Halo.hpp:818
typename base_type::buffer_type buffer_type
Communication buffer type.
Definition Cabana_Halo.hpp:686
typename base_type::execution_space execution_space
Kokkos execution space.
Definition Cabana_Halo.hpp:680
Scatter(HaloType halo, SliceType slice, const double overallocation=1.0)
Definition Cabana_Halo.hpp:700
auto totalSend()
Total scatter send size for this rank.
Definition Cabana_Halo.hpp:707
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:645
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:900
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:872
auto createGather(const HaloType &halo, const ParticleDataType &data, const double overallocation=1.0)
Create the gather.
Definition Cabana_Halo.hpp:620
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:216
Halo static type checker.
Definition Cabana_Halo.hpp:203
Slice static type checker.
Definition Cabana_Slice.hpp:861