Cabana 0.8.0-dev
 
Loading...
Searching...
No Matches
Cabana_SoA.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_SOA_HPP
17#define CABANA_SOA_HPP
18
20
21#include <Kokkos_Core.hpp>
22
23#include <cstdlib>
24#include <type_traits>
25#include <utility>
26
27namespace Cabana
28{
29//---------------------------------------------------------------------------//
30// SoA forward declaration.
31template <typename Types, int VectorLength>
32struct SoA;
33
34//---------------------------------------------------------------------------//
36template <class>
37struct is_soa_impl : public std::false_type
38{
39};
40
41template <class DataTypes, int VectorLength>
42struct is_soa_impl<SoA<DataTypes, VectorLength>> : public std::true_type
43{
44};
46
48template <class T>
49struct is_soa : public is_soa_impl<typename std::remove_cv<T>::type>::type
50{
51};
52
53//---------------------------------------------------------------------------//
54
55namespace Impl
56{
58
59//---------------------------------------------------------------------------//
60// Given an array layout and a potentially multi dimensional type T along with
61// its rank, compose the inner array type.
62template <typename T, std::size_t Rank, int VectorLength>
63struct InnerArrayTypeImpl;
64
65// rank-0 specialization.
66template <typename T, int VectorLength>
67struct InnerArrayTypeImpl<T, 0, VectorLength>
68{
69 using value_type = typename std::remove_all_extents<T>::type;
70 using type = value_type[VectorLength];
71};
72
73// rank-1 specialization.
74template <typename T, int VectorLength>
75struct InnerArrayTypeImpl<T, 1, VectorLength>
76{
77 using value_type = typename std::remove_all_extents<T>::type;
78 static constexpr std::size_t D0 = std::extent<T, 0>::value;
79 using type = value_type[D0][VectorLength];
80};
81
82// rank-2 specialization.
83template <typename T, int VectorLength>
84struct InnerArrayTypeImpl<T, 2, VectorLength>
85{
86 using value_type = typename std::remove_all_extents<T>::type;
87 static constexpr std::size_t D0 = std::extent<T, 0>::value;
88 static constexpr std::size_t D1 = std::extent<T, 1>::value;
89 using type = value_type[D0][D1][VectorLength];
90};
91
92// rank-3 specialization.
93template <typename T, int VectorLength>
94struct InnerArrayTypeImpl<T, 3, VectorLength>
95{
96 using value_type = typename std::remove_all_extents<T>::type;
97 static constexpr std::size_t D0 = std::extent<T, 0>::value;
98 static constexpr std::size_t D1 = std::extent<T, 1>::value;
99 static constexpr std::size_t D2 = std::extent<T, 2>::value;
100 using type = value_type[D0][D1][D2][VectorLength];
101};
102
103//---------------------------------------------------------------------------//
104// Inner array type.
105template <typename T, int VectorLength>
106struct InnerArrayType
107{
108 using type =
109 typename InnerArrayTypeImpl<T, std::rank<T>::value, VectorLength>::type;
110};
111
112//---------------------------------------------------------------------------//
120template <std::size_t M, int VectorLength, typename T>
121struct StructMember
122{
123 using array_type = typename InnerArrayType<T, VectorLength>::type;
124 array_type _data;
125};
126
127//---------------------------------------------------------------------------//
128// SoA implementation detail to hide the index sequence.
129template <int VectorLength, typename Sequence, typename... Types>
130struct SoAImpl;
131
132template <int VectorLength, std::size_t... Indices, typename... Types>
133struct SoAImpl<VectorLength, std::index_sequence<Indices...>, Types...>
134 : StructMember<Indices, VectorLength, Types>...
135{
136};
137
138//---------------------------------------------------------------------------//
139// Given an SoA cast it to to one of its member types.
140template <std::size_t M, class SoA_t>
141KOKKOS_FORCEINLINE_FUNCTION const typename SoA_t::template base<M>&
142soaMemberCast( const SoA_t& soa )
143{
144 static_assert( is_soa<SoA_t>::value, "soaMemberCast only for SoAs" );
145 return static_cast<const typename SoA_t::template base<M>&>( soa );
146}
147
148template <std::size_t M, class SoA_t>
149KOKKOS_FORCEINLINE_FUNCTION typename SoA_t::template base<M>&
150soaMemberCast( SoA_t& soa )
151{
152 static_assert( is_soa<SoA_t>::value, "soaMemberCast only for SoAs" );
153 return static_cast<typename SoA_t::template base<M>&>( soa );
154}
155
156//---------------------------------------------------------------------------//
157// Get a pointer to the first element of a member in a given SoA.
158template <std::size_t M, class SoA_t>
159typename SoA_t::template member_pointer_type<M> soaMemberPtr( SoA_t* p )
160{
161 static_assert( is_soa<SoA_t>::value, "soaMemberPtr only for SoAs" );
162 void* member = static_cast<typename SoA_t::template base<M>*>( p );
163 return static_cast<typename SoA_t::template member_pointer_type<M>>(
164 member );
165}
166
167//---------------------------------------------------------------------------//
168
170} // end namespace Impl
171
172//---------------------------------------------------------------------------//
173// Get template helper.
174
176template <std::size_t M, class SoA_t>
177KOKKOS_FORCEINLINE_FUNCTION typename std::enable_if<
179 typename SoA_t::template member_reference_type<M>>::type
180get( SoA_t& soa, const std::size_t a )
181{
182 return Impl::soaMemberCast<M>( soa )._data[a];
183}
184
186template <std::size_t M, class SoA_t>
187KOKKOS_FORCEINLINE_FUNCTION typename std::enable_if<
188 is_soa<SoA_t>::value,
189 typename SoA_t::template member_const_reference_type<M>>::type
190get( const SoA_t& soa, const std::size_t a )
191{
192 return Impl::soaMemberCast<M>( soa )._data[a];
193}
194
196template <std::size_t M, class SoA_t>
197KOKKOS_FORCEINLINE_FUNCTION typename std::enable_if<
198 is_soa<SoA_t>::value,
199 typename SoA_t::template member_reference_type<M>>::type
200get( SoA_t& soa, const std::size_t a, const std::size_t d0 )
201{
202 return Impl::soaMemberCast<M>( soa )._data[d0][a];
203}
204
206template <std::size_t M, class SoA_t>
207KOKKOS_FORCEINLINE_FUNCTION typename std::enable_if<
208 is_soa<SoA_t>::value,
209 typename SoA_t::template member_const_reference_type<M>>::type
210get( const SoA_t& soa, const std::size_t a, const std::size_t d0 )
211{
212 return Impl::soaMemberCast<M>( soa )._data[d0][a];
213}
214
216template <std::size_t M, class SoA_t>
217KOKKOS_FORCEINLINE_FUNCTION typename std::enable_if<
218 is_soa<SoA_t>::value,
219 typename SoA_t::template member_reference_type<M>>::type
220get( SoA_t& soa, const std::size_t a, const std::size_t d0,
221 const std::size_t d1 )
222{
223 return Impl::soaMemberCast<M>( soa )._data[d0][d1][a];
224}
225
227template <std::size_t M, class SoA_t>
228KOKKOS_FORCEINLINE_FUNCTION typename std::enable_if<
229 is_soa<SoA_t>::value,
230 typename SoA_t::template member_const_reference_type<M>>::type
231get( const SoA_t& soa, const std::size_t a, const std::size_t d0,
232 const std::size_t d1 )
233{
234 return Impl::soaMemberCast<M>( soa )._data[d0][d1][a];
235}
236
238template <std::size_t M, class SoA_t>
239KOKKOS_FORCEINLINE_FUNCTION typename std::enable_if<
240 is_soa<SoA_t>::value,
241 typename SoA_t::template member_reference_type<M>>::type
242get( SoA_t& soa, const std::size_t a, const std::size_t d0,
243 const std::size_t d1, const std::size_t d2 )
244{
245 return Impl::soaMemberCast<M>( soa )._data[d0][d1][d2][a];
246}
247
249template <std::size_t M, class SoA_t>
250KOKKOS_FORCEINLINE_FUNCTION typename std::enable_if<
251 is_soa<SoA_t>::value,
252 typename SoA_t::template member_const_reference_type<M>>::type
253get( const SoA_t& soa, const std::size_t a, const std::size_t d0,
254 const std::size_t d1, const std::size_t d2 )
255{
256 return Impl::soaMemberCast<M>( soa )._data[d0][d1][d2][a];
257}
258
259//---------------------------------------------------------------------------//
269template <typename... Types, int VectorLength>
270struct SoA<MemberTypes<Types...>, VectorLength>
271 : Impl::SoAImpl<VectorLength, std::make_index_sequence<sizeof...( Types )>,
272 Types...>
273{
275 static constexpr int vector_length = VectorLength;
276
278 using member_types = MemberTypes<Types...>;
279
281 static constexpr std::size_t number_of_members = member_types::size;
282
284 static constexpr std::size_t max_supported_rank = 3;
285
287 template <std::size_t M>
289
291 template <std::size_t M>
293 typename std::remove_all_extents<member_data_type<M>>::type;
294
296 template <std::size_t M>
298
300 template <std::size_t M>
302
304 template <std::size_t M>
306 typename std::add_pointer<member_value_type<M>>::type;
307
309 template <std::size_t M>
310 using base = Impl::StructMember<M, vector_length, member_data_type<M>>;
311
312 // -------------------------------
313 // Member data type properties.
314
322 template <std::size_t M>
323 KOKKOS_FORCEINLINE_FUNCTION constexpr std::size_t rank() const
324 {
325 return std::rank<member_data_type<M>>::value;
326 }
327
337 template <std::size_t M, std::size_t D>
338 KOKKOS_FORCEINLINE_FUNCTION constexpr std::size_t extent() const
339 {
340 return std::extent<member_data_type<M>, D>::value;
341 }
342};
343
344//---------------------------------------------------------------------------//
345
346namespace Impl
347{
349
350//---------------------------------------------------------------------------//
351// Member element copy operators.
352//---------------------------------------------------------------------------//
353
354// Copy a single member from one SoA to another.
355
356// Rank 0
357template <std::size_t M, int DstVectorLength, int SrcVectorLength,
358 typename... Types>
359KOKKOS_INLINE_FUNCTION typename std::enable_if<
360 ( 0 == std::rank<typename MemberTypeAtIndex<
361 M, MemberTypes<Types...>>::type>::value ),
362 void>::type
363soaElementMemberCopy( SoA<MemberTypes<Types...>, DstVectorLength>& dst,
364 const std::size_t dst_idx,
365 const SoA<MemberTypes<Types...>, SrcVectorLength>& src,
366 const std::size_t src_idx )
367{
368 get<M>( dst, dst_idx ) = get<M>( src, src_idx );
369}
370
371// Rank 1
372template <std::size_t M, int DstVectorLength, int SrcVectorLength,
373 typename... Types>
374KOKKOS_INLINE_FUNCTION typename std::enable_if<
375 ( 1 == std::rank<typename MemberTypeAtIndex<
376 M, MemberTypes<Types...>>::type>::value ),
377 void>::type
378soaElementMemberCopy( SoA<MemberTypes<Types...>, DstVectorLength>& dst,
379 const std::size_t dst_idx,
380 const SoA<MemberTypes<Types...>, SrcVectorLength>& src,
381 const std::size_t src_idx )
382{
383 for ( std::size_t i0 = 0; i0 < dst.template extent<M, 0>(); ++i0 )
384 get<M>( dst, dst_idx, i0 ) = get<M>( src, src_idx, i0 );
385}
386
387// Rank 2
388template <std::size_t M, int DstVectorLength, int SrcVectorLength,
389 typename... Types>
390KOKKOS_INLINE_FUNCTION typename std::enable_if<
391 ( 2 == std::rank<typename MemberTypeAtIndex<
392 M, MemberTypes<Types...>>::type>::value ),
393 void>::type
394soaElementMemberCopy( SoA<MemberTypes<Types...>, DstVectorLength>& dst,
395 const std::size_t dst_idx,
396 const SoA<MemberTypes<Types...>, SrcVectorLength>& src,
397 const std::size_t src_idx )
398{
399 for ( std::size_t i0 = 0; i0 < dst.template extent<M, 0>(); ++i0 )
400 for ( std::size_t i1 = 0; i1 < dst.template extent<M, 1>(); ++i1 )
401 get<M>( dst, dst_idx, i0, i1 ) = get<M>( src, src_idx, i0, i1 );
402}
403
404// Rank 3
405template <std::size_t M, int DstVectorLength, int SrcVectorLength,
406 typename... Types>
407KOKKOS_INLINE_FUNCTION typename std::enable_if<
408 ( 3 == std::rank<typename MemberTypeAtIndex<
409 M, MemberTypes<Types...>>::type>::value ),
410 void>::type
411soaElementMemberCopy( SoA<MemberTypes<Types...>, DstVectorLength>& dst,
412 const std::size_t dst_idx,
413 const SoA<MemberTypes<Types...>, SrcVectorLength>& src,
414 const std::size_t src_idx )
415{
416 for ( std::size_t i0 = 0; i0 < dst.template extent<M, 0>(); ++i0 )
417 for ( std::size_t i1 = 0; i1 < dst.template extent<M, 1>(); ++i1 )
418 for ( std::size_t i2 = 0; i2 < dst.template extent<M, 2>(); ++i2 )
419 get<M>( dst, dst_idx, i0, i1, i2 ) =
420 get<M>( src, src_idx, i0, i1, i2 );
421}
422
423// Copy the values of all members of an SoA from a source to a destination at
424// the given indices.
425template <std::size_t M, int DstVectorLength, int SrcVectorLength,
426 typename... Types>
427KOKKOS_INLINE_FUNCTION void soaElementCopy(
428 SoA<MemberTypes<Types...>, DstVectorLength>& dst, const std::size_t dst_idx,
429 const SoA<MemberTypes<Types...>, SrcVectorLength>& src,
430 const std::size_t src_idx, std::integral_constant<std::size_t, M> )
431{
432 soaElementMemberCopy<M>( dst, dst_idx, src, src_idx );
433 soaElementCopy( dst, dst_idx, src, src_idx,
434 std::integral_constant<std::size_t, M - 1>() );
435}
436
437template <int DstVectorLength, int SrcVectorLength, typename... Types>
438KOKKOS_INLINE_FUNCTION void soaElementCopy(
439 SoA<MemberTypes<Types...>, DstVectorLength>& dst, const std::size_t dst_idx,
440 const SoA<MemberTypes<Types...>, SrcVectorLength>& src,
441 const std::size_t src_idx, std::integral_constant<std::size_t, 0> )
442{
443 soaElementMemberCopy<0>( dst, dst_idx, src, src_idx );
444}
445
446// Copy the data from one struct at a given index to another.
447template <int DstVectorLength, int SrcVectorLength, typename... Types>
448KOKKOS_INLINE_FUNCTION void
449tupleCopy( SoA<MemberTypes<Types...>, DstVectorLength>& dst,
450 const std::size_t dst_idx,
451 const SoA<MemberTypes<Types...>, SrcVectorLength>& src,
452 const std::size_t src_idx )
453{
454 soaElementCopy(
455 dst, dst_idx, src, src_idx,
456 std::integral_constant<std::size_t, sizeof...( Types ) - 1>() );
457}
458
459//---------------------------------------------------------------------------//
461
462} // end namespace Impl
463} // end namespace Cabana
464
465#endif // end CABANA_SOA_HPP
AoSoA tuple member types.
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
Get the type of the member at a given index.
Definition Cabana_MemberTypes.hpp:75
General sequence of types for SoA and AoSoA member data.
Definition Cabana_MemberTypes.hpp:28
static constexpr std::size_t size
Definition Cabana_MemberTypes.hpp:30
KOKKOS_FORCEINLINE_FUNCTION constexpr std::size_t extent() const
Get the extent of a given member data dimension.
Definition Cabana_SoA.hpp:338
static constexpr std::size_t max_supported_rank
The maximum rank supported for member types.
Definition Cabana_SoA.hpp:284
MemberTypes< Types... > member_types
Member data types.
Definition Cabana_SoA.hpp:278
KOKKOS_FORCEINLINE_FUNCTION constexpr std::size_t rank() const
Get the rank of the data for a given member at index M.
Definition Cabana_SoA.hpp:323
member_value_type< M > const & member_const_reference_type
Const reference type at a given index M.
Definition Cabana_SoA.hpp:301
Impl::StructMember< M, vector_length, member_data_type< M > > base
Base type.
Definition Cabana_SoA.hpp:310
typename std::add_pointer< member_value_type< M > >::type member_pointer_type
Pointer type at a given index M.
Definition Cabana_SoA.hpp:305
typename std::remove_all_extents< member_data_type< M > >::type member_value_type
Value type at a given index M.
Definition Cabana_SoA.hpp:292
member_value_type< M > & member_reference_type
Reference type at a given index M.
Definition Cabana_SoA.hpp:297
static constexpr int vector_length
Vector length.
Definition Cabana_SoA.hpp:275
typename MemberTypeAtIndex< M, member_types >::type member_data_type
Member data type.
Definition Cabana_SoA.hpp:288
static constexpr std::size_t number_of_members
Number of member types.
Definition Cabana_SoA.hpp:281
Definition Cabana_SoA.hpp:32
SoA static type checker.
Definition Cabana_SoA.hpp:50