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 );
320 "Cabana::Grid::Experimental::SparseHalo::updateTileSpace: "
321 "Neighbor rank doesn't match id" );
334 template <
class ExecSpace,
class SparseMapType>
338 int num_n = _neighbor_ranks.size();
343 for (
int nid = 0; nid < num_n; nid++ )
345 auto& owned_space = _owned_tile_spaces[nid];
346 auto& owned_steering = _owned_tile_steering[nid];
348 auto& ghosted_space = _ghosted_tile_spaces[nid];
349 auto& ghosted_steering = _ghosted_tile_steering[nid];
351 auto& counting = _valid_counting[nid];
357 Kokkos::parallel_for(
358 Kokkos::RangePolicy<ExecSpace>( 0, map.capacity() ),
359 KOKKOS_LAMBDA(
const int index ) {
360 if ( map.valid_at( index ) )
362 auto tile_key = map.key_at( index );
364 map.key2ijk( tile_key, ti, tj, tk );
365 if ( owned_space.tileInRange( ti, tj, tk ) )
367 owned_steering( counting( Index::own )++ ) =
370 else if ( ghosted_space.tileInRange( ti, tj, tk ) )
372 ghosted_steering( counting( Index::ghost )++ ) =
392 for ( std::size_t i = 0; i < _valid_counting.size(); ++i )
393 Kokkos::deep_copy( _valid_counting[i], 0 );
394 for ( std::size_t i = 0; i < _neighbor_counting.size(); ++i )
395 Kokkos::deep_copy( _neighbor_counting[i], 0 );
397 for ( std::size_t i = 0; i < _owned_tile_steering.size(); ++i )
398 Kokkos::deep_copy( _owned_tile_steering[i], invalid_key );
399 for ( std::size_t i = 0; i < _ghosted_tile_steering.size(); ++i )
400 Kokkos::deep_copy( _ghosted_tile_steering[i], invalid_key );
401 for ( std::size_t i = 0; i < _tmp_tile_steering.size(); ++i )
402 Kokkos::deep_copy( _tmp_tile_steering[i], invalid_key );
417 MPI_Comm comm,
const bool is_neighbor_counting_collected =
false )
const
420 if ( is_neighbor_counting_collected )
424 int num_n = _neighbor_ranks.size();
428 std::vector<MPI_Request> counting_requests( 2 * num_n,
430 const int mpi_tag_counting = 1234;
433 for (
int nid = 0; nid < num_n; ++nid )
435 MPI_Irecv( _neighbor_counting[nid].data(),
436 Index::total *
sizeof(
int ), MPI_BYTE,
437 _neighbor_ranks[nid],
438 mpi_tag_counting + _receive_tags[nid], comm,
439 &counting_requests[nid] );
442 for (
int nid = 0; nid < num_n; ++nid )
444 MPI_Isend( _valid_counting[nid].data(),
445 Index::total *
sizeof(
int ), MPI_BYTE,
446 _neighbor_ranks[nid], mpi_tag_counting + _send_tags[nid],
447 comm, &counting_requests[nid + num_n] );
451 const int ec = MPI_Waitall( num_n, counting_requests.data() + num_n,
452 MPI_STATUSES_IGNORE );
455 if ( MPI_SUCCESS != ec )
456 throw std::logic_error(
457 "Cabana::Grid::Experimental::SparseHalo::"
458 "collectNeighborCounting: counting sending failed." );
472 MPI_Comm comm, std::vector<int>& valid_sends,
473 std::vector<int>& valid_recvs,
474 const bool is_neighbor_counting_collected =
false )
const
481 for ( std::size_t nid = 0; nid < _neighbor_ranks.size(); ++nid )
484 auto h_counting = Kokkos::create_mirror_view_and_copy(
485 Kokkos::HostSpace(), _valid_counting[nid] );
486 auto h_neighbor_counting = Kokkos::create_mirror_view_and_copy(
487 Kokkos::HostSpace(), _neighbor_counting[nid] );
491 if ( !( h_counting( Index::ghost ) == 0 ||
492 h_neighbor_counting( Index::own ) == 0 ) )
494 valid_sends.push_back( nid );
499 if ( !( h_counting( Index::own ) == 0 ||
500 h_neighbor_counting( Index::ghost ) == 0 ) )
502 valid_recvs.push_back( nid );
517 MPI_Comm comm, std::vector<int>& valid_sends,
518 std::vector<int>& valid_recvs,
519 const bool is_neighbor_counting_collected =
false )
const
526 for ( std::size_t nid = 0; nid < _neighbor_ranks.size(); ++nid )
528 auto h_counting = Kokkos::create_mirror_view_and_copy(
529 Kokkos::HostSpace(), _valid_counting[nid] );
530 auto h_neighbor_counting = Kokkos::create_mirror_view_and_copy(
531 Kokkos::HostSpace(), _neighbor_counting[nid] );
535 if ( !( h_counting( Index::own ) == 0 ||
536 h_neighbor_counting( Index::ghost ) == 0 ) )
538 valid_sends.push_back( nid );
543 if ( !( h_counting( Index::ghost ) == 0 ||
544 h_neighbor_counting( Index::own ) == 0 ) )
546 valid_recvs.push_back( nid );
562 template <
class ExecSpace,
class SparseArrayType>
563 void gather(
const ExecSpace& exec_space, SparseArrayType& sparse_array,
564 const bool is_neighbor_counting_collected =
false )
const
567 if ( 0 == _neighbor_ranks.size() )
571 auto comm =
getComm( sparse_array );
573 const auto& map = sparse_array.layout().sparseMap();
577 std::vector<int> valid_sends;
578 std::vector<int> valid_recvs;
580 is_neighbor_counting_collected );
585 std::vector<MPI_Request> steering_requests(
586 valid_recvs.size() + valid_sends.size(), MPI_REQUEST_NULL );
587 const int mpi_tag_steering = 3214;
592 for ( std::size_t i = 0; i < valid_recvs.size(); ++i )
594 int nid = valid_recvs[i];
595 Kokkos::View<int[2], Kokkos::HostSpace> h_neighbor_counting(
596 "tmp_host_neighbor_counting" );
597 Kokkos::deep_copy( h_neighbor_counting, _neighbor_counting[nid] );
599 MPI_Irecv( _tmp_tile_steering[nid].data(),
600 h_neighbor_counting( Index::own ) *
sizeof(
key_type ),
601 MPI_BYTE, _neighbor_ranks[nid],
602 mpi_tag_steering + _receive_tags[nid], comm,
603 &steering_requests[i] );
608 for ( std::size_t i = 0; i < valid_sends.size(); ++i )
610 int nid = valid_sends[i];
611 Kokkos::View<int[2], Kokkos::HostSpace> h_counting(
612 "tmp_host_counting" );
613 Kokkos::deep_copy( h_counting, _valid_counting[nid] );
615 MPI_Isend( _owned_tile_steering[nid].data(),
616 h_counting( Index::own ) *
sizeof(
key_type ), MPI_BYTE,
617 _neighbor_ranks[nid], mpi_tag_steering + _send_tags[nid],
618 comm, &steering_requests[i + valid_recvs.size()] );
622 const int ec_ss = MPI_Waitall(
623 valid_sends.size(), steering_requests.data() + valid_recvs.size(),
624 MPI_STATUSES_IGNORE );
625 if ( MPI_SUCCESS != ec_ss )
626 throw std::logic_error(
"Cabana::Grid::Experimental::SparseHalo::"
627 "gather: steering sending failed." );
634 std::vector<MPI_Request> requests(
635 valid_recvs.size() + valid_sends.size(), MPI_REQUEST_NULL );
636 const int mpi_tag = 2345;
639 for ( std::size_t i = 0; i < valid_recvs.size(); ++i )
641 int nid = valid_recvs[i];
642 Kokkos::View<int[2], Kokkos::HostSpace> h_neighbor_counting(
643 "tmp_host_neighbor_counting" );
645 Kokkos::deep_copy( h_neighbor_counting, _neighbor_counting[nid] );
647 MPI_Irecv( _ghosted_buffers[nid].data(),
650 MPI_BYTE, _neighbor_ranks[nid],
651 mpi_tag + _receive_tags[nid], comm, &requests[i] );
655 for ( std::size_t i = 0; i < valid_sends.size(); ++i )
657 int nid = valid_sends[i];
658 Kokkos::View<int[2], Kokkos::HostSpace> h_counting(
659 "tmp_host_counting" );
661 Kokkos::deep_copy( h_counting, _valid_counting[nid] );
664 _owned_tile_steering[nid], sparse_array,
665 h_counting( Index::own ) );
669 _owned_buffers[nid].data(),
671 MPI_BYTE, _neighbor_ranks[nid], mpi_tag + _send_tags[nid], comm,
672 &requests[i + valid_recvs.size()] );
676 for ( std::size_t i = 0; i < valid_recvs.size(); ++i )
679 int unpack_index = MPI_UNDEFINED;
680 MPI_Waitany( valid_recvs.size(), requests.data(), &unpack_index,
685 if ( MPI_UNDEFINED == unpack_index )
687 std::string(
"Cabana::Grid::Experimental::SparseHalo::"
688 "gather: data receiving failed, "
690 std::to_string( i ) +
", need " +
691 std::to_string( valid_recvs.size() ) );
695 int nid = valid_recvs[unpack_index];
696 auto h_neighbor_counting = Kokkos::create_mirror_view_and_copy(
697 Kokkos::HostSpace(), _neighbor_counting[nid] );
699 _ghosted_buffers[nid], _tmp_tile_steering[nid],
701 h_neighbor_counting( Index::own ) );
707 const int ec_data = MPI_Waitall( valid_sends.size(),
708 requests.data() + valid_recvs.size(),
709 MPI_STATUSES_IGNORE );
710 if ( MPI_SUCCESS != ec_data )
711 throw std::logic_error(
712 "sparse_halo_gather: data sending failed." );
715 for ( std::size_t i = 0; i < _tmp_tile_steering.size(); ++i )
716 Kokkos::deep_copy( _tmp_tile_steering[i], invalid_key );
734 template <
class ExecSpace,
class ReduceOp,
class SparseArrayType>
735 void scatter(
const ExecSpace& exec_space,
const ReduceOp& reduce_op,
736 SparseArrayType& sparse_array,
737 const bool is_neighbor_counting_collected =
false )
const
740 if ( 0 == _neighbor_ranks.size() )
744 auto comm =
getComm( sparse_array );
746 const auto& map = sparse_array.layout().sparseMap();
750 std::vector<int> valid_sends;
751 std::vector<int> valid_recvs;
753 is_neighbor_counting_collected );
758 std::vector<MPI_Request> steering_requests(
759 valid_recvs.size() + valid_sends.size(), MPI_REQUEST_NULL );
760 const int mpi_tag_steering = 214;
765 for ( std::size_t i = 0; i < valid_recvs.size(); ++i )
767 int nid = valid_recvs[i];
768 Kokkos::View<int[2], Kokkos::HostSpace> h_neighbor_counting(
769 "tmp_host_neighbor_counting" );
771 Kokkos::deep_copy( h_neighbor_counting, _neighbor_counting[nid] );
773 MPI_Irecv( _tmp_tile_steering[nid].data(),
774 h_neighbor_counting( Index::ghost ) *
sizeof(
key_type ),
775 MPI_BYTE, _neighbor_ranks[nid],
776 mpi_tag_steering + _receive_tags[nid], comm,
777 &steering_requests[i] );
782 for ( std::size_t i = 0; i < valid_sends.size(); ++i )
784 int nid = valid_sends[i];
785 Kokkos::View<int[2], Kokkos::HostSpace> h_counting(
786 "tmp_host_counting" );
788 Kokkos::deep_copy( h_counting, _valid_counting[nid] );
790 MPI_Isend( _ghosted_tile_steering[nid].data(),
791 h_counting( Index::ghost ) *
sizeof(
key_type ),
792 MPI_BYTE, _neighbor_ranks[nid],
793 mpi_tag_steering + _send_tags[nid], comm,
794 &steering_requests[i + valid_recvs.size()] );
798 const int ec_ss = MPI_Waitall(
799 valid_sends.size(), steering_requests.data() + valid_recvs.size(),
800 MPI_STATUSES_IGNORE );
801 if ( MPI_SUCCESS != ec_ss )
802 throw std::logic_error(
"Cabana::Grid::Experimental::SparseHalo::"
803 "scatter: steering sending failed." );
810 std::vector<MPI_Request> requests(
811 valid_recvs.size() + valid_sends.size(), MPI_REQUEST_NULL );
812 const int mpi_tag = 345;
815 for ( std::size_t i = 0; i < valid_recvs.size(); ++i )
817 int nid = valid_recvs[i];
818 Kokkos::View<int[2], Kokkos::HostSpace> h_neighbor_counting(
819 "tmp_host_neighbor_counting" );
821 Kokkos::deep_copy( h_neighbor_counting, _neighbor_counting[nid] );
823 MPI_Irecv( _owned_buffers[nid].data(),
826 MPI_BYTE, _neighbor_ranks[nid],
827 mpi_tag + _receive_tags[nid], comm, &requests[i] );
831 for ( std::size_t i = 0; i < valid_sends.size(); ++i )
833 int nid = valid_sends[i];
834 Kokkos::View<int[2], Kokkos::HostSpace> h_counting(
835 "tmp_host_counting" );
837 Kokkos::deep_copy( h_counting, _valid_counting[nid] );
838 packBuffer( exec_space, _ghosted_buffers[nid],
839 _ghosted_tile_steering[nid], sparse_array,
840 h_counting( Index::ghost ) );
843 MPI_Isend( _ghosted_buffers[nid].data(),
846 MPI_BYTE, _neighbor_ranks[nid],
847 mpi_tag + _send_tags[nid], comm,
848 &requests[i + valid_recvs.size()] );
852 for ( std::size_t i = 0; i < valid_recvs.size(); ++i )
855 int unpack_index = MPI_UNDEFINED;
856 MPI_Waitany( valid_recvs.size(), requests.data(), &unpack_index,
861 if ( MPI_UNDEFINED == unpack_index )
863 std::string(
"sparse_halo_scatter: data receiving failed, "
865 std::to_string( i ) +
", need " +
866 std::to_string( valid_recvs.size() ) );
870 int nid = valid_recvs[unpack_index];
871 auto h_neighbor_counting = Kokkos::create_mirror_view_and_copy(
872 Kokkos::HostSpace(), _neighbor_counting[nid] );
873 unpackBuffer( reduce_op, exec_space, _owned_buffers[nid],
874 _tmp_tile_steering[nid], sparse_array, map,
875 h_neighbor_counting( Index::ghost ) );
881 const int ec_data = MPI_Waitall( valid_sends.size(),
882 requests.data() + valid_recvs.size(),
883 MPI_STATUSES_IGNORE );
884 if ( MPI_SUCCESS != ec_data )
885 throw std::logic_error(
"Cabana::Grid::Experimental::SparseHalo::"
886 "scatter: data sending failed." );
889 for ( std::size_t i = 0; i < _tmp_tile_steering.size(); ++i )
890 Kokkos::deep_copy( _tmp_tile_steering[i], invalid_key );
905 template <
class ExecSpace,
class SparseArrayType>
908 SparseArrayType& sparse_array,
const int count )
const
910 Kokkos::parallel_for(
911 "Cabana::Grid::Experimental::SparseHalo::packBuffer",
912 Kokkos::RangePolicy<ExecSpace>( exec_space, 0, count ),
913 KOKKOS_LAMBDA(
const int i ) {
914 if ( tile_steering( i ) != invalid_key )
917 auto tile_key = tile_steering( i );
920 buffer( buffer_idx + lcid ) =
921 sparse_array.getTuple( tile_key, lcid );
930 KOKKOS_INLINE_FUNCTION
static void
933 array_val += buffer_val;
938 KOKKOS_INLINE_FUNCTION
static void
941 if ( buffer_val < array_val )
942 array_val = buffer_val;
947 KOKKOS_INLINE_FUNCTION
static void
950 if ( buffer_val > array_val )
951 array_val = buffer_val;
956 KOKKOS_INLINE_FUNCTION
static void
959 array_val = buffer_val;
976 template <
class ReduceOp, std::
size_t N, std::
size_t M,
class SoAType>
977 KOKKOS_FORCEINLINE_FUNCTION
static std::enable_if_t<3 == M, void>
979 SoAType& dst_soa,
const int soa_idx,
980 const Kokkos::Array<std::size_t, M>& extents,
981 const std::integral_constant<std::size_t, N>,
982 const std::integral_constant<std::size_t, M> )
984 for ( std::size_t d0 = 0; d0 < extents[0]; ++d0 )
985 for (
int d1 = 0; d1 < extents[1]; ++d1 )
986 for (
int d2 = 0; d2 < extents[2]; ++d2 )
1007 template <
class ReduceOp, std::
size_t N, std::
size_t M,
class SoAType>
1008 KOKKOS_FORCEINLINE_FUNCTION
static std::enable_if_t<2 == M, void>
1010 SoAType& dst_soa,
const int soa_idx,
1011 const Kokkos::Array<std::size_t, M>& extents,
1012 const std::integral_constant<std::size_t, N>,
1013 const std::integral_constant<std::size_t, M> )
1015 for ( std::size_t d0 = 0; d0 < extents[0]; ++d0 )
1016 for (
int d1 = 0; d1 < extents[1]; ++d1 )
1036 template <
class ReduceOp, std::
size_t N, std::
size_t M,
class SoAType>
1037 KOKKOS_FORCEINLINE_FUNCTION
static std::enable_if_t<1 == M, void>
1039 SoAType& dst_soa,
const int soa_idx,
1040 const Kokkos::Array<std::size_t, M>& extents,
1041 const std::integral_constant<std::size_t, N>,
1042 const std::integral_constant<std::size_t, M> )
1044 for ( std::size_t d0 = 0; d0 < extents[0]; ++d0 )
1063 template <
class ReduceOp, std::
size_t N, std::
size_t M,
class SoAType>
1064 KOKKOS_FORCEINLINE_FUNCTION
static std::enable_if_t<0 == M, void>
1066 SoAType& dst_soa,
const int soa_idx,
1067 const Kokkos::Array<std::size_t, M>&,
1068 const std::integral_constant<std::size_t, N>,
1069 const std::integral_constant<std::size_t, M> )
1084 template <
class ReduceOp,
class SoAType>
1085 KOKKOS_FORCEINLINE_FUNCTION
static void
1087 SoAType& dst_soa,
const int soa_idx,
1088 const std::integral_constant<std::size_t, 0> )
1091 auto extents = compute_member_extents<current_type>();
1093 reduce_op, src_tuple, dst_soa, soa_idx, extents,
1094 std::integral_constant<std::size_t, 0>(),
1095 std::integral_constant<std::size_t,
1096 std::rank<current_type>::value>() );
1109 template <
class ReduceOp, std::
size_t N,
class SoAType>
1110 KOKKOS_FORCEINLINE_FUNCTION
static void
1112 SoAType& dst_soa,
const int soa_idx,
1113 const std::integral_constant<std::size_t, N> )
1116 auto extents = compute_member_extents<current_type>();
1118 reduce_op, src_tuple, dst_soa, soa_idx, extents,
1119 std::integral_constant<std::size_t, N>(),
1120 std::integral_constant<std::size_t,
1121 std::rank<current_type>::value>() );
1126 unpackTuple( reduce_op, src_tuple, dst_soa, soa_idx,
1127 std::integral_constant<std::size_t, N - 1>() );
1131 unpackTuple( reduce_op, src_tuple, dst_soa, soa_idx,
1132 std::integral_constant<std::size_t, 0>() );
1150 template <
class ReduceOp,
class ExecSpace,
class SparseArrayType,
1151 class SparseMapType>
1155 const SparseArrayType& sparse_array, SparseMapType& map,
1156 const int count )
const
1158 Kokkos::parallel_for(
1159 "Cabana::Grid::Experimental::SparseHalo::unpackBuffer",
1160 Kokkos::RangePolicy<ExecSpace>( exec_space, 0, count ),
1161 KOKKOS_LAMBDA(
const int i ) {
1162 if ( tile_steering( i ) != invalid_key )
1164 auto tile_key = tile_steering( i );
1165 if ( map.isValidKey( tile_key ) )
1168 map.key2ijk( tile_key, ti, tj, tk );
1170 auto tile_id = map.queryTileFromTileKey( tile_key );
1175 auto& tuple = buffer( buffer_idx + lcid );
1177 sparse_array.accessTile( tile_id );
1179 reduce_op, tuple, data_access, lcid,
1180 std::integral_constant<std::size_t,
1191 template <std::
size_t M>
1192 static constexpr std::size_t compute_member_size()
1197 template <
typename Sequence>
1198 struct compute_member_size_list_impl;
1200 template <std::size_t... Is>
1201 struct compute_member_size_list_impl<std::index_sequence<Is...>>
1203 std::array<std::size_t, member_num> operator()()
1205 return { compute_member_size<Is>()... };
1210 typename Indices = std::make_index_sequence<N>>
1211 std::array<std::size_t, member_num> compute_member_size_list()
1213 compute_member_size_list_impl<Indices> op;
1218 template <
typename Type, std::
size_t M>
1219 KOKKOS_FORCEINLINE_FUNCTION
static constexpr std::size_t
1220 compute_one_member_extent()
1222 return std::extent<Type, M>::value;
1225 template <
class Type, std::
size_t M,
typename Sequence>
1226 struct compute_member_extents_impl;
1228 template <
class Type, std::size_t M, std::size_t... Is>
1229 struct compute_member_extents_impl<Type, M, std::index_sequence<Is...>>
1231 KOKKOS_FORCEINLINE_FUNCTION
1232 Kokkos::Array<std::size_t, M> operator()()
1234 return { compute_one_member_extent<Type, Is>()... };
1238 template <class Type, std::size_t M = std::rank<Type>::value,
1239 typename Indices = std::make_index_sequence<M>>
1240 KOKKOS_FORCEINLINE_FUNCTION
static Kokkos::Array<std::size_t, M>
1241 compute_member_extents()
1243 compute_member_extents_impl<Type, M, Indices> op;
1254 std::vector<int> _neighbor_ranks;
1256 std::vector<std::array<int, num_space_dim>> _valid_neighbor_ids;
1258 std::vector<int> _send_tags;
1260 std::vector<int> _receive_tags;
1263 std::vector<buffer_view> _owned_buffers;
1265 std::vector<buffer_view> _ghosted_buffers;
1268 std::vector<steering_view> _owned_tile_steering;
1270 std::vector<steering_view> _tmp_tile_steering;
1272 std::vector<steering_view> _ghosted_tile_steering;
1275 std::vector<counting_view> _valid_counting;
1277 std::vector<counting_view> _neighbor_counting;
1280 std::vector<tile_index_space> _owned_tile_spaces;
1282 std::vector<tile_index_space> _ghosted_tile_spaces;
1285 Kokkos::Array<std::size_t, member_num> _soa_member_bytes;
1287 std::size_t _soa_total_bytes;
1298template <
class MemorySpace,
unsigned long long cellBitsPerTileDim,
1299 class DataTypes,
class EntityType,
class MeshType,
1300 class SparseMapType,
class Pattern,
typename Value = int,
1301 typename Key = uint64_t>
1302auto createSparseHalo(
1303 const Pattern& pattern,
1304 const std::shared_ptr<
SparseArray<DataTypes, MemorySpace, EntityType,
1305 MeshType, SparseMapType>>
1308 using array_type =
SparseArray<DataTypes, MemorySpace, EntityType, MeshType,
1310 using memory_space =
typename array_type::memory_space;
1311 static constexpr std::size_t num_space_dim = array_type::num_space_dim;
1312 return std::make_shared<
1313 SparseHalo<memory_space, DataTypes, EntityType, num_space_dim,
1314 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:939
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:563
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:1009
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:335
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:978
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:957
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:1065
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:735
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:516
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:1086
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:931
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:389
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:906
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:416
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:471
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:1152
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:1038
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:1111
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:948
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