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(
112 "Cabana::Halo: Export ids and ranks different sizes!" );
113
114 auto neighbor_ids = this->createFromExportsAndTopology(
115 element_export_ranks, neighbor_ranks );
116 this->createExportSteering( neighbor_ids, element_export_ranks,
117 element_export_ids );
118 }
119
153 template <class IdViewType, class RankViewType>
154 Halo( MPI_Comm comm, const std::size_t num_local,
155 const IdViewType& element_export_ids,
156 const RankViewType& element_export_ranks )
157 : CommunicationPlan<MemorySpace>( comm )
158 , _num_local( num_local )
159 {
160 if ( element_export_ids.size() != element_export_ranks.size() )
161 throw std::runtime_error(
162 "Cabana::Halo: Export ids and ranks different sizes!" );
163
164 auto neighbor_ids = this->createFromExportsOnly( element_export_ranks );
165 this->createExportSteering( neighbor_ids, element_export_ranks,
166 element_export_ids );
167 }
168
174 std::size_t numLocal() const { return _num_local; }
175
183 std::size_t numGhost() const { return this->totalNumImport(); }
184
185 private:
186 std::size_t _num_local;
187};
188
189//---------------------------------------------------------------------------//
191template <typename>
192struct is_halo_impl : public std::false_type
193{
194};
195
196template <typename MemorySpace>
197struct is_halo_impl<Halo<MemorySpace>> : public std::true_type
198{
199};
201
203template <class T>
204struct is_halo : public is_halo_impl<typename std::remove_cv<T>::type>::type
205{
206};
207
217template <class Halo, class ParticleData>
219 const Halo& halo, const ParticleData& particles,
220 typename std::enable_if<( is_halo<Halo>::value ), int>::type* = 0 )
221{
222 // Check that the data is the right size.
223 return ( particles.size() == halo.numLocal() + halo.numGhost() );
224}
225
226template <class HaloType, class AoSoAType, class SFINAE = void>
227class Gather;
228
229//---------------------------------------------------------------------------//
241template <class HaloType, class AoSoAType>
242class Gather<HaloType, AoSoAType,
243 typename std::enable_if<is_aosoa<AoSoAType>::value>::type>
244 : public CommunicationData<HaloType, CommunicationDataAoSoA<AoSoAType>>
245{
246 public:
247 static_assert( is_halo<HaloType>::value, "" );
248
250 using base_type =
262
275 Gather( HaloType halo, AoSoAType aosoa, const double overallocation = 1.0 )
276 : base_type( halo, aosoa, overallocation )
277 {
278 reserve( _halo, aosoa );
279 }
280
282 auto totalSend() { return _halo.totalNumExport(); }
284 auto totalReceive() { return _halo.totalNumImport(); }
285
289 template <class ExecutionSpace>
290 void apply( ExecutionSpace )
291 {
292 Kokkos::Profiling::ScopedRegion region( "Cabana::Gather::apply" );
293
294 // Get the buffers and particle data (local copies for lambdas below).
295 auto send_buffer = this->getSendBuffer();
296 auto recv_buffer = this->getReceiveBuffer();
297 auto aosoa = this->getData();
298
299 // Get the steering vector for the sends.
300 auto steering = _halo.getExportSteering();
301 // Gather from the local data into a tuple-contiguous send buffer.
302 auto gather_send_buffer_func = KOKKOS_LAMBDA( const std::size_t i )
303 {
304 send_buffer( i ) = aosoa.getTuple( steering( i ) );
305 };
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 );
309 Kokkos::fence();
310
311 // The halo has it's own communication space so choose any mpi tag.
312 const int mpi_tag = 2345;
313
314 // Post non-blocking receives.
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 )
319 {
320 recv_range.second = recv_range.first + _halo.numImport( n );
321
322 auto recv_subview = Kokkos::subview( recv_buffer, recv_range );
323
324 MPI_Irecv( recv_subview.data(),
325 recv_subview.size() * sizeof( data_type ), MPI_BYTE,
326 _halo.neighborRank( n ), mpi_tag, _halo.comm(),
327 &( requests[n] ) );
328
329 recv_range.first = recv_range.second;
330 }
331
332 // Do blocking sends.
333 std::pair<std::size_t, std::size_t> send_range = { 0, 0 };
334 for ( int n = 0; n < num_n; ++n )
335 {
336 send_range.second = send_range.first + _halo.numExport( n );
337
338 auto send_subview = Kokkos::subview( send_buffer, send_range );
339
340 MPI_Send( send_subview.data(),
341 send_subview.size() * sizeof( data_type ), MPI_BYTE,
342 _halo.neighborRank( n ), mpi_tag, _halo.comm() );
343
344 send_range.first = send_range.second;
345 }
346
347 // Wait on non-blocking receives.
348 std::vector<MPI_Status> status( num_n );
349 const int ec =
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" );
354
355 // Extract the receive buffer into the ghosted elements.
356 std::size_t num_local = _halo.numLocal();
357 auto extract_recv_buffer_func = KOKKOS_LAMBDA( const std::size_t i )
358 {
359 std::size_t ghost_idx = i + num_local;
360 aosoa.setTuple( ghost_idx, recv_buffer( i ) );
361 };
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 );
365 Kokkos::fence();
366
367 // Barrier before completing to ensure synchronization.
368 MPI_Barrier( _halo.comm() );
369 }
370
371 void apply() override { apply( execution_space{} ); }
372
379 void reserve( const HaloType& halo, AoSoAType& aosoa )
380 {
381 if ( !haloCheckValidSize( halo, aosoa ) )
382 throw std::runtime_error(
383 "Cabana::Gather:reserve: "
384 "AoSoA is the wrong size for gather! (Label: " +
385 aosoa.label() + ")" );
386
387 this->reserveImpl( halo, aosoa, totalSend(), totalReceive() );
388 }
389
397 void reserve( const HaloType& halo, AoSoAType& aosoa,
398 const double overallocation )
399 {
400 if ( !haloCheckValidSize( halo, aosoa ) )
401 throw std::runtime_error(
402 "Cabana::Gather:reserve: "
403 "AoSoA is the wrong size for gather! (Label: " +
404 aosoa.label() + ")" );
405
406 this->reserveImpl( halo, aosoa, totalSend(), totalReceive(),
407 overallocation );
408 }
409
410 private:
411 plan_type _halo = base_type::_comm_plan;
412 using base_type::_recv_size;
413 using base_type::_send_size;
414};
415
427template <class HaloType, class SliceType>
428class Gather<HaloType, SliceType,
429 typename std::enable_if<is_slice<SliceType>::value>::type>
430 : public CommunicationData<HaloType, CommunicationDataSlice<SliceType>>
431{
432 public:
433 static_assert( is_halo<HaloType>::value, "" );
434
436 using base_type =
448
461 Gather( HaloType halo, SliceType slice, const double overallocation = 1.0 )
462 : base_type( halo, slice, overallocation )
463 {
464 reserve( _halo, slice );
465 }
466
468 auto totalSend() { return _halo.totalNumExport(); }
470 auto totalReceive() { return _halo.totalNumImport(); }
471
475 template <class ExecutionSpace>
476 void apply( ExecutionSpace )
477 {
478 Kokkos::Profiling::ScopedRegion region( "Cabana::Gather::apply" );
479
480 // Get the buffers (local copies for lambdas below).
481 auto send_buffer = this->getSendBuffer();
482 auto recv_buffer = this->getReceiveBuffer();
483 auto slice = this->getData();
484
485 // Get the number of components in the slice.
486 std::size_t num_comp = this->getSliceComponents();
487
488 // Get the raw slice data.
489 auto slice_data = slice.data();
490
491 // Get the steering vector for the sends.
492 auto steering = _halo.getExportSteering();
493
494 // Gather from the local data into a tuple-contiguous send buffer.
495 auto gather_send_buffer_func = KOKKOS_LAMBDA( const std::size_t i )
496 {
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];
503 };
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 );
507 Kokkos::fence();
508
509 // The halo has it's own communication space so choose any mpi tag.
510 const int mpi_tag = 2345;
511
512 // Post non-blocking receives.
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 )
517 {
518 recv_range.second = recv_range.first + _halo.numImport( n );
519
520 auto recv_subview =
521 Kokkos::subview( recv_buffer, recv_range, Kokkos::ALL );
522
523 MPI_Irecv( recv_subview.data(),
524 recv_subview.size() * sizeof( data_type ), MPI_BYTE,
525 _halo.neighborRank( n ), mpi_tag, _halo.comm(),
526 &( requests[n] ) );
527
528 recv_range.first = recv_range.second;
529 }
530
531 // Do blocking sends.
532 std::pair<std::size_t, std::size_t> send_range = { 0, 0 };
533 for ( int n = 0; n < num_n; ++n )
534 {
535 send_range.second = send_range.first + _halo.numExport( n );
536
537 auto send_subview =
538 Kokkos::subview( send_buffer, send_range, Kokkos::ALL );
539
540 MPI_Send( send_subview.data(),
541 send_subview.size() * sizeof( data_type ), MPI_BYTE,
542 _halo.neighborRank( n ), mpi_tag, _halo.comm() );
543
544 send_range.first = send_range.second;
545 }
546
547 // Wait on non-blocking receives.
548 std::vector<MPI_Status> status( num_n );
549 const int ec =
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" );
554
555 // Extract the receive buffer into the ghosted elements.
556 std::size_t num_local = _halo.numLocal();
557 auto extract_recv_buffer_func = KOKKOS_LAMBDA( const std::size_t i )
558 {
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] =
565 recv_buffer( i, n );
566 };
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 );
570 Kokkos::fence();
571
572 // Barrier before completing to ensure synchronization.
573 MPI_Barrier( _halo.comm() );
574 }
575
576 void apply() override { apply( execution_space{} ); }
577
586 void reserve( const HaloType& halo, const SliceType& slice,
587 const double overallocation )
588 {
589 if ( !haloCheckValidSize( halo, slice ) )
590 throw std::runtime_error(
591 "Cabana::Gather:reserve: "
592 "Slice is the wrong size for gather! (Label: " +
593 slice.label() + ")" );
594
595 this->reserveImpl( halo, slice, totalSend(), totalReceive(),
596 overallocation );
597 }
598
604 void reserve( const HaloType& halo, const SliceType& slice )
605 {
606 if ( !haloCheckValidSize( halo, slice ) )
607 throw std::runtime_error(
608 "Cabana::Gather:reserve: "
609 "Slice is the wrong size for gather! (Label: " +
610 slice.label() + ")" );
611
612 this->reserveImpl( halo, slice, totalSend(), totalReceive() );
613 }
614
615 private:
616 plan_type _halo = base_type::_comm_plan;
617 using base_type::_recv_size;
618 using base_type::_send_size;
619};
620
621//---------------------------------------------------------------------------//
635template <class HaloType, class ParticleDataType>
636auto createGather( const HaloType& halo, const ParticleDataType& data,
637 const double overallocation = 1.0 )
638{
639 return Gather<HaloType, ParticleDataType>( halo, data, overallocation );
640}
641
642//---------------------------------------------------------------------------//
660template <class HaloType, class ParticleDataType>
661void gather( const HaloType& halo, ParticleDataType& data )
662{
663 auto gather = createGather( halo, data );
664 gather.apply();
665}
666
667/**********
668 * SCATTER *
669 **********/
670
671//---------------------------------------------------------------------------//
683template <class HaloType, class SliceType>
685 : public CommunicationData<HaloType, CommunicationDataSlice<SliceType>>
686{
687 static_assert( is_halo<HaloType>::value, "" );
688
689 public:
691 using base_type =
703
716 Scatter( HaloType halo, SliceType slice, const double overallocation = 1.0 )
717 : base_type( halo, slice, overallocation )
718 {
719 reserve( _halo, slice );
720 }
721
723 auto totalSend() { return _halo.totalNumImport(); }
725 auto totalReceive() { return _halo.totalNumExport(); }
726
730 template <class ExecutionSpace>
731 void apply( ExecutionSpace )
732 {
733 Kokkos::Profiling::ScopedRegion region( "Cabana::Scatter::apply" );
734
735 // Get the buffers (local copies for lambdas below).
736 auto send_buffer = this->getSendBuffer();
737 auto recv_buffer = this->getReceiveBuffer();
738 auto slice = this->getData();
739
740 // Get the number of components in the slice.
741 std::size_t num_comp = this->getSliceComponents();
742
743 // Get the raw slice data. Wrap in a 1D Kokkos View so we can unroll the
744 // components of each slice element.
745 Kokkos::View<data_type*, memory_space,
746 Kokkos::MemoryTraits<Kokkos::Unmanaged>>
747 slice_data( slice.data(), slice.numSoA() * slice.stride( 0 ) );
748
749 // Extract the send buffer from the ghosted elements.
750 std::size_t num_local = _halo.numLocal();
751 auto extract_send_buffer_func = KOKKOS_LAMBDA( const std::size_t i )
752 {
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 );
760 };
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 );
764 Kokkos::fence();
765
766 // The halo has it's own communication space so choose any mpi tag.
767 const int mpi_tag = 2345;
768
769 // Post non-blocking receives.
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 )
774 {
775 recv_range.second = recv_range.first + _halo.numExport( n );
776
777 auto recv_subview =
778 Kokkos::subview( recv_buffer, recv_range, Kokkos::ALL );
779
780 MPI_Irecv( recv_subview.data(),
781 recv_subview.size() * sizeof( data_type ), MPI_BYTE,
782 _halo.neighborRank( n ), mpi_tag, _halo.comm(),
783 &( requests[n] ) );
784
785 recv_range.first = recv_range.second;
786 }
787
788 // Do blocking sends.
789 std::pair<std::size_t, std::size_t> send_range = { 0, 0 };
790 for ( int n = 0; n < num_n; ++n )
791 {
792 send_range.second = send_range.first + _halo.numImport( n );
793
794 auto send_subview =
795 Kokkos::subview( send_buffer, send_range, Kokkos::ALL );
796
797 MPI_Send( send_subview.data(),
798 send_subview.size() * sizeof( data_type ), MPI_BYTE,
799 _halo.neighborRank( n ), mpi_tag, _halo.comm() );
800
801 send_range.first = send_range.second;
802 }
803
804 // Wait on non-blocking receives.
805 std::vector<MPI_Status> status( num_n );
806 const int ec =
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" );
811
812 // Get the steering vector for the sends.
813 auto steering = _halo.getExportSteering();
814
815 // Scatter the ghosts in the receive buffer into the local values.
816 auto scatter_recv_buffer_func = KOKKOS_LAMBDA( const std::size_t i )
817 {
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 )
822 Kokkos::atomic_add(
823 &slice_data( slice_offset + SliceType::vector_length * n ),
824 recv_buffer( i, n ) );
825 };
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 );
829 Kokkos::fence();
830
831 // Barrier before completing to ensure synchronization.
832 MPI_Barrier( _halo.comm() );
833 }
834
835 void apply() override { apply( execution_space{} ); }
836
846 void reserve( const HaloType& halo, const SliceType& slice,
847 const double overallocation )
848 {
849 if ( !haloCheckValidSize( halo, slice ) )
850 throw std::runtime_error(
851 "Cabana::Scatter::reserve: "
852 "Slice is the wrong size for scatter! (Label: " +
853 slice.label() + ")" );
854
855 this->reserveImpl( halo, slice, totalSend(), totalReceive(),
856 overallocation );
857 }
858
864 void reserve( const HaloType& halo, const SliceType& slice )
865 {
866 if ( !haloCheckValidSize( halo, slice ) )
867 throw std::runtime_error(
868 "Cabana::Scatter::reserve: "
869 "Slice is the wrong size for scatter! (Label: " +
870 slice.label() + ")" );
871
872 this->reserveImpl( halo, slice, totalSend(), totalReceive() );
873 }
874
875 private:
879};
880
894template <class HaloType, class SliceType>
895auto createScatter( const HaloType& halo, const SliceType& slice,
896 const double overallocation = 1.0,
897 typename std::enable_if<( is_halo<HaloType>::value &&
899 int>::type* = 0 )
900{
901 return Scatter<HaloType, SliceType>( halo, slice, overallocation );
902}
903
904//---------------------------------------------------------------------------//
922template <class HaloType, class SliceType>
923void scatter( const HaloType& halo, SliceType& slice,
924 typename std::enable_if<( is_halo<HaloType>::value &&
926 int>::type* = 0 )
927{
928 auto scatter = createScatter( halo, slice );
929 scatter.apply();
930}
931
932//---------------------------------------------------------------------------//
933
934} // end namespace Cabana
935
936#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: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