Cabana 0.8.0-dev
 
Loading...
Searching...
No Matches
Cabana_Halo.hpp
Go to the documentation of this file.
1/****************************************************************************
2 * Copyright (c) 2018-2023 by the Cabana authors *
3 * All rights reserved. *
4 * *
5 * This file is part of the Cabana library. Cabana is distributed under a *
6 * BSD 3-clause license. For the licensing terms see the LICENSE file in *
7 * the top-level directory. *
8 * *
9 * SPDX-License-Identifier: BSD-3-Clause *
10 ****************************************************************************/
11
16#ifndef CABANA_HALO_HPP
17#define CABANA_HALO_HPP
18
19#include <Cabana_AoSoA.hpp>
21#include <Cabana_Slice.hpp>
22
23#include <Kokkos_Core.hpp>
24#include <Kokkos_Profiling_ScopedRegion.hpp>
25
26#include <mpi.h>
27
28#include <exception>
29#include <vector>
30
31namespace Cabana
32{
33//---------------------------------------------------------------------------//
58template <class MemorySpace>
59class Halo : public CommunicationPlan<MemorySpace>
60{
61 public:
102 template <class IdViewType, class RankViewType>
103 Halo( MPI_Comm comm, const std::size_t num_local,
104 const IdViewType& element_export_ids,
105 const RankViewType& element_export_ranks,
106 const std::vector<int>& neighbor_ranks )
107 : CommunicationPlan<MemorySpace>( comm )
108 , _num_local( num_local )
109 {
110 if ( element_export_ids.size() != element_export_ranks.size() )
111 throw std::runtime_error( "Export ids and ranks different sizes!" );
112
113 auto neighbor_ids = this->createFromExportsAndTopology(
114 element_export_ranks, neighbor_ranks );
115 this->createExportSteering( neighbor_ids, element_export_ranks,
116 element_export_ids );
117 }
118
152 template <class IdViewType, class RankViewType>
153 Halo( MPI_Comm comm, const std::size_t num_local,
154 const IdViewType& element_export_ids,
155 const RankViewType& element_export_ranks )
156 : CommunicationPlan<MemorySpace>( comm )
157 , _num_local( num_local )
158 {
159 if ( element_export_ids.size() != element_export_ranks.size() )
160 throw std::runtime_error( "Export ids and ranks different sizes!" );
161
162 auto neighbor_ids = this->createFromExportsOnly( element_export_ranks );
163 this->createExportSteering( neighbor_ids, element_export_ranks,
164 element_export_ids );
165 }
166
172 std::size_t numLocal() const { return _num_local; }
173
181 std::size_t numGhost() const { return this->totalNumImport(); }
182
183 private:
184 std::size_t _num_local;
185};
186
187//---------------------------------------------------------------------------//
189template <typename>
190struct is_halo_impl : public std::false_type
191{
192};
193
194template <typename MemorySpace>
195struct is_halo_impl<Halo<MemorySpace>> : public std::true_type
196{
197};
199
201template <class T>
202struct is_halo : public is_halo_impl<typename std::remove_cv<T>::type>::type
203{
204};
205
215template <class Halo, class ParticleData>
217 const Halo& halo, const ParticleData& particles,
218 typename std::enable_if<( is_halo<Halo>::value ), int>::type* = 0 )
219{
220 // Check that the data is the right size.
221 return ( particles.size() == halo.numLocal() + halo.numGhost() );
222}
223
224template <class HaloType, class AoSoAType, class SFINAE = void>
225class Gather;
226
227//---------------------------------------------------------------------------//
239template <class HaloType, class AoSoAType>
240class Gather<HaloType, AoSoAType,
241 typename std::enable_if<is_aosoa<AoSoAType>::value>::type>
242 : public CommunicationData<HaloType, CommunicationDataAoSoA<AoSoAType>>
243{
244 public:
245 static_assert( is_halo<HaloType>::value, "" );
246
248 using base_type =
260
273 Gather( HaloType halo, AoSoAType aosoa, const double overallocation = 1.0 )
274 : base_type( halo, aosoa, overallocation )
275 {
276 reserve( _halo, aosoa );
277 }
278
280 auto totalSend() { return _halo.totalNumExport(); }
282 auto totalReceive() { return _halo.totalNumImport(); }
283
287 template <class ExecutionSpace>
288 void apply( ExecutionSpace )
289 {
290 Kokkos::Profiling::ScopedRegion region( "Cabana::gather" );
291
292 // Get the buffers and particle data (local copies for lambdas below).
293 auto send_buffer = this->getSendBuffer();
294 auto recv_buffer = this->getReceiveBuffer();
295 auto aosoa = this->getData();
296
297 // Get the steering vector for the sends.
298 auto steering = _halo.getExportSteering();
299 // Gather from the local data into a tuple-contiguous send buffer.
300 auto gather_send_buffer_func = KOKKOS_LAMBDA( const std::size_t i )
301 {
302 send_buffer( i ) = aosoa.getTuple( steering( i ) );
303 };
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 );
307 Kokkos::fence();
308
309 // The halo has it's own communication space so choose any mpi tag.
310 const int mpi_tag = 2345;
311
312 // Post non-blocking receives.
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 )
317 {
318 recv_range.second = recv_range.first + _halo.numImport( n );
319
320 auto recv_subview = Kokkos::subview( recv_buffer, recv_range );
321
322 MPI_Irecv( recv_subview.data(),
323 recv_subview.size() * sizeof( data_type ), MPI_BYTE,
324 _halo.neighborRank( n ), mpi_tag, _halo.comm(),
325 &( requests[n] ) );
326
327 recv_range.first = recv_range.second;
328 }
329
330 // Do blocking sends.
331 std::pair<std::size_t, std::size_t> send_range = { 0, 0 };
332 for ( int n = 0; n < num_n; ++n )
333 {
334 send_range.second = send_range.first + _halo.numExport( n );
335
336 auto send_subview = Kokkos::subview( send_buffer, send_range );
337
338 MPI_Send( send_subview.data(),
339 send_subview.size() * sizeof( data_type ), MPI_BYTE,
340 _halo.neighborRank( n ), mpi_tag, _halo.comm() );
341
342 send_range.first = send_range.second;
343 }
344
345 // Wait on non-blocking receives.
346 std::vector<MPI_Status> status( num_n );
347 const int ec =
348 MPI_Waitall( requests.size(), requests.data(), status.data() );
349 if ( MPI_SUCCESS != ec )
350 throw std::logic_error( "Failed MPI Communication" );
351
352 // Extract the receive buffer into the ghosted elements.
353 std::size_t num_local = _halo.numLocal();
354 auto extract_recv_buffer_func = KOKKOS_LAMBDA( const std::size_t i )
355 {
356 std::size_t ghost_idx = i + num_local;
357 aosoa.setTuple( ghost_idx, recv_buffer( i ) );
358 };
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 );
362 Kokkos::fence();
363
364 // Barrier before completing to ensure synchronization.
365 MPI_Barrier( _halo.comm() );
366 }
367
368 void apply() override { apply( execution_space{} ); }
369
376 void reserve( const HaloType& halo, AoSoAType& aosoa )
377 {
378 if ( !haloCheckValidSize( halo, aosoa ) )
379 throw std::runtime_error( "AoSoA is the wrong size for gather!" );
380
381 this->reserveImpl( halo, aosoa, totalSend(), totalReceive() );
382 }
383
391 void reserve( const HaloType& halo, AoSoAType& aosoa,
392 const double overallocation )
393 {
394 if ( !haloCheckValidSize( halo, aosoa ) )
395 throw std::runtime_error( "AoSoA is the wrong size for gather!" );
396
397 this->reserveImpl( halo, aosoa, totalSend(), totalReceive(),
398 overallocation );
399 }
400
401 private:
402 plan_type _halo = base_type::_comm_plan;
403 using base_type::_recv_size;
404 using base_type::_send_size;
405};
406
418template <class HaloType, class SliceType>
419class Gather<HaloType, SliceType,
420 typename std::enable_if<is_slice<SliceType>::value>::type>
421 : public CommunicationData<HaloType, CommunicationDataSlice<SliceType>>
422{
423 public:
424 static_assert( is_halo<HaloType>::value, "" );
425
427 using base_type =
439
452 Gather( HaloType halo, SliceType slice, const double overallocation = 1.0 )
453 : base_type( halo, slice, overallocation )
454 {
455 reserve( _halo, slice );
456 }
457
459 auto totalSend() { return _halo.totalNumExport(); }
461 auto totalReceive() { return _halo.totalNumImport(); }
462
466 template <class ExecutionSpace>
467 void apply( ExecutionSpace )
468 {
469 Kokkos::Profiling::ScopedRegion region( "Cabana::gather" );
470
471 // Get the buffers (local copies for lambdas below).
472 auto send_buffer = this->getSendBuffer();
473 auto recv_buffer = this->getReceiveBuffer();
474 auto slice = this->getData();
475
476 // Get the number of components in the slice.
477 std::size_t num_comp = this->getSliceComponents();
478
479 // Get the raw slice data.
480 auto slice_data = slice.data();
481
482 // Get the steering vector for the sends.
483 auto steering = _halo.getExportSteering();
484
485 // Gather from the local data into a tuple-contiguous send buffer.
486 auto gather_send_buffer_func = KOKKOS_LAMBDA( const std::size_t i )
487 {
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];
494 };
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 );
498 Kokkos::fence();
499
500 // The halo has it's own communication space so choose any mpi tag.
501 const int mpi_tag = 2345;
502
503 // Post non-blocking receives.
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 )
508 {
509 recv_range.second = recv_range.first + _halo.numImport( n );
510
511 auto recv_subview =
512 Kokkos::subview( recv_buffer, recv_range, Kokkos::ALL );
513
514 MPI_Irecv( recv_subview.data(),
515 recv_subview.size() * sizeof( data_type ), MPI_BYTE,
516 _halo.neighborRank( n ), mpi_tag, _halo.comm(),
517 &( requests[n] ) );
518
519 recv_range.first = recv_range.second;
520 }
521
522 // Do blocking sends.
523 std::pair<std::size_t, std::size_t> send_range = { 0, 0 };
524 for ( int n = 0; n < num_n; ++n )
525 {
526 send_range.second = send_range.first + _halo.numExport( n );
527
528 auto send_subview =
529 Kokkos::subview( send_buffer, send_range, Kokkos::ALL );
530
531 MPI_Send( send_subview.data(),
532 send_subview.size() * sizeof( data_type ), MPI_BYTE,
533 _halo.neighborRank( n ), mpi_tag, _halo.comm() );
534
535 send_range.first = send_range.second;
536 }
537
538 // Wait on non-blocking receives.
539 std::vector<MPI_Status> status( num_n );
540 const int ec =
541 MPI_Waitall( requests.size(), requests.data(), status.data() );
542 if ( MPI_SUCCESS != ec )
543 throw std::logic_error( "Failed MPI Communication" );
544
545 // Extract the receive buffer into the ghosted elements.
546 std::size_t num_local = _halo.numLocal();
547 auto extract_recv_buffer_func = KOKKOS_LAMBDA( const std::size_t i )
548 {
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] =
555 recv_buffer( i, n );
556 };
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 );
560 Kokkos::fence();
561
562 // Barrier before completing to ensure synchronization.
563 MPI_Barrier( _halo.comm() );
564 }
565
566 void apply() override { apply( execution_space{} ); }
567
576 void reserve( const HaloType& halo, const SliceType& slice,
577 const double overallocation )
578 {
579 if ( !haloCheckValidSize( halo, slice ) )
580 throw std::runtime_error( "AoSoA is the wrong size for gather!" );
581
582 this->reserveImpl( halo, slice, totalSend(), totalReceive(),
583 overallocation );
584 }
585
591 void reserve( const HaloType& halo, const SliceType& slice )
592 {
593 if ( !haloCheckValidSize( halo, slice ) )
594 throw std::runtime_error( "AoSoA is the wrong size for gather!" );
595
596 this->reserveImpl( halo, slice, totalSend(), totalReceive() );
597 }
598
599 private:
600 plan_type _halo = base_type::_comm_plan;
601 using base_type::_recv_size;
602 using base_type::_send_size;
603};
604
605//---------------------------------------------------------------------------//
619template <class HaloType, class ParticleDataType>
620auto createGather( const HaloType& halo, const ParticleDataType& data,
621 const double overallocation = 1.0 )
622{
623 return Gather<HaloType, ParticleDataType>( halo, data, overallocation );
624}
625
626//---------------------------------------------------------------------------//
644template <class HaloType, class ParticleDataType>
645void gather( const HaloType& halo, ParticleDataType& data )
646{
647 auto gather = createGather( halo, data );
648 gather.apply();
649}
650
651/**********
652 * SCATTER *
653 **********/
654
655//---------------------------------------------------------------------------//
667template <class HaloType, class SliceType>
669 : public CommunicationData<HaloType, CommunicationDataSlice<SliceType>>
670{
671 static_assert( is_halo<HaloType>::value, "" );
672
673 public:
675 using base_type =
687
700 Scatter( HaloType halo, SliceType slice, const double overallocation = 1.0 )
701 : base_type( halo, slice, overallocation )
702 {
703 reserve( _halo, slice );
704 }
705
707 auto totalSend() { return _halo.totalNumImport(); }
709 auto totalReceive() { return _halo.totalNumExport(); }
710
714 template <class ExecutionSpace>
715 void apply( ExecutionSpace )
716 {
717 Kokkos::Profiling::ScopedRegion region( "Cabana::scatter" );
718
719 // Get the buffers (local copies for lambdas below).
720 auto send_buffer = this->getSendBuffer();
721 auto recv_buffer = this->getReceiveBuffer();
722 auto slice = this->getData();
723
724 // Get the number of components in the slice.
725 std::size_t num_comp = this->getSliceComponents();
726
727 // Get the raw slice data. Wrap in a 1D Kokkos View so we can unroll the
728 // components of each slice element.
729 Kokkos::View<data_type*, memory_space,
730 Kokkos::MemoryTraits<Kokkos::Unmanaged>>
731 slice_data( slice.data(), slice.numSoA() * slice.stride( 0 ) );
732
733 // Extract the send buffer from the ghosted elements.
734 std::size_t num_local = _halo.numLocal();
735 auto extract_send_buffer_func = KOKKOS_LAMBDA( const std::size_t i )
736 {
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 );
744 };
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 );
748 Kokkos::fence();
749
750 // The halo has it's own communication space so choose any mpi tag.
751 const int mpi_tag = 2345;
752
753 // Post non-blocking receives.
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 )
758 {
759 recv_range.second = recv_range.first + _halo.numExport( n );
760
761 auto recv_subview =
762 Kokkos::subview( recv_buffer, recv_range, Kokkos::ALL );
763
764 MPI_Irecv( recv_subview.data(),
765 recv_subview.size() * sizeof( data_type ), MPI_BYTE,
766 _halo.neighborRank( n ), mpi_tag, _halo.comm(),
767 &( requests[n] ) );
768
769 recv_range.first = recv_range.second;
770 }
771
772 // Do blocking sends.
773 std::pair<std::size_t, std::size_t> send_range = { 0, 0 };
774 for ( int n = 0; n < num_n; ++n )
775 {
776 send_range.second = send_range.first + _halo.numImport( n );
777
778 auto send_subview =
779 Kokkos::subview( send_buffer, send_range, Kokkos::ALL );
780
781 MPI_Send( send_subview.data(),
782 send_subview.size() * sizeof( data_type ), MPI_BYTE,
783 _halo.neighborRank( n ), mpi_tag, _halo.comm() );
784
785 send_range.first = send_range.second;
786 }
787
788 // Wait on non-blocking receives.
789 std::vector<MPI_Status> status( num_n );
790 const int ec =
791 MPI_Waitall( requests.size(), requests.data(), status.data() );
792 if ( MPI_SUCCESS != ec )
793 throw std::logic_error( "Failed MPI Communication" );
794
795 // Get the steering vector for the sends.
796 auto steering = _halo.getExportSteering();
797
798 // Scatter the ghosts in the receive buffer into the local values.
799 auto scatter_recv_buffer_func = KOKKOS_LAMBDA( const std::size_t i )
800 {
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 )
805 Kokkos::atomic_add(
806 &slice_data( slice_offset + SliceType::vector_length * n ),
807 recv_buffer( i, n ) );
808 };
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 );
812 Kokkos::fence();
813
814 // Barrier before completing to ensure synchronization.
815 MPI_Barrier( _halo.comm() );
816 }
817
818 void apply() override { apply( execution_space{} ); }
819
829 void reserve( const HaloType& halo, const SliceType& slice,
830 const double overallocation )
831 {
832 if ( !haloCheckValidSize( halo, slice ) )
833 throw std::runtime_error( "AoSoA is the wrong size for scatter!" );
834
835 this->reserveImpl( halo, slice, totalSend(), totalReceive(),
836 overallocation );
837 }
838
844 void reserve( const HaloType& halo, const SliceType& slice )
845 {
846 if ( !haloCheckValidSize( halo, slice ) )
847 throw std::runtime_error( "AoSoA is the wrong size for scatter!" );
848
849 this->reserveImpl( halo, slice, totalSend(), totalReceive() );
850 }
851
852 private:
856};
857
871template <class HaloType, class SliceType>
872auto createScatter( const HaloType& halo, const SliceType& slice,
873 const double overallocation = 1.0,
874 typename std::enable_if<( is_halo<HaloType>::value &&
876 int>::type* = 0 )
877{
878 return Scatter<HaloType, SliceType>( halo, slice, overallocation );
879}
880
881//---------------------------------------------------------------------------//
899template <class HaloType, class SliceType>
900void scatter( const HaloType& halo, SliceType& slice,
901 typename std::enable_if<( is_halo<HaloType>::value &&
903 int>::type* = 0 )
904{
905 auto scatter = createScatter( halo, slice );
906 scatter.apply();
907}
908
909//---------------------------------------------------------------------------//
910
911} // end namespace Cabana
912
913#endif // end CABANA_HALO_HPP
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