Cabana 0.8.0-dev
 
Loading...
Searching...
No Matches
Cabana_Grid_SparseIndexSpace.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_GRID_SPARSE_INDEXSPACE_HPP
17#define CABANA_GRID_SPARSE_INDEXSPACE_HPP
18
19#ifdef KOKKOS_ENABLE_SYCL
20#error Not supported with the Kokkos SYCL backend (device recursion)
21#endif
22
25
26#include <Kokkos_Core.hpp>
27#include <Kokkos_UnorderedMap.hpp>
28
29#include <array>
30#include <memory>
31#include <string>
32
33//---------------------------------------------------------------------------//
34// Naming convention:
35// Tile ID / Tile ijk = 3D tile indexing, i.e., (i, j, k)
36// Tile No. = 1D number indicating the tile position in the allocated array
37// Tile key / Hash key = 1D number, computed with the given indexing method and
38// used as hash key
39//---------------------------------------------------------------------------//
40
41namespace Cabana
42{
43namespace Grid
44{
45
46//---------------------------------------------------------------------------//
48enum class HashTypes : unsigned char
49{
50 Naive = 0, // Lexicographical Order
51 Morton = 1 // Morton Curve
52};
53
54//---------------------------------------------------------------------------//
55// bit operations for Morton Code computing
56//---------------------------------------------------------------------------//
57
58//---------------------------------------------------------------------------//
64template <typename Integer>
65KOKKOS_INLINE_FUNCTION constexpr Integer bitLength( Integer input_int ) noexcept
66{
67 if ( input_int )
68 return bitLength( input_int >> 1 ) + static_cast<Integer>( 1 );
69 else
70 return 0;
71}
72
73//---------------------------------------------------------------------------//
79template <typename Integer>
80KOKKOS_INLINE_FUNCTION constexpr Integer bitCount( Integer input_int ) noexcept
81{
82 return bitLength( input_int - 1 );
83}
84
85//---------------------------------------------------------------------------//
92template <typename Integer>
93KOKKOS_INLINE_FUNCTION constexpr Integer
94binaryReverse( Integer input_int, char loc = sizeof( Integer ) * 8 - 1 )
95{
96 if ( input_int == 0 )
97 return 0;
98 return ( ( input_int & 1 ) << loc ) |
99 binaryReverse( input_int >> 1, loc - 1 );
100}
101
102//---------------------------------------------------------------------------//
108template <typename Integer>
109KOKKOS_INLINE_FUNCTION constexpr unsigned countLeadingZeros( Integer input_int )
110{
111 unsigned res{ 0 };
112 input_int = binaryReverse( input_int );
113 if ( input_int == 0 )
114 return sizeof( Integer ) * 8;
115 while ( ( input_int & 1 ) == 0 )
116 res++, input_int >>= 1;
117 return res;
118}
119
120//---------------------------------------------------------------------------//
127KOKKOS_INLINE_FUNCTION
128constexpr int bitPack( const uint64_t mask, const uint64_t data )
129{
130 uint64_t slresult = 0;
131 uint64_t& ulresult{ slresult };
132 uint64_t uldata = data;
133 int count = 0;
134 ulresult = 0;
135
136 uint64_t rmask = binaryReverse( mask );
137 unsigned char lz{ 0 };
138
139 while ( rmask )
140 {
141 lz = countLeadingZeros( rmask );
142 uldata >>= lz;
143 ulresult <<= 1;
144 count++;
145 ulresult |= ( uldata & 1 );
146 uldata >>= 1;
147 rmask <<= lz + 1;
148 }
149 ulresult <<= 64 - count; // 64 bits (maybe not use a constant 64 ...?)
150 ulresult = binaryReverse( ulresult );
151 return (int)slresult;
152}
153
154//---------------------------------------------------------------------------//
161KOKKOS_INLINE_FUNCTION
162constexpr uint64_t bitSpread( const uint64_t mask, const int data )
163{
164 uint64_t rmask = binaryReverse( mask );
165 int dat = data;
166 uint64_t result = 0;
167 unsigned char lz{ 0 };
168 while ( rmask )
169 {
170 lz = countLeadingZeros( rmask ) + 1;
171 result = result << lz | ( dat & 1 );
172 dat >>= 1, rmask <<= lz;
173 }
174 result = binaryReverse( result ) >> countLeadingZeros( mask );
175 return result;
176}
177
178//---------------------------------------------------------------------------//
179// Tile Hash Key (hash) <=> TileID.
180//---------------------------------------------------------------------------//
181template <typename Key, HashTypes HashT>
183
184template <typename Key, HashTypes HashT>
186
194template <typename Key>
195struct TileID2HashKey<Key, HashTypes::Naive>
196{
198 using tid_to_key_type = TileID2HashKey<Key, HashTypes::Naive>;
200 static constexpr HashTypes hash_type = HashTypes::Naive;
201
203 TileID2HashKey( std::initializer_list<int> tnum )
204 {
205 std::copy( tnum.begin(), tnum.end(), _tile_num.data() );
206 _tile_num_j_mul_k = _tile_num[1] * _tile_num[2];
207 }
209 TileID2HashKey( int i, int j, int k )
210 {
211 _tile_num[0] = i;
212 _tile_num[1] = j;
213 _tile_num[2] = k;
214 _tile_num_j_mul_k = j * k;
215 }
216
221 KOKKOS_INLINE_FUNCTION
222 Key operator()( int tile_i, int tile_j, int tile_k ) const
223 {
224 return tile_i * _tile_num_j_mul_k + tile_j * _tile_num[2] + tile_k;
225 }
226
227 private:
228 // The index bounds of the tiles on the current MPI rank
229 Kokkos::Array<int, 3> _tile_num;
230 int _tile_num_j_mul_k;
231};
232
238template <typename Key>
239struct TileID2HashKey<Key, HashTypes::Morton>
240{
242 using tid_to_key_type = TileID2HashKey<Key, HashTypes::Morton>;
244 static constexpr HashTypes hash_type = HashTypes::Morton;
245
247 TileID2HashKey( std::initializer_list<int> tnum )
248 {
249 std::copy( tnum.begin(), tnum.end(), _tile_num.data() );
250 }
252 TileID2HashKey( int i, int j, int k )
253 {
254 _tile_num[0] = i;
255 _tile_num[1] = j;
256 _tile_num[2] = k;
257 }
259 enum : uint64_t
260 { // hand-coded now, can be improved by iterative func
261 page_kmask = ( 0x9249249249249249UL ),
262 page_jmask = ( 0x2492492492492492UL ),
263 page_imask = ( 0x4924924924924924UL )
264 };
265
270 KOKKOS_INLINE_FUNCTION
271 Key operator()( int tile_i, int tile_j, int tile_k ) const
272 {
273 return bitSpread( page_kmask, tile_k ) |
274 bitSpread( page_jmask, tile_j ) |
275 bitSpread( page_imask, tile_i );
276 }
277
278 private:
279 // The index bounds of the tiles on the current MPI rank
280 Kokkos::Array<int, 3> _tile_num;
281};
282
289template <typename Key>
290struct HashKey2TileID<Key, HashTypes::Naive>
291{
293 using key_to_tid_type = HashKey2TileID<Key, HashTypes::Naive>;
295 static constexpr HashTypes hash_type = HashTypes::Naive;
296
298 HashKey2TileID( std::initializer_list<int> tnum )
299 : _tile_num()
300 {
301 std::copy( tnum.begin(), tnum.end(), _tile_num.data() );
302 }
304 HashKey2TileID( int i, int j, int k )
305 {
306 _tile_num[0] = i;
307 _tile_num[1] = j;
308 _tile_num[2] = k;
309 }
310
316 KOKKOS_INLINE_FUNCTION
317 void operator()( Key tile_key, int& tile_i, int& tile_j, int& tile_k ) const
318 {
319 tile_k = tile_key % _tile_num[2];
320 tile_j = static_cast<Key>( tile_key / _tile_num[2] ) % _tile_num[1];
321 tile_i = static_cast<Key>( tile_key / _tile_num[2] / _tile_num[1] ) %
322 _tile_num[0];
323 }
324
325 private:
326 // The index bounds of the tiles on the current MPI rank
327 Kokkos::Array<int, 3> _tile_num;
328};
329
335template <typename Key>
336struct HashKey2TileID<Key, HashTypes::Morton>
337{
339 using key_to_tid_type = HashKey2TileID<Key, HashTypes::Morton>;
341 static constexpr HashTypes hash_type = HashTypes::Morton;
342
344 HashKey2TileID( std::initializer_list<int> tnum )
345 {
346 std::copy( tnum.begin(), tnum.end(), _tile_num.data() );
347 }
349 HashKey2TileID( int i, int j, int k )
350 {
351 _tile_num[0] = i;
352 _tile_num[1] = j;
353 _tile_num[2] = k;
354 }
356 enum : uint64_t
357 { // hand-coded now, can be improved by iterative func
358 page_kmask = ( 0x9249249249249249UL ),
359 page_jmask = ( 0x2492492492492492UL ),
360 page_imask = ( 0x4924924924924924UL )
361 };
362
368 KOKKOS_INLINE_FUNCTION
369 void operator()( Key tile_key, int& tile_i, int& tile_j, int& tile_k ) const
370 {
371 tile_k = bitPack( page_kmask, tile_key );
372 tile_j = bitPack( page_jmask, tile_key );
373 tile_i = bitPack( page_imask, tile_key );
374 }
375
376 private:
377 // The index bounds of the tiles on the current MPI rank
378 Kokkos::Array<int, 3> _tile_num;
379};
380
381//---------------------------------------------------------------------------//
382// Hierarchical index spaces
383// SparseMap <- BlockMap <- TileMap
384// Naming:
385// Block = MPI Rank
386// Tile = Sub-block with several cells
387// Cell = Basic grid unit
388//---------------------------------------------------------------------------//
389
391template <typename MemorySpace, unsigned long long CBits,
392 unsigned long long CNumPerDim, unsigned long long CNumPerTile,
393 HashTypes Hash, typename Key, typename Value>
394class BlockMap;
395
397template <int CBits, int CNumPerDim, int CNumPerTile>
398class TileMap;
399
408template <typename MemorySpace, unsigned long long CellPerTileDim = 4,
409 HashTypes Hash = HashTypes::Naive, typename Key = uint64_t,
410 typename Value = uint64_t>
412{
413 public:
415 static constexpr int rank = 3;
417 static constexpr unsigned long long cell_bits_per_tile_dim =
418 bitCount( CellPerTileDim );
421 static constexpr unsigned long long cell_num_per_tile_dim =
425 static constexpr unsigned long long cell_mask_per_tile_dim =
426 ( 1 << cell_bits_per_tile_dim ) - 1;
428 static constexpr unsigned long long cell_bits_per_tile =
432 static constexpr unsigned long long cell_mask_per_tile =
433 ( 1 << cell_bits_per_tile ) - 1;
435 static constexpr unsigned long long cell_num_per_tile =
438 using key_type = Key;
440 using value_type = Value;
442 static constexpr HashTypes hash_type = Hash;
444 using memory_space = MemorySpace;
445
452 SparseMap( const std::array<int, rank> size,
453 const unsigned int pre_alloc_size )
454 : _block_id_space( size[0] >> cell_bits_per_tile_dim,
457 1 << bitCount( pre_alloc_size ) )
458 {
459 std::fill( _min.data(), _min.data() + rank, 0 );
460 std::copy( size.begin(), size.end(), _max.data() );
461 }
462
470 KOKKOS_INLINE_FUNCTION
471 void insertCell( int cell_i, int cell_j, int cell_k ) const
472 {
474 cell_j >> cell_bits_per_tile_dim,
475 cell_k >> cell_bits_per_tile_dim );
476 }
477
483 KOKKOS_INLINE_FUNCTION
484 void insertTile( int tile_i, int tile_j, int tile_k ) const
485 {
486 _block_id_space.insert( tile_i, tile_j, tile_k );
487 }
488
493 KOKKOS_INLINE_FUNCTION
494 value_type queryTile( int cell_i, int cell_j, int cell_k ) const
495 {
496 // query the tile ID
497 auto tile_id = _block_id_space.find( cell_i >> cell_bits_per_tile_dim,
498 cell_j >> cell_bits_per_tile_dim,
499 cell_k >> cell_bits_per_tile_dim );
500 return tile_id;
501 }
502
507 KOKKOS_INLINE_FUNCTION
508 value_type queryTileFromTileId( const int tile_i, const int tile_j,
509 const int tile_k ) const
510 {
511 // query the tile ID
512 return _block_id_space.find( tile_i, tile_j, tile_k );
513 }
514
519 KOKKOS_INLINE_FUNCTION
521 {
522 return _block_id_space.findKey( tile_key );
523 }
524
529 KOKKOS_INLINE_FUNCTION
530 value_type queryCell( int cell_i, int cell_j, int cell_k ) const
531 {
532 // query the tile ID.
533 auto tile_id = queryTile( cell_i, cell_j, cell_k );
534 auto cell_id = cell_local_id( cell_i, cell_j, cell_k );
535 return static_cast<value_type>( ( tile_id << cell_bits_per_tile ) |
536 cell_id );
537 }
538
542 void clear() { _block_id_space.clear(); }
543
549 {
550 return _block_id_space.reserve( capacity );
551 }
552
556 KOKKOS_INLINE_FUNCTION
557 uint32_t capacity() const { return _block_id_space.capacity(); }
558
562 value_type size() const { return _block_id_space.validTileNumHost(); }
563
567 inline value_type sizeTile() const { return size(); }
568
572 inline value_type sizeCell() const
573 {
574 return sizeTile() << cell_bits_per_tile;
575 }
576
581 template <typename T>
582 inline value_type reservedTileSize( T factor ) const
583 {
584 return _block_id_space.reservedTileNumHost( factor );
585 }
586
591 template <typename T>
592 inline value_type reservedCellSize( T factor ) const
593 {
594 return reservedTileSize( factor ) << cell_bits_per_tile;
595 }
596
601 KOKKOS_INLINE_FUNCTION
602 bool valid_at( uint32_t index ) const
603 {
604 return _block_id_space.valid_at( index );
605 }
606
611 KOKKOS_INLINE_FUNCTION
612 bool isValidKey( key_type key ) const
613 {
614 return _block_id_space.isValidKey( key );
615 }
616
621 KOKKOS_INLINE_FUNCTION
622 key_type key_at( uint32_t index ) const
623 {
624 return _block_id_space.key_at( index );
625 }
626
631 KOKKOS_INLINE_FUNCTION
632 value_type value_at( uint32_t index ) const
633 {
634 return _block_id_space.value_at( index );
635 }
636
642 KOKKOS_INLINE_FUNCTION
643 void key2ijk( key_type& key, int& tile_i, int& tile_j, int& tile_k ) const
644 {
645 return _block_id_space.key2ijk( key, tile_i, tile_j, tile_k );
646 }
647
653 KOKKOS_INLINE_FUNCTION
654 key_type ijk2key( int tile_i, int tile_j, int tile_k ) const
655 {
656 return _block_id_space.ijk2key( tile_i, tile_j, tile_k );
657 }
658
664 KOKKOS_INLINE_FUNCTION
665 value_type cell_local_id( const int cell_i, const int cell_j,
666 const int cell_k ) const
667 {
668 return _tile_id_space.coordToOffset( cell_i & cell_mask_per_tile_dim,
669 cell_j & cell_mask_per_tile_dim,
670 cell_k & cell_mask_per_tile_dim );
671 }
672
673 private:
677 _block_id_space;
680 _tile_id_space;
682 Kokkos::Array<int, rank> _min;
683 Kokkos::Array<int, rank> _max;
684};
685
686//---------------------------------------------------------------------------//
691template <typename MemorySpace, class Scalar,
692 unsigned long long CellPerTileDim = 4,
693 HashTypes Hash = HashTypes::Naive, typename Key = uint64_t,
694 typename Value = uint64_t>
696 const std::shared_ptr<GlobalMesh<SparseMesh<Scalar>>>& global_mesh,
697 int pre_alloc_size )
698{
700 { global_mesh->globalNumCell( Dim::I ),
701 global_mesh->globalNumCell( Dim::J ),
702 global_mesh->globalNumCell( Dim::K ) },
703 pre_alloc_size );
704}
705
706//---------------------------------------------------------------------------//
717template <typename MemorySpace, unsigned long long CBits,
718 unsigned long long CNumPerDim, unsigned long long CNumPerTile,
719 HashTypes Hash, typename Key, typename Value>
721{
722 public:
724 static constexpr unsigned long long cell_bits_per_tile_dim = CBits;
726 static constexpr unsigned long long cell_num_per_tile_dim = CNumPerDim;
728 static constexpr unsigned long long cell_num_per_tile = CNumPerTile;
730 using key_type = Key;
732 using value_type = Value;
734 static constexpr HashTypes hash_type = Hash;
736 using bis_Type =
739
747 BlockMap( const int size_x, const int size_y, const int size_z,
748 const value_type pre_alloc_size )
749 : _tile_table_info( "hash_table_info" )
750 , _tile_table( size_x * size_y * size_z )
751 , _op_ijk2key( size_x, size_y, size_z )
752 , _op_key2ijk( size_x, size_y, size_z )
753 {
754 // hash table related init
755 auto tile_table_info_mirror =
756 Kokkos::create_mirror_view( Kokkos::HostSpace(), _tile_table_info );
757 tile_table_info_mirror( 0 ) = 0;
758 tile_table_info_mirror( 1 ) = pre_alloc_size;
759 Kokkos::deep_copy( _tile_table_info, tile_table_info_mirror );
760
761 // size related init
762 _block_size[0] = size_x;
763 _block_size[1] = size_y;
764 _block_size[2] = size_z;
765 }
766
771 void clear()
772 {
773 _tile_table.clear(); // clear hash table
774 auto tile_table_info_mirror = Kokkos::create_mirror_view_and_copy(
775 Kokkos::HostSpace(), _tile_table_info );
776 tile_table_info_mirror( 0 ) = 0;
777 Kokkos::deep_copy( _tile_table_info,
778 tile_table_info_mirror ); // clear valid size record
779 }
780
787 {
788 return _tile_table.rehash( capacity );
789 }
790
794 KOKKOS_INLINE_FUNCTION
795 uint32_t capacity() const
796 {
797 return _tile_table.capacity(); // hash_table capacity
798 }
799
804 KOKKOS_INLINE_FUNCTION
805 bool valid_at( uint32_t index ) const
806 {
807 return _tile_table.valid_at( index );
808 }
809
814 KOKKOS_INLINE_FUNCTION
815 bool isValidKey( key_type key ) const
816 {
817 return !( _tile_table.find( key ) == ~static_cast<uint32_t>( 0 ) );
818 }
819
824 KOKKOS_INLINE_FUNCTION
825 key_type key_at( uint32_t index ) const
826 {
827 return _tile_table.key_at( index );
828 }
829
834 KOKKOS_INLINE_FUNCTION
835 key_type value_at( uint32_t index ) const
836 {
837 return _tile_table.value_at( index );
838 }
839
843 KOKKOS_INLINE_FUNCTION
844 value_type validTileNumDev() const { return _tile_table_info( 0 ); }
845
850 {
851 auto tile_table_info_mirror = Kokkos::create_mirror_view_and_copy(
852 Kokkos::HostSpace(), _tile_table_info );
853 return tile_table_info_mirror( 0 );
854 }
855
859 template <typename T>
860 inline value_type reservedTileNumHost( T factor ) const
861 {
862 auto tile_table_info_mirror = Kokkos::create_mirror_view_and_copy(
863 Kokkos::HostSpace(), _tile_table_info );
864 value_type num = tile_table_info_mirror( 0 ) * factor;
865 tile_table_info_mirror( 1 ) = num;
866 Kokkos::deep_copy( _tile_table_info, tile_table_info_mirror );
867 return num;
868 }
869
874 KOKKOS_INLINE_FUNCTION
875 void insert( int tile_i, int tile_j, int tile_k ) const
876 {
877 // Note: reallocation will be performed after insert
878 // tile ijk => tile key
879 key_type tile_key = ijk2key( tile_i, tile_j, tile_k );
880 // Try to insert the tile key into the map. Give it a dummy value for
881 // now.
882 auto insert_result = _tile_table.insert( tile_key, 0 );
883 // If the tile key was actually inserted, atomically increment the
884 // counter Only threads that actually did a successful insert will call
885 // it
886 if ( !insert_result.existing() )
887 _tile_table.value_at( insert_result.index() ) =
888 Kokkos::atomic_fetch_add( &( _tile_table_info( 0 ) ), 1 );
889 }
890
895 KOKKOS_INLINE_FUNCTION
896 value_type find( int tile_i, int tile_j, int tile_k ) const
897 {
898 return _tile_table.value_at(
899 _tile_table.find( ijk2key( tile_i, tile_j, tile_k ) ) );
900 }
901
906 KOKKOS_INLINE_FUNCTION
907 value_type findKey( key_type tile_key ) const
908 {
909 return _tile_table.value_at( _tile_table.find( tile_key ) );
910 }
911
916 KOKKOS_INLINE_FUNCTION
917 key_type ijk2key( int tile_i, int tile_j, int tile_k ) const
918 {
919 return _op_ijk2key( tile_i, tile_j, tile_k );
920 }
921
927 KOKKOS_INLINE_FUNCTION
928 void key2ijk( key_type& key, int& tile_i, int& tile_j, int& tile_k ) const
929 {
930 return _op_key2ijk( key, tile_i, tile_j, tile_k );
931 }
932
933 private:
935 Kokkos::View<int[2], MemorySpace> _tile_table_info;
937 Kokkos::Array<int, 3> _block_size;
939 Kokkos::UnorderedMap<key_type, value_type, MemorySpace> _tile_table;
943};
944
945//---------------------------------------------------------------------------//
954template <int CBits, int CNumPerDim, int CNumPerTile>
956{
957 public:
959 static constexpr int cell_bits_per_tile_dim = CBits;
961 static constexpr int cell_num_per_tile_dim = CNumPerDim;
963 static constexpr int cell_num_per_tile = CNumPerTile;
965 static constexpr int rank = 3;
966
968
972 template <typename... Coords>
973 KOKKOS_INLINE_FUNCTION static constexpr auto
974 coordToOffset( Coords&&... coords ) -> uint64_t
975 {
976 return fromCoord<Coord2OffsetDim>( std::forward<Coords>( coords )... );
977 }
978
984 template <typename Key, typename... Coords>
985 KOKKOS_INLINE_FUNCTION static constexpr void
986 offsetToCoord( Key&& key, Coords&... coords )
987 {
988 toCoord<Offset2CoordDim>( std::forward<Key>( key ), coords... );
989 }
990
991 private:
993
998 struct Coord2OffsetDim
999 {
1000 template <typename Coord>
1001 KOKKOS_INLINE_FUNCTION constexpr auto operator()( int dim_no,
1002 Coord&& i )
1003 -> uint64_t
1004 {
1005 uint64_t result = static_cast<uint64_t>( i );
1006 for ( int i = 0; i < dim_no; i++ )
1007 result *= cell_num_per_tile_dim;
1008 return result;
1009 }
1010 };
1011
1017 struct Offset2CoordDim
1018 {
1019 template <typename Coord, typename Key>
1020 KOKKOS_INLINE_FUNCTION constexpr auto operator()( Coord& i,
1021 Key&& offset )
1022 -> uint64_t
1023 {
1024 i = offset % cell_num_per_tile_dim;
1025 return ( offset / cell_num_per_tile_dim );
1026 }
1027 };
1028
1034 template <typename Func, typename... Coords>
1035 KOKKOS_INLINE_FUNCTION static constexpr auto fromCoord( Coords&&... coords )
1036 -> uint64_t
1037 {
1038 static_assert( sizeof...( Coords ) == rank,
1039 "Dimension of coordinate mismatch" );
1040 using integer = std::common_type_t<Coords...>;
1041 static_assert( std::is_integral<integer>::value,
1042 "Coordinate should be integral type" );
1043 return fromCoordImpl<Func>( 0, coords... );
1044 }
1045
1054 template <typename Func, typename Key, typename... Coords>
1055 KOKKOS_INLINE_FUNCTION static constexpr void toCoord( Key&& key,
1056 Coords&... coords )
1057 {
1058 static_assert( sizeof...( Coords ) == rank,
1059 "Dimension of coordinate mismatch" );
1060 using integer = std::common_type_t<Coords...>;
1061 static_assert( std::is_integral<integer>::value,
1062 "Coordinate should be integral type" );
1063 return toCoordImpl<Func>( 0, std::forward<Key>( key ), coords... );
1064 }
1065
1071 template <typename Func, typename Coord>
1072 KOKKOS_INLINE_FUNCTION static constexpr auto fromCoordImpl( int&& dim_no,
1073 Coord&& i )
1074 {
1075 return Func()( dim_no, std::forward<Coord>( i ) );
1076 }
1077
1084 template <typename Func, typename Coord, typename... Coords>
1085 KOKKOS_INLINE_FUNCTION static constexpr auto
1086 fromCoordImpl( int&& dim_no, Coord&& i, Coords&&... is )
1087 {
1088 auto result = Func()( dim_no, std::forward<Coord>( i ) );
1089 if ( dim_no + 1 < rank )
1090 result += fromCoordImpl<Func>( dim_no + 1,
1091 std::forward<Coords>( is )... );
1092 return result;
1093 }
1094
1101 template <typename Func, typename Key, typename Coord>
1102 KOKKOS_INLINE_FUNCTION static constexpr void
1103 toCoordImpl( int&& dim_no, Key&& key, Coord& i ) noexcept
1104 {
1105 if ( dim_no < rank )
1106 Func()( i, std::forward<Key>( key ) );
1107 }
1108
1116 template <typename Func, typename Key, typename Coord, typename... Coords>
1117 KOKKOS_INLINE_FUNCTION static constexpr void
1118 toCoordImpl( int&& dim_no, Key&& key, Coord& i, Coords&... is ) noexcept
1119 {
1120 auto new_key = Func()( i, std::forward<Key>( key ) );
1121 if ( dim_no + 1 < rank )
1122 toCoordImpl<Func>( dim_no + 1, new_key, is... );
1123 }
1124};
1125
1126template <long N>
1127class IndexSpace;
1128
1129//---------------------------------------------------------------------------//
1134template <std::size_t N, unsigned long long cellBitsPerTileDim,
1135 typename std::enable_if_t<( N == 3 ), bool> = true>
1137{
1138 public:
1140 static constexpr std::size_t Rank = N;
1143 static constexpr unsigned long long cell_bits_per_tile_dim =
1144 cellBitsPerTileDim;
1146 static constexpr unsigned long long cell_num_per_tile =
1147 1 << ( cell_bits_per_tile_dim * Rank );
1148
1151 : IndexSpace<N>()
1152 {
1153 }
1154
1156 TileIndexSpace( const std::initializer_list<long>& size )
1157 : IndexSpace<N>( size )
1158 {
1159 }
1160
1162 TileIndexSpace( const std::initializer_list<long>& min,
1163 const std::initializer_list<long>& max )
1164 : IndexSpace<N>( min, max )
1165 {
1166 }
1167
1169 template <typename... Params>
1170 TileIndexSpace( Params&&... pars )
1171 : IndexSpace<N>( std::forward<Params>( pars )... )
1172 {
1173 }
1174
1176 KOKKOS_INLINE_FUNCTION
1177 long min( const long dim ) const { return IndexSpace<N>::min( dim ); }
1178
1180 KOKKOS_INLINE_FUNCTION
1181 long max( const long dim ) const { return IndexSpace<N>::max( dim ); }
1182
1184 KOKKOS_INLINE_FUNCTION
1185 Kokkos::Array<long, Rank> min() const { return IndexSpace<N>::min(); }
1186
1188 KOKKOS_INLINE_FUNCTION
1189 Kokkos::Array<long, Rank> max() const { return IndexSpace<N>::max(); }
1190
1192 KOKKOS_FORCEINLINE_FUNCTION
1193 long sizeTile() const { return IndexSpace<N>::size(); }
1194
1196 KOKKOS_FORCEINLINE_FUNCTION
1197 long sizeCell() const { return ( sizeTile() * cell_num_per_tile ); }
1198
1200 template <int NSD = N>
1201 KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t<3 == NSD, bool>
1202 tileInRange( const long tile_i, const long tile_j, const long tile_k ) const
1203 {
1204 long index[N] = { tile_i, tile_j, tile_k };
1205 return IndexSpace<N>::inRange( index );
1206 }
1207
1209 template <int NSD = N>
1210 KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t<3 == NSD, bool>
1211 cellInRange( const long cell_i, const long cell_j, const long cell_k ) const
1212 {
1213 return tileInRange( cell_i >> cell_bits_per_tile_dim,
1214 cell_j >> cell_bits_per_tile_dim,
1215 cell_k >> cell_bits_per_tile_dim );
1216 }
1217};
1218
1219} // namespace Grid
1220} // namespace Cabana
1221
1222#endif
Logical grid indexing.
KOKKOS_INLINE_FUNCTION constexpr Integer bitCount(Integer input_int) noexcept
(Host/Device) Compute the lease bit number needed to index input integer
Definition Cabana_Grid_SparseIndexSpace.hpp:80
KOKKOS_INLINE_FUNCTION constexpr Integer binaryReverse(Integer input_int, char loc=sizeof(Integer) *8 - 1)
(Host/Device) Given a integer, reverse the corresponding binary string, return the resulting integer.
Definition Cabana_Grid_SparseIndexSpace.hpp:94
KOKKOS_INLINE_FUNCTION constexpr uint64_t bitSpread(const uint64_t mask, const int data)
(Host/Device) Spread out the data bits where the corresponding bit of the mask is 1
Definition Cabana_Grid_SparseIndexSpace.hpp:162
KOKKOS_INLINE_FUNCTION constexpr Integer bitLength(Integer input_int) noexcept
(Host/Device) Compute the least bit number/length needed to represent the given input integer
Definition Cabana_Grid_SparseIndexSpace.hpp:65
HashTypes
Hash table type tag.
Definition Cabana_Grid_SparseIndexSpace.hpp:49
KOKKOS_INLINE_FUNCTION constexpr int bitPack(const uint64_t mask, const uint64_t data)
(Host/Device) Pack up the data bits where the corresponding bit of the mask is 1
Definition Cabana_Grid_SparseIndexSpace.hpp:128
KOKKOS_INLINE_FUNCTION constexpr unsigned countLeadingZeros(Integer input_int)
(Host/Device) Count the leading zeros in the corresponding binary string of the input integer
Definition Cabana_Grid_SparseIndexSpace.hpp:109
SparseMap< MemorySpace, CellPerTileDim, Hash, Key, Value > createSparseMap(const std::shared_ptr< GlobalMesh< SparseMesh< Scalar > > > &global_mesh, int pre_alloc_size)
Creation function for SparseMap from GlobalMesh<SparseMesh>
Definition Cabana_Grid_SparseIndexSpace.hpp:695
Declaration of BlockMap.
Definition Cabana_Grid_SparseIndexSpace.hpp:721
KOKKOS_INLINE_FUNCTION value_type validTileNumDev() const
(Device) Valid tile number inside current block (MPI rank)
Definition Cabana_Grid_SparseIndexSpace.hpp:844
KOKKOS_INLINE_FUNCTION key_type key_at(uint32_t index) const
(Device) Get tile key at index.
Definition Cabana_Grid_SparseIndexSpace.hpp:825
BlockMap(const int size_x, const int size_y, const int size_z, const value_type pre_alloc_size)
(Host) Constructor
Definition Cabana_Grid_SparseIndexSpace.hpp:747
KOKKOS_INLINE_FUNCTION value_type find(int tile_i, int tile_j, int tile_k) const
(Device) Query the tile No. from the hash table
Definition Cabana_Grid_SparseIndexSpace.hpp:896
KOKKOS_INLINE_FUNCTION key_type ijk2key(int tile_i, int tile_j, int tile_k) const
(Device) Transfer tile ijk to tile hash key
Definition Cabana_Grid_SparseIndexSpace.hpp:917
Key key_type
Tile hash key type.
Definition Cabana_Grid_SparseIndexSpace.hpp:730
KOKKOS_INLINE_FUNCTION bool valid_at(uint32_t index) const
(Device) Valid tile at index.
Definition Cabana_Grid_SparseIndexSpace.hpp:805
KOKKOS_INLINE_FUNCTION value_type findKey(key_type tile_key) const
(Device) Query the tile No. from the hash table
Definition Cabana_Grid_SparseIndexSpace.hpp:907
BlockMap< MemorySpace, cell_bits_per_tile_dim, cell_num_per_tile_dim, cell_num_per_tile, hash_type, key_type, value_type > bis_Type
Self type.
Definition Cabana_Grid_SparseIndexSpace.hpp:736
KOKKOS_INLINE_FUNCTION bool isValidKey(key_type key) const
(Device) Check if the tile key is valid.
Definition Cabana_Grid_SparseIndexSpace.hpp:815
KOKKOS_INLINE_FUNCTION key_type value_at(uint32_t index) const
(Device) get block id value at index
Definition Cabana_Grid_SparseIndexSpace.hpp:835
value_type validTileNumHost() const
(Host) Valid tile number inside current block (MPI rank)
Definition Cabana_Grid_SparseIndexSpace.hpp:849
Value value_type
Tile number type.
Definition Cabana_Grid_SparseIndexSpace.hpp:732
bool reserve(const value_type capacity)
(Host) Set new capacity lower bound on the unordered map (Only for hash table, not for capacity of al...
Definition Cabana_Grid_SparseIndexSpace.hpp:786
value_type reservedTileNumHost(T factor) const
(Host) Reserved tile number inside current block (MPI rank)
Definition Cabana_Grid_SparseIndexSpace.hpp:860
KOKKOS_INLINE_FUNCTION void insert(int tile_i, int tile_j, int tile_k) const
(Device) Insert a tile into the hash table
Definition Cabana_Grid_SparseIndexSpace.hpp:875
KOKKOS_INLINE_FUNCTION void key2ijk(key_type &key, int &tile_i, int &tile_j, int &tile_k) const
(Device) Transfer tile hash key to tile ijk
Definition Cabana_Grid_SparseIndexSpace.hpp:928
void clear()
(Host) Clear tile hash table (Host, required by unordered map clear())
Definition Cabana_Grid_SparseIndexSpace.hpp:771
Global mesh partial specialization for uniform mesh.
Definition Cabana_Grid_GlobalMesh.hpp:49
Structured index space.
Definition Cabana_Grid_IndexSpace.hpp:37
KOKKOS_INLINE_FUNCTION bool inRange(const long index[N]) const
Determine if a set of indices is within the range of the index space.
Definition Cabana_Grid_IndexSpace.hpp:150
KOKKOS_INLINE_FUNCTION Kokkos::Array< long, Rank > max() const
Get the maximum indices in all dimensions.
Definition Cabana_Grid_IndexSpace.hpp:121
KOKKOS_INLINE_FUNCTION Kokkos::Array< long, Rank > min() const
Get the minimum indices in all dimensions.
Definition Cabana_Grid_IndexSpace.hpp:113
KOKKOS_INLINE_FUNCTION long size() const
Get the total size of the index space.
Definition Cabana_Grid_IndexSpace.hpp:140
IndexSpace()
Default constructor.
Definition Cabana_Grid_IndexSpace.hpp:43
Sparse index space, with a hierarchical structure (cell->tile->block)
Definition Cabana_Grid_SparseIndexSpace.hpp:412
KOKKOS_INLINE_FUNCTION value_type queryTileFromTileId(const int tile_i, const int tile_j, const int tile_k) const
(Device) Query the 1D tile key from the 3D tile ijk
Definition Cabana_Grid_SparseIndexSpace.hpp:508
MemorySpace memory_space
memory space
Definition Cabana_Grid_SparseIndexSpace.hpp:444
KOKKOS_INLINE_FUNCTION void key2ijk(key_type &key, int &tile_i, int &tile_j, int &tile_k) const
(Device) Transfer tile hash key to tile ijk
Definition Cabana_Grid_SparseIndexSpace.hpp:643
KOKKOS_INLINE_FUNCTION value_type queryTileFromTileKey(const key_type tile_key) const
(Device) Query the 1D tile key from the 1D tile key
Definition Cabana_Grid_SparseIndexSpace.hpp:520
void clear()
(Host) Clear tile hash table (required by unordered map clear())
Definition Cabana_Grid_SparseIndexSpace.hpp:542
KOKKOS_INLINE_FUNCTION value_type value_at(uint32_t index) const
(Device) get tile id value at index
Definition Cabana_Grid_SparseIndexSpace.hpp:632
value_type sizeCell() const
(Host) Valid cell number inside current block (MPI rank)
Definition Cabana_Grid_SparseIndexSpace.hpp:572
KOKKOS_INLINE_FUNCTION value_type queryCell(int cell_i, int cell_j, int cell_k) const
(Device) Query the 1D cell key from the 3D cell ijk
Definition Cabana_Grid_SparseIndexSpace.hpp:530
static constexpr unsigned long long cell_bits_per_tile
Number of bits (total) needed to index the cells inside a tile.
Definition Cabana_Grid_SparseIndexSpace.hpp:428
KOKKOS_INLINE_FUNCTION key_type key_at(uint32_t index) const
(Device) Get block key at index
Definition Cabana_Grid_SparseIndexSpace.hpp:622
KOKKOS_INLINE_FUNCTION bool valid_at(uint32_t index) const
(Device) Valid block at index
Definition Cabana_Grid_SparseIndexSpace.hpp:602
static constexpr unsigned long long cell_num_per_tile_dim
Definition Cabana_Grid_SparseIndexSpace.hpp:421
KOKKOS_INLINE_FUNCTION key_type ijk2key(int tile_i, int tile_j, int tile_k) const
(Device) Transfer tile ijk to til key
Definition Cabana_Grid_SparseIndexSpace.hpp:654
KOKKOS_INLINE_FUNCTION bool isValidKey(key_type key) const
(Device) Check if the tile key is valid.
Definition Cabana_Grid_SparseIndexSpace.hpp:612
static constexpr int rank
Number of dimensions, 3 = ijk.
Definition Cabana_Grid_SparseIndexSpace.hpp:415
value_type size() const
(Host) Valid tile number inside current block (MPI rank)
Definition Cabana_Grid_SparseIndexSpace.hpp:562
KOKKOS_INLINE_FUNCTION uint32_t capacity() const
(Host/Device) Require capacity of the index hash table
Definition Cabana_Grid_SparseIndexSpace.hpp:557
KOKKOS_INLINE_FUNCTION void insertCell(int cell_i, int cell_j, int cell_k) const
(Device) Insert a cell
Definition Cabana_Grid_SparseIndexSpace.hpp:471
static constexpr unsigned long long cell_num_per_tile
Number of cells (total) inside each tile.
Definition Cabana_Grid_SparseIndexSpace.hpp:435
KOKKOS_INLINE_FUNCTION value_type queryTile(int cell_i, int cell_j, int cell_k) const
(Device) Query the 1D tile key from the 3D cell ijk
Definition Cabana_Grid_SparseIndexSpace.hpp:494
Value value_type
Tile number type.
Definition Cabana_Grid_SparseIndexSpace.hpp:440
static constexpr unsigned long long cell_mask_per_tile_dim
Definition Cabana_Grid_SparseIndexSpace.hpp:425
value_type reservedCellSize(T factor) const
(Host) Reserved cell number inside current block (MPI rank)
Definition Cabana_Grid_SparseIndexSpace.hpp:592
SparseMap(const std::array< int, rank > size, const unsigned int pre_alloc_size)
(Host) Constructor
Definition Cabana_Grid_SparseIndexSpace.hpp:452
value_type sizeTile() const
(Host) Valid tile number inside current block (MPI rank)
Definition Cabana_Grid_SparseIndexSpace.hpp:567
static constexpr unsigned long long cell_mask_per_tile
Cell mask (combine all dimensions dimension)
Definition Cabana_Grid_SparseIndexSpace.hpp:432
static constexpr HashTypes hash_type
Hash table type.
Definition Cabana_Grid_SparseIndexSpace.hpp:442
KOKKOS_INLINE_FUNCTION void insertTile(int tile_i, int tile_j, int tile_k) const
(Device) Insert a tile (to hash table); Note that the tile ijk should be global
Definition Cabana_Grid_SparseIndexSpace.hpp:484
KOKKOS_INLINE_FUNCTION value_type cell_local_id(const int cell_i, const int cell_j, const int cell_k) const
(Device) Get local cell ID from cell IJK
Definition Cabana_Grid_SparseIndexSpace.hpp:665
Key key_type
Tile hash key type.
Definition Cabana_Grid_SparseIndexSpace.hpp:438
value_type reservedTileSize(T factor) const
(Host) Reserved tile number inside current block (MPI rank)
Definition Cabana_Grid_SparseIndexSpace.hpp:582
static constexpr unsigned long long cell_bits_per_tile_dim
Number of bits (per dimension) needed to index the cells inside a tile.
Definition Cabana_Grid_SparseIndexSpace.hpp:417
bool reserve(const value_type capacity)
(Host) Set new capacity lower bound on the unordered map
Definition Cabana_Grid_SparseIndexSpace.hpp:548
KOKKOS_FORCEINLINE_FUNCTION long sizeTile() const
Get the total number of tiles of the index space.
Definition Cabana_Grid_SparseIndexSpace.hpp:1193
TileIndexSpace()
brief Default constructor.
Definition Cabana_Grid_SparseIndexSpace.hpp:1150
static constexpr std::size_t Rank
Definition Cabana_Grid_SparseIndexSpace.hpp:1140
KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t< 3==NSD, bool > cellInRange(const long cell_i, const long cell_j, const long cell_k) const
Determine if given cell indices is within the range of the index space.
Definition Cabana_Grid_SparseIndexSpace.hpp:1211
TileIndexSpace(Params &&... pars)
Other constructors.
Definition Cabana_Grid_SparseIndexSpace.hpp:1170
TileIndexSpace(const std::initializer_list< long > &min, const std::initializer_list< long > &max)
Other constructors.
Definition Cabana_Grid_SparseIndexSpace.hpp:1162
KOKKOS_INLINE_FUNCTION Kokkos::Array< long, Rank > max() const
Get the maximum indices in all dimensions.
Definition Cabana_Grid_SparseIndexSpace.hpp:1189
KOKKOS_INLINE_FUNCTION long max(const long dim) const
Definition Cabana_Grid_SparseIndexSpace.hpp:1181
KOKKOS_INLINE_FUNCTION long min(const long dim) const
Definition Cabana_Grid_SparseIndexSpace.hpp:1177
static constexpr unsigned long long cell_num_per_tile
Definition Cabana_Grid_SparseIndexSpace.hpp:1146
static constexpr unsigned long long cell_bits_per_tile_dim
Definition Cabana_Grid_SparseIndexSpace.hpp:1143
KOKKOS_FORCEINLINE_FUNCTION long sizeCell() const
Get the total number of cells of the index space.
Definition Cabana_Grid_SparseIndexSpace.hpp:1197
KOKKOS_INLINE_FUNCTION Kokkos::Array< long, Rank > min() const
Get the minimum indices in all dimensions.
Definition Cabana_Grid_SparseIndexSpace.hpp:1185
TileIndexSpace(const std::initializer_list< long > &size)
Other constructors.
Definition Cabana_Grid_SparseIndexSpace.hpp:1156
KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t< 3==NSD, bool > tileInRange(const long tile_i, const long tile_j, const long tile_k) const
Determine if given tile indices is within the range of the index space.
Definition Cabana_Grid_SparseIndexSpace.hpp:1202
Declaration of TileMap.
Definition Cabana_Grid_SparseIndexSpace.hpp:956
static KOKKOS_INLINE_FUNCTION constexpr auto coordToOffset(Coords &&... coords) -> uint64_t
Cell ijk <=> Cell Id.
Definition Cabana_Grid_SparseIndexSpace.hpp:974
static constexpr int cell_num_per_tile_dim
Number of cells (per dimension) inside each tile.
Definition Cabana_Grid_SparseIndexSpace.hpp:961
static constexpr int cell_bits_per_tile_dim
Number of bits (per dimension) needed to index the cells inside a tile.
Definition Cabana_Grid_SparseIndexSpace.hpp:959
static constexpr int cell_num_per_tile
Number of cells (total) inside each tile.
Definition Cabana_Grid_SparseIndexSpace.hpp:963
static KOKKOS_INLINE_FUNCTION constexpr void offsetToCoord(Key &&key, Coords &... coords)
(Host/Device) Compute from offset to coordinates
Definition Cabana_Grid_SparseIndexSpace.hpp:986
static constexpr int rank
Indexing dimension, currently only serves 3D representations.
Definition Cabana_Grid_SparseIndexSpace.hpp:965
Core: particle data structures and algorithms.
Definition Cabana_AoSoA.hpp:36
Definition Cabana_Grid_SparseIndexSpace.hpp:185
Sparse mesh tag.
Definition Cabana_Grid_Types.hpp:253
Definition Cabana_Grid_SparseIndexSpace.hpp:182