12#ifndef CABANA_GRID_SPARSEHALO_HPP
13#define CABANA_GRID_SPARSEHALO_HPP
24#include <Kokkos_Core.hpp>
48template <
class MemorySpace,
class DataTypes,
class EntityType,
49 std::size_t NumSpaceDim,
unsigned long long cellBitsPerTileDim,
50 typename Value = int,
typename Key = uint64_t>
72 invalid_key = ~static_cast<key_type>( 0 )
81 template <std::
size_t M>
85 static constexpr std::size_t
member_num = aosoa_member_types::size;
112 Kokkos::MemoryTraits<Kokkos::Atomic>>;
121 template <
class SparseArrayType>
123 const std::shared_ptr<SparseArrayType>& sparse_array )
124 : _pattern( pattern )
127 auto neighbor_id = [](
const std::array<int, num_space_dim>& ijk )
137 auto flip_id = [=](
const std::array<int, num_space_dim>& ijk )
139 std::array<int, num_space_dim> flip_ijk;
141 flip_ijk[d] = -ijk[d];
147 auto soa_byte_array = compute_member_size_list();
148 for ( std::size_t i = 0; i <
member_num; ++i )
149 _soa_member_bytes[i] = soa_byte_array[i];
150 _soa_total_bytes = std::max(
151 std::accumulate( soa_byte_array.begin(), soa_byte_array.end(), 0 ),
155 auto local_grid = sparse_array->layout().localGrid();
159 local_grid->neighborRank( std::array<int, 3>( { 0, 0, 0 } ) );
163 auto neighbors = _pattern.getNeighbors();
164 for (
const auto& n : neighbors )
167 int rank = local_grid->neighborRank( n );
173 _neighbor_ranks.push_back( rank );
176 _send_tags.push_back( neighbor_id( n ) );
179 _receive_tags.push_back( neighbor_id( flip_id( n ) ) );
183 _owned_tile_steering, _owned_tile_spaces );
186 _ghosted_tile_steering, _ghosted_tile_spaces );
188 auto& own_index_space = _owned_tile_spaces.back();
189 auto& ghost_index_space = _ghosted_tile_spaces.back();
190 int tmp_steering_size =
191 own_index_space.sizeTile() > ghost_index_space.sizeTile()
192 ? own_index_space.sizeTile()
193 : ghost_index_space.sizeTile();
194 _tmp_tile_steering.push_back(
197 _valid_counting.push_back(
199 _neighbor_counting.push_back(
201 Kokkos::deep_copy( _valid_counting.back(), 0 );
202 Kokkos::deep_copy( _neighbor_counting.back(), 0 );
204 _valid_neighbor_ids.emplace_back( n );
210 template <
class SparseArrayType>
211 MPI_Comm
getComm(
const SparseArrayType sparse_array )
const
213 return sparse_array.layout().localGrid()->globalGrid().comm();
227 template <
class DecompositionTag,
class LocalGr
idType>
229 const std::shared_ptr<LocalGridType>& local_grid,
230 const std::array<int, num_space_dim>& nid,
231 std::vector<buffer_view>& buffers,
232 std::vector<steering_view>& steering,
233 std::vector<tile_index_space>& spaces )
237 local_grid->template sharedTileIndexSpace<cell_bits_per_tile_dim>(
239 auto& index_space = spaces.back();
243 buffer_view(
"halo_buffer", index_space.sizeCell() ) );
247 steering_view(
"halo_tile_steering", index_space.sizeTile() ) );
249 Kokkos::deep_copy( steering.back(), invalid_key );
258 template <
class LocalGr
idType>
262 _owned_tile_spaces.clear();
263 _ghosted_tile_spaces.clear();
266 auto neighbors = _pattern.getNeighbors();
267 for ( std::size_t i = 0; i < _valid_neighbor_ids.size(); ++i )
270 auto& n = _valid_neighbor_ids[i];
272 int rank = local_grid->neighborRank( n );
276 if ( rank == _neighbor_ranks[i] )
279 _owned_tile_spaces.push_back(
281 ->
template sharedTileIndexSpace<cell_bits_per_tile_dim>(
283 _ghosted_tile_spaces.push_back(
285 ->
template sharedTileIndexSpace<cell_bits_per_tile_dim>(
289 auto& own_index_space = _owned_tile_spaces.back();
290 auto& ghost_index_space = _ghosted_tile_spaces.back();
293 int own_tile_size = own_index_space.sizeTile();
294 int ghost_tile_size = ghost_index_space.sizeTile();
295 int tmp_steering_size = own_tile_size > ghost_tile_size
302 if ( own_tile_size > _owned_tile_steering[i].extent( 0 ) )
304 Kokkos::resize( _owned_tile_steering[i], own_tile_size );
305 Kokkos::resize( _owned_buffers[i],
306 own_index_space.sizeCell() );
308 if ( ghost_tile_size > _ghosted_tile_steering[i].extent( 0 ) )
310 Kokkos::resize( _ghosted_tile_steering[i],
312 Kokkos::resize( _ghosted_buffers[i],
313 ghost_index_space.sizeCell() );
315 if ( tmp_steering_size > _tmp_tile_steering[i].extent( 0 ) )
316 Kokkos::resize( _tmp_tile_steering[i], tmp_steering_size );
319 std::runtime_error(
"neighbor rank doesn't match id" );
332 template <
class ExecSpace,
class SparseMapType>
336 int num_n = _neighbor_ranks.size();
341 for (
int nid = 0; nid < num_n; nid++ )
343 auto& owned_space = _owned_tile_spaces[nid];
344 auto& owned_steering = _owned_tile_steering[nid];
346 auto& ghosted_space = _ghosted_tile_spaces[nid];
347 auto& ghosted_steering = _ghosted_tile_steering[nid];
349 auto& counting = _valid_counting[nid];
355 Kokkos::parallel_for(
356 Kokkos::RangePolicy<ExecSpace>( 0, map.capacity() ),
357 KOKKOS_LAMBDA(
const int index ) {
358 if ( map.valid_at( index ) )
360 auto tile_key = map.key_at( index );
362 map.key2ijk( tile_key, ti, tj, tk );
363 if ( owned_space.tileInRange( ti, tj, tk ) )
365 owned_steering( counting( Index::own )++ ) =
368 else if ( ghosted_space.tileInRange( ti, tj, tk ) )
370 ghosted_steering( counting( Index::ghost )++ ) =
390 for ( std::size_t i = 0; i < _valid_counting.size(); ++i )
391 Kokkos::deep_copy( _valid_counting[i], 0 );
392 for ( std::size_t i = 0; i < _neighbor_counting.size(); ++i )
393 Kokkos::deep_copy( _neighbor_counting[i], 0 );
395 for ( std::size_t i = 0; i < _owned_tile_steering.size(); ++i )
396 Kokkos::deep_copy( _owned_tile_steering[i], invalid_key );
397 for ( std::size_t i = 0; i < _ghosted_tile_steering.size(); ++i )
398 Kokkos::deep_copy( _ghosted_tile_steering[i], invalid_key );
399 for ( std::size_t i = 0; i < _tmp_tile_steering.size(); ++i )
400 Kokkos::deep_copy( _tmp_tile_steering[i], invalid_key );
415 MPI_Comm comm,
const bool is_neighbor_counting_collected =
false )
const
418 if ( is_neighbor_counting_collected )
422 int num_n = _neighbor_ranks.size();
426 std::vector<MPI_Request> counting_requests( 2 * num_n,
428 const int mpi_tag_counting = 1234;
431 for (
int nid = 0; nid < num_n; ++nid )
433 MPI_Irecv( _neighbor_counting[nid].data(),
434 Index::total *
sizeof(
int ), MPI_BYTE,
435 _neighbor_ranks[nid],
436 mpi_tag_counting + _receive_tags[nid], comm,
437 &counting_requests[nid] );
440 for (
int nid = 0; nid < num_n; ++nid )
442 MPI_Isend( _valid_counting[nid].data(),
443 Index::total *
sizeof(
int ), MPI_BYTE,
444 _neighbor_ranks[nid], mpi_tag_counting + _send_tags[nid],
445 comm, &counting_requests[nid + num_n] );
449 const int ec = MPI_Waitall( num_n, counting_requests.data() + num_n,
450 MPI_STATUSES_IGNORE );
453 if ( MPI_SUCCESS != ec )
454 throw std::logic_error(
"sparse_halo: counting sending failed." );
468 MPI_Comm comm, std::vector<int>& valid_sends,
469 std::vector<int>& valid_recvs,
470 const bool is_neighbor_counting_collected =
false )
const
477 for ( std::size_t nid = 0; nid < _neighbor_ranks.size(); ++nid )
480 auto h_counting = Kokkos::create_mirror_view_and_copy(
481 Kokkos::HostSpace(), _valid_counting[nid] );
482 auto h_neighbor_counting = Kokkos::create_mirror_view_and_copy(
483 Kokkos::HostSpace(), _neighbor_counting[nid] );
487 if ( !( h_counting( Index::ghost ) == 0 ||
488 h_neighbor_counting( Index::own ) == 0 ) )
490 valid_sends.push_back( nid );
495 if ( !( h_counting( Index::own ) == 0 ||
496 h_neighbor_counting( Index::ghost ) == 0 ) )
498 valid_recvs.push_back( nid );
513 MPI_Comm comm, std::vector<int>& valid_sends,
514 std::vector<int>& valid_recvs,
515 const bool is_neighbor_counting_collected =
false )
const
522 for ( std::size_t nid = 0; nid < _neighbor_ranks.size(); ++nid )
524 auto h_counting = Kokkos::create_mirror_view_and_copy(
525 Kokkos::HostSpace(), _valid_counting[nid] );
526 auto h_neighbor_counting = Kokkos::create_mirror_view_and_copy(
527 Kokkos::HostSpace(), _neighbor_counting[nid] );
531 if ( !( h_counting( Index::own ) == 0 ||
532 h_neighbor_counting( Index::ghost ) == 0 ) )
534 valid_sends.push_back( nid );
539 if ( !( h_counting( Index::ghost ) == 0 ||
540 h_neighbor_counting( Index::own ) == 0 ) )
542 valid_recvs.push_back( nid );
558 template <
class ExecSpace,
class SparseArrayType>
559 void gather(
const ExecSpace& exec_space, SparseArrayType& sparse_array,
560 const bool is_neighbor_counting_collected =
false )
const
563 if ( 0 == _neighbor_ranks.size() )
567 auto comm =
getComm( sparse_array );
569 const auto& map = sparse_array.layout().sparseMap();
573 std::vector<int> valid_sends;
574 std::vector<int> valid_recvs;
576 is_neighbor_counting_collected );
581 std::vector<MPI_Request> steering_requests(
582 valid_recvs.size() + valid_sends.size(), MPI_REQUEST_NULL );
583 const int mpi_tag_steering = 3214;
588 for ( std::size_t i = 0; i < valid_recvs.size(); ++i )
590 int nid = valid_recvs[i];
591 Kokkos::View<int[2], Kokkos::HostSpace> h_neighbor_counting(
592 "tmp_host_neighbor_counting" );
593 Kokkos::deep_copy( h_neighbor_counting, _neighbor_counting[nid] );
595 MPI_Irecv( _tmp_tile_steering[nid].data(),
596 h_neighbor_counting( Index::own ) *
sizeof(
key_type ),
597 MPI_BYTE, _neighbor_ranks[nid],
598 mpi_tag_steering + _receive_tags[nid], comm,
599 &steering_requests[i] );
604 for ( std::size_t i = 0; i < valid_sends.size(); ++i )
606 int nid = valid_sends[i];
607 Kokkos::View<int[2], Kokkos::HostSpace> h_counting(
608 "tmp_host_counting" );
609 Kokkos::deep_copy( h_counting, _valid_counting[nid] );
611 MPI_Isend( _owned_tile_steering[nid].data(),
612 h_counting( Index::own ) *
sizeof(
key_type ), MPI_BYTE,
613 _neighbor_ranks[nid], mpi_tag_steering + _send_tags[nid],
614 comm, &steering_requests[i + valid_recvs.size()] );
618 const int ec_ss = MPI_Waitall(
619 valid_sends.size(), steering_requests.data() + valid_recvs.size(),
620 MPI_STATUSES_IGNORE );
621 if ( MPI_SUCCESS != ec_ss )
622 throw std::logic_error(
623 "sparse_halo_gather: steering sending failed." );
630 std::vector<MPI_Request> requests(
631 valid_recvs.size() + valid_sends.size(), MPI_REQUEST_NULL );
632 const int mpi_tag = 2345;
635 for ( std::size_t i = 0; i < valid_recvs.size(); ++i )
637 int nid = valid_recvs[i];
638 Kokkos::View<int[2], Kokkos::HostSpace> h_neighbor_counting(
639 "tmp_host_neighbor_counting" );
641 Kokkos::deep_copy( h_neighbor_counting, _neighbor_counting[nid] );
643 MPI_Irecv( _ghosted_buffers[nid].data(),
646 MPI_BYTE, _neighbor_ranks[nid],
647 mpi_tag + _receive_tags[nid], comm, &requests[i] );
651 for ( std::size_t i = 0; i < valid_sends.size(); ++i )
653 int nid = valid_sends[i];
654 Kokkos::View<int[2], Kokkos::HostSpace> h_counting(
655 "tmp_host_counting" );
657 Kokkos::deep_copy( h_counting, _valid_counting[nid] );
660 _owned_tile_steering[nid], sparse_array,
661 h_counting( Index::own ) );
665 _owned_buffers[nid].data(),
667 MPI_BYTE, _neighbor_ranks[nid], mpi_tag + _send_tags[nid], comm,
668 &requests[i + valid_recvs.size()] );
672 for ( std::size_t i = 0; i < valid_recvs.size(); ++i )
675 int unpack_index = MPI_UNDEFINED;
676 MPI_Waitany( valid_recvs.size(), requests.data(), &unpack_index,
681 if ( MPI_UNDEFINED == unpack_index )
683 std::string(
"sparse_halo_gather: data receiving failed, "
685 std::to_string( i ) +
", need " +
686 std::to_string( valid_recvs.size() ) );
690 int nid = valid_recvs[unpack_index];
691 auto h_neighbor_counting = Kokkos::create_mirror_view_and_copy(
692 Kokkos::HostSpace(), _neighbor_counting[nid] );
694 _ghosted_buffers[nid], _tmp_tile_steering[nid],
696 h_neighbor_counting( Index::own ) );
702 const int ec_data = MPI_Waitall( valid_sends.size(),
703 requests.data() + valid_recvs.size(),
704 MPI_STATUSES_IGNORE );
705 if ( MPI_SUCCESS != ec_data )
706 throw std::logic_error(
707 "sparse_halo_gather: data sending failed." );
710 for ( std::size_t i = 0; i < _tmp_tile_steering.size(); ++i )
711 Kokkos::deep_copy( _tmp_tile_steering[i], invalid_key );
729 template <
class ExecSpace,
class ReduceOp,
class SparseArrayType>
730 void scatter(
const ExecSpace& exec_space,
const ReduceOp& reduce_op,
731 SparseArrayType& sparse_array,
732 const bool is_neighbor_counting_collected =
false )
const
735 if ( 0 == _neighbor_ranks.size() )
739 auto comm =
getComm( sparse_array );
741 const auto& map = sparse_array.layout().sparseMap();
745 std::vector<int> valid_sends;
746 std::vector<int> valid_recvs;
748 is_neighbor_counting_collected );
753 std::vector<MPI_Request> steering_requests(
754 valid_recvs.size() + valid_sends.size(), MPI_REQUEST_NULL );
755 const int mpi_tag_steering = 214;
760 for ( std::size_t i = 0; i < valid_recvs.size(); ++i )
762 int nid = valid_recvs[i];
763 Kokkos::View<int[2], Kokkos::HostSpace> h_neighbor_counting(
764 "tmp_host_neighbor_counting" );
766 Kokkos::deep_copy( h_neighbor_counting, _neighbor_counting[nid] );
768 MPI_Irecv( _tmp_tile_steering[nid].data(),
769 h_neighbor_counting( Index::ghost ) *
sizeof(
key_type ),
770 MPI_BYTE, _neighbor_ranks[nid],
771 mpi_tag_steering + _receive_tags[nid], comm,
772 &steering_requests[i] );
777 for ( std::size_t i = 0; i < valid_sends.size(); ++i )
779 int nid = valid_sends[i];
780 Kokkos::View<int[2], Kokkos::HostSpace> h_counting(
781 "tmp_host_counting" );
783 Kokkos::deep_copy( h_counting, _valid_counting[nid] );
785 MPI_Isend( _ghosted_tile_steering[nid].data(),
786 h_counting( Index::ghost ) *
sizeof(
key_type ),
787 MPI_BYTE, _neighbor_ranks[nid],
788 mpi_tag_steering + _send_tags[nid], comm,
789 &steering_requests[i + valid_recvs.size()] );
793 const int ec_ss = MPI_Waitall(
794 valid_sends.size(), steering_requests.data() + valid_recvs.size(),
795 MPI_STATUSES_IGNORE );
796 if ( MPI_SUCCESS != ec_ss )
797 throw std::logic_error(
798 "sparse_halo_scatter: steering sending failed." );
805 std::vector<MPI_Request> requests(
806 valid_recvs.size() + valid_sends.size(), MPI_REQUEST_NULL );
807 const int mpi_tag = 345;
810 for ( std::size_t i = 0; i < valid_recvs.size(); ++i )
812 int nid = valid_recvs[i];
813 Kokkos::View<int[2], Kokkos::HostSpace> h_neighbor_counting(
814 "tmp_host_neighbor_counting" );
816 Kokkos::deep_copy( h_neighbor_counting, _neighbor_counting[nid] );
818 MPI_Irecv( _owned_buffers[nid].data(),
821 MPI_BYTE, _neighbor_ranks[nid],
822 mpi_tag + _receive_tags[nid], comm, &requests[i] );
826 for ( std::size_t i = 0; i < valid_sends.size(); ++i )
828 int nid = valid_sends[i];
829 Kokkos::View<int[2], Kokkos::HostSpace> h_counting(
830 "tmp_host_counting" );
832 Kokkos::deep_copy( h_counting, _valid_counting[nid] );
833 packBuffer( exec_space, _ghosted_buffers[nid],
834 _ghosted_tile_steering[nid], sparse_array,
835 h_counting( Index::ghost ) );
838 MPI_Isend( _ghosted_buffers[nid].data(),
841 MPI_BYTE, _neighbor_ranks[nid],
842 mpi_tag + _send_tags[nid], comm,
843 &requests[i + valid_recvs.size()] );
847 for ( std::size_t i = 0; i < valid_recvs.size(); ++i )
850 int unpack_index = MPI_UNDEFINED;
851 MPI_Waitany( valid_recvs.size(), requests.data(), &unpack_index,
856 if ( MPI_UNDEFINED == unpack_index )
858 std::string(
"sparse_halo_scatter: data receiving failed, "
860 std::to_string( i ) +
", need " +
861 std::to_string( valid_recvs.size() ) );
865 int nid = valid_recvs[unpack_index];
866 auto h_neighbor_counting = Kokkos::create_mirror_view_and_copy(
867 Kokkos::HostSpace(), _neighbor_counting[nid] );
868 unpackBuffer( reduce_op, exec_space, _owned_buffers[nid],
869 _tmp_tile_steering[nid], sparse_array, map,
870 h_neighbor_counting( Index::ghost ) );
876 const int ec_data = MPI_Waitall( valid_sends.size(),
877 requests.data() + valid_recvs.size(),
878 MPI_STATUSES_IGNORE );
879 if ( MPI_SUCCESS != ec_data )
880 throw std::logic_error(
881 "sparse_halo_scatter: data sending failed." );
884 for ( std::size_t i = 0; i < _tmp_tile_steering.size(); ++i )
885 Kokkos::deep_copy( _tmp_tile_steering[i], invalid_key );
900 template <
class ExecSpace,
class SparseArrayType>
903 SparseArrayType& sparse_array,
const int count )
const
905 Kokkos::parallel_for(
906 "pack_spares_halo_buffer",
907 Kokkos::RangePolicy<ExecSpace>( exec_space, 0, count ),
908 KOKKOS_LAMBDA(
const int i ) {
909 if ( tile_steering( i ) != invalid_key )
912 auto tile_key = tile_steering( i );
915 buffer( buffer_idx + lcid ) =
916 sparse_array.getTuple( tile_key, lcid );
925 KOKKOS_INLINE_FUNCTION
static void
928 array_val += buffer_val;
933 KOKKOS_INLINE_FUNCTION
static void
936 if ( buffer_val < array_val )
937 array_val = buffer_val;
942 KOKKOS_INLINE_FUNCTION
static void
945 if ( buffer_val > array_val )
946 array_val = buffer_val;
951 KOKKOS_INLINE_FUNCTION
static void
954 array_val = buffer_val;
971 template <
class ReduceOp, std::
size_t N, std::
size_t M,
class SoAType>
972 KOKKOS_FORCEINLINE_FUNCTION
static std::enable_if_t<3 == M, void>
974 SoAType& dst_soa,
const int soa_idx,
975 const Kokkos::Array<std::size_t, M>& extents,
976 const std::integral_constant<std::size_t, N>,
977 const std::integral_constant<std::size_t, M> )
979 for ( std::size_t d0 = 0; d0 < extents[0]; ++d0 )
980 for (
int d1 = 0; d1 < extents[1]; ++d1 )
981 for (
int d2 = 0; d2 < extents[2]; ++d2 )
1002 template <
class ReduceOp, std::
size_t N, std::
size_t M,
class SoAType>
1003 KOKKOS_FORCEINLINE_FUNCTION
static std::enable_if_t<2 == M, void>
1005 SoAType& dst_soa,
const int soa_idx,
1006 const Kokkos::Array<std::size_t, M>& extents,
1007 const std::integral_constant<std::size_t, N>,
1008 const std::integral_constant<std::size_t, M> )
1010 for ( std::size_t d0 = 0; d0 < extents[0]; ++d0 )
1011 for (
int d1 = 0; d1 < extents[1]; ++d1 )
1031 template <
class ReduceOp, std::
size_t N, std::
size_t M,
class SoAType>
1032 KOKKOS_FORCEINLINE_FUNCTION
static std::enable_if_t<1 == M, void>
1034 SoAType& dst_soa,
const int soa_idx,
1035 const Kokkos::Array<std::size_t, M>& extents,
1036 const std::integral_constant<std::size_t, N>,
1037 const std::integral_constant<std::size_t, M> )
1039 for ( std::size_t d0 = 0; d0 < extents[0]; ++d0 )
1058 template <
class ReduceOp, std::
size_t N, std::
size_t M,
class SoAType>
1059 KOKKOS_FORCEINLINE_FUNCTION
static std::enable_if_t<0 == M, void>
1061 SoAType& dst_soa,
const int soa_idx,
1062 const Kokkos::Array<std::size_t, M>&,
1063 const std::integral_constant<std::size_t, N>,
1064 const std::integral_constant<std::size_t, M> )
1079 template <
class ReduceOp,
class SoAType>
1080 KOKKOS_FORCEINLINE_FUNCTION
static void
1082 SoAType& dst_soa,
const int soa_idx,
1083 const std::integral_constant<std::size_t, 0> )
1086 auto extents = compute_member_extents<current_type>();
1088 reduce_op, src_tuple, dst_soa, soa_idx, extents,
1089 std::integral_constant<std::size_t, 0>(),
1090 std::integral_constant<std::size_t,
1091 std::rank<current_type>::value>() );
1104 template <
class ReduceOp, std::
size_t N,
class SoAType>
1105 KOKKOS_FORCEINLINE_FUNCTION
static void
1107 SoAType& dst_soa,
const int soa_idx,
1108 const std::integral_constant<std::size_t, N> )
1111 auto extents = compute_member_extents<current_type>();
1113 reduce_op, src_tuple, dst_soa, soa_idx, extents,
1114 std::integral_constant<std::size_t, N>(),
1115 std::integral_constant<std::size_t,
1116 std::rank<current_type>::value>() );
1121 unpackTuple( reduce_op, src_tuple, dst_soa, soa_idx,
1122 std::integral_constant<std::size_t, N - 1>() );
1126 unpackTuple( reduce_op, src_tuple, dst_soa, soa_idx,
1127 std::integral_constant<std::size_t, 0>() );
1145 template <
class ReduceOp,
class ExecSpace,
class SparseArrayType,
1146 class SparseMapType>
1150 const SparseArrayType& sparse_array, SparseMapType& map,
1151 const int count )
const
1153 Kokkos::parallel_for(
1154 "unpack_spares_halo_buffer",
1155 Kokkos::RangePolicy<ExecSpace>( exec_space, 0, count ),
1156 KOKKOS_LAMBDA(
const int i ) {
1157 if ( tile_steering( i ) != invalid_key )
1159 auto tile_key = tile_steering( i );
1160 if ( map.isValidKey( tile_key ) )
1163 map.key2ijk( tile_key, ti, tj, tk );
1165 auto tile_id = map.queryTileFromTileKey( tile_key );
1170 auto& tuple = buffer( buffer_idx + lcid );
1172 sparse_array.accessTile( tile_id );
1174 reduce_op, tuple, data_access, lcid,
1175 std::integral_constant<std::size_t,
1186 template <std::
size_t M>
1187 static constexpr std::size_t compute_member_size()
1192 template <
typename Sequence>
1193 struct compute_member_size_list_impl;
1195 template <std::size_t... Is>
1196 struct compute_member_size_list_impl<std::index_sequence<Is...>>
1198 std::array<std::size_t, member_num> operator()()
1200 return { compute_member_size<Is>()... };
1205 typename Indices = std::make_index_sequence<N>>
1206 std::array<std::size_t, member_num> compute_member_size_list()
1208 compute_member_size_list_impl<Indices> op;
1213 template <
typename Type, std::
size_t M>
1214 KOKKOS_FORCEINLINE_FUNCTION
static constexpr std::size_t
1215 compute_one_member_extent()
1217 return std::extent<Type, M>::value;
1220 template <
class Type, std::
size_t M,
typename Sequence>
1221 struct compute_member_extents_impl;
1223 template <
class Type, std::size_t M, std::size_t... Is>
1224 struct compute_member_extents_impl<Type, M, std::index_sequence<Is...>>
1226 KOKKOS_FORCEINLINE_FUNCTION
1227 Kokkos::Array<std::size_t, M> operator()()
1229 return { compute_one_member_extent<Type, Is>()... };
1233 template <class Type, std::size_t M = std::rank<Type>::value,
1234 typename Indices = std::make_index_sequence<M>>
1235 KOKKOS_FORCEINLINE_FUNCTION
static Kokkos::Array<std::size_t, M>
1236 compute_member_extents()
1238 compute_member_extents_impl<Type, M, Indices> op;
1249 std::vector<int> _neighbor_ranks;
1251 std::vector<std::array<int, num_space_dim>> _valid_neighbor_ids;
1253 std::vector<int> _send_tags;
1255 std::vector<int> _receive_tags;
1258 std::vector<buffer_view> _owned_buffers;
1260 std::vector<buffer_view> _ghosted_buffers;
1263 std::vector<steering_view> _owned_tile_steering;
1265 std::vector<steering_view> _tmp_tile_steering;
1267 std::vector<steering_view> _ghosted_tile_steering;
1270 std::vector<counting_view> _valid_counting;
1272 std::vector<counting_view> _neighbor_counting;
1275 std::vector<tile_index_space> _owned_tile_spaces;
1277 std::vector<tile_index_space> _ghosted_tile_spaces;
1280 Kokkos::Array<std::size_t, member_num> _soa_member_bytes;
1282 std::size_t _soa_total_bytes;
1293template <
class MemorySpace,
unsigned long long cellBitsPerTileDim,
1294 class DataTypes,
class EntityType,
class MeshType,
1295 class SparseMapType,
class Pattern,
typename Value = int,
1296 typename Key = uint64_t>
1297auto createSparseHalo(
1298 const Pattern& pattern,
1299 const std::shared_ptr<
SparseArray<DataTypes, MemorySpace, EntityType,
1300 MeshType, SparseMapType>>
1303 using array_type =
SparseArray<DataTypes, MemorySpace, EntityType, MeshType,
1305 using memory_space =
typename array_type::memory_space;
1306 static constexpr std::size_t num_space_dim = array_type::num_space_dim;
1307 return std::make_shared<
1308 SparseHalo<memory_space, DataTypes, EntityType, num_space_dim,
1309 cellBitsPerTileDim, Value, Key>>( pattern, array );
Multi-node grid scatter/gather.
Sparse grid fields arrays using AoSoA.
AoSoA tuple member types.
Struct-of-Arrays for building AoSoA.
Tuple of single particle information to build AoSoA.
Sparse array of field data on the local sparse mesh; Array data is stored in AoSoA manner,...
Definition Cabana_Grid_SparseArray.hpp:316
Definition Cabana_Grid_SparseHalo.hpp:52
static KOKKOS_INLINE_FUNCTION void unpackOp(ScatterReduce::Min, const T &buffer_val, T &array_val)
Reduce an element into the buffer. Min reduction.
Definition Cabana_Grid_SparseHalo.hpp:934
void gather(const ExecSpace &exec_space, SparseArrayType &sparse_array, const bool is_neighbor_counting_collected=false) const
Gather data into our ghosted share space from their owners.
Definition Cabana_Grid_SparseHalo.hpp:559
DataTypes aosoa_member_types
data members in AoSoA structure
Definition Cabana_Grid_SparseHalo.hpp:76
static KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t< 2==M, void > unpackTupleMember(const ReduceOp &reduce_op, const tuple_type &src_tuple, SoAType &dst_soa, const int soa_idx, const Kokkos::Array< std::size_t, M > &extents, const std::integral_constant< std::size_t, N >, const std::integral_constant< std::size_t, M >)
Unpack a sparse arrays element (a tuple) in a buffer (for case tuple members with rank == 2)
Definition Cabana_Grid_SparseHalo.hpp:1004
Kokkos::View< key_type *, memory_space > steering_view
Definition Cabana_Grid_SparseHalo.hpp:97
void register_halo(SparseMapType &map)
register valid halos (according to grid activation status in sparse map) in the steerings
Definition Cabana_Grid_SparseHalo.hpp:333
Index
index (own or ghost)
Definition Cabana_Grid_SparseHalo.hpp:103
typename Cabana::MemberTypeAtIndex< M, aosoa_member_types >::type member_data_type
AoSoA member data type.
Definition Cabana_Grid_SparseHalo.hpp:82
static KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t< 3==M, void > unpackTupleMember(const ReduceOp &reduce_op, const tuple_type &src_tuple, SoAType &dst_soa, const int soa_idx, const Kokkos::Array< std::size_t, M > &extents, const std::integral_constant< std::size_t, N >, const std::integral_constant< std::size_t, M >)
Unpack a sparse arrays element (a tuple) in a buffer (for case tuple members with rank == 3)
Definition Cabana_Grid_SparseHalo.hpp:973
static KOKKOS_INLINE_FUNCTION void unpackOp(ScatterReduce::Replace, const T &buffer_val, T &array_val)
Reduce an element into the buffer. Replace reduction.
Definition Cabana_Grid_SparseHalo.hpp:952
static KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t< 0==M, void > unpackTupleMember(const ReduceOp &reduce_op, const tuple_type &src_tuple, SoAType &dst_soa, const int soa_idx, const Kokkos::Array< std::size_t, M > &, const std::integral_constant< std::size_t, N >, const std::integral_constant< std::size_t, M >)
Unpack a sparse arrays element (a tuple) in a buffer (for case tuple members with rank == 0)
Definition Cabana_Grid_SparseHalo.hpp:1060
void updateTileSpace(const std::shared_ptr< LocalGridType > &local_grid)
update tile index space according to current partition
Definition Cabana_Grid_SparseHalo.hpp:259
void scatter(const ExecSpace &exec_space, const ReduceOp &reduce_op, SparseArrayType &sparse_array, const bool is_neighbor_counting_collected=false) const
Scatter data from our ghosts to their owners using the given type of reduce operation.
Definition Cabana_Grid_SparseHalo.hpp:730
void gatherValidSendAndRecvRanks(MPI_Comm comm, std::vector< int > &valid_sends, std::vector< int > &valid_recvs, const bool is_neighbor_counting_collected=false) const
collect all valid ranks for sparse grid gather operations
Definition Cabana_Grid_SparseHalo.hpp:512
static constexpr std::size_t member_num
AoSoA member #.
Definition Cabana_Grid_SparseHalo.hpp:85
EntityType entity_type
entity type on sparse grid
Definition Cabana_Grid_SparseHalo.hpp:60
SparseHalo(const halo_pattern_type pattern, const std::shared_ptr< SparseArrayType > &sparse_array)
constructor
Definition Cabana_Grid_SparseHalo.hpp:122
KeyValue
invalid key in sparse map
Definition Cabana_Grid_SparseHalo.hpp:71
Key key_type
key type in sparse map
Definition Cabana_Grid_SparseHalo.hpp:68
static KOKKOS_FORCEINLINE_FUNCTION void unpackTuple(const ReduceOp &reduce_op, const tuple_type &src_tuple, SoAType &dst_soa, const int soa_idx, const std::integral_constant< std::size_t, 0 >)
Unpack a sparse arrays tuple for it's member with index 0.
Definition Cabana_Grid_SparseHalo.hpp:1081
NodeHaloPattern< NumSpaceDim > halo_pattern_type
sparse grid halo pattern (TODO currently reusing Halo's Node pattern)
Definition Cabana_Grid_SparseHalo.hpp:63
static KOKKOS_INLINE_FUNCTION void unpackOp(ScatterReduce::Sum, const T &buffer_val, T &array_val)
Reduce an element into the buffer. Sum reduction.
Definition Cabana_Grid_SparseHalo.hpp:926
MPI_Comm getComm(const SparseArrayType sparse_array) const
Get the communicator.
Definition Cabana_Grid_SparseHalo.hpp:211
void clear(MPI_Comm comm)
clear guiding information in sparse halo,
Definition Cabana_Grid_SparseHalo.hpp:387
void packBuffer(const ExecSpace &exec_space, const buffer_view &buffer, const steering_view &tile_steering, SparseArrayType &sparse_array, const int count) const
Pack sparse arrays at halo regions into a buffer.
Definition Cabana_Grid_SparseHalo.hpp:901
Kokkos::View< int[2], memory_space, Kokkos::MemoryTraits< Kokkos::Atomic > > counting_view
Definition Cabana_Grid_SparseHalo.hpp:111
Value value_type
value type of entities on sparse grid
Definition Cabana_Grid_SparseHalo.hpp:66
void collectNeighborCounting(MPI_Comm comm, const bool is_neighbor_counting_collected=false) const
neighbor tile counting, communication needed only if the counting is non-zero
Definition Cabana_Grid_SparseHalo.hpp:414
void scatterValidSendAndRecvRanks(MPI_Comm comm, std::vector< int > &valid_sends, std::vector< int > &valid_recvs, const bool is_neighbor_counting_collected=false) const
collect all valid ranks for sparse grid scatter operations
Definition Cabana_Grid_SparseHalo.hpp:467
static constexpr std::size_t num_space_dim
sparse array dimension number
Definition Cabana_Grid_SparseHalo.hpp:55
void unpackBuffer(const ReduceOp &reduce_op, const ExecSpace &exec_space, const buffer_view &buffer, const steering_view &tile_steering, const SparseArrayType &sparse_array, SparseMapType &map, const int count) const
Unpack a sparse array communication buffer.
Definition Cabana_Grid_SparseHalo.hpp:1147
void buildCommData(DecompositionTag decomposition_tag, const std::shared_ptr< LocalGridType > &local_grid, const std::array< int, num_space_dim > &nid, std::vector< buffer_view > &buffers, std::vector< steering_view > &steering, std::vector< tile_index_space > &spaces)
Build communication data.
Definition Cabana_Grid_SparseHalo.hpp:228
Cabana::Tuple< aosoa_member_types > tuple_type
AoSoA tuple type.
Definition Cabana_Grid_SparseHalo.hpp:78
Kokkos::View< tuple_type *, memory_space > buffer_view
communication data buffer view type
Definition Cabana_Grid_SparseHalo.hpp:94
static KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t< 1==M, void > unpackTupleMember(const ReduceOp &reduce_op, const tuple_type &src_tuple, SoAType &dst_soa, const int soa_idx, const Kokkos::Array< std::size_t, M > &extents, const std::integral_constant< std::size_t, N >, const std::integral_constant< std::size_t, M >)
Unpack a sparse arrays element (a tuple) in a buffer (for case tuple members with rank == 1)
Definition Cabana_Grid_SparseHalo.hpp:1033
static KOKKOS_FORCEINLINE_FUNCTION void unpackTuple(const ReduceOp &reduce_op, const tuple_type &src_tuple, SoAType &dst_soa, const int soa_idx, const std::integral_constant< std::size_t, N >)
Unpack a sparse arrays tuple for all members when element ID!=0.
Definition Cabana_Grid_SparseHalo.hpp:1106
TileIndexSpace< num_space_dim, cell_bits_per_tile_dim > tile_index_space
tile index space type TODO
Definition Cabana_Grid_SparseHalo.hpp:99
MemorySpace memory_space
memory space to store the sparse grid
Definition Cabana_Grid_SparseHalo.hpp:58
static KOKKOS_INLINE_FUNCTION void unpackOp(ScatterReduce::Max, const T &buffer_val, T &array_val)
Reduce an element into the buffer. Max reduction.
Definition Cabana_Grid_SparseHalo.hpp:943
static constexpr unsigned long long cell_num_per_tile
sparse grid hierarchy: cell # per dimension
Definition Cabana_Grid_SparseHalo.hpp:90
static constexpr unsigned long long cell_bits_per_tile_dim
sparse grid hierarchy: cell id bit# per dimension
Definition Cabana_Grid_SparseHalo.hpp:87
Definition Cabana_Grid_Halo.hpp:76
Index space with tile as unit; _min and _max forms the tile range. Note this is for sparse grid only,...
Definition Cabana_Grid_SparseIndexSpace.hpp:1137
Core: particle data structures and algorithms.
Definition Cabana_AoSoA.hpp:36
KOKKOS_FORCEINLINE_FUNCTION std::enable_if< is_parameter_pack< ParameterPack_t >::value, typenameParameterPack_t::templatevalue_type< N > & >::type get(ParameterPack_t &pp)
Get an element from a parameter pack.
Definition Cabana_ParameterPack.hpp:129
Ghosted decomposition tag.
Definition Cabana_Grid_Types.hpp:197
Owned decomposition tag.
Definition Cabana_Grid_Types.hpp:190
Definition Cabana_Grid_Halo.hpp:173
Definition Cabana_Grid_Halo.hpp:167
Definition Cabana_Grid_Halo.hpp:181
Sum values from neighboring ranks into this rank's data.
Definition Cabana_Grid_Halo.hpp:161
Get the type of the member at a given index.
Definition Cabana_MemberTypes.hpp:75
Definition Cabana_Tuple.hpp:32