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, class BuildType = Export>
59class Halo : public CommunicationPlan<MemorySpace>
60{
61 public:
102 template <class IdViewType, class RankViewType, typename T = BuildType,
103 std::enable_if_t<std::is_same<T, Export>::value, int> = 0>
104 Halo( MPI_Comm comm, const std::size_t num_local,
105 const IdViewType& element_ids, const RankViewType& element_ranks,
106 const std::vector<int>& neighbor_ranks )
107 : CommunicationPlan<MemorySpace>( comm )
108 , _num_local( num_local )
109 {
110 if ( element_ids.size() != element_ranks.size() )
111 throw std::runtime_error( "Cabana::Halo (export): ids and ranks "
112 "views are different sizes!" );
113
114 auto neighbor_ids = this->createWithTopology(
115 BuildType(), element_ranks, neighbor_ranks );
116 this->createExportSteering( neighbor_ids, element_ranks, element_ids );
117 }
118
151 template <class IdViewType, class RankViewType, typename T = BuildType,
152 std::enable_if_t<std::is_same<T, Export>::value, int> = 0>
153 Halo( MPI_Comm comm, const std::size_t num_local,
154 const IdViewType& element_ids, const RankViewType& element_ranks )
155 : CommunicationPlan<MemorySpace>( comm )
156 , _num_local( num_local )
157 {
158 if ( element_ids.size() != element_ranks.size() )
159 throw std::runtime_error( "Cabana::Halo (export): ids and ranks "
160 "views are different sizes!" );
161
162 auto neighbor_ids =
163 this->createWithoutTopology( BuildType(), element_ranks );
164 this->createExportSteering( neighbor_ids, element_ranks, element_ids );
165 }
166
207 template <class IdViewType, class RankViewType, typename T = BuildType,
208 std::enable_if_t<std::is_same<T, Import>::value, int> = 0>
209 Halo( MPI_Comm comm, const std::size_t num_local,
210 const IdViewType& element_ids, const RankViewType& element_ranks,
211 const std::vector<int>& neighbor_ranks )
212 : CommunicationPlan<MemorySpace>( comm )
213 , _num_local( num_local )
214 {
215 if ( element_ids.size() != element_ranks.size() )
216 throw std::runtime_error( "Cabana::Halo (import): ids and ranks "
217 "views are different sizes!" );
218
219 auto neighbor_ids_ranks_indices = this->createWithTopology(
220 BuildType(), element_ranks, element_ids, neighbor_ranks );
221 this->createExportSteering( std::get<0>( neighbor_ids_ranks_indices ),
222 std::get<1>( neighbor_ids_ranks_indices ),
223 std::get<2>( neighbor_ids_ranks_indices ) );
224 }
225
257 template <class IdViewType, class RankViewType, typename T = BuildType,
258 std::enable_if_t<std::is_same<T, Import>::value, int> = 0>
259 Halo( MPI_Comm comm, const std::size_t num_local,
260 const IdViewType& element_ids, const RankViewType& element_ranks )
261 : CommunicationPlan<MemorySpace>( comm )
262 , _num_local( num_local )
263 {
264 if ( element_ids.size() != element_ranks.size() )
265 throw std::runtime_error( "Cabana::Halo (import): ids and ranks "
266 "views are different sizes!" );
267
268 auto neighbor_ids_ranks_indices = this->createWithoutTopology(
269 BuildType(), element_ranks, element_ids );
270 this->createExportSteering( std::get<0>( neighbor_ids_ranks_indices ),
271 std::get<1>( neighbor_ids_ranks_indices ),
272 std::get<2>( neighbor_ids_ranks_indices ) );
273 }
274
280 std::size_t numLocal() const { return _num_local; }
281
289 std::size_t numGhost() const { return this->totalNumImport(); }
290
291 private:
292 std::size_t _num_local;
293};
294
295//---------------------------------------------------------------------------//
297template <typename>
298struct is_halo_impl : public std::false_type
299{
300};
301
302template <typename MemorySpace, typename BuildType>
303struct is_halo_impl<Halo<MemorySpace, BuildType>> : public std::true_type
304{
305};
307
309template <class T>
310struct is_halo : public is_halo_impl<typename std::remove_cv<T>::type>::type
311{
312};
313
323template <class Halo, class ParticleData>
325 const Halo& halo, const ParticleData& particles,
326 typename std::enable_if<( is_halo<Halo>::value ), int>::type* = 0 )
327{
328 // Check that the data is the right size.
329 return ( particles.size() == halo.numLocal() + halo.numGhost() );
330}
331
332template <class HaloType, class AoSoAType, class SFINAE = void>
333class Gather;
334
335//---------------------------------------------------------------------------//
347template <class HaloType, class AoSoAType>
348class Gather<HaloType, AoSoAType,
349 typename std::enable_if<is_aosoa<AoSoAType>::value>::type>
350 : public CommunicationData<HaloType, CommunicationDataAoSoA<AoSoAType>>
351{
352 public:
353 static_assert( is_halo<HaloType>::value, "" );
354
356 using base_type =
368
381 Gather( HaloType halo, AoSoAType aosoa, const double overallocation = 1.0 )
382 : base_type( halo, aosoa, overallocation )
383 {
384 reserve( _halo, aosoa );
385 }
386
388 auto totalSend() { return _halo.totalNumExport(); }
390 auto totalReceive() { return _halo.totalNumImport(); }
391
395 template <class ExecutionSpace>
396 void apply( ExecutionSpace )
397 {
398 Kokkos::Profiling::ScopedRegion region( "Cabana::Gather::apply" );
399
400 // Get the buffers and particle data (local copies for lambdas below).
401 auto send_buffer = this->getSendBuffer();
402 auto recv_buffer = this->getReceiveBuffer();
403 auto aosoa = this->getData();
404
405 // Get the steering vector for the sends.
406 auto steering = _halo.getExportSteering();
407 // Gather from the local data into a tuple-contiguous send buffer.
408 auto gather_send_buffer_func = KOKKOS_LAMBDA( const std::size_t i )
409 {
410 send_buffer( i ) = aosoa.getTuple( steering( i ) );
411 };
412 Kokkos::RangePolicy<ExecutionSpace> send_policy( 0, _send_size );
413 Kokkos::parallel_for( "Cabana::Gather::gather_send_buffer", send_policy,
414 gather_send_buffer_func );
415 Kokkos::fence();
416
417 // The halo has it's own communication space so choose any mpi tag.
418 const int mpi_tag = 2345;
419
420 // Post non-blocking receives.
421 int num_n = _halo.numNeighbor();
422 std::vector<MPI_Request> requests( num_n );
423 std::pair<std::size_t, std::size_t> recv_range = { 0, 0 };
424 for ( int n = 0; n < num_n; ++n )
425 {
426 recv_range.second = recv_range.first + _halo.numImport( n );
427
428 auto recv_subview = Kokkos::subview( recv_buffer, recv_range );
429
430 MPI_Irecv( recv_subview.data(),
431 recv_subview.size() * sizeof( data_type ), MPI_BYTE,
432 _halo.neighborRank( n ), mpi_tag, _halo.comm(),
433 &( requests[n] ) );
434
435 recv_range.first = recv_range.second;
436 }
437
438 // Do blocking sends.
439 std::pair<std::size_t, std::size_t> send_range = { 0, 0 };
440 for ( int n = 0; n < num_n; ++n )
441 {
442 send_range.second = send_range.first + _halo.numExport( n );
443
444 auto send_subview = Kokkos::subview( send_buffer, send_range );
445
446 MPI_Send( send_subview.data(),
447 send_subview.size() * sizeof( data_type ), MPI_BYTE,
448 _halo.neighborRank( n ), mpi_tag, _halo.comm() );
449
450 send_range.first = send_range.second;
451 }
452
453 // Wait on non-blocking receives.
454 std::vector<MPI_Status> status( num_n );
455 const int ec =
456 MPI_Waitall( requests.size(), requests.data(), status.data() );
457 if ( MPI_SUCCESS != ec )
458 throw std::logic_error(
459 "Cabana::Gather::apply (AoSoA): Failed MPI Communication" );
460
461 // Extract the receive buffer into the ghosted elements.
462 std::size_t num_local = _halo.numLocal();
463 auto extract_recv_buffer_func = KOKKOS_LAMBDA( const std::size_t i )
464 {
465 std::size_t ghost_idx = i + num_local;
466 aosoa.setTuple( ghost_idx, recv_buffer( i ) );
467 };
468 Kokkos::RangePolicy<ExecutionSpace> recv_policy( 0, _recv_size );
469 Kokkos::parallel_for( "Cabana::Gather::apply::extract_recv_buffer",
470 recv_policy, extract_recv_buffer_func );
471 Kokkos::fence();
472
473 // Barrier before completing to ensure synchronization.
474 MPI_Barrier( _halo.comm() );
475 }
476
477 void apply() override { apply( execution_space{} ); }
478
485 void reserve( const HaloType& halo, AoSoAType& aosoa )
486 {
487 if ( !haloCheckValidSize( halo, aosoa ) )
488 throw std::runtime_error(
489 "Cabana::Gather:reserve: "
490 "AoSoA is the wrong size for gather! (Label: " +
491 aosoa.label() + ")" );
492
493 this->reserveImpl( halo, aosoa, totalSend(), totalReceive() );
494 }
495
503 void reserve( const HaloType& halo, AoSoAType& aosoa,
504 const double overallocation )
505 {
506 if ( !haloCheckValidSize( halo, aosoa ) )
507 throw std::runtime_error(
508 "Cabana::Gather:reserve: "
509 "AoSoA is the wrong size for gather! (Label: " +
510 aosoa.label() + ")" );
511
512 this->reserveImpl( halo, aosoa, totalSend(), totalReceive(),
513 overallocation );
514 }
515
516 private:
517 plan_type _halo = base_type::_comm_plan;
518 using base_type::_recv_size;
519 using base_type::_send_size;
520};
521
533template <class HaloType, class SliceType>
534class Gather<HaloType, SliceType,
535 typename std::enable_if<is_slice<SliceType>::value>::type>
536 : public CommunicationData<HaloType, CommunicationDataSlice<SliceType>>
537{
538 public:
539 static_assert( is_halo<HaloType>::value, "" );
540
542 using base_type =
554
567 Gather( HaloType halo, SliceType slice, const double overallocation = 1.0 )
568 : base_type( halo, slice, overallocation )
569 {
570 reserve( _halo, slice );
571 }
572
574 auto totalSend() { return _halo.totalNumExport(); }
576 auto totalReceive() { return _halo.totalNumImport(); }
577
581 template <class ExecutionSpace>
582 void apply( ExecutionSpace )
583 {
584 Kokkos::Profiling::ScopedRegion region( "Cabana::Gather::apply" );
585
586 // Get the buffers (local copies for lambdas below).
587 auto send_buffer = this->getSendBuffer();
588 auto recv_buffer = this->getReceiveBuffer();
589 auto slice = this->getData();
590
591 // Get the number of components in the slice.
592 std::size_t num_comp = this->getSliceComponents();
593
594 // Get the raw slice data.
595 auto slice_data = slice.data();
596
597 // Get the steering vector for the sends.
598 auto steering = _halo.getExportSteering();
599
600 // Gather from the local data into a tuple-contiguous send buffer.
601 auto gather_send_buffer_func = KOKKOS_LAMBDA( const std::size_t i )
602 {
603 auto s = SliceType::index_type::s( steering( i ) );
604 auto a = SliceType::index_type::a( steering( i ) );
605 std::size_t slice_offset = s * slice.stride( 0 ) + a;
606 for ( std::size_t n = 0; n < num_comp; ++n )
607 send_buffer( i, n ) =
608 slice_data[slice_offset + n * SliceType::vector_length];
609 };
610 Kokkos::RangePolicy<ExecutionSpace> send_policy( 0, _send_size );
611 Kokkos::parallel_for( "Cabana::Gather::gather_send_buffer", send_policy,
612 gather_send_buffer_func );
613 Kokkos::fence();
614
615 // The halo has it's own communication space so choose any mpi tag.
616 const int mpi_tag = 2345;
617
618 // Post non-blocking receives.
619 int num_n = _halo.numNeighbor();
620 std::vector<MPI_Request> requests( num_n );
621 std::pair<std::size_t, std::size_t> recv_range = { 0, 0 };
622 for ( int n = 0; n < num_n; ++n )
623 {
624 recv_range.second = recv_range.first + _halo.numImport( n );
625
626 auto recv_subview =
627 Kokkos::subview( recv_buffer, recv_range, Kokkos::ALL );
628
629 MPI_Irecv( recv_subview.data(),
630 recv_subview.size() * sizeof( data_type ), MPI_BYTE,
631 _halo.neighborRank( n ), mpi_tag, _halo.comm(),
632 &( requests[n] ) );
633
634 recv_range.first = recv_range.second;
635 }
636
637 // Do blocking sends.
638 std::pair<std::size_t, std::size_t> send_range = { 0, 0 };
639 for ( int n = 0; n < num_n; ++n )
640 {
641 send_range.second = send_range.first + _halo.numExport( n );
642
643 auto send_subview =
644 Kokkos::subview( send_buffer, send_range, Kokkos::ALL );
645
646 MPI_Send( send_subview.data(),
647 send_subview.size() * sizeof( data_type ), MPI_BYTE,
648 _halo.neighborRank( n ), mpi_tag, _halo.comm() );
649
650 send_range.first = send_range.second;
651 }
652
653 // Wait on non-blocking receives.
654 std::vector<MPI_Status> status( num_n );
655 const int ec =
656 MPI_Waitall( requests.size(), requests.data(), status.data() );
657 if ( MPI_SUCCESS != ec )
658 throw std::logic_error(
659 "Cabana::Gather::apply (Slice): Failed MPI Communication" );
660
661 // Extract the receive buffer into the ghosted elements.
662 std::size_t num_local = _halo.numLocal();
663 auto extract_recv_buffer_func = KOKKOS_LAMBDA( const std::size_t i )
664 {
665 std::size_t ghost_idx = i + num_local;
666 auto s = SliceType::index_type::s( ghost_idx );
667 auto a = SliceType::index_type::a( ghost_idx );
668 std::size_t slice_offset = s * slice.stride( 0 ) + a;
669 for ( std::size_t n = 0; n < num_comp; ++n )
670 slice_data[slice_offset + SliceType::vector_length * n] =
671 recv_buffer( i, n );
672 };
673 Kokkos::RangePolicy<ExecutionSpace> recv_policy( 0, _recv_size );
674 Kokkos::parallel_for( "Cabana::Gather::extract_recv_buffer",
675 recv_policy, extract_recv_buffer_func );
676 Kokkos::fence();
677
678 // Barrier before completing to ensure synchronization.
679 MPI_Barrier( _halo.comm() );
680 }
681
682 void apply() override { apply( execution_space{} ); }
683
692 void reserve( const HaloType& halo, const SliceType& slice,
693 const double overallocation )
694 {
695 if ( !haloCheckValidSize( halo, slice ) )
696 throw std::runtime_error(
697 "Cabana::Gather:reserve: "
698 "Slice is the wrong size for gather! (Label: " +
699 slice.label() + ")" );
700
701 this->reserveImpl( halo, slice, totalSend(), totalReceive(),
702 overallocation );
703 }
704
710 void reserve( const HaloType& halo, const SliceType& slice )
711 {
712 if ( !haloCheckValidSize( halo, slice ) )
713 throw std::runtime_error(
714 "Cabana::Gather:reserve: "
715 "Slice is the wrong size for gather! (Label: " +
716 slice.label() + ")" );
717
718 this->reserveImpl( halo, slice, totalSend(), totalReceive() );
719 }
720
721 private:
722 plan_type _halo = base_type::_comm_plan;
723 using base_type::_recv_size;
724 using base_type::_send_size;
725};
726
727//---------------------------------------------------------------------------//
741template <class HaloType, class ParticleDataType>
742auto createGather( const HaloType& halo, const ParticleDataType& data,
743 const double overallocation = 1.0 )
744{
745 return Gather<HaloType, ParticleDataType>( halo, data, overallocation );
746}
747
748//---------------------------------------------------------------------------//
766template <class HaloType, class ParticleDataType>
767void gather( const HaloType& halo, ParticleDataType& data )
768{
769 auto gather = createGather( halo, data );
770 gather.apply();
771}
772
773/**********
774 * SCATTER *
775 **********/
776
777//---------------------------------------------------------------------------//
789template <class HaloType, class SliceType>
791 : public CommunicationData<HaloType, CommunicationDataSlice<SliceType>>
792{
793 static_assert( is_halo<HaloType>::value, "" );
794
795 public:
797 using base_type =
809
822 Scatter( HaloType halo, SliceType slice, const double overallocation = 1.0 )
823 : base_type( halo, slice, overallocation )
824 {
825 reserve( _halo, slice );
826 }
827
829 auto totalSend() { return _halo.totalNumImport(); }
831 auto totalReceive() { return _halo.totalNumExport(); }
832
836 template <class ExecutionSpace>
837 void apply( ExecutionSpace )
838 {
839 Kokkos::Profiling::ScopedRegion region( "Cabana::Scatter::apply" );
840
841 // Get the buffers (local copies for lambdas below).
842 auto send_buffer = this->getSendBuffer();
843 auto recv_buffer = this->getReceiveBuffer();
844 auto slice = this->getData();
845
846 // Get the number of components in the slice.
847 std::size_t num_comp = this->getSliceComponents();
848
849 // Get the raw slice data. Wrap in a 1D Kokkos View so we can unroll the
850 // components of each slice element.
851 Kokkos::View<data_type*, memory_space,
852 Kokkos::MemoryTraits<Kokkos::Unmanaged>>
853 slice_data( slice.data(), slice.numSoA() * slice.stride( 0 ) );
854
855 // Extract the send buffer from the ghosted elements.
856 std::size_t num_local = _halo.numLocal();
857 auto extract_send_buffer_func = KOKKOS_LAMBDA( const std::size_t i )
858 {
859 std::size_t ghost_idx = i + num_local;
860 auto s = SliceType::index_type::s( ghost_idx );
861 auto a = SliceType::index_type::a( ghost_idx );
862 std::size_t slice_offset = s * slice.stride( 0 ) + a;
863 for ( std::size_t n = 0; n < num_comp; ++n )
864 send_buffer( i, n ) =
865 slice_data( slice_offset + SliceType::vector_length * n );
866 };
867 Kokkos::RangePolicy<ExecutionSpace> send_policy( 0, _send_size );
868 Kokkos::parallel_for( "Cabana::Scatter::apply::extract_send_buffer",
869 send_policy, extract_send_buffer_func );
870 Kokkos::fence();
871
872 // The halo has it's own communication space so choose any mpi tag.
873 const int mpi_tag = 2345;
874
875 // Post non-blocking receives.
876 int num_n = _halo.numNeighbor();
877 std::vector<MPI_Request> requests( num_n );
878 std::pair<std::size_t, std::size_t> recv_range = { 0, 0 };
879 for ( int n = 0; n < num_n; ++n )
880 {
881 recv_range.second = recv_range.first + _halo.numExport( n );
882
883 auto recv_subview =
884 Kokkos::subview( recv_buffer, recv_range, Kokkos::ALL );
885
886 MPI_Irecv( recv_subview.data(),
887 recv_subview.size() * sizeof( data_type ), MPI_BYTE,
888 _halo.neighborRank( n ), mpi_tag, _halo.comm(),
889 &( requests[n] ) );
890
891 recv_range.first = recv_range.second;
892 }
893
894 // Do blocking sends.
895 std::pair<std::size_t, std::size_t> send_range = { 0, 0 };
896 for ( int n = 0; n < num_n; ++n )
897 {
898 send_range.second = send_range.first + _halo.numImport( n );
899
900 auto send_subview =
901 Kokkos::subview( send_buffer, send_range, Kokkos::ALL );
902
903 MPI_Send( send_subview.data(),
904 send_subview.size() * sizeof( data_type ), MPI_BYTE,
905 _halo.neighborRank( n ), mpi_tag, _halo.comm() );
906
907 send_range.first = send_range.second;
908 }
909
910 // Wait on non-blocking receives.
911 std::vector<MPI_Status> status( num_n );
912 const int ec =
913 MPI_Waitall( requests.size(), requests.data(), status.data() );
914 if ( MPI_SUCCESS != ec )
915 throw std::logic_error( "Cabana::Scatter::apply (Slice): "
916 "Failed MPI Communication" );
917
918 // Get the steering vector for the sends.
919 auto steering = _halo.getExportSteering();
920
921 // Scatter the ghosts in the receive buffer into the local values.
922 auto scatter_recv_buffer_func = KOKKOS_LAMBDA( const std::size_t i )
923 {
924 auto s = SliceType::index_type::s( steering( i ) );
925 auto a = SliceType::index_type::a( steering( i ) );
926 std::size_t slice_offset = s * slice.stride( 0 ) + a;
927 for ( std::size_t n = 0; n < num_comp; ++n )
928 Kokkos::atomic_add(
929 &slice_data( slice_offset + SliceType::vector_length * n ),
930 recv_buffer( i, n ) );
931 };
932 Kokkos::RangePolicy<ExecutionSpace> recv_policy( 0, _recv_size );
933 Kokkos::parallel_for( "Cabana::Scatter::apply::scatter_recv_buffer",
934 recv_policy, scatter_recv_buffer_func );
935 Kokkos::fence();
936
937 // Barrier before completing to ensure synchronization.
938 MPI_Barrier( _halo.comm() );
939 }
940
941 void apply() override { apply( execution_space{} ); }
942
952 void reserve( const HaloType& halo, const SliceType& slice,
953 const double overallocation )
954 {
955 if ( !haloCheckValidSize( halo, slice ) )
956 throw std::runtime_error(
957 "Cabana::Scatter::reserve: "
958 "Slice is the wrong size for scatter! (Label: " +
959 slice.label() + ")" );
960
961 this->reserveImpl( halo, slice, totalSend(), totalReceive(),
962 overallocation );
963 }
964
970 void reserve( const HaloType& halo, const SliceType& slice )
971 {
972 if ( !haloCheckValidSize( halo, slice ) )
973 throw std::runtime_error(
974 "Cabana::Scatter::reserve: "
975 "Slice is the wrong size for scatter! (Label: " +
976 slice.label() + ")" );
977
978 this->reserveImpl( halo, slice, totalSend(), totalReceive() );
979 }
980
981 private:
985};
986
1000template <class HaloType, class SliceType>
1001auto createScatter( const HaloType& halo, const SliceType& slice,
1002 const double overallocation = 1.0,
1003 typename std::enable_if<( is_halo<HaloType>::value &&
1005 int>::type* = 0 )
1006{
1007 return Scatter<HaloType, SliceType>( halo, slice, overallocation );
1008}
1009
1010//---------------------------------------------------------------------------//
1028template <class HaloType, class SliceType>
1029void scatter( const HaloType& halo, SliceType& slice,
1030 typename std::enable_if<( is_halo<HaloType>::value &&
1032 int>::type* = 0 )
1033{
1034 auto scatter = createScatter( halo, slice );
1035 scatter.apply();
1036}
1037
1038//---------------------------------------------------------------------------//
1039
1040} // end namespace Cabana
1041
1042#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:1742
buffer_type getSendBuffer() const
Definition Cabana_CommunicationPlan.hpp:1772
particle_data_type getData() const
Definition Cabana_CommunicationPlan.hpp:1777
plan_type _comm_plan
Definition Cabana_CommunicationPlan.hpp:1870
std::size_t _recv_size
Definition Cabana_CommunicationPlan.hpp:1878
typename comm_data_type::data_type data_type
Definition Cabana_CommunicationPlan.hpp:1752
typename comm_data_type::buffer_type buffer_type
Definition Cabana_CommunicationPlan.hpp:1754
auto getSliceComponents()
Definition Cabana_CommunicationPlan.hpp:1867
HaloType plan_type
Definition Cabana_CommunicationPlan.hpp:1740
CommunicationData(const HaloType &comm_plan, const particle_data_type &particles, const double overallocation=1.0)
Definition Cabana_CommunicationPlan.hpp:1762
typename comm_data_type::memory_space memory_space
Definition Cabana_CommunicationPlan.hpp:1750
buffer_type getReceiveBuffer() const
Definition Cabana_CommunicationPlan.hpp:1774
std::size_t _send_size
Definition Cabana_CommunicationPlan.hpp:1876
void createExportSteering(const PackViewType &neighbor_ids, const RankViewType &element_export_ranks)
Create the export steering vector.
Definition Cabana_CommunicationPlan.hpp:1504
MPI_Comm comm() const
Get the MPI communicator.
Definition Cabana_CommunicationPlan.hpp:480
std::size_t totalNumImport() const
Get the total number of imports this rank will do.
Definition Cabana_CommunicationPlan.hpp:537
CommunicationPlan(MPI_Comm comm)
Constructor.
Definition Cabana_CommunicationPlan.hpp:458
typename base_type::memory_space memory_space
Kokkos memory space.
Definition Cabana_Halo.hpp:363
void apply() override
Perform the communication (migrate, gather, scatter).
Definition Cabana_Halo.hpp:477
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:503
auto totalSend()
Total gather send size for this rank.
Definition Cabana_Halo.hpp:388
typename base_type::data_type data_type
Communication data type.
Definition Cabana_Halo.hpp:365
Gather(HaloType halo, AoSoAType aosoa, const double overallocation=1.0)
Definition Cabana_Halo.hpp:381
auto totalReceive()
Total gather receive size for this rank.
Definition Cabana_Halo.hpp:390
void apply(ExecutionSpace)
Perform the gather operation.
Definition Cabana_Halo.hpp:396
typename base_type::buffer_type buffer_type
Communication buffer type.
Definition Cabana_Halo.hpp:367
typename base_type::plan_type plan_type
Communication plan type (Halo)
Definition Cabana_Halo.hpp:359
typename base_type::execution_space execution_space
Kokkos execution space.
Definition Cabana_Halo.hpp:361
void reserve(const HaloType &halo, AoSoAType &aosoa)
Reserve new buffers as needed and update the halo and AoSoA data.
Definition Cabana_Halo.hpp:485
CommunicationData< HaloType, CommunicationDataAoSoA< AoSoAType > > base_type
Base type.
Definition Cabana_Halo.hpp:356
typename base_type::memory_space memory_space
Kokkos memory space.
Definition Cabana_Halo.hpp:549
typename base_type::buffer_type buffer_type
Communication buffer type.
Definition Cabana_Halo.hpp:553
CommunicationData< HaloType, CommunicationDataSlice< SliceType > > base_type
Base type.
Definition Cabana_Halo.hpp:542
void apply(ExecutionSpace)
Perform the gather operation.
Definition Cabana_Halo.hpp:582
void apply() override
Perform the communication (migrate, gather, scatter).
Definition Cabana_Halo.hpp:682
auto totalReceive()
Total gather receive size for this rank.
Definition Cabana_Halo.hpp:576
Gather(HaloType halo, SliceType slice, const double overallocation=1.0)
Definition Cabana_Halo.hpp:567
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:692
typename base_type::execution_space execution_space
Kokkos execution space.
Definition Cabana_Halo.hpp:547
typename base_type::plan_type plan_type
Communication plan type (Halo)
Definition Cabana_Halo.hpp:545
auto totalSend()
Total gather send size for this rank.
Definition Cabana_Halo.hpp:574
void reserve(const HaloType &halo, const SliceType &slice)
Reserve new buffers as needed and update the halo and slice data.
Definition Cabana_Halo.hpp:710
typename base_type::data_type data_type
Communication data type.
Definition Cabana_Halo.hpp:551
Definition Cabana_Halo.hpp:333
A communication plan for scattering and gathering of ghosted data.
Definition Cabana_Halo.hpp:60
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:289
Halo(MPI_Comm comm, const std::size_t num_local, const IdViewType &element_ids, const RankViewType &element_ranks, const std::vector< int > &neighbor_ranks)
Neighbor and export rank constructor. Use this when you don't know who you will receiving from - only...
Definition Cabana_Halo.hpp:104
std::size_t numLocal() const
Get the number of elements locally owned by this rank.
Definition Cabana_Halo.hpp:280
Halo(MPI_Comm comm, const std::size_t num_local, const IdViewType &element_ids, const RankViewType &element_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
Synchronously scatter data from the ghosts to the local decomposition of a slice using the halo rever...
Definition Cabana_Halo.hpp:792
void reserve(const HaloType &halo, const SliceType &slice)
Reserve new buffers as needed and update the halo and slice data.
Definition Cabana_Halo.hpp:970
CommunicationData< HaloType, CommunicationDataSlice< SliceType > > base_type
Base type.
Definition Cabana_Halo.hpp:797
typename base_type::memory_space memory_space
Kokkos memory space.
Definition Cabana_Halo.hpp:804
void apply(ExecutionSpace)
Perform the scatter operation.
Definition Cabana_Halo.hpp:837
typename base_type::data_type data_type
Communication data type.
Definition Cabana_Halo.hpp:806
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:952
typename base_type::plan_type plan_type
Communication plan type (Halo).
Definition Cabana_Halo.hpp:800
auto totalReceive()
Total scatter receive size for this rank.
Definition Cabana_Halo.hpp:831
void apply() override
Perform the communication (migrate, gather, scatter).
Definition Cabana_Halo.hpp:941
typename base_type::buffer_type buffer_type
Communication buffer type.
Definition Cabana_Halo.hpp:808
typename base_type::execution_space execution_space
Kokkos execution space.
Definition Cabana_Halo.hpp:802
Scatter(HaloType halo, SliceType slice, const double overallocation=1.0)
Definition Cabana_Halo.hpp:822
auto totalSend()
Total scatter send size for this rank.
Definition Cabana_Halo.hpp:829
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:767
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:1029
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:1001
auto createGather(const HaloType &halo, const ParticleDataType &data, const double overallocation=1.0)
Create the gather.
Definition Cabana_Halo.hpp:742
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:324
Halo static type checker.
Definition Cabana_Halo.hpp:311
Slice static type checker.
Definition Cabana_Slice.hpp:868