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 build( num_local, element_ids, element_ranks, neighbor_ranks );
111 }
112
145 template <class IdViewType, class RankViewType, typename T = BuildType,
146 std::enable_if_t<std::is_same<T, Export>::value, int> = 0>
147 Halo( MPI_Comm comm, const std::size_t num_local,
148 const IdViewType& element_ids, const RankViewType& element_ranks )
149 : CommunicationPlan<MemorySpace>( comm )
150 , _num_local( num_local )
151 {
152 build( num_local, element_ids, element_ranks );
153 }
154
195 template <class IdViewType, class RankViewType, typename T = BuildType,
196 std::enable_if_t<std::is_same<T, Import>::value, int> = 0>
197 Halo( MPI_Comm comm, const std::size_t num_local,
198 const IdViewType& element_ids, const RankViewType& element_ranks,
199 const std::vector<int>& neighbor_ranks )
200 : CommunicationPlan<MemorySpace>( comm )
201 {
202 build( num_local, element_ids, element_ranks, neighbor_ranks );
203 }
204
236 template <class IdViewType, class RankViewType, typename T = BuildType,
237 std::enable_if_t<std::is_same<T, Import>::value, int> = 0>
238 Halo( MPI_Comm comm, const std::size_t num_local,
239 const IdViewType& element_ids, const RankViewType& element_ranks )
240 : CommunicationPlan<MemorySpace>( comm )
241 {
242 build( num_local, element_ids, element_ranks );
243 }
244
250 template <class IdViewType, class RankViewType, typename T = BuildType,
251 std::enable_if_t<std::is_same<T, Export>::value, int> = 0>
252 void build( const std::size_t num_local, const IdViewType& element_ids,
253 const RankViewType& element_ranks,
254 const std::vector<int>& neighbor_ranks )
255 {
256 _num_local = num_local;
257 if ( element_ids.size() != element_ranks.size() )
258 throw std::runtime_error( "Cabana::Halo (export): ids and ranks "
259 "views are different sizes!" );
260
261 auto neighbor_ids = this->createWithTopology(
262 BuildType(), element_ranks, neighbor_ranks );
263 this->createExportSteering( neighbor_ids, element_ranks, element_ids );
264 }
265
271 template <class IdViewType, class RankViewType, typename T = BuildType,
272 std::enable_if_t<std::is_same<T, Export>::value, int> = 0>
273 void build( const std::size_t num_local, const IdViewType& element_ids,
274 const RankViewType& element_ranks )
275 {
276 _num_local = num_local;
277 if ( element_ids.size() != element_ranks.size() )
278 throw std::runtime_error( "Cabana::Halo (export): ids and ranks "
279 "views are different sizes!" );
280
281 auto neighbor_ids =
282 this->createWithoutTopology( BuildType(), element_ranks );
283 this->createExportSteering( neighbor_ids, element_ranks, element_ids );
284 }
285
291 template <class IdViewType, class RankViewType, typename T = BuildType,
292 std::enable_if_t<std::is_same<T, Import>::value, int> = 0>
293 void build( const std::size_t num_local, const IdViewType& element_ids,
294 const RankViewType& element_ranks,
295 const std::vector<int>& neighbor_ranks )
296 {
297 _num_local = num_local;
298 if ( element_ids.size() != element_ranks.size() )
299 throw std::runtime_error( "Cabana::Halo (import): ids and ranks "
300 "views are different sizes!" );
301
302 auto neighbor_ids_ranks_indices = this->createWithTopology(
303 BuildType(), element_ranks, element_ids, neighbor_ranks );
304 this->createExportSteering( std::get<0>( neighbor_ids_ranks_indices ),
305 std::get<1>( neighbor_ids_ranks_indices ),
306 std::get<2>( neighbor_ids_ranks_indices ) );
307 }
308
314 template <class IdViewType, class RankViewType, typename T = BuildType,
315 std::enable_if_t<std::is_same<T, Import>::value, int> = 0>
316 void build( const std::size_t num_local, const IdViewType& element_ids,
317 const RankViewType& element_ranks )
318 {
319 _num_local = num_local;
320 if ( element_ids.size() != element_ranks.size() )
321 throw std::runtime_error( "Cabana::Halo (import): ids and ranks "
322 "views are different sizes!" );
323
324 auto neighbor_ids_ranks_indices = this->createWithoutTopology(
325 BuildType(), element_ranks, element_ids );
326 this->createExportSteering( std::get<0>( neighbor_ids_ranks_indices ),
327 std::get<1>( neighbor_ids_ranks_indices ),
328 std::get<2>( neighbor_ids_ranks_indices ) );
329 }
330
336 std::size_t numLocal() const { return _num_local; }
337
345 std::size_t numGhost() const { return this->totalNumImport(); }
346
347 private:
348 std::size_t _num_local;
349};
350
351//---------------------------------------------------------------------------//
353template <typename>
354struct is_halo_impl : public std::false_type
355{
356};
357
358template <typename MemorySpace, typename BuildType>
359struct is_halo_impl<Halo<MemorySpace, BuildType>> : public std::true_type
360{
361};
363
365template <class T>
366struct is_halo : public is_halo_impl<typename std::remove_cv<T>::type>::type
367{
368};
369
379template <class Halo, class ParticleData>
381 const Halo& halo, const ParticleData& particles,
382 typename std::enable_if<( is_halo<Halo>::value ), int>::type* = 0 )
383{
384 // Check that the data is the right size.
385 return ( particles.size() == halo.numLocal() + halo.numGhost() );
386}
387
388template <class HaloType, class AoSoAType, class SFINAE = void>
389class Gather;
390
391//---------------------------------------------------------------------------//
403template <class HaloType, class AoSoAType>
404class Gather<HaloType, AoSoAType,
405 typename std::enable_if<is_aosoa<AoSoAType>::value>::type>
406 : public CommunicationData<HaloType, CommunicationDataAoSoA<AoSoAType>>
407{
408 public:
409 static_assert( is_halo<HaloType>::value, "" );
410
412 using base_type =
424
437 Gather( HaloType halo, AoSoAType aosoa, const double overallocation = 1.0 )
438 : base_type( halo, aosoa, overallocation )
439 {
440 reserve( _comm_plan, aosoa );
441 }
442
444 auto totalSend() { return _comm_plan.totalNumExport(); }
446 auto totalReceive() { return _comm_plan.totalNumImport(); }
448 auto totalSend( const HaloType& halo ) { return halo.totalNumExport(); }
450 auto totalReceive( const HaloType& halo ) { return halo.totalNumImport(); }
451
455 template <class ExecutionSpace>
456 void apply( ExecutionSpace )
457 {
458 Kokkos::Profiling::ScopedRegion region( "Cabana::Gather::apply" );
459
460 // Get the buffers and particle data (local copies for lambdas below).
461 auto send_buffer = this->getSendBuffer();
462 auto recv_buffer = this->getReceiveBuffer();
463 auto aosoa = this->getData();
464
465 // Get the steering vector for the sends.
466 auto steering = _comm_plan.getExportSteering();
467 // Gather from the local data into a tuple-contiguous send buffer.
468 auto gather_send_buffer_func = KOKKOS_LAMBDA( const std::size_t i )
469 {
470 send_buffer( i ) = aosoa.getTuple( steering( i ) );
471 };
472 Kokkos::RangePolicy<ExecutionSpace> send_policy( 0, _send_size );
473 Kokkos::parallel_for( "Cabana::Gather::gather_send_buffer", send_policy,
474 gather_send_buffer_func );
475 Kokkos::fence();
476
477 // The halo has it's own communication space so choose any mpi tag.
478 const int mpi_tag = 2345;
479
480 // Post non-blocking receives.
481 int num_n = _comm_plan.numNeighbor();
482 std::vector<MPI_Request> requests( num_n );
483 std::pair<std::size_t, std::size_t> recv_range = { 0, 0 };
484 for ( int n = 0; n < num_n; ++n )
485 {
486 recv_range.second = recv_range.first + _comm_plan.numImport( n );
487
488 auto recv_subview = Kokkos::subview( recv_buffer, recv_range );
489
490 MPI_Irecv( recv_subview.data(),
491 recv_subview.size() * sizeof( data_type ), MPI_BYTE,
492 _comm_plan.neighborRank( n ), mpi_tag, _comm_plan.comm(),
493 &( requests[n] ) );
494
495 recv_range.first = recv_range.second;
496 }
497
498 // Do blocking sends.
499 std::pair<std::size_t, std::size_t> send_range = { 0, 0 };
500 for ( int n = 0; n < num_n; ++n )
501 {
502 send_range.second = send_range.first + _comm_plan.numExport( n );
503
504 auto send_subview = Kokkos::subview( send_buffer, send_range );
505
506 MPI_Send( send_subview.data(),
507 send_subview.size() * sizeof( data_type ), MPI_BYTE,
508 _comm_plan.neighborRank( n ), mpi_tag,
509 _comm_plan.comm() );
510
511 send_range.first = send_range.second;
512 }
513
514 // Wait on non-blocking receives.
515 std::vector<MPI_Status> status( num_n );
516 const int ec =
517 MPI_Waitall( requests.size(), requests.data(), status.data() );
518 if ( MPI_SUCCESS != ec )
519 throw std::logic_error(
520 "Cabana::Gather::apply (AoSoA): Failed MPI Communication" );
521
522 // Extract the receive buffer into the ghosted elements.
523 std::size_t num_local = _comm_plan.numLocal();
524 auto extract_recv_buffer_func = KOKKOS_LAMBDA( const std::size_t i )
525 {
526 std::size_t ghost_idx = i + num_local;
527 aosoa.setTuple( ghost_idx, recv_buffer( i ) );
528 };
529 Kokkos::RangePolicy<ExecutionSpace> recv_policy( 0, _recv_size );
530 Kokkos::parallel_for( "Cabana::Gather::apply::extract_recv_buffer",
531 recv_policy, extract_recv_buffer_func );
532 Kokkos::fence();
533
534 // Barrier before completing to ensure synchronization.
535 MPI_Barrier( _comm_plan.comm() );
536 }
537
538 void apply() override { apply( execution_space{} ); }
539
546 void reserve( const HaloType& halo, AoSoAType& aosoa )
547 {
548 if ( !haloCheckValidSize( halo, aosoa ) )
549 throw std::runtime_error(
550 "Cabana::Gather:reserve: "
551 "AoSoA is the wrong size for gather! (Label: " +
552 aosoa.label() + ")" );
553
554 this->reserveImpl( halo, aosoa, totalSend( halo ),
555 totalReceive( halo ) );
556 }
557
565 void reserve( const HaloType& halo, AoSoAType& aosoa,
566 const double overallocation )
567 {
568 if ( !haloCheckValidSize( halo, aosoa ) )
569 throw std::runtime_error(
570 "Cabana::Gather:reserve: "
571 "AoSoA is the wrong size for gather! (Label: " +
572 aosoa.label() + ")" );
573
574 this->reserveImpl( halo, aosoa, totalSend( halo ), totalReceive( halo ),
575 overallocation );
576 }
577
578 private:
579 using base_type::_comm_plan;
580 using base_type::_recv_size;
581 using base_type::_send_size;
582};
583
595template <class HaloType, class SliceType>
596class Gather<HaloType, SliceType,
597 typename std::enable_if<is_slice<SliceType>::value>::type>
598 : public CommunicationData<HaloType, CommunicationDataSlice<SliceType>>
599{
600 public:
601 static_assert( is_halo<HaloType>::value, "" );
602
604 using base_type =
616
629 Gather( HaloType halo, SliceType slice, const double overallocation = 1.0 )
630 : base_type( halo, slice, overallocation )
631 {
632 reserve( _comm_plan, slice );
633 }
634
636 auto totalSend() { return _comm_plan.totalNumExport(); }
638 auto totalReceive() { return _comm_plan.totalNumImport(); }
640 auto totalSend( const HaloType& halo ) { return halo.totalNumExport(); }
642 auto totalReceive( const HaloType& halo ) { return halo.totalNumImport(); }
643
647 template <class ExecutionSpace>
648 void apply( ExecutionSpace )
649 {
650 Kokkos::Profiling::ScopedRegion region( "Cabana::Gather::apply" );
651
652 // Get the buffers (local copies for lambdas below).
653 auto send_buffer = this->getSendBuffer();
654 auto recv_buffer = this->getReceiveBuffer();
655 auto slice = this->getData();
656
657 // Get the number of components in the slice.
658 std::size_t num_comp = this->getSliceComponents();
659
660 // Get the raw slice data.
661 auto slice_data = slice.data();
662
663 // Get the steering vector for the sends.
664 auto steering = _comm_plan.getExportSteering();
665
666 // Gather from the local data into a tuple-contiguous send buffer.
667 auto gather_send_buffer_func = KOKKOS_LAMBDA( const std::size_t i )
668 {
669 auto s = SliceType::index_type::s( steering( i ) );
670 auto a = SliceType::index_type::a( steering( i ) );
671 std::size_t slice_offset = s * slice.stride( 0 ) + a;
672 for ( std::size_t n = 0; n < num_comp; ++n )
673 send_buffer( i, n ) =
674 slice_data[slice_offset + n * SliceType::vector_length];
675 };
676 Kokkos::RangePolicy<ExecutionSpace> send_policy( 0, _send_size );
677 Kokkos::parallel_for( "Cabana::Gather::gather_send_buffer", send_policy,
678 gather_send_buffer_func );
679 Kokkos::fence();
680
681 // The halo has it's own communication space so choose any mpi tag.
682 const int mpi_tag = 2345;
683
684 // Post non-blocking receives.
685 int num_n = _comm_plan.numNeighbor();
686 std::vector<MPI_Request> requests( num_n );
687 std::pair<std::size_t, std::size_t> recv_range = { 0, 0 };
688 for ( int n = 0; n < num_n; ++n )
689 {
690 recv_range.second = recv_range.first + _comm_plan.numImport( n );
691
692 auto recv_subview =
693 Kokkos::subview( recv_buffer, recv_range, Kokkos::ALL );
694
695 MPI_Irecv( recv_subview.data(),
696 recv_subview.size() * sizeof( data_type ), MPI_BYTE,
697 _comm_plan.neighborRank( n ), mpi_tag, _comm_plan.comm(),
698 &( requests[n] ) );
699
700 recv_range.first = recv_range.second;
701 }
702
703 // Do blocking sends.
704 std::pair<std::size_t, std::size_t> send_range = { 0, 0 };
705 for ( int n = 0; n < num_n; ++n )
706 {
707 send_range.second = send_range.first + _comm_plan.numExport( n );
708
709 auto send_subview =
710 Kokkos::subview( send_buffer, send_range, Kokkos::ALL );
711
712 MPI_Send( send_subview.data(),
713 send_subview.size() * sizeof( data_type ), MPI_BYTE,
714 _comm_plan.neighborRank( n ), mpi_tag,
715 _comm_plan.comm() );
716
717 send_range.first = send_range.second;
718 }
719
720 // Wait on non-blocking receives.
721 std::vector<MPI_Status> status( num_n );
722 const int ec =
723 MPI_Waitall( requests.size(), requests.data(), status.data() );
724 if ( MPI_SUCCESS != ec )
725 throw std::logic_error(
726 "Cabana::Gather::apply (Slice): Failed MPI Communication" );
727
728 // Extract the receive buffer into the ghosted elements.
729 std::size_t num_local = _comm_plan.numLocal();
730 auto extract_recv_buffer_func = KOKKOS_LAMBDA( const std::size_t i )
731 {
732 std::size_t ghost_idx = i + num_local;
733 auto s = SliceType::index_type::s( ghost_idx );
734 auto a = SliceType::index_type::a( ghost_idx );
735 std::size_t slice_offset = s * slice.stride( 0 ) + a;
736 for ( std::size_t n = 0; n < num_comp; ++n )
737 slice_data[slice_offset + SliceType::vector_length * n] =
738 recv_buffer( i, n );
739 };
740 Kokkos::RangePolicy<ExecutionSpace> recv_policy( 0, _recv_size );
741 Kokkos::parallel_for( "Cabana::Gather::extract_recv_buffer",
742 recv_policy, extract_recv_buffer_func );
743 Kokkos::fence();
744
745 // Barrier before completing to ensure synchronization.
746 MPI_Barrier( _comm_plan.comm() );
747 }
748
749 void apply() override { apply( execution_space{} ); }
750
759 void reserve( const HaloType& halo, const SliceType& slice,
760 const double overallocation )
761 {
762 if ( !haloCheckValidSize( halo, slice ) )
763 throw std::runtime_error(
764 "Cabana::Gather:reserve: "
765 "Slice is the wrong size for gather! (Label: " +
766 slice.label() + ")" );
767
768 // Cannot use totalSend(), totalReceive() because it may be inconsistent
769 // with the new plan.
770 this->reserveImpl( halo, slice, totalSend( halo ), totalReceive( halo ),
771 overallocation );
772 }
773
779 void reserve( const HaloType& halo, const SliceType& slice )
780 {
781 if ( !haloCheckValidSize( halo, slice ) )
782 throw std::runtime_error(
783 "Cabana::Gather:reserve: "
784 "Slice is the wrong size for gather! (Label: " +
785 slice.label() + ")" );
786
787 this->reserveImpl( halo, slice, totalSend( halo ),
788 totalReceive( halo ) );
789 }
790
791 private:
792 using base_type::_comm_plan;
793 using base_type::_recv_size;
794 using base_type::_send_size;
795};
796
797//---------------------------------------------------------------------------//
811template <class HaloType, class ParticleDataType>
812auto createGather( const HaloType& halo, const ParticleDataType& data,
813 const double overallocation = 1.0 )
814{
815 return Gather<HaloType, ParticleDataType>( halo, data, overallocation );
816}
817
818//---------------------------------------------------------------------------//
836template <class HaloType, class ParticleDataType>
837void gather( const HaloType& halo, ParticleDataType& data )
838{
839 auto gather = createGather( halo, data );
840 gather.apply();
841}
842
843/**********
844 * SCATTER *
845 **********/
846
847//---------------------------------------------------------------------------//
859template <class HaloType, class SliceType>
861 : public CommunicationData<HaloType, CommunicationDataSlice<SliceType>>
862{
863 static_assert( is_halo<HaloType>::value, "" );
864
865 public:
867 using base_type =
879
892 Scatter( HaloType halo, SliceType slice, const double overallocation = 1.0 )
893 : base_type( halo, slice, overallocation )
894 {
895 reserve( _comm_plan, slice );
896 }
897
899 auto totalSend() { return _comm_plan.totalNumImport(); }
901 auto totalReceive() { return _comm_plan.totalNumExport(); }
903 auto totalSend( const HaloType& halo ) { return halo.totalNumImport(); }
905 auto totalReceive( const HaloType& halo ) { return halo.totalNumExport(); }
906
910 template <class ExecutionSpace>
911 void apply( ExecutionSpace )
912 {
913 Kokkos::Profiling::ScopedRegion region( "Cabana::Scatter::apply" );
914
915 // Get the buffers (local copies for lambdas below).
916 auto send_buffer = this->getSendBuffer();
917 auto recv_buffer = this->getReceiveBuffer();
918 auto slice = this->getData();
919
920 // Get the number of components in the slice.
921 std::size_t num_comp = this->getSliceComponents();
922
923 // Get the raw slice data. Wrap in a 1D Kokkos View so we can unroll the
924 // components of each slice element.
925 Kokkos::View<data_type*, memory_space,
926 Kokkos::MemoryTraits<Kokkos::Unmanaged>>
927 slice_data( slice.data(), slice.numSoA() * slice.stride( 0 ) );
928
929 // Extract the send buffer from the ghosted elements.
930 std::size_t num_local = _comm_plan.numLocal();
931 auto extract_send_buffer_func = KOKKOS_LAMBDA( const std::size_t i )
932 {
933 std::size_t ghost_idx = i + num_local;
934 auto s = SliceType::index_type::s( ghost_idx );
935 auto a = SliceType::index_type::a( ghost_idx );
936 std::size_t slice_offset = s * slice.stride( 0 ) + a;
937 for ( std::size_t n = 0; n < num_comp; ++n )
938 send_buffer( i, n ) =
939 slice_data( slice_offset + SliceType::vector_length * n );
940 };
941 Kokkos::RangePolicy<ExecutionSpace> send_policy( 0, _send_size );
942 Kokkos::parallel_for( "Cabana::Scatter::apply::extract_send_buffer",
943 send_policy, extract_send_buffer_func );
944 Kokkos::fence();
945
946 // The halo has it's own communication space so choose any mpi tag.
947 const int mpi_tag = 2345;
948
949 // Post non-blocking receives.
950 int num_n = _comm_plan.numNeighbor();
951 std::vector<MPI_Request> requests( num_n );
952 std::pair<std::size_t, std::size_t> recv_range = { 0, 0 };
953 for ( int n = 0; n < num_n; ++n )
954 {
955 recv_range.second = recv_range.first + _comm_plan.numExport( n );
956
957 auto recv_subview =
958 Kokkos::subview( recv_buffer, recv_range, Kokkos::ALL );
959
960 MPI_Irecv( recv_subview.data(),
961 recv_subview.size() * sizeof( data_type ), MPI_BYTE,
962 _comm_plan.neighborRank( n ), mpi_tag, _comm_plan.comm(),
963 &( requests[n] ) );
964
965 recv_range.first = recv_range.second;
966 }
967
968 // Do blocking sends.
969 std::pair<std::size_t, std::size_t> send_range = { 0, 0 };
970 for ( int n = 0; n < num_n; ++n )
971 {
972 send_range.second = send_range.first + _comm_plan.numImport( n );
973
974 auto send_subview =
975 Kokkos::subview( send_buffer, send_range, Kokkos::ALL );
976
977 MPI_Send( send_subview.data(),
978 send_subview.size() * sizeof( data_type ), MPI_BYTE,
979 _comm_plan.neighborRank( n ), mpi_tag,
980 _comm_plan.comm() );
981
982 send_range.first = send_range.second;
983 }
984
985 // Wait on non-blocking receives.
986 std::vector<MPI_Status> status( num_n );
987 const int ec =
988 MPI_Waitall( requests.size(), requests.data(), status.data() );
989 if ( MPI_SUCCESS != ec )
990 throw std::logic_error( "Cabana::Scatter::apply (Slice): "
991 "Failed MPI Communication" );
992
993 // Get the steering vector for the sends.
994 auto steering = _comm_plan.getExportSteering();
995
996 // Scatter the ghosts in the receive buffer into the local values.
997 auto scatter_recv_buffer_func = KOKKOS_LAMBDA( const std::size_t i )
998 {
999 auto s = SliceType::index_type::s( steering( i ) );
1000 auto a = SliceType::index_type::a( steering( i ) );
1001 std::size_t slice_offset = s * slice.stride( 0 ) + a;
1002 for ( std::size_t n = 0; n < num_comp; ++n )
1003 Kokkos::atomic_add(
1004 &slice_data( slice_offset + SliceType::vector_length * n ),
1005 recv_buffer( i, n ) );
1006 };
1007 Kokkos::RangePolicy<ExecutionSpace> recv_policy( 0, _recv_size );
1008 Kokkos::parallel_for( "Cabana::Scatter::apply::scatter_recv_buffer",
1009 recv_policy, scatter_recv_buffer_func );
1010 Kokkos::fence();
1011
1012 // Barrier before completing to ensure synchronization.
1013 MPI_Barrier( _comm_plan.comm() );
1014 }
1015
1016 void apply() override { apply( execution_space{} ); }
1017
1027 void reserve( const HaloType& halo, const SliceType& slice,
1028 const double overallocation )
1029 {
1030 if ( !haloCheckValidSize( halo, slice ) )
1031 throw std::runtime_error(
1032 "Cabana::Scatter::reserve: "
1033 "Slice is the wrong size for scatter! (Label: " +
1034 slice.label() + ")" );
1035
1036 this->reserveImpl( halo, slice, totalSend( halo ), totalReceive( halo ),
1037 overallocation );
1038 }
1039
1045 void reserve( const HaloType& halo, const SliceType& slice )
1046 {
1047 if ( !haloCheckValidSize( halo, slice ) )
1048 throw std::runtime_error(
1049 "Cabana::Scatter::reserve: "
1050 "Slice is the wrong size for scatter! (Label: " +
1051 slice.label() + ")" );
1052
1053 this->reserveImpl( halo, slice, totalSend( halo ),
1054 totalReceive( halo ) );
1055 }
1056
1057 private:
1061};
1062
1076template <class HaloType, class SliceType>
1077auto createScatter( const HaloType& halo, const SliceType& slice,
1078 const double overallocation = 1.0,
1079 typename std::enable_if<( is_halo<HaloType>::value &&
1081 int>::type* = 0 )
1082{
1083 return Scatter<HaloType, SliceType>( halo, slice, overallocation );
1084}
1085
1086//---------------------------------------------------------------------------//
1104template <class HaloType, class SliceType>
1105void scatter( const HaloType& halo, SliceType& slice,
1106 typename std::enable_if<( is_halo<HaloType>::value &&
1108 int>::type* = 0 )
1109{
1110 auto scatter = createScatter( halo, slice );
1111 scatter.apply();
1112}
1113
1114//---------------------------------------------------------------------------//
1115
1116} // end namespace Cabana
1117
1118#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
Kokkos::View< size_type *, memory_space > createWithoutTopology(ExecutionSpace exec_space, Export, const RankViewType &element_export_ranks)
Export rank creator. Use this when you don't know who you will receiving from - only who you are send...
Definition Cabana_CommunicationPlan.hpp:770
Kokkos::View< size_type *, memory_space > createWithTopology(ExecutionSpace exec_space, Export, const RankViewType &element_export_ranks, const std::vector< int > &neighbor_ranks)
Neighbor and export rank creator. Use this when you already know which ranks neighbor each other (i....
Definition Cabana_CommunicationPlan.hpp:608
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
auto totalSend(const HaloType &halo)
Total gather send size for this rank.
Definition Cabana_Halo.hpp:448
typename base_type::memory_space memory_space
Kokkos memory space.
Definition Cabana_Halo.hpp:419
auto totalReceive(const HaloType &halo)
Total gather receive size for this rank.
Definition Cabana_Halo.hpp:450
void apply() override
Perform the communication (migrate, gather, scatter).
Definition Cabana_Halo.hpp:538
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:565
auto totalSend()
Total gather send size for this rank.
Definition Cabana_Halo.hpp:444
typename base_type::data_type data_type
Communication data type.
Definition Cabana_Halo.hpp:421
Gather(HaloType halo, AoSoAType aosoa, const double overallocation=1.0)
Definition Cabana_Halo.hpp:437
auto totalReceive()
Total gather receive size for this rank.
Definition Cabana_Halo.hpp:446
void apply(ExecutionSpace)
Perform the gather operation.
Definition Cabana_Halo.hpp:456
typename base_type::buffer_type buffer_type
Communication buffer type.
Definition Cabana_Halo.hpp:423
typename base_type::plan_type plan_type
Communication plan type (Halo)
Definition Cabana_Halo.hpp:415
typename base_type::execution_space execution_space
Kokkos execution space.
Definition Cabana_Halo.hpp:417
void reserve(const HaloType &halo, AoSoAType &aosoa)
Reserve new buffers as needed and update the halo and AoSoA data.
Definition Cabana_Halo.hpp:546
CommunicationData< HaloType, CommunicationDataAoSoA< AoSoAType > > base_type
Base type.
Definition Cabana_Halo.hpp:412
auto totalSend(const HaloType &halo)
Total gather send size for this rank.
Definition Cabana_Halo.hpp:640
typename base_type::memory_space memory_space
Kokkos memory space.
Definition Cabana_Halo.hpp:611
typename base_type::buffer_type buffer_type
Communication buffer type.
Definition Cabana_Halo.hpp:615
CommunicationData< HaloType, CommunicationDataSlice< SliceType > > base_type
Base type.
Definition Cabana_Halo.hpp:604
void apply(ExecutionSpace)
Perform the gather operation.
Definition Cabana_Halo.hpp:648
void apply() override
Perform the communication (migrate, gather, scatter).
Definition Cabana_Halo.hpp:749
auto totalReceive()
Total gather receive size for this rank.
Definition Cabana_Halo.hpp:638
Gather(HaloType halo, SliceType slice, const double overallocation=1.0)
Definition Cabana_Halo.hpp:629
auto totalReceive(const HaloType &halo)
Total gather receive size for this rank.
Definition Cabana_Halo.hpp:642
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:759
typename base_type::execution_space execution_space
Kokkos execution space.
Definition Cabana_Halo.hpp:609
typename base_type::plan_type plan_type
Communication plan type (Halo)
Definition Cabana_Halo.hpp:607
auto totalSend()
Total gather send size for this rank.
Definition Cabana_Halo.hpp:636
void reserve(const HaloType &halo, const SliceType &slice)
Reserve new buffers as needed and update the halo and slice data.
Definition Cabana_Halo.hpp:779
typename base_type::data_type data_type
Communication data type.
Definition Cabana_Halo.hpp:613
Definition Cabana_Halo.hpp:389
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:345
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:336
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:147
void build(const std::size_t num_local, const IdViewType &element_ids, const RankViewType &element_ranks, const std::vector< int > &neighbor_ranks)
Neighbor and export rank (re)build interface.
Definition Cabana_Halo.hpp:252
void build(const std::size_t num_local, const IdViewType &element_ids, const RankViewType &element_ranks)
Export rank (re)build interface.
Definition Cabana_Halo.hpp:273
Synchronously scatter data from the ghosts to the local decomposition of a slice using the halo rever...
Definition Cabana_Halo.hpp:862
void reserve(const HaloType &halo, const SliceType &slice)
Reserve new buffers as needed and update the halo and slice data.
Definition Cabana_Halo.hpp:1045
CommunicationData< HaloType, CommunicationDataSlice< SliceType > > base_type
Base type.
Definition Cabana_Halo.hpp:867
typename base_type::memory_space memory_space
Kokkos memory space.
Definition Cabana_Halo.hpp:874
void apply(ExecutionSpace)
Perform the scatter operation.
Definition Cabana_Halo.hpp:911
auto totalSend(const HaloType &halo)
Total gather send size for this rank.
Definition Cabana_Halo.hpp:903
typename base_type::data_type data_type
Communication data type.
Definition Cabana_Halo.hpp:876
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:1027
typename base_type::plan_type plan_type
Communication plan type (Halo).
Definition Cabana_Halo.hpp:870
auto totalReceive()
Total scatter receive size for this rank.
Definition Cabana_Halo.hpp:901
void apply() override
Perform the communication (migrate, gather, scatter).
Definition Cabana_Halo.hpp:1016
typename base_type::buffer_type buffer_type
Communication buffer type.
Definition Cabana_Halo.hpp:878
typename base_type::execution_space execution_space
Kokkos execution space.
Definition Cabana_Halo.hpp:872
auto totalReceive(const HaloType &halo)
Total gather receive size for this rank.
Definition Cabana_Halo.hpp:905
Scatter(HaloType halo, SliceType slice, const double overallocation=1.0)
Definition Cabana_Halo.hpp:892
auto totalSend()
Total scatter send size for this rank.
Definition Cabana_Halo.hpp:899
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:837
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:1105
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:1077
auto createGather(const HaloType &halo, const ParticleDataType &data, const double overallocation=1.0)
Create the gather.
Definition Cabana_Halo.hpp:812
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:380
Halo static type checker.
Definition Cabana_Halo.hpp:367
Slice static type checker.
Definition Cabana_Slice.hpp:868